Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add backend method #1995

Merged
merged 4 commits into from
Oct 24, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions qiskit_ibm_runtime/base_primitive.py
Original file line number Diff line number Diff line change
Expand Up @@ -234,6 +234,10 @@ def options(self) -> OptionsT:
"""Return options"""
return self._options

def backend(self) -> BackendV1 | BackendV2:
"""Return the backend the primitive query will be run on."""
return self._backend

def _set_options(self, options: Optional[Union[Dict, OptionsT]] = None) -> None:
"""Set options."""
if options is None:
Expand Down
4 changes: 4 additions & 0 deletions qiskit_ibm_runtime/noise_learner/noise_learner.py
Original file line number Diff line number Diff line change
Expand Up @@ -221,6 +221,10 @@ def _program_id(cls) -> str:
"""Return the program ID."""
return "noise-learner"

def backend(self) -> BackendV2:
"""Return the backend the primitive query will be run on."""
return self._backend

def _set_options(
self, options: Optional[Union[Dict, NoiseLearnerOptions, EstimatorOptions]] = None
) -> None:
Expand Down
2 changes: 2 additions & 0 deletions release-notes/unreleased/1995.feat.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
:class:`.SamplerV2`, :class:`.EstimatorV2`, and :class:`.noise_learner.NoiseLearner` now each has
a ``backend()`` method that returns the backend the class is configured with.
55 changes: 16 additions & 39 deletions test/unit/test_ibm_primitives_v2.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,13 +23,12 @@
from qiskit.circuit.library import RealAmplitudes
from qiskit.quantum_info import SparsePauliOp

from qiskit_ibm_runtime import Session
from qiskit_ibm_runtime import Session, Batch
from qiskit_ibm_runtime.utils.default_session import _DEFAULT_SESSION
from qiskit_ibm_runtime import EstimatorV2, SamplerV2
from qiskit_ibm_runtime.estimator import Estimator as IBMBaseEstimator
from qiskit_ibm_runtime.fake_provider import FakeManilaV2
from qiskit_ibm_runtime.exceptions import IBMInputValueError
from qiskit_ibm_runtime.options.utils import Unset

from ..ibm_test_case import IBMTestCase
from ..utils import (
Expand Down Expand Up @@ -630,6 +629,21 @@ def test_abstract_circuits(self, primitive):
with self.assertRaisesRegex(IBMInputValueError, "target hardware"):
inst.run(pubs=[tuple(pub)])

@data(EstimatorV2, SamplerV2)
def test_get_backend_primitive(self, primitive):
"""Test getting the backend used in the primitive."""
backend = get_mocked_backend()
inst = primitive(mode=backend)
self.assertEqual(inst.backend().name, backend.name)

@combine(primitive=[EstimatorV2, SamplerV2], session=[Session, Batch])
def test_get_backend_session(self, primitive, session):
"""Test getting the backend used in the primitive when session is used."""
backend = FakeManilaV2()
with session(backend=backend):
inst = primitive()
self.assertEqual(inst.backend().name, backend.name)

def _update_dict(self, dict1, dict2):
for key, val in dict1.items():
if isinstance(val, dict):
Expand All @@ -643,40 +657,3 @@ def _assert_dict_partially_equal(self, dict1, dict2):
dict_paritally_equal(dict1, dict2),
f"{dict1} and {dict2} not partially equal.",
)

def test_qctrl_supported_values_for_options_estimator(self):
"""Test exception when options levels not supported for Estimator V2."""
no_resilience_options = {
"measure_mitigation": Unset,
"measure_noise_learning": {},
"zne_mitigation": Unset,
"zne": {},
"pec_mitigation": Unset,
"pec": {},
"layer_noise_learning": {},
}

options_good = [
# Minimum working settings
{},
# No warnings, we need resilience options here because by default they are getting populated.
{"resilience": no_resilience_options},
# Arbitrary resilience options(issue warning)
{
"resilience_level": 1,
"resilience": {"measure_mitigation": True},
},
# Resilience level > 1 (issue warning)
{"resilience_level": 2},
# Twirling (issue warning)
{"twirling": {"strategy": "active"}},
# Dynamical_decoupling (issue warning)
{"dynamical_decoupling": {"sequence_type": "XY4"}},
]
session = get_mocked_session()
session.service.backend().configuration().simulator = False
for options in options_good:
with self.subTest(msg=f"EstimatorV2, {options}"):
print(options)
inst = EstimatorV2(mode=session, options=options)
_ = inst.run(**get_primitive_inputs(inst))
6 changes: 6 additions & 0 deletions test/unit/test_noise_learner.py
Original file line number Diff line number Diff line change
Expand Up @@ -125,3 +125,9 @@ def test_not_supported_in_local_mode(self):
"""Test exception when circuits is not ISA."""
with self.assertRaisesRegex(ValueError, "not currently supported in local mode"):
NoiseLearner(FakeSherbrooke())

def test_get_backend(self):
"""Test getting the backend used."""
backend = get_mocked_backend()
inst = NoiseLearner(backend)
self.assertEqual(inst.backend().name, backend.name)