Skip to content

Commit

Permalink
Adding NoiseLearner class and related functionality (#1805)
Browse files Browse the repository at this point in the history
Co-authored-by: Ian Hincks <[email protected]>
  • Loading branch information
SamFerracin and ihincks authored Jul 31, 2024
1 parent 2d5713f commit 68502f9
Show file tree
Hide file tree
Showing 14 changed files with 959 additions and 60 deletions.
1 change: 1 addition & 0 deletions docs/apidocs/index.rst
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ qiskit-ibm-runtime API reference
:maxdepth: 1

runtime_service
noise_learner
options
transpiler
qiskit_ibm_runtime.transpiler.passes.scheduling
Expand Down
4 changes: 4 additions & 0 deletions docs/apidocs/noise_learner.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
.. automodule:: qiskit_ibm_runtime.noise_learner
:no-members:
:no-inherited-members:
:no-special-members:
103 changes: 43 additions & 60 deletions qiskit_ibm_runtime/base_primitive.py
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,48 @@
OptionsT = TypeVar("OptionsT", bound=BaseOptions)


def _get_mode_service_backend(
mode: Optional[Union[BackendV1, BackendV2, Session, Batch, str]] = None
) -> tuple[
Union[Session, Batch, None],
Union[QiskitRuntimeService, QiskitRuntimeLocalService, None],
Union[BackendV1, BackendV2, None],
]:
"""
A utility function that returns mode, service, and backend for a given execution mode.
Args:
mode: The execution mode used to make the primitive query. It can be
* A :class:`Backend` if you are using job mode.
* A :class:`Session` if you are using session execution mode.
* A :class:`Batch` if you are using batch execution mode.
"""

if isinstance(mode, (Session, Batch)):
return mode, mode.service, mode._backend
elif isinstance(mode, IBMBackend): # type: ignore[unreachable]
return None, mode.service, mode
elif isinstance(mode, (BackendV1, BackendV2)):
return None, QiskitRuntimeLocalService(), mode
elif isinstance(mode, str):
service = (
QiskitRuntimeService()
if QiskitRuntimeService.global_service is None
else QiskitRuntimeService.global_service
)
return None, service, service.backend(mode)
elif mode is not None: # type: ignore[unreachable]
raise ValueError("mode must be of type Backend, Session, Batch or None")
elif get_cm_session():
mode = get_cm_session()
service = mode.service # type: ignore
backend = service.backend(name=mode.backend(), instance=mode._instance) # type: ignore
return mode, service, backend # type: ignore
else:
raise ValueError("A backend or session must be specified.")


class BasePrimitiveV2(ABC, Generic[OptionsT]):
"""Base class for Qiskit Runtime primitives."""

Expand Down Expand Up @@ -78,68 +120,9 @@ def __init__(
Raises:
ValueError: Invalid arguments are given.
"""
self._mode: Optional[Union[Session, Batch]] = None
self._service: QiskitRuntimeService | QiskitRuntimeLocalService = None
self._backend: Optional[BackendV1 | BackendV2] = None

self._mode, self._service, self._backend = _get_mode_service_backend(mode)
self._set_options(options)

if isinstance(mode, (Session, Batch)):
self._mode = mode
self._service = self._mode.service
self._backend = self._mode._backend
elif isinstance(mode, IBMBackend): # type: ignore[unreachable]
if get_cm_session():
warnings.warn(
(
"Passing a backend as the mode currently runs the job in job mode even "
"if inside of a session/batch context manager. As of qiskit-ibm-runtime "
"version 0.26.0, this behavior is deprecated and in a future "
"release no sooner than than 3 months "
"after the release date, the session/batch will take precendence and "
"the job will not run in job mode. To ensure that jobs are run in session/batch "
"mode, pass in the session/batch or leave the mode parameter emtpy."
),
DeprecationWarning,
stacklevel=3,
)
self._service = mode.service
self._backend = mode
elif isinstance(mode, (BackendV1, BackendV2)):
self._service = QiskitRuntimeLocalService()
self._backend = mode
elif isinstance(mode, str):
if get_cm_session():
warnings.warn(
(
"Passing a backend as the mode currently runs the job in job mode even "
"if inside of a session/batch context manager. As of qiskit-ibm-runtime "
"version 0.26.0, this behavior is deprecated and in a future "
"release no sooner than than 3 months "
"after the release date, the session/batch will take precendence and "
"the job will not run in job mode. To ensure that jobs are run in session/batch "
"mode, pass in the session/batch or leave the mode parameter emtpy."
),
DeprecationWarning,
stacklevel=3,
)
self._service = (
QiskitRuntimeService()
if QiskitRuntimeService.global_service is None
else QiskitRuntimeService.global_service
)
self._backend = self._service.backend(mode)
elif mode is not None: # type: ignore[unreachable]
raise ValueError("mode must be of type Backend, Session, Batch or None")
elif get_cm_session():
self._mode = get_cm_session()
self._service = self._mode.service
self._backend = self._service.backend( # type: ignore
name=self._mode.backend(), instance=self._mode._instance
)
else:
raise ValueError("A backend or session must be specified.")

def _run(self, pubs: Union[list[EstimatorPub], list[SamplerPub]]) -> RuntimeJobV2:
"""Run the primitive.
Expand Down
2 changes: 2 additions & 0 deletions qiskit_ibm_runtime/constants.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
from qiskit.providers.jobstatus import JobStatus

from .utils.result_decoder import ResultDecoder
from .utils.noise_learner_result_decoder import NoiseLearnerResultDecoder
from .utils.estimator_result_decoder import EstimatorResultDecoder
from .utils.sampler_result_decoder import SamplerResultDecoder
from .utils.runner_result import RunnerResult
Expand All @@ -39,6 +40,7 @@
DEFAULT_DECODERS = {
"sampler": [ResultDecoder, SamplerResultDecoder],
"estimator": [ResultDecoder, EstimatorResultDecoder],
"noise-learner": NoiseLearnerResultDecoder,
"circuit-runner": RunnerResult,
"qasm3-runner": RunnerResult,
}
33 changes: 33 additions & 0 deletions qiskit_ibm_runtime/noise_learner/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
# This code is part of Qiskit.
#
# (C) Copyright IBM 2024
#
# 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.

"""
====================================================================
Noise learner (:mod:`qiskit_ibm_runtime.noise_learner.NoiseLearner`)
====================================================================
.. currentmodule:: qiskit_ibm_runtime.noise_learner
The tools to characterize the noise processes affecting the gates in noisy
quantum circuits.
Classes
=======
.. autosummary::
:toctree: ../stubs/
NoiseLearner
"""

from .noise_learner import NoiseLearner
Loading

0 comments on commit 68502f9

Please sign in to comment.