-
Notifications
You must be signed in to change notification settings - Fork 198
[executor-preview] Test noise_learner_v3.py #2498
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
Changes from 11 commits
beae738
744998a
61219cf
58cbf58
ac1b037
b8ef040
dc109fd
572e6b5
ab3fd6f
cb6d769
17f20f8
4de1380
4b98826
c47364c
9d41d86
65fa1ff
ece67ad
7bf4a45
3830096
531f77b
0d94a67
dad394b
1932874
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -26,7 +26,6 @@ | |
| from ..batch import Batch | ||
| from ..fake_provider.local_service import QiskitRuntimeLocalService | ||
| from ..options.noise_learner_v3_options import NoiseLearnerV3Options | ||
| from ..qiskit_runtime_service import QiskitRuntimeService | ||
| from ..runtime_job_v2 import RuntimeJobV2 | ||
|
|
||
| # pylint: disable=unused-import,cyclic-import | ||
|
|
@@ -77,48 +76,16 @@ def __init__( | |
| mode: Optional[Union[BackendV2, Session, Batch]] = None, | ||
| options: Optional[NoiseLearnerV3Options] = None, | ||
| ): | ||
| self._session: BackendV2 | None = None | ||
| self._backend: BackendV2 | ||
| self._service: QiskitRuntimeService | ||
|
|
||
| self._options = options or NoiseLearnerV3Options() | ||
| if ( | ||
| isinstance(self._options.experimental, UnsetType) | ||
| or self._options.experimental.get("image") is None | ||
| ): | ||
| self._options.experimental = {} | ||
|
|
||
| if isinstance(mode, (Session, Batch)): | ||
| self._session = mode | ||
| self._backend = self._session._backend | ||
| self._service = self._session.service | ||
| elif open_session := get_cm_session(): | ||
| if open_session != mode: | ||
| if open_session._backend != mode: | ||
| raise ValueError( | ||
| "The backend passed in to the primitive is different from the session " | ||
| "backend. Please check which backend you intend to use or leave the mode " | ||
| "parameter empty to use the session backend." | ||
| ) | ||
| logger.warning( | ||
| "A backend was passed in as the mode but a session context manager " | ||
| "is open so this job will run inside this session/batch " | ||
| "instead of in job mode." | ||
| ) | ||
| self._session = open_session | ||
| self._backend = self._session._backend | ||
| self._service = self._session.service | ||
| elif isinstance(mode, BackendV2): | ||
| self._backend = mode | ||
| self._service = self._backend.service | ||
| else: | ||
| raise ValueError( | ||
| "A backend or session/batch must be specified, or a session/batch must be open." | ||
| ) | ||
| self._mode, self._service, self._backend = _get_mode_service_backend(mode) | ||
|
|
||
| if isinstance(self._service, QiskitRuntimeLocalService): # type: ignore[unreachable] | ||
| raise ValueError("``NoiseLearner`` not currently supported in local mode.") | ||
| self._session, self._service, self._backend = _get_mode_service_backend(mode) | ||
| if isinstance(self._service, QiskitRuntimeLocalService): | ||
| raise ValueError("``NoiseLearnerV3`` is currently not supported in local mode.") | ||
|
|
||
| @property | ||
| def options(self) -> NoiseLearnerV3Options: | ||
|
|
@@ -144,15 +111,14 @@ def run(self, instructions: Iterable[CircuitInstruction]) -> RuntimeJobV2: | |
| IBMInputValueError: If an instruction cannot be learned by any of the supported learning | ||
| protocols. | ||
| """ | ||
| if self._backend: | ||
| target = getattr(self._backend, "target", None) | ||
| if target and not is_simulator(self._backend): | ||
| for instruction in instructions: | ||
| validate_instruction(instruction, target) | ||
|
|
||
| configuration = getattr(self._backend, "configuration", None) | ||
| if configuration and not is_simulator(self._backend): | ||
| validate_options(self.options, configuration()) | ||
| target = getattr(self._backend, "target", None) | ||
| if target and not is_simulator(self._backend): | ||
|
||
| for instruction in instructions: | ||
| validate_instruction(instruction, target) | ||
|
|
||
| configuration = getattr(self._backend, "configuration", None) | ||
| if configuration and not is_simulator(self._backend): | ||
| validate_options(self.options, configuration()) | ||
|
|
||
| inputs = noise_learner_v3_inputs_to_0_1(instructions, self.options).model_dump() | ||
| inputs["version"] = 3 # TODO: this is a work-around for the dispatch | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,92 @@ | ||
| # This code is part of Qiskit. | ||
| # | ||
| # (C) Copyright IBM 2025. | ||
| # | ||
| # 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. | ||
|
|
||
| """Tests the `NoiseLearnerV3` class.""" | ||
|
|
||
| from test.utils import get_mocked_backend, get_mocked_session | ||
|
|
||
| from qiskit_ibm_runtime import Session | ||
| from qiskit_ibm_runtime.noise_learner_v3 import NoiseLearnerV3 | ||
|
|
||
| from ...ibm_test_case import IBMTestCase | ||
|
|
||
|
|
||
| class TestNoiseLearnerV3(IBMTestCase): | ||
| """Tests the ``NoiseLearnerV3`` class.""" | ||
|
|
||
| def test_init_with_backend(self): | ||
| """Test ``NoiseLearnerV3.init`` when the input mode is an ``IBMBackend``.""" | ||
| backend = get_mocked_backend() | ||
| service = backend.service | ||
| service.reset_mock() | ||
| noise_learner = NoiseLearnerV3(mode=backend) | ||
| self.assertEqual(noise_learner._session, None) | ||
| self.assertEqual(noise_learner._backend, backend) | ||
| self.assertEqual(noise_learner._service, service) | ||
|
|
||
| def test_init_with_session(self): | ||
| """Test ``NoiseLearnerV3.init`` when the input mode is a session.""" | ||
| backend_name = "ibm_hello" | ||
| session = get_mocked_session(get_mocked_backend(backend_name)) | ||
| session.reset_mock() | ||
| session.service.reset_mock() | ||
|
||
| noise_learner = NoiseLearnerV3(mode=session) | ||
| self.assertEqual(noise_learner._session, session) | ||
| self.assertEqual(noise_learner._backend.name, backend_name) | ||
| self.assertEqual(noise_learner._service, session.service) | ||
|
|
||
| def test_session_context_manager(self): | ||
| """Test ``NoiseLearnerV3.init`` inside a session context manager.""" | ||
| backend = get_mocked_backend() | ||
| service = backend.service | ||
| service.reset_mock() | ||
| with Session(backend=backend) as session: | ||
| noise_learner = NoiseLearnerV3() | ||
| self.assertEqual(noise_learner._session, session) | ||
| self.assertEqual(noise_learner._backend, backend) | ||
| self.assertEqual(noise_learner._service, service) | ||
|
|
||
| def test_init_with_backend_inside_session_context_manager(self): | ||
| """Test ``NoiseLearnerV3.init`` inside a session context manager, | ||
| when the input mode is an ``IBMBackend``.""" | ||
| backend = get_mocked_backend() | ||
| service = backend.service | ||
| service.reset_mock() | ||
| with Session(backend=backend) as session: | ||
| noise_learner = NoiseLearnerV3(mode=backend) | ||
| self.assertEqual(noise_learner._session, session) | ||
| self.assertEqual(noise_learner._backend, backend) | ||
| self.assertEqual(noise_learner._service, service) | ||
|
|
||
| def test_run_of_session_is_selected(self): | ||
SamFerracin marked this conversation as resolved.
Show resolved
Hide resolved
|
||
| """Test that ``NoiseLearner.run`` selects the ``run`` method | ||
| of the session, if a session is specified.""" | ||
| backend_name = "ibm_hello" | ||
| session = get_mocked_session(get_mocked_backend(backend_name)) | ||
| session.reset_mock() | ||
| session.service.reset_mock() | ||
| noise_learner = NoiseLearnerV3(mode=session) | ||
| session._run = lambda *args, **kwargs: "session" | ||
| session.service._run = lambda *args, **kwargs: "service" | ||
| selected_run = noise_learner.run([]) | ||
| self.assertEqual(selected_run, "session") | ||
|
|
||
| def test_run_of_service_is_selected(self): | ||
| """Test that ``NoiseLearner.run`` selects the ``run`` method | ||
| of the service, if a session is not specified.""" | ||
| backend = get_mocked_backend() | ||
| service = backend.service | ||
| service.reset_mock() | ||
| noise_learner = NoiseLearnerV3(mode=backend) | ||
| service._run = lambda *args, **kwargs: "service" | ||
| selected_run = noise_learner.run([]) | ||
| self.assertEqual(selected_run, "service") | ||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Was the part above redundant, because
_get_mode_service_backendjust undoes what was done above?There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The part above was some copying of the content of
_get_mode_service_backend, with some editing, that introduced bugs. Some cases were addressed (correctly or incorrectly) by the part above, without ever reaching the call to_get_mode_service_backend. Other cases did reach the call, and went through the same process again inside the function.