From d1d16145e1c01248e5e336656dadbb5482b7a304 Mon Sep 17 00:00:00 2001 From: kevin-tian Date: Thu, 1 Feb 2024 19:45:06 -0500 Subject: [PATCH 1/2] Move provider's session & remove qiskit-ibm-provider --- qiskit_ibm_runtime/base_primitive.py | 2 +- qiskit_ibm_runtime/ibm_backend.py | 4 +- qiskit_ibm_runtime/provider_session.py | 134 +++++++++++++++++++++++++ requirements.txt | 1 - setup.py | 1 - 5 files changed, 137 insertions(+), 5 deletions(-) create mode 100644 qiskit_ibm_runtime/provider_session.py diff --git a/qiskit_ibm_runtime/base_primitive.py b/qiskit_ibm_runtime/base_primitive.py index 13c759584..c7bb67fb9 100644 --- a/qiskit_ibm_runtime/base_primitive.py +++ b/qiskit_ibm_runtime/base_primitive.py @@ -22,7 +22,7 @@ from qiskit.providers.options import Options as TerraOptions -from qiskit_ibm_provider.session import get_cm_session as get_cm_provider_session +from .provider_session import get_cm_session as get_cm_provider_session from .options import Options from .options.utils import set_default_error_levels diff --git a/qiskit_ibm_runtime/ibm_backend.py b/qiskit_ibm_runtime/ibm_backend.py index 5e0604e00..9f36daecb 100644 --- a/qiskit_ibm_runtime/ibm_backend.py +++ b/qiskit_ibm_runtime/ibm_backend.py @@ -41,9 +41,9 @@ from qiskit.transpiler.target import Target # temporary until we unite the 2 Session classes -from qiskit_ibm_provider.session import ( +from .provider_session import ( Session as ProviderSession, -) # temporary until we unite the 2 Session classes +) from .utils.utils import validate_job_tags from . import qiskit_runtime_service # pylint: disable=unused-import,cyclic-import diff --git a/qiskit_ibm_runtime/provider_session.py b/qiskit_ibm_runtime/provider_session.py new file mode 100644 index 000000000..5d52cdd14 --- /dev/null +++ b/qiskit_ibm_runtime/provider_session.py @@ -0,0 +1,134 @@ +# This code is part of Qiskit. +# +# (C) Copyright IBM 2022. +# +# This code is licensed under the Apache License, Version 2.0. You may +# obtain a copy of this license in the LICENSE.txt file in the root directory +# of this source tree or at http://www.apache.org/licenses/LICENSE-2.0. +# +# Any modifications or derivative works of this code must retain this +# copyright notice, and modified files need to carry a notice indicating +# that they have been altered from the originals. + +"""Qiskit Runtime flexible session.""" + +from typing import Optional, Type, Union +from types import TracebackType +from contextvars import ContextVar + +from .utils.converters import hms_to_seconds + + +class Session: + """Class for creating a flexible Qiskit Runtime session. + + A Qiskit Runtime ``session`` allows you to group a collection of iterative calls to + the quantum computer. A session is started when the first job within the session + is started. Subsequent jobs within the session are prioritized by the scheduler. + Data used within a session, such as transpiled circuits, is also cached to avoid + unnecessary overhead. + + You can open a Qiskit Runtime session using this ``Session`` class + and submit one or more jobs. + + For example:: + + from qiskit.test.reference_circuits import ReferenceCircuits + from qiskit_ibm_runtime import QiskitRuntimeService + + circ = ReferenceCircuits.bell() + backend = QiskitRuntimeService().get_backend("ibmq_qasm_simulator") + + backend.open_session() + job = backend.run(circ) + print(f"Job ID: {job.job_id()}") + print(f"Result: {job.result()}") + # Close the session only if all jobs are finished and + # you don't need to run more in the session. + backend.cancel_session() + + Session can also be used as a context manager:: + + with backend.open_session() as session: + job = backend.run(ReferenceCircuits.bell()) + + """ + + def __init__( + self, + max_time: Optional[Union[int, str]] = None, + ): + """Session constructor. + + Args: + max_time: (EXPERIMENTAL setting, can break between releases without warning) + Maximum amount of time, a runtime session can be open before being + forcibly closed. Can be specified as seconds (int) or a string like "2h 30m 40s". + This value must be in between 300 seconds and the + `system imposed maximum + `_. + + Raises: + ValueError: If an input value is invalid. + """ + self._instance = None + self._session_id: Optional[str] = None + self._active = True + + self._max_time = ( + max_time + if max_time is None or isinstance(max_time, int) + else hms_to_seconds(max_time, "Invalid max_time value: ") + ) + + @property + def session_id(self) -> str: + """Return the session ID. + + Returns: + Session ID. None until a job runs in the session. + """ + return self._session_id + + @property + def active(self) -> bool: + """Return the status of the session. + + Returns: + True if the session is active, False otherwise. + """ + return self._active + + def cancel(self) -> None: + """Set the session._active status to False""" + self._active = False + + def __enter__(self) -> "Session": + set_cm_session(self) + return self + + def __exit__( + self, + exc_type: Optional[Type[BaseException]], + exc_val: Optional[BaseException], + exc_tb: Optional[TracebackType], + ) -> None: + set_cm_session(None) + + +# Default session +_DEFAULT_SESSION: ContextVar[Optional[Session]] = ContextVar( + "_DEFAULT_SESSION", default=None +) +_IN_SESSION_CM: ContextVar[bool] = ContextVar("_IN_SESSION_CM", default=False) + + +def set_cm_session(session: Optional[Session]) -> None: + """Set the context manager session.""" + _DEFAULT_SESSION.set(session) + _IN_SESSION_CM.set(session is not None) + + +def get_cm_session() -> Session: + """Return the context managed session.""" + return _DEFAULT_SESSION.get() diff --git a/requirements.txt b/requirements.txt index 9203f9632..15b6946d2 100644 --- a/requirements.txt +++ b/requirements.txt @@ -7,4 +7,3 @@ python-dateutil>=2.8.0 websocket-client>=1.5.1 typing-extensions>=4.0.0 ibm-platform-services>=0.22.6 -qiskit-ibm-provider>=0.8.0 diff --git a/setup.py b/setup.py index 273fb9768..c5845888d 100644 --- a/setup.py +++ b/setup.py @@ -27,7 +27,6 @@ "python-dateutil>=2.8.0", "websocket-client>=1.5.1", "ibm-platform-services>=0.22.6", - "qiskit-ibm-provider>=0.8.0", ] # Handle version. From 99d8334fef167045478c2e424db607ed9680b299 Mon Sep 17 00:00:00 2001 From: kevin-tian Date: Thu, 1 Feb 2024 19:58:34 -0500 Subject: [PATCH 2/2] fix black --- qiskit_ibm_runtime/ibm_backend.py | 2 +- qiskit_ibm_runtime/provider_session.py | 4 +--- 2 files changed, 2 insertions(+), 4 deletions(-) diff --git a/qiskit_ibm_runtime/ibm_backend.py b/qiskit_ibm_runtime/ibm_backend.py index 9f36daecb..accf571d0 100644 --- a/qiskit_ibm_runtime/ibm_backend.py +++ b/qiskit_ibm_runtime/ibm_backend.py @@ -43,7 +43,7 @@ # temporary until we unite the 2 Session classes from .provider_session import ( Session as ProviderSession, -) +) from .utils.utils import validate_job_tags from . import qiskit_runtime_service # pylint: disable=unused-import,cyclic-import diff --git a/qiskit_ibm_runtime/provider_session.py b/qiskit_ibm_runtime/provider_session.py index 5d52cdd14..dad3dc407 100644 --- a/qiskit_ibm_runtime/provider_session.py +++ b/qiskit_ibm_runtime/provider_session.py @@ -117,9 +117,7 @@ def __exit__( # Default session -_DEFAULT_SESSION: ContextVar[Optional[Session]] = ContextVar( - "_DEFAULT_SESSION", default=None -) +_DEFAULT_SESSION: ContextVar[Optional[Session]] = ContextVar("_DEFAULT_SESSION", default=None) _IN_SESSION_CM: ContextVar[bool] = ContextVar("_IN_SESSION_CM", default=False)