From 8f15c79e7661ee1802cfac3378af31c54c8b3e4d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Elena=20Pe=C3=B1a=20Tapia?= <57907331+ElePT@users.noreply.github.com> Date: Mon, 5 Feb 2024 22:32:28 +0100 Subject: [PATCH] Update uses of `FakeBackends` to be compatible with 0.45 and 1.0 (#808) * Update uses of FakeBackends to be compatible with 0.45 and 1.0 * Update import path --- qiskit_ibm_provider/jupyter/__init__.py | 6 ++--- qiskit_ibm_provider/jupyter/backend_info.py | 17 ++++++-------- qiskit_ibm_provider/jupyter/config_widget.py | 8 ++----- qiskit_ibm_provider/jupyter/gates_widget.py | 7 ++---- qiskit_ibm_provider/jupyter/jobs_widget.py | 12 ++++------ qiskit_ibm_provider/jupyter/qubits_widget.py | 8 ++----- qiskit_ibm_provider/test/ibm_provider_mock.py | 11 ++++++---- .../transpiler/passes/scheduling/__init__.py | 14 ++++++++++-- .../visualization/interactive/error_map.py | 9 ++++++-- .../visualization/interactive/gate_map.py | 11 +++++++--- test/fake_account_client.py | 9 ++++---- test/unit/mock/fake_account_client.py | 10 ++++++--- test/unit/test_backend.py | 22 +++++++++++-------- test/unit/test_ibm_job_states.py | 8 +++++-- test/unit/test_serialization.py | 9 ++++++-- .../passes/scheduling/test_scheduler.py | 18 +++++++++------ 16 files changed, 103 insertions(+), 76 deletions(-) diff --git a/qiskit_ibm_provider/jupyter/__init__.py b/qiskit_ibm_provider/jupyter/__init__.py index caa315684..5e2876ce3 100644 --- a/qiskit_ibm_provider/jupyter/__init__.py +++ b/qiskit_ibm_provider/jupyter/__init__.py @@ -34,7 +34,7 @@ :hide-output: from qiskit_ibm_provider.test.ibm_provider_mock import mock_get_backend - mock_get_backend('FakeVigo') + mock_get_backend('Fake1Q') .. jupyter-execute:: @@ -71,8 +71,8 @@ if "ipykernel" in sys.modules: from IPython import get_ipython # pylint: disable=import-error + from qiskit.providers import BackendV2 from .dashboard.dashboard import IBMDashboardMagic - from qiskit.providers.fake_provider.fake_backend import FakeBackendV2 as FakeBackend from ..ibm_backend import IBMBackend from .backend_info import backend_widget @@ -82,4 +82,4 @@ HTML_FORMATTER = _IP.display_formatter.formatters["text/html"] # Make backend_widget the html repr for IBM Quantum backends HTML_FORMATTER.for_type(IBMBackend, backend_widget) - HTML_FORMATTER.for_type(FakeBackend, backend_widget) + HTML_FORMATTER.for_type(BackendV2, backend_widget) diff --git a/qiskit_ibm_provider/jupyter/backend_info.py b/qiskit_ibm_provider/jupyter/backend_info.py index 75b97b090..eb1c2e510 100644 --- a/qiskit_ibm_provider/jupyter/backend_info.py +++ b/qiskit_ibm_provider/jupyter/backend_info.py @@ -14,12 +14,10 @@ """Interactive backend widget.""" import threading -from typing import Union import ipyvuetify as vue from IPython.display import display # pylint: disable=import-error -from qiskit.providers.fake_provider.fake_backend import FakeBackendV2 as FakeBackend - +from qiskit.providers import BackendV2 from qiskit_ibm_provider.ibm_backend import IBMBackend from .config_widget import config_tab from .gates_widget import gates_tab @@ -29,9 +27,7 @@ from ..utils.hgp import to_instance_format -def _async_job_loader( - tab: vue.TabItem, backend: Union[IBMBackend, FakeBackend] -) -> None: +def _async_job_loader(tab: vue.TabItem, backend: BackendV2) -> None: """Asynchronous job loader. Args: @@ -41,18 +37,19 @@ def _async_job_loader( tab.children = [jobs_tab(backend)] -def backend_widget(backend: Union[IBMBackend, FakeBackend]) -> None: +def backend_widget(backend: BackendV2) -> None: """Display backend information as a widget. Args: backend: Display information about this backend. """ vue.theme.dark = False - if isinstance(backend, FakeBackend): + if isinstance(backend, IBMBackend): + instance = backend._api_client._params.instance + else: + # fake backend cred = backend._credentials instance = to_instance_format(cred.hub, cred.group, cred.project) - else: - instance = backend._api_client._params.instance last_tab = vue.TabItem(children=[]) card = vue.Card( height=600, diff --git a/qiskit_ibm_provider/jupyter/config_widget.py b/qiskit_ibm_provider/jupyter/config_widget.py index e68ffc183..f4b42616d 100644 --- a/qiskit_ibm_provider/jupyter/config_widget.py +++ b/qiskit_ibm_provider/jupyter/config_widget.py @@ -13,16 +13,12 @@ """Widget for the backend configuration tab.""" -from typing import Union - import ipywidgets as wid -from qiskit.providers.fake_provider.fake_backend import FakeBackendV2 as FakeBackend - -from qiskit_ibm_provider.ibm_backend import IBMBackend +from qiskit.providers import BackendV2 from qiskit_ibm_provider.visualization.interactive import iplot_gate_map -def config_tab(backend: Union[IBMBackend, FakeBackend]) -> wid.GridBox: +def config_tab(backend: BackendV2) -> wid.GridBox: """The backend configuration widget. Args: diff --git a/qiskit_ibm_provider/jupyter/gates_widget.py b/qiskit_ibm_provider/jupyter/gates_widget.py index 21fa28bdc..04d03a6d8 100644 --- a/qiskit_ibm_provider/jupyter/gates_widget.py +++ b/qiskit_ibm_provider/jupyter/gates_widget.py @@ -14,15 +14,12 @@ """Widget for backend gates tab.""" import math -from typing import Union import ipywidgets as wid -from qiskit.providers.fake_provider.fake_backend import FakeBackendV2 as FakeBackend +from qiskit.providers import BackendV2 -from qiskit_ibm_provider.ibm_backend import IBMBackend - -def gates_tab(backend: Union[IBMBackend, FakeBackend]) -> wid.GridBox: +def gates_tab(backend: BackendV2) -> wid.GridBox: """Construct the multiple qubit gate error widget. Args: diff --git a/qiskit_ibm_provider/jupyter/jobs_widget.py b/qiskit_ibm_provider/jupyter/jobs_widget.py index cffb9b512..7dabfb3ca 100644 --- a/qiskit_ibm_provider/jupyter/jobs_widget.py +++ b/qiskit_ibm_provider/jupyter/jobs_widget.py @@ -14,13 +14,11 @@ """Interactive Jobs widget.""" import datetime -from typing import Any, Union +from typing import Any import ipywidgets as wid import plotly.graph_objects as go -from qiskit.providers.fake_provider.fake_backend import FakeBackendV2 as FakeBackend - -from ..ibm_backend import IBMBackend +from qiskit.providers import BackendV2 from ..visualization.interactive.plotly_wrapper import PlotlyWidget MONTH_NAMES = { @@ -104,9 +102,7 @@ def _job_table_builder(sel_dict: dict) -> str: return table_html -def _job_summary( - backend: Union[IBMBackend, FakeBackend], **kwargs: Any -) -> PlotlyWidget: +def _job_summary(backend: BackendV2, **kwargs: Any) -> PlotlyWidget: """Interactive jobs summary for a backend. Args: @@ -280,7 +276,7 @@ def callback(trace, selection, _): # pylint: disable=unused-argument return sun_wid -def jobs_tab(backend: Union[IBMBackend, FakeBackend], **kwargs: Any) -> wid.HBox: +def jobs_tab(backend: BackendV2, **kwargs: Any) -> wid.HBox: """Construct a widget containing job information for an input backend. Args: diff --git a/qiskit_ibm_provider/jupyter/qubits_widget.py b/qiskit_ibm_provider/jupyter/qubits_widget.py index 8e5845dcf..0abfc5778 100644 --- a/qiskit_ibm_provider/jupyter/qubits_widget.py +++ b/qiskit_ibm_provider/jupyter/qubits_widget.py @@ -13,15 +13,11 @@ """Widget for qubit properties tab.""" -from typing import Union - import ipywidgets as wid -from qiskit.providers.fake_provider.fake_backend import FakeBackendV2 as FakeBackend - -from qiskit_ibm_provider.ibm_backend import IBMBackend +from qiskit.providers import BackendV2 -def qubits_tab(backend: Union[IBMBackend, FakeBackend]) -> wid.VBox: +def qubits_tab(backend: BackendV2) -> wid.VBox: """The qubit properties widget. Args: diff --git a/qiskit_ibm_provider/test/ibm_provider_mock.py b/qiskit_ibm_provider/test/ibm_provider_mock.py index 7326d4003..1d2e12391 100644 --- a/qiskit_ibm_provider/test/ibm_provider_mock.py +++ b/qiskit_ibm_provider/test/ibm_provider_mock.py @@ -1,6 +1,6 @@ # This code is part of Qiskit. # -# (C) Copyright IBM 2021. +# (C) Copyright IBM 2021, 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 @@ -14,7 +14,7 @@ from unittest.mock import MagicMock -from qiskit.test import mock as backend_mocks +from qiskit.providers import fake_provider as backend_mocks import qiskit_ibm_provider @@ -29,15 +29,18 @@ def mock_get_backend(backend): value to qiskit_ibm_provider.IBMProvider after you finish using your mock. Args: backend (str): The class name as a string for the fake device to - return. For example, FakeVigo. + return. For example, Fake1Q. Raises: NameError: If the specified value of backend """ + print(backend_mocks) mock_ibm_provider = MagicMock() if not hasattr(backend_mocks, backend): raise NameError( - "The specified backend name is not a valid mock from " "qiskit.test.mock" + "The specified backend name is not a valid backend from " + "qiskit.providers.fake_provider" ) + print(backend_mocks, backend, getattr(backend_mocks, backend)) fake_backend = getattr(backend_mocks, backend)() mock_ibm_provider.get_backend.return_value = fake_backend mock_ibm_provider.return_value = mock_ibm_provider diff --git a/qiskit_ibm_provider/transpiler/passes/scheduling/__init__.py b/qiskit_ibm_provider/transpiler/passes/scheduling/__init__.py index cc8627234..4d5991f90 100644 --- a/qiskit_ibm_provider/transpiler/passes/scheduling/__init__.py +++ b/qiskit_ibm_provider/transpiler/passes/scheduling/__init__.py @@ -32,6 +32,13 @@ Below we demonstrate how to schedule and pad a teleportation circuit with delays for a dynamic circuit backend's execution model: +.. jupyter-execute:: + :hide-code: + :hide-output: + + import warnings + warnings.filterwarnings("ignore", category=DeprecationWarning) + .. jupyter-execute:: from qiskit.circuit import ClassicalRegister, QuantumCircuit, QuantumRegister @@ -41,10 +48,13 @@ from qiskit_ibm_provider.transpiler.passes.scheduling import DynamicCircuitInstructionDurations from qiskit_ibm_provider.transpiler.passes.scheduling import ALAPScheduleAnalysis from qiskit_ibm_provider.transpiler.passes.scheduling import PadDelay - from qiskit.providers.fake_provider import FakeJakarta + try: + from qiskit.providers.fake_provider import Fake7QPulseV1 + except ImportError: + from qiskit.providers.fake_provider import FakeJakarta as Fake7QPulseV1 - backend = FakeJakarta() + backend = Fake7QPulseV1() # Temporary workaround for mock backends. For real backends this is not required. backend.configuration().basis_gates.append("if_else") diff --git a/qiskit_ibm_provider/visualization/interactive/error_map.py b/qiskit_ibm_provider/visualization/interactive/error_map.py index 4586df400..bc8a922b6 100644 --- a/qiskit_ibm_provider/visualization/interactive/error_map.py +++ b/qiskit_ibm_provider/visualization/interactive/error_map.py @@ -60,7 +60,10 @@ def iplot_error_map( :hide-output: from qiskit_ibm_provider.test.ibm_provider_mock import mock_get_backend - mock_get_backend('FakeVigo') + # Generate a mock provider for the sake of this example. + # This line will allow the mocked ``IBMProvider`` to return + # a fake backend in the following cell. + mock_get_backend('FakeOpenPulse2Q') .. jupyter-execute:: @@ -68,7 +71,9 @@ def iplot_error_map( from qiskit_ibm_provider.visualization import iplot_error_map provider = IBMProvider(group='open', project='main') - backend = provider.get_backend('ibmq_vigo') + # Note that this is a mock provider, replace ``FakeOpenPulse2Q`` + # with any of the currently available IBM devices. + backend = provider.get_backend('FakeOpenPulse2Q') iplot_error_map(backend, as_widget=True) """ diff --git a/qiskit_ibm_provider/visualization/interactive/gate_map.py b/qiskit_ibm_provider/visualization/interactive/gate_map.py index 172c0d37f..498913af7 100644 --- a/qiskit_ibm_provider/visualization/interactive/gate_map.py +++ b/qiskit_ibm_provider/visualization/interactive/gate_map.py @@ -64,15 +64,20 @@ def iplot_gate_map( :hide-output: from qiskit_ibm_provider.test.ibm_provider_mock import mock_get_backend - mock_get_backend('FakeVigo') + # Generate a mock provider for the sake of this example. + # This line will allow the mocked ``IBMProvider`` to return + # a fake backend in the following cell. + mock_get_backend('FakeOpenPulse2Q') .. jupyter-execute:: from qiskit_ibm_provider import IBMProvider from qiskit_ibm_provider.visualization import iplot_gate_map - provider = IBMProvider(group='open', project='main') - backend = provider.get_backend('ibmq_vigo') + provider = IBMProvider(group='open', project='main') + # Note that this is a mock provider, replace ``FakeOpenPulse2Q`` + # with any of the currently available IBM devices. + backend = provider.get_backend('FakeOpenPulse2Q') iplot_gate_map(backend, as_widget=True) """ diff --git a/test/fake_account_client.py b/test/fake_account_client.py index 9e745c0ca..77b27da20 100644 --- a/test/fake_account_client.py +++ b/test/fake_account_client.py @@ -23,9 +23,10 @@ from random import randrange from typing import Dict, Any -from qiskit.providers.fake_provider.backends.poughkeepsie.fake_poughkeepsie import ( - FakePoughkeepsie, -) +try: + from qiskit.providers.fake_provider import Fake20QV1 +except ImportError: + from qiskit.providers.fake_provider import FakePoughkeepsie as Fake20QV1 from qiskit_ibm_provider.api.exceptions import ( RequestsApiError, @@ -452,7 +453,7 @@ def job_final_status(self, job_id, *_args, **_kwargs): def job_properties(self, *_args, **_kwargs): """Return the backend properties of a job.""" - props = FakePoughkeepsie().properties().to_dict() + props = Fake20QV1().properties().to_dict() if self._props_count > 0: self._props_count -= 1 new_dt = datetime.now() + timedelta(hours=randrange(300)) diff --git a/test/unit/mock/fake_account_client.py b/test/unit/mock/fake_account_client.py index 8d447e327..3a1ca968c 100644 --- a/test/unit/mock/fake_account_client.py +++ b/test/unit/mock/fake_account_client.py @@ -15,15 +15,19 @@ from datetime import datetime as python_datetime from typing import List, Dict, Any, Optional -from qiskit.providers.fake_provider.backends.lima.fake_lima import FakeLima from qiskit.providers.exceptions import QiskitBackendNotFoundError +try: + from qiskit.providers.fake_provider import Fake5QV1 +except ImportError: + from qiskit.providers.fake_provider import FakeLima as Fake5QV1 + class FakeApiBackend: """Fake backend.""" def __init__(self, config_update=None, status_update=None): - fake_backend = FakeLima() + fake_backend = Fake5QV1() self.properties = fake_backend.properties().to_dict() self.defaults = fake_backend.defaults().to_dict() @@ -60,7 +64,7 @@ def __init__( ] """ self._hgp = hgp - self._fake_backend = FakeLima() + self._fake_backend = Fake5QV1() self._backends = [] if not specs: specs = [{}] * num_backends diff --git a/test/unit/test_backend.py b/test/unit/test_backend.py index 557ef2d31..08551ad92 100644 --- a/test/unit/test_backend.py +++ b/test/unit/test_backend.py @@ -17,9 +17,13 @@ import warnings from qiskit import transpile, qasm3, QuantumCircuit -from qiskit.providers.fake_provider import FakeManila from qiskit.providers.models import BackendStatus, BackendProperties +try: + from qiskit.providers.fake_provider import Fake5QV1 +except ImportError: + from qiskit.providers.fake_provider import FakeManila as Fake5QV1 + from qiskit_ibm_provider.ibm_backend import IBMBackend from qiskit_ibm_provider.exceptions import IBMBackendValueError @@ -31,7 +35,7 @@ class TestBackend(IBMTestCase): def test_raise_faulty_qubits(self): """Test faulty qubits is raised.""" - fake_backend = FakeManila() + fake_backend = Fake5QV1() num_qubits = fake_backend.configuration().num_qubits circ = QuantumCircuit(num_qubits, num_qubits) for i in range(num_qubits): @@ -50,7 +54,7 @@ def test_raise_faulty_qubits(self): def test_raise_faulty_qubits_many(self): """Test faulty qubits is raised if one circuit uses it.""" - fake_backend = FakeManila() + fake_backend = Fake5QV1() num_qubits = fake_backend.configuration().num_qubits circ1 = QuantumCircuit(1, 1) @@ -72,7 +76,7 @@ def test_raise_faulty_qubits_many(self): def test_raise_faulty_edge(self): """Test faulty edge is raised.""" - fake_backend = FakeManila() + fake_backend = Fake5QV1() num_qubits = fake_backend.configuration().num_qubits circ = QuantumCircuit(num_qubits, num_qubits) for i in range(num_qubits - 2): @@ -92,7 +96,7 @@ def test_raise_faulty_edge(self): def test_faulty_qubit_not_used(self): """Test faulty qubit is not raise if not used.""" - fake_backend = FakeManila() + fake_backend = Fake5QV1() circ = QuantumCircuit(2, 2) for i in range(2): circ.x(i) @@ -111,7 +115,7 @@ def test_faulty_qubit_not_used(self): def test_faulty_edge_not_used(self): """Test faulty edge is not raised if not used.""" - fake_backend = FakeManila() + fake_backend = Fake5QV1() coupling_map = fake_backend.configuration().coupling_map circ = QuantumCircuit(2, 2) @@ -186,7 +190,7 @@ def test_dynamic_circuits_warning(self): # pylint: disable=not-context-manager # backend is not faulty because no faulty parameters given - backend = self._create_faulty_backend(model_backend=FakeManila()) + backend = self._create_faulty_backend(model_backend=Fake5QV1()) circuits = [] circ = QuantumCircuit(2, 2) @@ -228,7 +232,7 @@ def test_dynamic_circuits_warning(self): def _create_dc_test_backend(self): """Create a test backend with an IfElseOp enables.""" - model_backend = FakeManila() + model_backend = Fake5QV1() properties = model_backend.properties() out_backend = IBMBackend( @@ -344,7 +348,7 @@ def test_deepcopy(self): def test_too_many_circuits(self): """Test exception when number of circuits exceeds backend._max_circuits""" - model_backend = FakeManila() + model_backend = Fake5QV1() backend = IBMBackend( configuration=model_backend.configuration(), provider=mock.MagicMock(), diff --git a/test/unit/test_ibm_job_states.py b/test/unit/test_ibm_job_states.py index b0a4bcc94..52d4e9869 100644 --- a/test/unit/test_ibm_job_states.py +++ b/test/unit/test_ibm_job_states.py @@ -28,7 +28,11 @@ from qiskit import transpile from qiskit.providers import JobTimeoutError from qiskit.providers.jobstatus import JobStatus -from qiskit.providers.fake_provider.backends.bogota.fake_bogota import FakeBogota + +try: + from qiskit.providers.fake_provider import Fake5QV1 +except ImportError: + from qiskit.providers.fake_provider import FakeBogota as Fake5QV1 from qiskit.test.reference_circuits import ReferenceCircuits @@ -316,7 +320,7 @@ def test_transpiling_status(self): def run_with_api(self, api): """Creates a new ``IBMJob`` running with the provided API object.""" - backend = IBMBackend(FakeBogota().configuration(), MagicMock(), api_client=api) + backend = IBMBackend(Fake5QV1().configuration(), MagicMock(), api_client=api) backend._provider._runtime_client = api circuit = transpile(ReferenceCircuits.bell()) self._current_api = api diff --git a/test/unit/test_serialization.py b/test/unit/test_serialization.py index 77f6ce68c..3aa95920a 100644 --- a/test/unit/test_serialization.py +++ b/test/unit/test_serialization.py @@ -20,7 +20,12 @@ from qiskit import assemble, QuantumCircuit, QuantumRegister, ClassicalRegister from qiskit.circuit import Parameter -from qiskit.providers.fake_provider import FakeNairobi + +try: + from qiskit.providers.fake_provider import Fake7QPulseV1 +except ImportError: + from qiskit.providers.fake_provider import FakeNairobi as Fake7QPulseV1 + from qiskit_aer.noise import NoiseModel from qiskit_ibm_provider.utils.json_encoder import IBMJsonEncoder @@ -93,7 +98,7 @@ def test_circuit_metadata(self, metadata_test): def test_noise_model(self): """Test encoding and decoding a noise model.""" - noise_model = NoiseModel.from_backend(FakeNairobi()) + noise_model = NoiseModel.from_backend(Fake7QPulseV1()) self.assertIsInstance(noise_model, NoiseModel) encoded = json.dumps(noise_model, cls=RuntimeEncoder) self.assertIsInstance(encoded, str) diff --git a/test/unit/transpiler/passes/scheduling/test_scheduler.py b/test/unit/transpiler/passes/scheduling/test_scheduler.py index 4b50fda37..4068c6d1b 100644 --- a/test/unit/transpiler/passes/scheduling/test_scheduler.py +++ b/test/unit/transpiler/passes/scheduling/test_scheduler.py @@ -15,12 +15,16 @@ from unittest.mock import patch from qiskit import ClassicalRegister, QuantumCircuit, QuantumRegister, transpile -from qiskit.providers.fake_provider import FakeJakarta from qiskit.pulse import Schedule, Play, Constant, DriveChannel from qiskit.transpiler.passes import ConvertConditionsToIfOps from qiskit.transpiler.passmanager import PassManager from qiskit.transpiler.exceptions import TranspilerError +try: + from qiskit.providers.fake_provider import Fake7QPulseV1 +except ImportError: + from qiskit.providers.fake_provider import FakeJakarta as Fake7QPulseV1 + from qiskit_ibm_provider.transpiler.passes.scheduling.pad_delay import PadDelay from qiskit_ibm_provider.transpiler.passes.scheduling.scheduler import ( ALAPScheduleAnalysis, @@ -846,12 +850,12 @@ def test_c_if_plugin_conversion_with_transpile(self): after transpilation with the plugin.""" # Patch the test backend with the plugin with patch.object( - FakeJakarta, + Fake7QPulseV1, "get_translation_stage_plugin", return_value="ibm_dynamic_circuits", create=True, ): - backend = FakeJakarta() + backend = Fake7QPulseV1() # Temporary workaround for mock backends. For real backends this is not required. backend.configuration().basis_gates.append("if_else") @@ -1863,7 +1867,7 @@ def test_for_loop(self): def test_transpile_mock_backend(self): """Test scheduling works with transpilation.""" - backend = FakeJakarta() + backend = Fake7QPulseV1() # Temporary workaround for mock backends. For real backends this is not required. backend.configuration().basis_gates.append("if_else") backend.configuration().basis_gates.append("while_loop") @@ -1911,7 +1915,7 @@ def test_transpile_mock_backend(self): def test_transpile_both_paths(self): """Test scheduling works with both fast- and standard path after transpiling.""" - backend = FakeJakarta() + backend = Fake7QPulseV1() # Temporary workaround for mock backends. For real backends this is not required. backend.configuration().basis_gates.append("if_else") @@ -1960,12 +1964,12 @@ def test_c_if_plugin_conversion_with_transpile(self): transpilation with the plugin.""" # Patch the test backend with the plugin with patch.object( - FakeJakarta, + Fake7QPulseV1, "get_translation_stage_plugin", return_value="ibm_dynamic_circuits", create=True, ): - backend = FakeJakarta() + backend = Fake7QPulseV1() # Temporary workaround for mock backends. For real backends this is not required. backend.configuration().basis_gates.append("if_else")