diff --git a/qiskit/circuit/add_control.py b/qiskit/circuit/add_control.py index 2b374d54c455..98c9b4d4e452 100644 --- a/qiskit/circuit/add_control.py +++ b/qiskit/circuit/add_control.py @@ -73,7 +73,7 @@ def control( ) -> ControlledGate: """Return controlled version of gate using controlled rotations. This function first checks the name of the operation to see if it knows of a method from which - to generate a controlled version. Currently these are `x`, `rx`, `ry`, and `rz`. + to generate a controlled version. Currently, these are ``x``, ``rx``, ``ry``, and ``rz``. If a method is not directly known, it calls the unroller to convert to `u1`, `u3`, and `cx` gates. diff --git a/qiskit/compiler/transpiler.py b/qiskit/compiler/transpiler.py index adf60ca91e56..fd93fde5989f 100644 --- a/qiskit/compiler/transpiler.py +++ b/qiskit/compiler/transpiler.py @@ -315,10 +315,28 @@ def callback_func(**kwargs): optimization_level = config.get("transpile_optimization_level", 2) if backend is not None and getattr(backend, "version", 0) <= 1: - # This is a temporary conversion step to allow for a smoother transition - # to a fully target-based transpiler pipeline while maintaining the behavior - # of `transpile` with BackendV1 inputs. - backend = BackendV2Converter(backend) + warnings.warn( + "The `transpile` function will stop supporting inputs of " + f"type `BackendV1` ( {backend} ) in the `backend` parameter in a future " + "release no earlier than 2.0. `BackendV1` is deprecated and implementations " + "should move to `BackendV2`.", + category=DeprecationWarning, + stacklevel=2, + ) + with warnings.catch_warnings(): + # This is a temporary conversion step to allow for a smoother transition + # to a fully target-based transpiler pipeline while maintaining the behavior + # of `transpile` with BackendV1 inputs. + # TODO BackendV1 is deprecated and this path can be + # removed once it gets removed: + # https://github.com/Qiskit/qiskit/pull/12850 + warnings.filterwarnings( + "ignore", + category=DeprecationWarning, + message=r".+qiskit\.providers\.backend_compat\.BackendV2Converter.+", + module="qiskit", + ) + backend = BackendV2Converter(backend) if ( scheduling_method is not None diff --git a/qiskit/providers/backend.py b/qiskit/providers/backend.py index 931dbed479ec..6d9ed51043ec 100644 --- a/qiskit/providers/backend.py +++ b/qiskit/providers/backend.py @@ -23,6 +23,7 @@ from qiskit.providers.provider import Provider from qiskit.providers.models.backendstatus import BackendStatus from qiskit.circuit.gate import Instruction +from qiskit.utils import deprecate_func class Backend: @@ -43,7 +44,7 @@ class BackendV1(Backend, ABC): This abstract class is to be used for Backend objects. There are several classes of information contained in a Backend. The first are the attributes of the class itself. These should be used to - defined the immutable characteristics of the backend. The ``options`` + define the immutable characteristics of the backend. The ``options`` attribute of the backend is used to contain the dynamic user configurable options of the backend. It should be used more for runtime options that configure how the backend is used. For example, something like a @@ -71,6 +72,14 @@ class BackendV1(Backend, ABC): version = 1 + @deprecate_func( + since="1.2", + removal_timeline="in the 2.0 release", + additional_msg="If the backend only encapsulates a hardware description, " + "consider constructing a Target directly. If it is part of a provider " + "that gives access to execution, consider using Primitives instead. " + "Alternatively, consider moving to BackendV2 (see https://qisk.it/backendV1-to-V2).", + ) def __init__(self, configuration, provider=None, **fields): """Initialize a backend class diff --git a/qiskit/providers/backend_compat.py b/qiskit/providers/backend_compat.py index e567c330a958..f554897d34c4 100644 --- a/qiskit/providers/backend_compat.py +++ b/qiskit/providers/backend_compat.py @@ -390,10 +390,13 @@ def __init__( self._properties = None self._defaults = None - if hasattr(self._backend, "properties"): - self._properties = self._backend.properties() - if hasattr(self._backend, "defaults"): - self._defaults = self._backend.defaults() + with warnings.catch_warnings(): + # The class QobjExperimentHeader is deprecated + warnings.filterwarnings("ignore", category=DeprecationWarning, module="qiskit") + if hasattr(self._backend, "properties"): + self._properties = self._backend.properties() + if hasattr(self._backend, "defaults"): + self._defaults = self._backend.defaults() self._target = None self._name_mapping = name_mapping diff --git a/qiskit/providers/basic_provider/basic_simulator.py b/qiskit/providers/basic_provider/basic_simulator.py index 1d1205294677..32666c57f184 100644 --- a/qiskit/providers/basic_provider/basic_simulator.py +++ b/qiskit/providers/basic_provider/basic_simulator.py @@ -236,24 +236,32 @@ def configuration(self) -> BackendConfiguration: for name in self.target.operation_names ] - self._configuration = BackendConfiguration( - backend_name=self.name, - backend_version=self.backend_version, - n_qubits=self.num_qubits, - basis_gates=self.target.operation_names, - gates=gates, - local=True, - simulator=True, - conditional=True, - open_pulse=False, - memory=True, - # This max_shots is used by the assembler, setting it to 0 - # to maintain the behavior from the previous implementation. - # Not related to the actual shots set in the backend options - max_shots=0, - coupling_map=None, - description="A python simulator for quantum experiments", - ) + with warnings.catch_warnings(): + # TODO Provider models are deprecated + # https://github.com/Qiskit/qiskit/issues/12843 + warnings.filterwarnings( + "ignore", + category=DeprecationWarning, + message=r".+qiskit\.providers\.models\.backendconfiguration\..+", + ) + self._configuration = BackendConfiguration( + backend_name=self.name, + backend_version=self.backend_version, + n_qubits=self.num_qubits, + basis_gates=self.target.operation_names, + gates=gates, + local=True, + simulator=True, + conditional=True, + open_pulse=False, + memory=True, + # This max_shots is used by the assembler, setting it to 0 + # to maintain the behavior from the previous implementation. + # Not related to the actual shots set in the backend options + max_shots=0, + coupling_map=None, + description="A python simulator for quantum experiments", + ) return self._configuration @classmethod diff --git a/qiskit/providers/fake_provider/fake_qasm_backend.py b/qiskit/providers/fake_provider/fake_qasm_backend.py index 55dad4aff601..7ad7222f7907 100644 --- a/qiskit/providers/fake_provider/fake_qasm_backend.py +++ b/qiskit/providers/fake_provider/fake_qasm_backend.py @@ -16,6 +16,7 @@ import json import os +import warnings from qiskit.exceptions import QiskitError from qiskit.providers.models import BackendProperties, QasmBackendConfiguration @@ -61,7 +62,10 @@ def _set_props_from_json(self): raise QiskitError("No properties file has been defined") props = self._load_json(self.props_filename) decode_backend_properties(props) - self._properties = BackendProperties.from_dict(props) + with warnings.catch_warnings(): + # This raises the BackendProperties deprecation warning internally + warnings.filterwarnings("ignore", category=DeprecationWarning, module="qiskit") + self._properties = BackendProperties.from_dict(props) def _load_json(self, filename): with open(os.path.join(self.dirname, filename)) as f_json: diff --git a/qiskit/providers/models/__init__.py b/qiskit/providers/models/__init__.py index bf90a9d16c0e..58fafed92986 100644 --- a/qiskit/providers/models/__init__.py +++ b/qiskit/providers/models/__init__.py @@ -38,6 +38,7 @@ GateProperties Nduv """ +import warnings from .backendconfiguration import ( BackendConfiguration, @@ -50,3 +51,13 @@ from .backendstatus import BackendStatus from .jobstatus import JobStatus from .pulsedefaults import PulseDefaults, Command + + +warnings.warn( + "qiskit.providers.models is deprecated since Qiskit 1.2 and will be removed in Qiskit 2.0." + "With the removal of Qobj, there is no need for these schema-conformant objects. If you still need" + "to use them, it could be because you are using a BackendV1, which is also deprecated in favor" + "of BackendV2", + DeprecationWarning, + 2, +) diff --git a/qiskit/providers/models/backendconfiguration.py b/qiskit/providers/models/backendconfiguration.py index ebd0a6d9bbb6..a50745c9572c 100644 --- a/qiskit/providers/models/backendconfiguration.py +++ b/qiskit/providers/models/backendconfiguration.py @@ -26,6 +26,7 @@ DriveChannel, MeasureChannel, ) +from qiskit.utils import deprecate_func class GateConfig: @@ -38,6 +39,15 @@ class GateConfig: and CX. """ + @deprecate_func( + since="1.2", + removal_timeline="in the 2.0 release", + additional_msg="The models in ``qiskit.providers.models`` are part " + "of the deprecated `BackendV1` workflow and no longer necessary for `BackendV2`. If a user " + "workflow requires these representations it likely relies on deprecated functionality and " + "should be updated to use `BackendV2`.", + stacklevel=3, + ) def __init__( self, name, @@ -141,6 +151,14 @@ class UchannelLO: scale: Scale factor for qubit frequency. """ + @deprecate_func( + since="1.2", + removal_timeline="in the 2.0 release", + additional_msg="The models in ``qiskit.providers.models`` are part " + "of the deprecated `BackendV1` workflow and no longer necessary for `BackendV2`. If a user " + "workflow requires these representations it likely relies on deprecated functionality and " + "should be updated to use `BackendV2`.", + ) def __init__(self, q, scale): """Initialize a UchannelLOSchema object @@ -211,6 +229,15 @@ class QasmBackendConfiguration: _data = {} + @deprecate_func( + since="1.2", + removal_timeline="in the 2.0 release", + additional_msg="The models in ``qiskit.providers.models`` are part " + "of the deprecated `BackendV1` workflow and no longer necessary for `BackendV2`. If a user " + "workflow requires these representations it likely relies on deprecated functionality and " + "should be updated to use `BackendV2`.", + stacklevel=3, + ) def __init__( self, backend_name, @@ -491,9 +518,19 @@ def __contains__(self, item): class BackendConfiguration(QasmBackendConfiguration): - """Backwards compat shim representing an abstract backend configuration.""" + """Backwards compatibility shim representing an abstract backend configuration.""" - pass + @deprecate_func( + since="1.2", + removal_timeline="in the 2.0 release", + additional_msg="The models in ``qiskit.providers.models`` are part " + "of the deprecated `BackendV1` workflow and no longer necessary for `BackendV2`. If a user " + "workflow requires these representations it likely relies on deprecated functionality and " + "should be updated to use `BackendV2`.", + stacklevel=3, + ) + def __init__(self, *args, **kwargs): + super().__init__(*args, **kwargs) class PulseBackendConfiguration(QasmBackendConfiguration): @@ -501,6 +538,15 @@ class PulseBackendConfiguration(QasmBackendConfiguration): about the set up of the device which can be useful for building Pulse programs. """ + @deprecate_func( + since="1.2", + removal_timeline="in the 2.0 release", + additional_msg="The models in ``qiskit.providers.models`` are part " + "of the deprecated `BackendV1` workflow and no longer necessary for `BackendV2`. If a user " + "workflow requires these representations it likely relies on deprecated functionality and " + "should be updated to use `BackendV2`.", + stacklevel=3, + ) def __init__( self, backend_name: str, diff --git a/qiskit/providers/models/backendproperties.py b/qiskit/providers/models/backendproperties.py index 332aac7c5edd..75e7cd18d03a 100644 --- a/qiskit/providers/models/backendproperties.py +++ b/qiskit/providers/models/backendproperties.py @@ -18,6 +18,7 @@ import dateutil.parser from qiskit.providers.exceptions import BackendPropertyError +from qiskit.utils import deprecate_func from qiskit.utils.units import apply_prefix PropertyT = Tuple[Any, datetime.datetime] @@ -172,6 +173,15 @@ class BackendProperties: _data = {} + @deprecate_func( + since="1.2", + removal_timeline="in the 2.0 release", + additional_msg="The models in ``qiskit.providers.models`` and related objects are part " + "of the deprecated `BackendV1` workflow, and no longer necessary for `BackendV2`. If a user " + "workflow requires these representations it likely relies on deprecated functionality and " + "should be updated to use `BackendV2`.", + stacklevel=3, + ) def __init__( self, backend_name, backend_version, last_update_date, qubits, gates, general, **kwargs ): @@ -248,6 +258,7 @@ def from_dict(cls, data): qubits.append(nduvs) gates = [GateProperties.from_dict(x) for x in in_data.pop("gates")] general = [Nduv.from_dict(x) for x in in_data.pop("general")] + return cls( backend_name, backend_version, last_update_date, qubits, gates, general, **in_data ) diff --git a/qiskit/transpiler/preset_passmanagers/__init__.py b/qiskit/transpiler/preset_passmanagers/__init__.py index 6092573876f1..cad512c07a52 100644 --- a/qiskit/transpiler/preset_passmanagers/__init__.py +++ b/qiskit/transpiler/preset_passmanagers/__init__.py @@ -57,12 +57,12 @@ .. autofunction:: generate_scheduling .. currentmodule:: qiskit.transpiler.preset_passmanagers """ - +from .generate_preset_pass_manager import generate_preset_pass_manager from .level0 import level_0_pass_manager from .level1 import level_1_pass_manager from .level2 import level_2_pass_manager from .level3 import level_3_pass_manager -from .generate_preset_pass_manager import generate_preset_pass_manager + __all__ = [ "level_0_pass_manager", diff --git a/qiskit/transpiler/preset_passmanagers/generate_preset_pass_manager.py b/qiskit/transpiler/preset_passmanagers/generate_preset_pass_manager.py index bdbac42c8055..a9a9a5e2f029 100644 --- a/qiskit/transpiler/preset_passmanagers/generate_preset_pass_manager.py +++ b/qiskit/transpiler/preset_passmanagers/generate_preset_pass_manager.py @@ -15,6 +15,7 @@ """ import copy +import warnings from qiskit.circuit.controlflow import CONTROL_FLOW_OP_NAMES from qiskit.circuit.library.standard_gates import get_standard_gate_name_mapping @@ -254,6 +255,14 @@ def generate_preset_pass_manager( # This is a temporary conversion step to allow for a smoother transition # to a fully target-based transpiler pipeline while maintaining the behavior # of `transpile` with BackendV1 inputs. + warnings.warn( + "The `generate_preset_pass_manager` function will stop supporting inputs of " + f"type `BackendV1` ( {backend} ) in the `backend` parameter in a future " + "release no earlier than 2.0. `BackendV1` is deprecated and implementations " + "should move to `BackendV2`.", + category=DeprecationWarning, + stacklevel=2, + ) backend = BackendV2Converter(backend) # Check if a custom inst_map was specified before overwriting inst_map @@ -331,7 +340,17 @@ def generate_preset_pass_manager( if timing_constraints is None: timing_constraints = target.timing_constraints() if backend_properties is None: - backend_properties = target_to_backend_properties(target) + with warnings.catch_warnings(): + # TODO this approach (target-to-properties) is going to be removed soon (1.3) in favor + # of backend-to-target approach + # https://github.com/Qiskit/qiskit/pull/12850 + warnings.filterwarnings( + "ignore", + category=DeprecationWarning, + message=r".+qiskit\.transpiler\.target\.target_to_backend_properties.+", + module="qiskit", + ) + backend_properties = target_to_backend_properties(target) # Parse non-target dependent pm options initial_layout = _parse_initial_layout(initial_layout) diff --git a/qiskit/transpiler/target.py b/qiskit/transpiler/target.py index 001e8020962b..da4a44a8ee02 100644 --- a/qiskit/transpiler/target.py +++ b/qiskit/transpiler/target.py @@ -20,6 +20,7 @@ from __future__ import annotations import itertools +import warnings from typing import Optional, List, Any from collections.abc import Mapping @@ -55,6 +56,7 @@ # full target from qiskit.providers.backend import QubitProperties # pylint: disable=unused-import from qiskit.providers.models.backendproperties import BackendProperties +from qiskit.utils import deprecate_func logger = logging.getLogger(__name__) @@ -1164,6 +1166,15 @@ def from_configuration( Mapping.register(Target) +@deprecate_func( + since="1.2", + removal_timeline="in the 2.0 release", + additional_msg="This method is used to build an element from the deprecated " + "``qiskit.providers.models`` module. These models are part of the deprecated `BackendV1` " + "workflow and no longer necessary for `BackendV2`. If a user workflow requires these " + "representations it likely relies on deprecated functionality and " + "should be updated to use `BackendV2`.", +) def target_to_backend_properties(target: Target): """Convert a :class:`~.Target` object into a legacy :class:`~.BackendProperties`""" @@ -1242,6 +1253,9 @@ def target_to_backend_properties(target: Target): if gates or qubits: properties_dict["gates"] = gates properties_dict["qubits"] = qubits - return BackendProperties.from_dict(properties_dict) + with warnings.catch_warnings(): + # This raises BackendProperties internally + warnings.filterwarnings("ignore", category=DeprecationWarning) + return BackendProperties.from_dict(properties_dict) else: return None diff --git a/qiskit/utils/deprecation.py b/qiskit/utils/deprecation.py index 294ea9414924..aebea233282e 100644 --- a/qiskit/utils/deprecation.py +++ b/qiskit/utils/deprecation.py @@ -29,6 +29,7 @@ def deprecate_func( package_name: str = "qiskit", removal_timeline: str = "no earlier than 3 months after the release date", is_property: bool = False, + stacklevel: int = 2, ): """Decorator to indicate a function has been deprecated. @@ -50,7 +51,7 @@ def deprecate_func( is_property: If the deprecated function is a `@property`, set this to True so that the generated message correctly describes it as such. (This isn't necessary for property setters, as their docstring is ignored by Python.) - + stacklevel: Stack level passed to :func:`warnings.warn`. Returns: Callable: The decorated callable. """ @@ -92,7 +93,7 @@ def decorator(func): @functools.wraps(func) def wrapper(*args, **kwargs): - warnings.warn(msg, category=category, stacklevel=2) + warnings.warn(msg, category=category, stacklevel=stacklevel) return func(*args, **kwargs) add_deprecation_to_docstring(wrapper, msg, since=since, pending=pending) diff --git a/releasenotes/notes/backendv1-d0d0642ed38fed3c.yaml b/releasenotes/notes/backendv1-d0d0642ed38fed3c.yaml new file mode 100644 index 000000000000..3b19a7ab9a2c --- /dev/null +++ b/releasenotes/notes/backendv1-d0d0642ed38fed3c.yaml @@ -0,0 +1,14 @@ +--- +deprecations_providers: + - | + The :class:`.BackendV1` class is deprecated and it will be removed not earlier than the next major release. + There are several migration paths available depending on the main purpose of the backend object:: + + - To expose backend information with no access to execution (just a hardware description), consider constructing a :class:`.Target` directly. + - To provides access to execution capabilities, consider relying on the primitives interfaces instead. + - Alternatively, to continue providing simultaneous :class:`.Target` (hardware information) and ``run`` (execution) capabilities, consider moving to :class:`.BackendV2` (see ). + + - | + The models in :mod:`qiskit.providers.models` are part of the deprecated :class:`.BackendV1` workflow + and no longer necessary for :class:`.BackendV2`. If a user workflow requires these representations it + likely relies on deprecated functionality and should be updated to use :class:`.BackendV2`. diff --git a/test/python/circuit/test_parameters.py b/test/python/circuit/test_parameters.py index c2df1a423ec4..ad336a0ad6bb 100644 --- a/test/python/circuit/test_parameters.py +++ b/test/python/circuit/test_parameters.py @@ -1093,7 +1093,12 @@ def test_transpile_across_optimization_levelsV1(self, opt_level): qc.measure(range(5 - 1), range(5 - 1)) with self.assertWarns(DeprecationWarning): backend = Fake5QV1() - transpile(qc, backend, optimization_level=opt_level) + with self.assertWarnsRegex( + DeprecationWarning, + expected_regex="The `transpile` function will " + "stop supporting inputs of type `BackendV1`", + ): + transpile(qc, backend, optimization_level=opt_level) @data(0, 1, 2, 3) def test_transpile_across_optimization_levels(self, opt_level): diff --git a/test/python/circuit/test_scheduled_circuit.py b/test/python/circuit/test_scheduled_circuit.py index c934b5b5e04c..ce5cd8213105 100644 --- a/test/python/circuit/test_scheduled_circuit.py +++ b/test/python/circuit/test_scheduled_circuit.py @@ -78,13 +78,18 @@ def test_schedule_circuit_when_transpile_option_tells_dt(self): qc.delay(100, 0, unit="ns") # 450[dt] qc.h(0) qc.h(1) - sc = transpile( - qc, - self.backend_without_dt, - scheduling_method="alap", - dt=self.dt, - layout_method="trivial", - ) + with self.assertWarnsRegex( + DeprecationWarning, + expected_regex="The `transpile` function will " + "stop supporting inputs of type `BackendV1`", + ): + sc = transpile( + qc, + self.backend_without_dt, + scheduling_method="alap", + dt=self.dt, + layout_method="trivial", + ) self.assertEqual(sc.duration, 450546) self.assertEqual(sc.unit, "dt") self.assertEqual(sc.data[0].operation.name, "delay") @@ -104,9 +109,14 @@ def test_schedule_circuit_in_sec_when_no_one_tells_dt(self): qc.delay(100, 0, unit="ns") qc.h(0) qc.h(1) - sc = transpile( - qc, self.backend_without_dt, scheduling_method="alap", layout_method="trivial" - ) + with self.assertWarnsRegex( + DeprecationWarning, + expected_regex="The `transpile` function will " + "stop supporting inputs of type `BackendV1`", + ): + sc = transpile( + qc, self.backend_without_dt, scheduling_method="alap", layout_method="trivial" + ) self.assertAlmostEqual(sc.duration, 450610 * self.dt) self.assertEqual(sc.unit, "s") self.assertEqual(sc.data[0].operation.name, "delay") @@ -128,13 +138,23 @@ def test_cannot_schedule_circuit_with_mixed_SI_and_dt_when_no_one_tells_dt(self) qc.delay(30, 0, unit="dt") qc.h(0) qc.h(1) - with self.assertRaises(QiskitError): - transpile(qc, self.backend_without_dt, scheduling_method="alap") + with self.assertWarnsRegex( + DeprecationWarning, + expected_regex="The `transpile` function will " + "stop supporting inputs of type `BackendV1`", + ): + with self.assertRaises(QiskitError): + transpile(qc, self.backend_without_dt, scheduling_method="alap") def test_transpile_single_delay_circuit(self): qc = QuantumCircuit(1) qc.delay(1234, 0) - sc = transpile(qc, backend=self.backend_with_dt, scheduling_method="alap") + with self.assertWarnsRegex( + DeprecationWarning, + expected_regex="The `transpile` function will " + "stop supporting inputs of type `BackendV1`", + ): + sc = transpile(qc, backend=self.backend_with_dt, scheduling_method="alap") self.assertEqual(sc.duration, 1234) self.assertEqual(sc.data[0].operation.name, "delay") self.assertEqual(sc.data[0].operation.duration, 1234) @@ -145,7 +165,12 @@ def test_transpile_t1_circuit(self): qc.x(0) # 320 [dt] qc.delay(1000, 0, unit="ns") # 4500 [dt] qc.measure_all() - scheduled = transpile(qc, backend=self.backend_with_dt, scheduling_method="alap") + with self.assertWarnsRegex( + DeprecationWarning, + expected_regex="The `transpile` function will " + "stop supporting inputs of type `BackendV1`", + ): + scheduled = transpile(qc, backend=self.backend_with_dt, scheduling_method="alap") self.assertEqual(scheduled.duration, 8004) def test_transpile_delay_circuit_with_backend(self): @@ -153,9 +178,14 @@ def test_transpile_delay_circuit_with_backend(self): qc.h(0) qc.delay(100, 1, unit="ns") # 450 [dt] qc.cx(0, 1) # 1760 [dt] - scheduled = transpile( - qc, backend=self.backend_with_dt, scheduling_method="alap", layout_method="trivial" - ) + with self.assertWarnsRegex( + DeprecationWarning, + expected_regex="The `transpile` function will " + "stop supporting inputs of type `BackendV1`", + ): + scheduled = transpile( + qc, backend=self.backend_with_dt, scheduling_method="alap", layout_method="trivial" + ) self.assertEqual(scheduled.duration, 1826) def test_transpile_delay_circuit_without_backend(self): @@ -187,7 +217,12 @@ def test_transpile_circuit_with_custom_instruction(self): def test_transpile_delay_circuit_with_dt_but_without_scheduling_method(self): qc = QuantumCircuit(1) qc.delay(100, 0, unit="ns") - transpiled = transpile(qc, backend=self.backend_with_dt) + with self.assertWarnsRegex( + DeprecationWarning, + expected_regex="The `transpile` function will " + "stop supporting inputs of type `BackendV1`", + ): + transpiled = transpile(qc, backend=self.backend_with_dt) self.assertEqual(transpiled.duration, None) # not scheduled self.assertEqual(transpiled.data[0].operation.duration, 450) # unit is converted ns -> dt @@ -212,7 +247,12 @@ def test_invalidate_schedule_circuit_if_new_instruction_is_appended(self): qc.h(0) qc.delay(500 * self.dt, 1, "s") qc.cx(0, 1) - scheduled = transpile(qc, backend=self.backend_with_dt, scheduling_method="alap") + with self.assertWarnsRegex( + DeprecationWarning, + expected_regex="The `transpile` function will " + "stop supporting inputs of type `BackendV1`", + ): + scheduled = transpile(qc, backend=self.backend_with_dt, scheduling_method="alap") # append a gate to a scheduled circuit scheduled.h(0) self.assertEqual(scheduled.duration, None) @@ -245,21 +285,31 @@ def test_unit_seconds_when_using_backend_durations(self): qc.delay(500 * self.dt, 1, "s") qc.cx(0, 1) # usual case - scheduled = transpile( - qc, backend=self.backend_with_dt, scheduling_method="alap", layout_method="trivial" - ) + with self.assertWarnsRegex( + DeprecationWarning, + expected_regex="The `transpile` function will " + "stop supporting inputs of type `BackendV1`", + ): + scheduled = transpile( + qc, backend=self.backend_with_dt, scheduling_method="alap", layout_method="trivial" + ) self.assertEqual(scheduled.duration, 1876) # update durations durations = InstructionDurations.from_backend(self.backend_with_dt) durations.update([("cx", [0, 1], 1000 * self.dt, "s")]) - scheduled = transpile( - qc, - backend=self.backend_with_dt, - scheduling_method="alap", - instruction_durations=durations, - layout_method="trivial", - ) + with self.assertWarnsRegex( + DeprecationWarning, + expected_regex="The `transpile` function will " + "stop supporting inputs of type `BackendV1`", + ): + scheduled = transpile( + qc, + backend=self.backend_with_dt, + scheduling_method="alap", + instruction_durations=durations, + layout_method="trivial", + ) self.assertEqual(scheduled.duration, 1500) def test_per_qubit_durations(self): @@ -348,13 +398,23 @@ def test_change_dt_in_transpile(self): qc.x(0) qc.measure(0, 0) # default case - scheduled = transpile(qc, backend=self.backend_with_dt, scheduling_method="asap") + with self.assertWarnsRegex( + DeprecationWarning, + expected_regex="The `transpile` function will " + "stop supporting inputs of type `BackendV1`", + ): + scheduled = transpile(qc, backend=self.backend_with_dt, scheduling_method="asap") org_duration = scheduled.duration # halve dt in sec = double duration in dt - scheduled = transpile( - qc, backend=self.backend_with_dt, scheduling_method="asap", dt=self.dt / 2 - ) + with self.assertWarnsRegex( + DeprecationWarning, + expected_regex="The `transpile` function will " + "stop supporting inputs of type `BackendV1`", + ): + scheduled = transpile( + qc, backend=self.backend_with_dt, scheduling_method="asap", dt=self.dt / 2 + ) self.assertEqual(scheduled.duration, org_duration * 2) @data("asap", "alap") @@ -366,7 +426,12 @@ def test_duration_on_same_instruction_instance(self, scheduling_method): qc = QuantumCircuit(3) qc.cz(0, 1) qc.cz(1, 2) - sc = transpile(qc, backend=self.backend_with_dt, scheduling_method=scheduling_method) + with self.assertWarnsRegex( + DeprecationWarning, + expected_regex="The `transpile` function will " + "stop supporting inputs of type `BackendV1`", + ): + sc = transpile(qc, backend=self.backend_with_dt, scheduling_method=scheduling_method) cxs = [inst.operation for inst in sc.data if inst.operation.name == "cx"] self.assertNotEqual(cxs[0].duration, cxs[1].duration) @@ -404,7 +469,12 @@ def test_can_transpile_circuits_after_assigning_parameters(self): qc.delay(idle_dur, 0, "us") qc.measure(0, 0) qc = qc.assign_parameters({idle_dur: 0.1}) - circ = transpile(qc, self.backend_with_dt) + with self.assertWarnsRegex( + DeprecationWarning, + expected_regex="The `transpile` function will " + "stop supporting inputs of type `BackendV1`", + ): + circ = transpile(qc, self.backend_with_dt) self.assertEqual(circ.duration, None) # not scheduled self.assertEqual(circ.data[1].operation.duration, 450) # converted in dt @@ -414,7 +484,12 @@ def test_can_transpile_and_assemble_circuits_with_assigning_parameters_inbetween qc.x(0) qc.delay(idle_dur, 0, "us") qc.measure(0, 0) - circ = transpile(qc, self.backend_with_dt) + with self.assertWarnsRegex( + DeprecationWarning, + expected_regex="The `transpile` function will " + "stop supporting inputs of type `BackendV1`", + ): + circ = transpile(qc, self.backend_with_dt) circ = circ.assign_parameters({idle_dur: 0.1}) with self.assertWarns(DeprecationWarning): qobj = assemble(circ, self.backend_with_dt) @@ -428,7 +503,12 @@ def test_can_transpile_circuits_with_unbounded_parameters(self): qc.delay(idle_dur, 0, "us") qc.measure(0, 0) # not assign parameter - circ = transpile(qc, self.backend_with_dt) + with self.assertWarnsRegex( + DeprecationWarning, + expected_regex="The `transpile` function will " + "stop supporting inputs of type `BackendV1`", + ): + circ = transpile(qc, self.backend_with_dt) self.assertEqual(circ.duration, None) # not scheduled self.assertEqual(circ.data[1].operation.unit, "dt") # converted in dt self.assertEqual( @@ -441,7 +521,12 @@ def test_fail_to_assemble_circuits_with_unbounded_parameters(self): qc.x(0) qc.delay(idle_dur, 0, "us") qc.measure(0, 0) - qc = transpile(qc, self.backend_with_dt) + with self.assertWarnsRegex( + DeprecationWarning, + expected_regex="The `transpile` function will " + "stop supporting inputs of type `BackendV1`", + ): + qc = transpile(qc, self.backend_with_dt) with self.assertRaises(DeprecationWarning): assemble(qc, self.backend_with_dt) @@ -453,7 +538,12 @@ def test_can_schedule_circuits_with_bounded_parameters(self, scheduling_method): qc.delay(idle_dur, 0, "us") qc.measure(0, 0) qc = qc.assign_parameters({idle_dur: 0.1}) - circ = transpile(qc, self.backend_with_dt, scheduling_method=scheduling_method) + with self.assertWarnsRegex( + DeprecationWarning, + expected_regex="The `transpile` function will " + "stop supporting inputs of type `BackendV1`", + ): + circ = transpile(qc, self.backend_with_dt, scheduling_method=scheduling_method) self.assertIsNotNone(circ.duration) # scheduled @data("asap", "alap") @@ -463,6 +553,12 @@ def test_fail_to_schedule_circuits_with_unbounded_parameters(self, scheduling_me qc.x(0) qc.delay(idle_dur, 0, "us") qc.measure(0, 0) - # not assign parameter - with self.assertRaises(TranspilerError): - transpile(qc, self.backend_with_dt, scheduling_method=scheduling_method) + + with self.assertWarnsRegex( + DeprecationWarning, + expected_regex="The `transpile` function will " + "stop supporting inputs of type `BackendV1`", + ): + # unassigned parameter + with self.assertRaises(TranspilerError): + transpile(qc, self.backend_with_dt, scheduling_method=scheduling_method) diff --git a/test/python/compiler/test_sequencer.py b/test/python/compiler/test_sequencer.py index e32d6370367b..ae75348a5cdf 100644 --- a/test/python/compiler/test_sequencer.py +++ b/test/python/compiler/test_sequencer.py @@ -41,9 +41,19 @@ def test_transpile_and_sequence_agree_with_schedule(self): qc.h(0) qc.cx(0, 1) qc.measure_all() - sc = transpile(qc, self.backend, scheduling_method="alap") + with self.assertWarnsRegex( + DeprecationWarning, + expected_regex="The `transpile` function will " + "stop supporting inputs of type `BackendV1`", + ): + sc = transpile(qc, self.backend, scheduling_method="alap") actual = sequence(sc, self.backend) - expected = schedule(transpile(qc, self.backend), self.backend) + with self.assertWarnsRegex( + DeprecationWarning, + expected_regex="The `transpile` function will " + "stop supporting inputs of type `BackendV1`", + ): + expected = schedule(transpile(qc, self.backend), self.backend) self.assertEqual(actual, pad(expected)) def test_transpile_and_sequence_agree_with_schedule_for_circuit_with_delay(self): @@ -52,9 +62,19 @@ def test_transpile_and_sequence_agree_with_schedule_for_circuit_with_delay(self) qc.delay(500, 0, unit="ns") qc.h(0) qc.measure(0, 0) - sc = transpile(qc, self.backend, scheduling_method="alap") + with self.assertWarnsRegex( + DeprecationWarning, + expected_regex="The `transpile` function will " + "stop supporting inputs of type `BackendV1`", + ): + sc = transpile(qc, self.backend, scheduling_method="alap") actual = sequence(sc, self.backend) - expected = schedule(transpile(qc, self.backend), self.backend) + with self.assertWarnsRegex( + DeprecationWarning, + expected_regex="The `transpile` function will " + "stop supporting inputs of type `BackendV1`", + ): + expected = schedule(transpile(qc, self.backend), self.backend) self.assertEqual( actual.exclude(instruction_types=[pulse.Delay]), expected.exclude(instruction_types=[pulse.Delay]), @@ -65,7 +85,17 @@ def test_transpile_and_sequence_agree_with_schedule_for_circuits_without_measure qc = QuantumCircuit(2, name="bell_without_measurement") qc.h(0) qc.cx(0, 1) - sc = transpile(qc, self.backend, scheduling_method="alap") + with self.assertWarnsRegex( + DeprecationWarning, + expected_regex="The `transpile` function will " + "stop supporting inputs of type `BackendV1`", + ): + sc = transpile(qc, self.backend, scheduling_method="alap") actual = sequence(sc, self.backend) - expected = schedule(transpile(qc, self.backend), self.backend) + with self.assertWarnsRegex( + DeprecationWarning, + expected_regex="The `transpile` function will " + "stop supporting inputs of type `BackendV1`", + ): + expected = schedule(transpile(qc, self.backend), self.backend) self.assertEqual(actual, pad(expected)) diff --git a/test/python/compiler/test_transpiler.py b/test/python/compiler/test_transpiler.py index 46acff9d40d6..90dda73c0739 100644 --- a/test/python/compiler/test_transpiler.py +++ b/test/python/compiler/test_transpiler.py @@ -1305,7 +1305,7 @@ def test_transpiled_basis_gates_calibrations(self): circ.add_calibration("h", [0], q0_x180) transpiled_circuit = transpile( - circ, backend=GenericBackendV2(num_qubits=4), seed_transpiler=42 + circ, backend=GenericBackendV2(num_qubits=4, seed=42), seed_transpiler=42 ) self.assertEqual(transpiled_circuit.calibrations, circ.calibrations) @@ -1325,7 +1325,7 @@ def test_transpile_calibrated_custom_gate_on_diff_qubit(self): with self.assertRaises(QiskitError): transpile( circ, - backend=GenericBackendV2(num_qubits=4), + backend=GenericBackendV2(num_qubits=4, seed=42), layout_method="trivial", seed_transpiler=42, optimization_level=1, @@ -1368,7 +1368,7 @@ def test_transpile_subset_of_calibrated_gates(self): transpiled_circ = transpile( circ, - backend=GenericBackendV2(num_qubits=4), + backend=GenericBackendV2(num_qubits=4, seed=42), layout_method="trivial", seed_transpiler=42, ) @@ -1390,7 +1390,7 @@ def q0_rxt(tau): transpiled_circ = transpile( circ, - backend=GenericBackendV2(num_qubits=4), + backend=GenericBackendV2(num_qubits=4, seed=42), layout_method="trivial", seed_transpiler=42, ) @@ -1554,11 +1554,12 @@ def test_scheduling_timing_constraints(self): [0, 0], ) with self.assertRaisesRegex(TranspilerError, error_msgs[duration]): - _ = transpile( - qc, - backend=backend, - timing_constraints=timing_constraints, - ) + with self.assertWarns(DeprecationWarning): + _ = transpile( + qc, + backend=backend, + timing_constraints=timing_constraints, + ) def test_scheduling_instruction_constraints(self): """Test that scheduling-related loose transpile constraints @@ -1566,7 +1567,7 @@ def test_scheduling_instruction_constraints(self): with self.assertWarns(DeprecationWarning): backend_v1 = Fake27QPulseV1() - backend_v2 = BackendV2Converter(backend_v1) + backend_v2 = BackendV2Converter(backend_v1) qc = QuantumCircuit(2) qc.h(0) qc.delay(500, 1, "dt") @@ -1575,16 +1576,27 @@ def test_scheduling_instruction_constraints(self): durations = InstructionDurations.from_backend(backend_v1) durations.update([("cx", [0, 1], 1000, "dt")]) - for backend in [backend_v1, backend_v2]: - with self.subTest(backend=backend): - scheduled = transpile( - qc, - backend=backend, - scheduling_method="alap", - instruction_durations=durations, - layout_method="trivial", - ) - self.assertEqual(scheduled.duration, 1500) + with self.assertWarnsRegex( + DeprecationWarning, + expected_regex="The `transpile` function will stop supporting inputs of type `BackendV1` ", + ): + scheduled = transpile( + qc, + backend=backend_v1, + scheduling_method="alap", + instruction_durations=durations, + layout_method="trivial", + ) + self.assertEqual(scheduled.duration, 1500) + + scheduled = transpile( + qc, + backend=backend_v2, + scheduling_method="alap", + instruction_durations=durations, + layout_method="trivial", + ) + self.assertEqual(scheduled.duration, 1500) def test_scheduling_dt_constraints(self): """Test that scheduling-related loose transpile constraints @@ -1592,20 +1604,26 @@ def test_scheduling_dt_constraints(self): with self.assertWarns(DeprecationWarning): backend_v1 = Fake27QPulseV1() - backend_v2 = BackendV2Converter(backend_v1) + backend_v2 = BackendV2Converter(backend_v1) qc = QuantumCircuit(1, 1) qc.x(0) qc.measure(0, 0) original_dt = 2.2222222222222221e-10 original_duration = 3504 - for backend in [backend_v1, backend_v2]: - with self.subTest(backend=backend): - # halve dt in sec = double duration in dt - scheduled = transpile( - qc, backend=backend, scheduling_method="asap", dt=original_dt / 2 - ) - self.assertEqual(scheduled.duration, original_duration * 2) + with self.assertWarnsRegex( + DeprecationWarning, + expected_regex="The `transpile` function will stop supporting inputs of type `BackendV1` ", + ): + # halve dt in sec = double duration in dt + scheduled = transpile( + qc, backend=backend_v1, scheduling_method="asap", dt=original_dt / 2 + ) + self.assertEqual(scheduled.duration, original_duration * 2) + + # halve dt in sec = double duration in dt + scheduled = transpile(qc, backend=backend_v2, scheduling_method="asap", dt=original_dt / 2) + self.assertEqual(scheduled.duration, original_duration * 2) def test_backend_props_constraints(self): """Test that loose transpile constraints @@ -1613,7 +1631,7 @@ def test_backend_props_constraints(self): with self.assertWarns(DeprecationWarning): backend_v1 = Fake20QV1() - backend_v2 = BackendV2Converter(backend_v1) + backend_v2 = BackendV2Converter(backend_v1) qr1 = QuantumRegister(3, "qr1") qr2 = QuantumRegister(2, "qr2") qc = QuantumCircuit(qr1, qr2) @@ -1625,7 +1643,8 @@ def test_backend_props_constraints(self): # generate a fake backend with same number of qubits # but different backend properties fake_backend = GenericBackendV2(num_qubits=20, seed=42) - custom_backend_properties = target_to_backend_properties(fake_backend.target) + with self.assertWarns(DeprecationWarning): + custom_backend_properties = target_to_backend_properties(fake_backend.target) # expected layout for custom_backend_properties # (different from expected layout for Fake20QV1) @@ -1652,17 +1671,28 @@ def test_backend_props_constraints(self): 17: Qubit(QuantumRegister(15, "ancilla"), 14), } - for backend in [backend_v1, backend_v2]: - with self.subTest(backend=backend): - result = transpile( - qc, - backend=backend, - backend_properties=custom_backend_properties, - optimization_level=2, - seed_transpiler=42, - ) + with self.assertWarnsRegex( + DeprecationWarning, + expected_regex="The `transpile` function will stop supporting inputs of type `BackendV1` ", + ): + result = transpile( + qc, + backend=backend_v1, + backend_properties=custom_backend_properties, + optimization_level=2, + seed_transpiler=42, + ) + + self.assertEqual(result._layout.initial_layout._p2v, vf2_layout) + result = transpile( + qc, + backend=backend_v2, + backend_properties=custom_backend_properties, + optimization_level=2, + seed_transpiler=42, + ) - self.assertEqual(result._layout.initial_layout._p2v, vf2_layout) + self.assertEqual(result._layout.initial_layout._p2v, vf2_layout) @data(1, 2, 3) def test_no_infinite_loop(self, optimization_level): @@ -2101,9 +2131,9 @@ def test_transpile_annotated_ops_with_backend_v1(self, opt_level): qc.append(AnnotatedOperation(HGate(), PowerModifier(3)), [2]) with self.assertWarns(DeprecationWarning): backend = Fake20QV1() - transpiled = transpile( - qc, optimization_level=opt_level, backend=backend, seed_transpiler=42 - ) + transpiled = transpile( + qc, optimization_level=opt_level, backend=backend, seed_transpiler=42 + ) self.assertLessEqual(set(transpiled.count_ops().keys()), {"u1", "u2", "u3", "cx"}) @combine(opt_level=[0, 1, 2, 3]) @@ -2449,12 +2479,12 @@ def test_qasm3_output_v1(self, optimization_level): with self.assertWarns(DeprecationWarning): backend = Fake20QV1() - transpiled = transpile( - self._regular_circuit(), - backend=backend, - optimization_level=optimization_level, - seed_transpiler=2022_10_17, - ) + transpiled = transpile( + self._regular_circuit(), + backend=backend, + optimization_level=optimization_level, + seed_transpiler=2022_10_17, + ) # TODO: There's not a huge amount we can sensibly test for the output here until we can # round-trip the OpenQASM 3 back into a Terra circuit. Mostly we're concerned that the dump # itself doesn't throw an error, though. diff --git a/test/python/primitives/test_backend_estimator_v2.py b/test/python/primitives/test_backend_estimator_v2.py index ad6b4c6abfdb..12a932b83819 100644 --- a/test/python/primitives/test_backend_estimator_v2.py +++ b/test/python/primitives/test_backend_estimator_v2.py @@ -33,8 +33,20 @@ from qiskit.quantum_info import SparsePauliOp from qiskit.transpiler.preset_passmanagers import generate_preset_pass_manager from qiskit.utils import optionals - -BACKENDS = [BasicSimulator(), Fake7QPulseV1(), BackendV2Converter(Fake7QPulseV1())] +from ..legacy_cmaps import LAGOS_CMAP + +BACKENDS_V1 = [Fake7QPulseV1()] +BACKENDS_V2 = [ + BasicSimulator(), + BackendV2Converter(Fake7QPulseV1()), + GenericBackendV2( + num_qubits=7, + basis_gates=["id", "rz", "sx", "x", "cx", "reset"], + coupling_map=LAGOS_CMAP, + seed=42, + ), +] +BACKENDS = BACKENDS_V1 + BACKENDS_V2 @ddt @@ -73,7 +85,7 @@ def setUp(self): [1, 2, 3, 4, 5, 6], ) - @combine(backend=BACKENDS, abelian_grouping=[True, False]) + @combine(backend=BACKENDS_V2, abelian_grouping=[True, False]) def test_estimator_run(self, backend, abelian_grouping): """Test Estimator.run()""" psi1, psi2 = self.psi @@ -120,7 +132,59 @@ def test_estimator_run(self, backend, abelian_grouping): np.testing.assert_allclose(result4[0].data.evs, [1.55555728, -1.08766318], rtol=self._rtol) np.testing.assert_allclose(result4[1].data.evs, [0.17849238], rtol=self._rtol) - @combine(backend=BACKENDS, abelian_grouping=[True, False]) + @combine(backend=BACKENDS_V1, abelian_grouping=[True, False]) + def test_estimator_run_v1(self, backend, abelian_grouping): + """Test Estimator.run()""" + psi1, psi2 = self.psi + hamiltonian1, hamiltonian2, hamiltonian3 = self.hamiltonian + theta1, theta2, theta3 = self.theta + with self.assertWarnsRegex( + DeprecationWarning, + expected_regex="The `generate_preset_pass_manager` function will stop supporting " + "inputs of type `BackendV1`", + ): + pm = generate_preset_pass_manager(optimization_level=0, backend=backend) + psi1, psi2 = pm.run([psi1, psi2]) + estimator = BackendEstimatorV2(backend=backend, options=self._options) + estimator.options.abelian_grouping = abelian_grouping + # Specify the circuit and observable by indices. + # calculate [ ] + ham1 = hamiltonian1.apply_layout(psi1.layout) + job = estimator.run([(psi1, ham1, [theta1])]) + result = job.result() + np.testing.assert_allclose(result[0].data.evs, [1.5555572817900956], rtol=self._rtol) + + # Objects can be passed instead of indices. + # Note that passing objects has an overhead + # since the corresponding indices need to be searched. + # User can append a circuit and observable. + # calculate [ ] + ham1 = hamiltonian1.apply_layout(psi2.layout) + result2 = estimator.run([(psi2, ham1, theta2)]).result() + np.testing.assert_allclose(result2[0].data.evs, [2.97797666], rtol=self._rtol) + + # calculate [ , ] + ham2 = hamiltonian2.apply_layout(psi1.layout) + ham3 = hamiltonian3.apply_layout(psi1.layout) + result3 = estimator.run([(psi1, [ham2, ham3], theta1)]).result() + np.testing.assert_allclose(result3[0].data.evs, [-0.551653, 0.07535239], rtol=self._rtol) + + # calculate [ [, + # ], + # [] ] + ham1 = hamiltonian1.apply_layout(psi1.layout) + ham3 = hamiltonian3.apply_layout(psi1.layout) + ham2 = hamiltonian2.apply_layout(psi2.layout) + result4 = estimator.run( + [ + (psi1, [ham1, ham3], [theta1, theta3]), + (psi2, ham2, theta2), + ] + ).result() + np.testing.assert_allclose(result4[0].data.evs, [1.55555728, -1.08766318], rtol=self._rtol) + np.testing.assert_allclose(result4[1].data.evs, [0.17849238], rtol=self._rtol) + + @combine(backend=BACKENDS_V2, abelian_grouping=[True, False]) def test_estimator_with_pub(self, backend, abelian_grouping): """Test estimator with explicit EstimatorPubs.""" psi1, psi2 = self.psi @@ -146,7 +210,38 @@ def test_estimator_with_pub(self, backend, abelian_grouping): np.testing.assert_allclose(result4[0].data.evs, [1.55555728, -1.08766318], rtol=self._rtol) np.testing.assert_allclose(result4[1].data.evs, [0.17849238], rtol=self._rtol) - @combine(backend=BACKENDS, abelian_grouping=[True, False]) + @combine(backend=BACKENDS_V1, abelian_grouping=[True, False]) + def test_estimator_with_pub_v1(self, backend, abelian_grouping): + """Test estimator with explicit EstimatorPubs.""" + psi1, psi2 = self.psi + hamiltonian1, hamiltonian2, hamiltonian3 = self.hamiltonian + theta1, theta2, theta3 = self.theta + with self.assertWarnsRegex( + DeprecationWarning, + expected_regex="The `generate_preset_pass_manager` function will stop supporting " + "inputs of type `BackendV1`", + ): + pm = generate_preset_pass_manager(optimization_level=0, backend=backend) + psi1, psi2 = pm.run([psi1, psi2]) + + ham1 = hamiltonian1.apply_layout(psi1.layout) + ham3 = hamiltonian3.apply_layout(psi1.layout) + obs1 = ObservablesArray.coerce([ham1, ham3]) + bind1 = BindingsArray.coerce({tuple(psi1.parameters): [theta1, theta3]}) + pub1 = EstimatorPub(psi1, obs1, bind1) + + ham2 = hamiltonian2.apply_layout(psi2.layout) + obs2 = ObservablesArray.coerce(ham2) + bind2 = BindingsArray.coerce({tuple(psi2.parameters): theta2}) + pub2 = EstimatorPub(psi2, obs2, bind2) + + estimator = BackendEstimatorV2(backend=backend, options=self._options) + estimator.options.abelian_grouping = abelian_grouping + result4 = estimator.run([pub1, pub2]).result() + np.testing.assert_allclose(result4[0].data.evs, [1.55555728, -1.08766318], rtol=self._rtol) + np.testing.assert_allclose(result4[1].data.evs, [0.17849238], rtol=self._rtol) + + @combine(backend=BACKENDS_V2, abelian_grouping=[True, False]) def test_estimator_run_no_params(self, backend, abelian_grouping): """test for estimator without parameters""" circuit = self.ansatz.assign_parameters([0, 1, 1, 2, 3, 5]) @@ -158,7 +253,24 @@ def test_estimator_run_no_params(self, backend, abelian_grouping): result = est.run([(circuit, observable)]).result() np.testing.assert_allclose(result[0].data.evs, [-1.284366511861733], rtol=self._rtol) - @combine(backend=BACKENDS, abelian_grouping=[True, False]) + @combine(backend=BACKENDS_V1, abelian_grouping=[True, False]) + def test_estimator_run_no_params_v1(self, backend, abelian_grouping): + """test for estimator without parameters""" + circuit = self.ansatz.assign_parameters([0, 1, 1, 2, 3, 5]) + with self.assertWarnsRegex( + DeprecationWarning, + expected_regex="The `generate_preset_pass_manager` function will " + "stop supporting inputs of type `BackendV1`", + ): + pm = generate_preset_pass_manager(optimization_level=0, backend=backend) + circuit = pm.run(circuit) + est = BackendEstimatorV2(backend=backend, options=self._options) + est.options.abelian_grouping = abelian_grouping + observable = self.observable.apply_layout(circuit.layout) + result = est.run([(circuit, observable)]).result() + np.testing.assert_allclose(result[0].data.evs, [-1.284366511861733], rtol=self._rtol) + + @combine(backend=BACKENDS_V2, abelian_grouping=[True, False]) def test_run_single_circuit_observable(self, backend, abelian_grouping): """Test for single circuit and single observable case.""" est = BackendEstimatorV2(backend=backend, options=self._options) @@ -216,7 +328,70 @@ def test_run_single_circuit_observable(self, backend, abelian_grouping): np.testing.assert_allclose(result[0].data.evs, target, rtol=self._rtol) self.assertEqual(result[0].metadata["target_precision"], self._precision) - @combine(backend=BACKENDS, abelian_grouping=[True, False]) + @combine(backend=BACKENDS_V1, abelian_grouping=[True, False]) + def test_run_single_circuit_observable_v1(self, backend, abelian_grouping): + """Test for single circuit and single observable case.""" + est = BackendEstimatorV2(backend=backend, options=self._options) + est.options.abelian_grouping = abelian_grouping + with self.assertWarnsRegex( + DeprecationWarning, + expected_regex="The `generate_preset_pass_manager` function will stop supporting " + "inputs of type `BackendV1`", + ): + pm = generate_preset_pass_manager(optimization_level=0, backend=backend) + + with self.subTest("No parameter"): + qc = QuantumCircuit(1) + qc.x(0) + qc = pm.run(qc) + op = SparsePauliOp("Z") + op = op.apply_layout(qc.layout) + param_vals = [None, [], [[]], np.array([]), np.array([[]]), [np.array([])]] + target = [-1] + for val in param_vals: + self.subTest(f"{val}") + result = est.run([(qc, op, val)]).result() + np.testing.assert_allclose(result[0].data.evs, target, rtol=self._rtol) + self.assertEqual(result[0].metadata["target_precision"], self._precision) + + with self.subTest("One parameter"): + param = Parameter("x") + qc = QuantumCircuit(1) + qc.ry(param, 0) + qc = pm.run(qc) + op = SparsePauliOp("Z") + op = op.apply_layout(qc.layout) + param_vals = [ + [np.pi], + np.array([np.pi]), + ] + target = [-1] + for val in param_vals: + self.subTest(f"{val}") + result = est.run([(qc, op, val)]).result() + np.testing.assert_allclose(result[0].data.evs, target, rtol=self._rtol) + self.assertEqual(result[0].metadata["target_precision"], self._precision) + + with self.subTest("More than one parameter"): + qc = self.psi[0] + qc = pm.run(qc) + op = self.hamiltonian[0] + op = op.apply_layout(qc.layout) + param_vals = [ + self.theta[0], + [self.theta[0]], + np.array(self.theta[0]), + np.array([self.theta[0]]), + [np.array(self.theta[0])], + ] + target = [1.5555572817900956] + for val in param_vals: + self.subTest(f"{val}") + result = est.run([(qc, op, val)]).result() + np.testing.assert_allclose(result[0].data.evs, target, rtol=self._rtol) + self.assertEqual(result[0].metadata["target_precision"], self._precision) + + @combine(backend=BACKENDS_V2, abelian_grouping=[True, False]) def test_run_1qubit(self, backend, abelian_grouping): """Test for 1-qubit cases""" qc = QuantumCircuit(1) @@ -246,7 +421,42 @@ def test_run_1qubit(self, backend, abelian_grouping): result = est.run([(qc2, op_4)]).result() np.testing.assert_allclose(result[0].data.evs, [-1], rtol=self._rtol) - @combine(backend=BACKENDS, abelian_grouping=[True, False]) + @combine(backend=BACKENDS_V1, abelian_grouping=[True, False]) + def test_run_1qubit_v1(self, backend, abelian_grouping): + """Test for 1-qubit cases""" + qc = QuantumCircuit(1) + qc2 = QuantumCircuit(1) + qc2.x(0) + with self.assertWarnsRegex( + DeprecationWarning, + expected_regex="The `generate_preset_pass_manager` function will stop supporting " + "inputs of type `BackendV1`", + ): + pm = generate_preset_pass_manager(optimization_level=0, backend=backend) + qc, qc2 = pm.run([qc, qc2]) + + op = SparsePauliOp.from_list([("I", 1)]) + op2 = SparsePauliOp.from_list([("Z", 1)]) + + est = BackendEstimatorV2(backend=backend, options=self._options) + est.options.abelian_grouping = abelian_grouping + op_1 = op.apply_layout(qc.layout) + result = est.run([(qc, op_1)]).result() + np.testing.assert_allclose(result[0].data.evs, [1], rtol=self._rtol) + + op_2 = op2.apply_layout(qc.layout) + result = est.run([(qc, op_2)]).result() + np.testing.assert_allclose(result[0].data.evs, [1], rtol=self._rtol) + + op_3 = op.apply_layout(qc2.layout) + result = est.run([(qc2, op_3)]).result() + np.testing.assert_allclose(result[0].data.evs, [1], rtol=self._rtol) + + op_4 = op2.apply_layout(qc2.layout) + result = est.run([(qc2, op_4)]).result() + np.testing.assert_allclose(result[0].data.evs, [-1], rtol=self._rtol) + + @combine(backend=BACKENDS_V2, abelian_grouping=[True, False]) def test_run_2qubits(self, backend, abelian_grouping): """Test for 2-qubit cases (to check endian)""" qc = QuantumCircuit(2) @@ -285,6 +495,50 @@ def test_run_2qubits(self, backend, abelian_grouping): result = est.run([(qc2, op_6)]).result() np.testing.assert_allclose(result[0].data.evs, [-1], rtol=self._rtol) + @combine(backend=BACKENDS_V1, abelian_grouping=[True, False]) + def test_run_2qubits_v1(self, backend, abelian_grouping): + """Test for 2-qubit cases (to check endian)""" + qc = QuantumCircuit(2) + qc2 = QuantumCircuit(2) + qc2.x(0) + with self.assertWarnsRegex( + DeprecationWarning, + expected_regex="The `generate_preset_pass_manager` function will stop supporting " + "inputs of type `BackendV1`", + ): + pm = generate_preset_pass_manager(optimization_level=0, backend=backend) + qc, qc2 = pm.run([qc, qc2]) + + op = SparsePauliOp.from_list([("II", 1)]) + op2 = SparsePauliOp.from_list([("ZI", 1)]) + op3 = SparsePauliOp.from_list([("IZ", 1)]) + + est = BackendEstimatorV2(backend=backend, options=self._options) + est.options.abelian_grouping = abelian_grouping + op_1 = op.apply_layout(qc.layout) + result = est.run([(qc, op_1)]).result() + np.testing.assert_allclose(result[0].data.evs, [1], rtol=self._rtol) + + op_2 = op.apply_layout(qc2.layout) + result = est.run([(qc2, op_2)]).result() + np.testing.assert_allclose(result[0].data.evs, [1], rtol=self._rtol) + + op_3 = op2.apply_layout(qc.layout) + result = est.run([(qc, op_3)]).result() + np.testing.assert_allclose(result[0].data.evs, [1], rtol=self._rtol) + + op_4 = op2.apply_layout(qc2.layout) + result = est.run([(qc2, op_4)]).result() + np.testing.assert_allclose(result[0].data.evs, [1], rtol=self._rtol) + + op_5 = op3.apply_layout(qc.layout) + result = est.run([(qc, op_5)]).result() + np.testing.assert_allclose(result[0].data.evs, [1], rtol=self._rtol) + + op_6 = op3.apply_layout(qc2.layout) + result = est.run([(qc2, op_6)]).result() + np.testing.assert_allclose(result[0].data.evs, [-1], rtol=self._rtol) + @combine(backend=BACKENDS, abelian_grouping=[True, False]) def test_run_errors(self, backend, abelian_grouping): """Test for errors""" @@ -322,7 +576,7 @@ def test_run_errors(self, backend, abelian_grouping): with self.assertRaisesRegex(ValueError, "An invalid Estimator pub-like was given"): _ = est.run((qc, op)).result() - @combine(backend=BACKENDS, abelian_grouping=[True, False]) + @combine(backend=BACKENDS_V2, abelian_grouping=[True, False]) def test_run_numpy_params(self, backend, abelian_grouping): """Test for numpy array as parameter values""" qc = RealAmplitudes(num_qubits=2, reps=2) @@ -350,7 +604,40 @@ def test_run_numpy_params(self, backend, abelian_grouping): self.assertEqual(result[0].data.evs.shape, (k,)) np.testing.assert_allclose(result[0].data.evs, target[0].data.evs, rtol=self._rtol) - @combine(backend=BACKENDS, abelian_grouping=[True, False]) + @combine(backend=BACKENDS_V1, abelian_grouping=[True, False]) + def test_run_numpy_params_v1(self, backend, abelian_grouping): + """Test for numpy array as parameter values""" + qc = RealAmplitudes(num_qubits=2, reps=2) + with self.assertWarnsRegex( + DeprecationWarning, + expected_regex="The `generate_preset_pass_manager` function will stop supporting " + "inputs of type `BackendV1`", + ): + pm = generate_preset_pass_manager(optimization_level=0, backend=backend) + qc = pm.run(qc) + op = SparsePauliOp.from_list([("IZ", 1), ("XI", 2), ("ZY", -1)]) + op = op.apply_layout(qc.layout) + k = 5 + params_array = self._rng.random((k, qc.num_parameters)) + params_list = params_array.tolist() + params_list_array = list(params_array) + statevector_estimator = StatevectorEstimator(seed=123) + target = statevector_estimator.run([(qc, op, params_list)]).result() + + backend_estimator = BackendEstimatorV2(backend=backend, options=self._options) + backend_estimator.options.abelian_grouping = abelian_grouping + + with self.subTest("ndarrary"): + result = backend_estimator.run([(qc, op, params_array)]).result() + self.assertEqual(result[0].data.evs.shape, (k,)) + np.testing.assert_allclose(result[0].data.evs, target[0].data.evs, rtol=self._rtol) + + with self.subTest("list of ndarray"): + result = backend_estimator.run([(qc, op, params_list_array)]).result() + self.assertEqual(result[0].data.evs.shape, (k,)) + np.testing.assert_allclose(result[0].data.evs, target[0].data.evs, rtol=self._rtol) + + @combine(backend=BACKENDS_V2, abelian_grouping=[True, False]) def test_precision(self, backend, abelian_grouping): """Test for precision""" estimator = BackendEstimatorV2(backend=backend, options=self._options) @@ -372,7 +659,34 @@ def test_precision(self, backend, abelian_grouping): result = job.result() np.testing.assert_allclose(result[0].data.evs, [1.5555572817900956], rtol=self._rtol) - @combine(backend=BACKENDS, abelian_grouping=[True, False]) + @combine(backend=BACKENDS_V1, abelian_grouping=[True, False]) + def test_precision_v1(self, backend, abelian_grouping): + """Test for precision""" + estimator = BackendEstimatorV2(backend=backend, options=self._options) + estimator.options.abelian_grouping = abelian_grouping + with self.assertWarnsRegex( + DeprecationWarning, + expected_regex="The `generate_preset_pass_manager` function will stop supporting " + "inputs of type `BackendV1`", + ): + pm = generate_preset_pass_manager(optimization_level=0, backend=backend) + psi1 = pm.run(self.psi[0]) + hamiltonian1 = self.hamiltonian[0].apply_layout(psi1.layout) + theta1 = self.theta[0] + job = estimator.run([(psi1, hamiltonian1, [theta1])]) + result = job.result() + np.testing.assert_allclose(result[0].data.evs, [1.901141473854881], rtol=self._rtol) + # The result of the second run is the same + job = estimator.run([(psi1, hamiltonian1, [theta1]), (psi1, hamiltonian1, [theta1])]) + result = job.result() + np.testing.assert_allclose(result[0].data.evs, [1.901141473854881], rtol=self._rtol) + np.testing.assert_allclose(result[1].data.evs, [1.901141473854881], rtol=self._rtol) + # apply smaller precision value + job = estimator.run([(psi1, hamiltonian1, [theta1])], precision=self._precision * 0.5) + result = job.result() + np.testing.assert_allclose(result[0].data.evs, [1.5555572817900956], rtol=self._rtol) + + @combine(backend=BACKENDS_V2, abelian_grouping=[True, False]) def test_diff_precision(self, backend, abelian_grouping): """Test for running different precisions at once""" estimator = BackendEstimatorV2(backend=backend, options=self._options) @@ -388,6 +702,27 @@ def test_diff_precision(self, backend, abelian_grouping): np.testing.assert_allclose(result[0].data.evs, [1.901141473854881], rtol=self._rtol) np.testing.assert_allclose(result[1].data.evs, [1.901141473854881], rtol=self._rtol) + @combine(backend=BACKENDS_V1, abelian_grouping=[True, False]) + def test_diff_precision_v1(self, backend, abelian_grouping): + """Test for running different precisions at once""" + estimator = BackendEstimatorV2(backend=backend, options=self._options) + estimator.options.abelian_grouping = abelian_grouping + with self.assertWarnsRegex( + DeprecationWarning, + expected_regex="The `generate_preset_pass_manager` function will stop supporting " + "inputs of type `BackendV1`", + ): + pm = generate_preset_pass_manager(optimization_level=0, backend=backend) + psi1 = pm.run(self.psi[0]) + hamiltonian1 = self.hamiltonian[0].apply_layout(psi1.layout) + theta1 = self.theta[0] + job = estimator.run( + [(psi1, hamiltonian1, [theta1]), (psi1, hamiltonian1, [theta1], self._precision * 0.8)] + ) + result = job.result() + np.testing.assert_allclose(result[0].data.evs, [1.901141473854881], rtol=self._rtol) + np.testing.assert_allclose(result[1].data.evs, [1.901141473854881], rtol=self._rtol) + @unittest.skipUnless(optionals.HAS_AER, "qiskit-aer is required to run this test") @combine(abelian_grouping=[True, False]) def test_aer(self, abelian_grouping): diff --git a/test/python/primitives/test_backend_sampler.py b/test/python/primitives/test_backend_sampler.py index f0fdb4f07f8c..27e438d30874 100644 --- a/test/python/primitives/test_backend_sampler.py +++ b/test/python/primitives/test_backend_sampler.py @@ -34,6 +34,12 @@ BACKENDS = [Fake7QPulseV1(), BackendV2Converter(Fake7QPulseV1())] +BACKENDS_V1 = [Fake7QPulseV1()] +BACKENDS_V2 = [ + BackendV2Converter(Fake7QPulseV1()), +] +BACKENDS = BACKENDS_V1 + BACKENDS_V2 + class CallbackPass(DummyAP): """A dummy analysis pass that calls a callback when executed""" @@ -236,8 +242,37 @@ def test_run_errors(self, backend): with self.assertRaises(ValueError): sampler.run([qc2], [[1e2]]).result() - @combine(backend=BACKENDS) - def test_run_empty_parameter(self, backend): + @combine(backend=BACKENDS_V1) + def test_run_empty_parameter_v1(self, backend): + """Test for empty parameter""" + n = 5 + qc = QuantumCircuit(n, n - 1) + qc.measure(range(n - 1), range(n - 1)) + with self.assertWarns(DeprecationWarning): + sampler = BackendSampler(backend=backend) + with self.subTest("one circuit"): + with self.assertWarnsRegex( + DeprecationWarning, + expected_regex="The `transpile` function will " + "stop supporting inputs of type `BackendV1`", + ): + result = sampler.run([qc], shots=1000).result() + self.assertEqual(len(result.quasi_dists), 1) + for q_d in result.quasi_dists: + quasi_dist = {k: v for k, v in q_d.items() if v != 0.0} + self.assertDictAlmostEqual(quasi_dist, {0: 1.0}, delta=0.1) + self.assertEqual(len(result.metadata), 1) + + with self.subTest("two circuits"): + result = sampler.run([qc, qc], shots=1000).result() + self.assertEqual(len(result.quasi_dists), 2) + for q_d in result.quasi_dists: + quasi_dist = {k: v for k, v in q_d.items() if v != 0.0} + self.assertDictAlmostEqual(quasi_dist, {0: 1.0}, delta=0.1) + self.assertEqual(len(result.metadata), 2) + + @combine(backend=BACKENDS_V2) + def test_run_empty_parameter_v2(self, backend): """Test for empty parameter""" n = 5 qc = QuantumCircuit(n, n - 1) diff --git a/test/python/primitives/test_backend_sampler_v2.py b/test/python/primitives/test_backend_sampler_v2.py index 6e899dca58f9..372ae3a6715c 100644 --- a/test/python/primitives/test_backend_sampler_v2.py +++ b/test/python/primitives/test_backend_sampler_v2.py @@ -34,8 +34,20 @@ from qiskit.providers.basic_provider import BasicSimulator from qiskit.providers.fake_provider import Fake7QPulseV1, GenericBackendV2 from qiskit.transpiler.preset_passmanagers import generate_preset_pass_manager - -BACKENDS = [BasicSimulator(), Fake7QPulseV1(), BackendV2Converter(Fake7QPulseV1())] +from ..legacy_cmaps import LAGOS_CMAP + +BACKENDS_V1 = [Fake7QPulseV1()] +BACKENDS_V2 = [ + BasicSimulator(), + BackendV2Converter(Fake7QPulseV1()), + GenericBackendV2( + num_qubits=7, + basis_gates=["id", "rz", "sx", "x", "cx", "reset"], + coupling_map=LAGOS_CMAP, + seed=42, + ), +] +BACKENDS = BACKENDS_V1 + BACKENDS_V2 @ddt @@ -85,7 +97,63 @@ def _assert_allclose(self, bitarray: BitArray, target: NDArray | BitArray, rtol= tgt = np.array([target_counts.get(i, 0) for i in range(max_key + 1)]) np.testing.assert_allclose(ary, tgt, rtol=rtol, atol=atol, err_msg=f"index: {idx}") - @combine(backend=BACKENDS) + @combine(backend=BACKENDS_V1) + def test_sampler_run_v1(self, backend): + """Test run().""" + with self.assertWarnsRegex( + DeprecationWarning, + expected_regex="The `generate_preset_pass_manager` function will " + "stop supporting inputs of type `BackendV1`", + ): + pm = generate_preset_pass_manager(optimization_level=0, backend=backend) + + with self.subTest("single"): + bell, _, target = self._cases[1] + bell = pm.run(bell) + sampler = BackendSamplerV2(backend=backend, options=self._options) + job = sampler.run([bell], shots=self._shots) + result = job.result() + self.assertIsInstance(result, PrimitiveResult) + self.assertIsInstance(result.metadata, dict) + self.assertEqual(len(result), 1) + self.assertIsInstance(result[0], PubResult) + self.assertIsInstance(result[0].data, DataBin) + self.assertIsInstance(result[0].data.meas, BitArray) + self._assert_allclose(result[0].data.meas, np.array(target)) + + with self.subTest("single with param"): + pqc, param_vals, target = self._cases[2] + sampler = BackendSamplerV2(backend=backend, options=self._options) + pqc = pm.run(pqc) + params = (param.name for param in pqc.parameters) + job = sampler.run([(pqc, {params: param_vals})], shots=self._shots) + result = job.result() + self.assertIsInstance(result, PrimitiveResult) + self.assertIsInstance(result.metadata, dict) + self.assertEqual(len(result), 1) + self.assertIsInstance(result[0], PubResult) + self.assertIsInstance(result[0].data, DataBin) + self.assertIsInstance(result[0].data.meas, BitArray) + self._assert_allclose(result[0].data.meas, np.array(target)) + + with self.subTest("multiple"): + pqc, param_vals, target = self._cases[2] + sampler = BackendSamplerV2(backend=backend, options=self._options) + pqc = pm.run(pqc) + params = (param.name for param in pqc.parameters) + job = sampler.run( + [(pqc, {params: [param_vals, param_vals, param_vals]})], shots=self._shots + ) + result = job.result() + self.assertIsInstance(result, PrimitiveResult) + self.assertIsInstance(result.metadata, dict) + self.assertEqual(len(result), 1) + self.assertIsInstance(result[0], PubResult) + self.assertIsInstance(result[0].data, DataBin) + self.assertIsInstance(result[0].data.meas, BitArray) + self._assert_allclose(result[0].data.meas, np.array([target, target, target])) + + @combine(backend=BACKENDS_V2) def test_sampler_run(self, backend): """Test run().""" pm = generate_preset_pass_manager(optimization_level=0, backend=backend) @@ -136,7 +204,25 @@ def test_sampler_run(self, backend): self.assertIsInstance(result[0].data.meas, BitArray) self._assert_allclose(result[0].data.meas, np.array([target, target, target])) - @combine(backend=BACKENDS) + @combine(backend=BACKENDS_V1) + def test_sampler_run_multiple_times_v1(self, backend): + """Test run() returns the same results if the same input is given.""" + bell, _, _ = self._cases[1] + sampler = BackendSamplerV2(backend=backend, options=self._options) + with self.assertWarnsRegex( + DeprecationWarning, + expected_regex="The `generate_preset_pass_manager` function will " + "stop supporting inputs of type `BackendV1`", + ): + pm = generate_preset_pass_manager(optimization_level=0, backend=backend) + bell = pm.run(bell) + result1 = sampler.run([bell], shots=self._shots).result() + meas1 = result1[0].data.meas + result2 = sampler.run([bell], shots=self._shots).result() + meas2 = result2[0].data.meas + self._assert_allclose(meas1, meas2, rtol=0) + + @combine(backend=BACKENDS_V2) def test_sampler_run_multiple_times(self, backend): """Test run() returns the same results if the same input is given.""" bell, _, _ = self._cases[1] @@ -149,7 +235,25 @@ def test_sampler_run_multiple_times(self, backend): meas2 = result2[0].data.meas self._assert_allclose(meas1, meas2, rtol=0) - @combine(backend=BACKENDS) + @combine(backend=BACKENDS_V1) + def test_sample_run_multiple_circuits_v1(self, backend): + """Test run() with multiple circuits.""" + bell, _, target = self._cases[1] + sampler = BackendSamplerV2(backend=backend, options=self._options) + with self.assertWarnsRegex( + DeprecationWarning, + expected_regex="The `generate_preset_pass_manager` function will " + "stop supporting inputs of type `BackendV1`", + ): + pm = generate_preset_pass_manager(optimization_level=0, backend=backend) + bell = pm.run(bell) + result = sampler.run([bell, bell, bell], shots=self._shots).result() + self.assertEqual(len(result), 3) + self._assert_allclose(result[0].data.meas, np.array(target)) + self._assert_allclose(result[1].data.meas, np.array(target)) + self._assert_allclose(result[2].data.meas, np.array(target)) + + @combine(backend=BACKENDS_V2) def test_sample_run_multiple_circuits(self, backend): """Test run() with multiple circuits.""" bell, _, target = self._cases[1] @@ -162,13 +266,14 @@ def test_sample_run_multiple_circuits(self, backend): self._assert_allclose(result[1].data.meas, np.array(target)) self._assert_allclose(result[2].data.meas, np.array(target)) - @combine(backend=BACKENDS) - def test_sampler_run_with_parameterized_circuits(self, backend): + @combine(backend=BACKENDS_V1) + def test_sampler_run_with_parameterized_circuits_v1(self, backend): """Test run() with parameterized circuits.""" pqc1, param1, target1 = self._cases[4] pqc2, param2, target2 = self._cases[5] pqc3, param3, target3 = self._cases[6] - pm = generate_preset_pass_manager(optimization_level=0, backend=backend) + with self.assertWarns(DeprecationWarning): + pm = generate_preset_pass_manager(optimization_level=0, backend=backend) pqc1, pqc2, pqc3 = pm.run([pqc1, pqc2, pqc3]) sampler = BackendSamplerV2(backend=backend, options=self._options) @@ -180,7 +285,7 @@ def test_sampler_run_with_parameterized_circuits(self, backend): self._assert_allclose(result[1].data.meas, np.array(target2)) self._assert_allclose(result[2].data.meas, np.array(target3)) - @combine(backend=BACKENDS) + @combine(backend=BACKENDS_V2) def test_run_1qubit(self, backend): """test for 1-qubit cases""" qc = QuantumCircuit(1) @@ -197,7 +302,29 @@ def test_run_1qubit(self, backend): for i in range(2): self._assert_allclose(result[i].data.meas, np.array({i: self._shots})) - @combine(backend=BACKENDS) + @combine(backend=BACKENDS_V1) + def test_run_1qubit_v1(self, backend): + """test for 1-qubit cases""" + qc = QuantumCircuit(1) + qc.measure_all() + qc2 = QuantumCircuit(1) + qc2.x(0) + qc2.measure_all() + with self.assertWarnsRegex( + DeprecationWarning, + expected_regex="The `generate_preset_pass_manager` function will " + "stop supporting inputs of type `BackendV1`", + ): + pm = generate_preset_pass_manager(optimization_level=0, backend=backend) + qc, qc2 = pm.run([qc, qc2]) + + sampler = BackendSamplerV2(backend=backend, options=self._options) + result = sampler.run([qc, qc2], shots=self._shots).result() + self.assertEqual(len(result), 2) + for i in range(2): + self._assert_allclose(result[i].data.meas, np.array({i: self._shots})) + + @combine(backend=BACKENDS_V2) def test_run_2qubit(self, backend): """test for 2-qubit cases""" qc0 = QuantumCircuit(2) @@ -220,7 +347,35 @@ def test_run_2qubit(self, backend): for i in range(4): self._assert_allclose(result[i].data.meas, np.array({i: self._shots})) - @combine(backend=BACKENDS) + @combine(backend=BACKENDS_V1) + def test_run_2qubit_v1(self, backend): + """test for 2-qubit cases""" + qc0 = QuantumCircuit(2) + qc0.measure_all() + qc1 = QuantumCircuit(2) + qc1.x(0) + qc1.measure_all() + qc2 = QuantumCircuit(2) + qc2.x(1) + qc2.measure_all() + qc3 = QuantumCircuit(2) + qc3.x([0, 1]) + qc3.measure_all() + with self.assertWarnsRegex( + DeprecationWarning, + expected_regex="The `generate_preset_pass_manager` function will " + "stop supporting inputs of type `BackendV1`", + ): + pm = generate_preset_pass_manager(optimization_level=0, backend=backend) + qc0, qc1, qc2, qc3 = pm.run([qc0, qc1, qc2, qc3]) + + sampler = BackendSamplerV2(backend=backend, options=self._options) + result = sampler.run([qc0, qc1, qc2, qc3], shots=self._shots).result() + self.assertEqual(len(result), 4) + for i in range(4): + self._assert_allclose(result[i].data.meas, np.array({i: self._shots})) + + @combine(backend=BACKENDS_V2) def test_run_single_circuit(self, backend): """Test for single circuit case.""" sampler = BackendSamplerV2(backend=backend, options=self._options) @@ -278,7 +433,70 @@ def test_run_single_circuit(self, backend): self.assertEqual(len(result), 1) self._assert_allclose(result[0].data.meas, target) - @combine(backend=BACKENDS) + @combine(backend=BACKENDS_V1) + def test_run_single_circuit_v1(self, backend): + """Test for single circuit case.""" + sampler = BackendSamplerV2(backend=backend, options=self._options) + with self.assertWarnsRegex( + DeprecationWarning, + expected_regex="The `generate_preset_pass_manager` function will " + "stop supporting inputs of type `BackendV1`", + ): + pm = generate_preset_pass_manager(optimization_level=0, backend=backend) + + with self.subTest("No parameter"): + circuit, _, target = self._cases[1] + circuit = pm.run(circuit) + param_target = [ + (None, np.array(target)), + ({}, np.array(target)), + ] + for param, target in param_target: + with self.subTest(f"{circuit.name} w/ {param}"): + result = sampler.run([(circuit, param)], shots=self._shots).result() + self.assertEqual(len(result), 1) + self._assert_allclose(result[0].data.meas, target) + + with self.subTest("One parameter"): + circuit = QuantumCircuit(1, 1, name="X gate") + param = Parameter("x") + circuit.ry(param, 0) + circuit.measure(0, 0) + circuit = pm.run(circuit) + param_target = [ + ({"x": np.pi}, np.array({1: self._shots})), + ({param: np.pi}, np.array({1: self._shots})), + ({"x": np.array(np.pi)}, np.array({1: self._shots})), + ({param: np.array(np.pi)}, np.array({1: self._shots})), + ({"x": [np.pi]}, np.array({1: self._shots})), + ({param: [np.pi]}, np.array({1: self._shots})), + ({"x": np.array([np.pi])}, np.array({1: self._shots})), + ({param: np.array([np.pi])}, np.array({1: self._shots})), + ] + for param, target in param_target: + with self.subTest(f"{circuit.name} w/ {param}"): + result = sampler.run([(circuit, param)], shots=self._shots).result() + self.assertEqual(len(result), 1) + self._assert_allclose(result[0].data.c, target) + + with self.subTest("More than one parameter"): + circuit, param, target = self._cases[3] + circuit = pm.run(circuit) + param_target = [ + (param, np.array(target)), + (tuple(param), np.array(target)), + (np.array(param), np.array(target)), + ((param,), np.array([target])), + ([param], np.array([target])), + (np.array([param]), np.array([target])), + ] + for param, target in param_target: + with self.subTest(f"{circuit.name} w/ {param}"): + result = sampler.run([(circuit, param)], shots=self._shots).result() + self.assertEqual(len(result), 1) + self._assert_allclose(result[0].data.meas, target) + + @combine(backend=BACKENDS_V2) def test_run_reverse_meas_order(self, backend): """test for sampler with reverse measurement order""" x = Parameter("x") @@ -305,7 +523,39 @@ def test_run_reverse_meas_order(self, backend): # qc({x: pi/2, y: 0}) self._assert_allclose(result[1].data.c, np.array({1: self._shots / 2, 5: self._shots / 2})) - @combine(backend=BACKENDS) + @combine(backend=BACKENDS_V1) + def test_run_reverse_meas_order_v1(self, backend): + """test for sampler with reverse measurement order""" + x = Parameter("x") + y = Parameter("y") + + qc = QuantumCircuit(3, 3) + qc.rx(x, 0) + qc.rx(y, 1) + qc.x(2) + qc.measure(0, 2) + qc.measure(1, 1) + qc.measure(2, 0) + with self.assertWarnsRegex( + DeprecationWarning, + expected_regex="The `generate_preset_pass_manager` function will " + "stop supporting inputs of type `BackendV1`", + ): + pm = generate_preset_pass_manager(optimization_level=0, backend=backend) + qc = pm.run(qc) + + sampler = BackendSamplerV2(backend=backend) + sampler.options.seed_simulator = self._seed + result = sampler.run([(qc, [0, 0]), (qc, [np.pi / 2, 0])], shots=self._shots).result() + self.assertEqual(len(result), 2) + + # qc({x: 0, y: 0}) + self._assert_allclose(result[0].data.c, np.array({1: self._shots})) + + # qc({x: pi/2, y: 0}) + self._assert_allclose(result[1].data.c, np.array({1: self._shots / 2, 5: self._shots / 2})) + + @combine(backend=BACKENDS_V2) def test_run_errors(self, backend): """Test for errors with run method""" qc1 = QuantumCircuit(1) @@ -357,7 +607,64 @@ def test_run_errors(self, backend): with self.assertRaisesRegex(ValueError, "Note that if you want to run a single pub,"): _ = sampler.run((qc2, [0, 1])).result() - @combine(backend=BACKENDS) + @combine(backend=BACKENDS_V1) + def test_run_errors_v1(self, backend): + """Test for errors with run method""" + qc1 = QuantumCircuit(1) + qc1.measure_all() + qc2 = RealAmplitudes(num_qubits=1, reps=1) + qc2.measure_all() + with self.assertWarnsRegex( + DeprecationWarning, + expected_regex="The `generate_preset_pass_manager` function will " + "stop supporting inputs of type `BackendV1`", + ): + pm = generate_preset_pass_manager(optimization_level=0, backend=backend) + qc1, qc2 = pm.run([qc1, qc2]) + + sampler = BackendSamplerV2(backend=backend) + with self.subTest("set parameter values to a non-parameterized circuit"): + with self.assertRaises(ValueError): + _ = sampler.run([(qc1, [1e2])]).result() + with self.subTest("missing all parameter values for a parameterized circuit"): + with self.assertRaises(ValueError): + _ = sampler.run([qc2]).result() + with self.assertRaises(ValueError): + _ = sampler.run([(qc2, [])]).result() + with self.assertRaises(ValueError): + _ = sampler.run([(qc2, None)]).result() + with self.subTest("missing some parameter values for a parameterized circuit"): + with self.assertRaises(ValueError): + _ = sampler.run([(qc2, [1e2])]).result() + with self.subTest("too many parameter values for a parameterized circuit"): + with self.assertRaises(ValueError): + _ = sampler.run([(qc2, [1e2] * 100)]).result() + with self.subTest("negative shots, run arg"): + with self.assertRaises(ValueError): + _ = sampler.run([qc1], shots=-1).result() + with self.subTest("negative shots, pub-like"): + with self.assertRaises(ValueError): + _ = sampler.run([(qc1, None, -1)]).result() + with self.subTest("negative shots, pub"): + with self.assertRaises(ValueError): + _ = sampler.run([SamplerPub(qc1, shots=-1)]).result() + with self.subTest("zero shots, run arg"): + with self.assertRaises(ValueError): + _ = sampler.run([qc1], shots=0).result() + with self.subTest("zero shots, pub-like"): + with self.assertRaises(ValueError): + _ = sampler.run([(qc1, None, 0)]).result() + with self.subTest("zero shots, pub"): + with self.assertRaises(ValueError): + _ = sampler.run([SamplerPub(qc1, shots=0)]).result() + with self.subTest("missing []"): + with self.assertRaisesRegex(ValueError, "An invalid Sampler pub-like was given"): + _ = sampler.run(qc1).result() + with self.subTest("missing [] for pqc"): + with self.assertRaisesRegex(ValueError, "Note that if you want to run a single pub,"): + _ = sampler.run((qc2, [0, 1])).result() + + @combine(backend=BACKENDS_V2) def test_run_empty_parameter(self, backend): """Test for empty parameter""" n = 5 @@ -377,17 +684,42 @@ def test_run_empty_parameter(self, backend): for i in range(2): self._assert_allclose(result[i].data.c, np.array({0: self._shots})) - @combine(backend=BACKENDS) - def test_run_numpy_params(self, backend): - """Test for numpy array as parameter values""" - qc = RealAmplitudes(num_qubits=2, reps=2) - qc.measure_all() - pm = generate_preset_pass_manager(optimization_level=0, backend=backend) + @combine(backend=BACKENDS_V1) + def test_run_empty_parameter_v1(self, backend): + """Test for empty parameter""" + n = 5 + qc = QuantumCircuit(n, n - 1) + qc.measure(range(n - 1), range(n - 1)) + with self.assertWarnsRegex( + DeprecationWarning, + expected_regex="The `generate_preset_pass_manager` function will " + "stop supporting inputs of type `BackendV1`", + ): + pm = generate_preset_pass_manager(optimization_level=0, backend=backend) qc = pm.run(qc) - k = 5 - params_array = np.linspace(0, 1, k * qc.num_parameters).reshape((k, qc.num_parameters)) - params_list = params_array.tolist() - sampler = StatevectorSampler(seed=self._seed) + sampler = BackendSamplerV2(backend=backend, options=self._options) + with self.subTest("one circuit"): + result = sampler.run([qc], shots=self._shots).result() + self.assertEqual(len(result), 1) + self._assert_allclose(result[0].data.c, np.array({0: self._shots})) + + with self.subTest("two circuits"): + result = sampler.run([qc, qc], shots=self._shots).result() + self.assertEqual(len(result), 2) + for i in range(2): + self._assert_allclose(result[i].data.c, np.array({0: self._shots})) + + @combine(backend=BACKENDS_V2) + def test_run_numpy_params(self, backend): + """Test for numpy array as parameter values""" + qc = RealAmplitudes(num_qubits=2, reps=2) + qc.measure_all() + pm = generate_preset_pass_manager(optimization_level=0, backend=backend) + qc = pm.run(qc) + k = 5 + params_array = np.linspace(0, 1, k * qc.num_parameters).reshape((k, qc.num_parameters)) + params_list = params_array.tolist() + sampler = StatevectorSampler(seed=self._seed) target = sampler.run([(qc, params_list)], shots=self._shots).result() with self.subTest("ndarray"): @@ -407,7 +739,42 @@ def test_run_numpy_params(self, backend): result[i].data.meas, np.array(target[0].data.meas.get_int_counts(i)) ) - @combine(backend=BACKENDS) + @combine(backend=BACKENDS_V1) + def test_run_numpy_params_v1(self, backend): + """Test for numpy array as parameter values""" + qc = RealAmplitudes(num_qubits=2, reps=2) + qc.measure_all() + with self.assertWarnsRegex( + DeprecationWarning, + expected_regex="The `generate_preset_pass_manager` function will " + "stop supporting inputs of type `BackendV1`", + ): + pm = generate_preset_pass_manager(optimization_level=0, backend=backend) + qc = pm.run(qc) + k = 5 + params_array = np.linspace(0, 1, k * qc.num_parameters).reshape((k, qc.num_parameters)) + params_list = params_array.tolist() + sampler = StatevectorSampler(seed=self._seed) + target = sampler.run([(qc, params_list)], shots=self._shots).result() + + with self.subTest("ndarray"): + sampler = BackendSamplerV2(backend=backend, options=self._options) + result = sampler.run([(qc, params_array)], shots=self._shots).result() + self.assertEqual(len(result), 1) + self._assert_allclose(result[0].data.meas, target[0].data.meas) + + with self.subTest("split a list"): + sampler = BackendSamplerV2(backend=backend, options=self._options) + result = sampler.run( + [(qc, params) for params in params_list], shots=self._shots + ).result() + self.assertEqual(len(result), k) + for i in range(k): + self._assert_allclose( + result[i].data.meas, np.array(target[0].data.meas.get_int_counts(i)) + ) + + @combine(backend=BACKENDS_V2) def test_run_with_shots_option(self, backend): """test with shots option.""" bell, _, _ = self._cases[1] @@ -471,7 +838,76 @@ def test_run_with_shots_option(self, backend): self.assertEqual(result[1].data.meas.num_shots, shots2) self.assertEqual(sum(result[1].data.meas.get_counts().values()), shots2) - @combine(backend=BACKENDS) + @combine(backend=BACKENDS_V1) + def test_run_with_shots_option_v1(self, backend): + """test with shots option.""" + bell, _, _ = self._cases[1] + with self.assertWarnsRegex( + DeprecationWarning, + expected_regex="The `generate_preset_pass_manager` function will " + "stop supporting inputs of type `BackendV1`", + ): + pm = generate_preset_pass_manager(optimization_level=0, backend=backend) + bell = pm.run(bell) + shots = 100 + + with self.subTest("run arg"): + sampler = BackendSamplerV2(backend=backend, options=self._options) + result = sampler.run([bell], shots=shots).result() + self.assertEqual(len(result), 1) + self.assertEqual(result[0].data.meas.num_shots, shots) + self.assertEqual(sum(result[0].data.meas.get_counts().values()), shots) + + with self.subTest("default shots"): + sampler = BackendSamplerV2(backend=backend, options=self._options) + default_shots = sampler.options.default_shots + result = sampler.run([bell]).result() + self.assertEqual(len(result), 1) + self.assertEqual(result[0].data.meas.num_shots, default_shots) + self.assertEqual(sum(result[0].data.meas.get_counts().values()), default_shots) + + with self.subTest("setting default shots"): + default_shots = 100 + sampler = BackendSamplerV2(backend=backend, options=self._options) + sampler.options.default_shots = default_shots + self.assertEqual(sampler.options.default_shots, default_shots) + result = sampler.run([bell]).result() + self.assertEqual(len(result), 1) + self.assertEqual(result[0].data.meas.num_shots, default_shots) + self.assertEqual(sum(result[0].data.meas.get_counts().values()), default_shots) + + with self.subTest("pub-like"): + sampler = BackendSamplerV2(backend=backend, options=self._options) + result = sampler.run([(bell, None, shots)]).result() + self.assertEqual(len(result), 1) + self.assertEqual(result[0].data.meas.num_shots, shots) + self.assertEqual(sum(result[0].data.meas.get_counts().values()), shots) + + with self.subTest("pub"): + sampler = BackendSamplerV2(backend=backend, options=self._options) + result = sampler.run([SamplerPub(bell, shots=shots)]).result() + self.assertEqual(len(result), 1) + self.assertEqual(result[0].data.meas.num_shots, shots) + self.assertEqual(sum(result[0].data.meas.get_counts().values()), shots) + + with self.subTest("multiple pubs"): + sampler = BackendSamplerV2(backend=backend, options=self._options) + shots1 = 100 + shots2 = 200 + result = sampler.run( + [ + SamplerPub(bell, shots=shots1), + SamplerPub(bell, shots=shots2), + ], + shots=self._shots, + ).result() + self.assertEqual(len(result), 2) + self.assertEqual(result[0].data.meas.num_shots, shots1) + self.assertEqual(sum(result[0].data.meas.get_counts().values()), shots1) + self.assertEqual(result[1].data.meas.num_shots, shots2) + self.assertEqual(sum(result[1].data.meas.get_counts().values()), shots2) + + @combine(backend=BACKENDS_V2) def test_run_shots_result_size(self, backend): """test with shots option to validate the result size""" n = 7 # should be less than or equal to the number of qubits of backend @@ -486,7 +922,27 @@ def test_run_shots_result_size(self, backend): self.assertLessEqual(result[0].data.meas.num_shots, self._shots) self.assertEqual(sum(result[0].data.meas.get_counts().values()), self._shots) - @combine(backend=BACKENDS) + @combine(backend=BACKENDS_V1) + def test_run_shots_result_size_v1(self, backend): + """test with shots option to validate the result size""" + n = 7 # should be less than or equal to the number of qubits of backend + qc = QuantumCircuit(n) + qc.h(range(n)) + qc.measure_all() + with self.assertWarnsRegex( + DeprecationWarning, + expected_regex="The `generate_preset_pass_manager` function will " + "stop supporting inputs of type `BackendV1`", + ): + pm = generate_preset_pass_manager(optimization_level=0, backend=backend) + qc = pm.run(qc) + sampler = BackendSamplerV2(backend=backend, options=self._options) + result = sampler.run([qc], shots=self._shots).result() + self.assertEqual(len(result), 1) + self.assertLessEqual(result[0].data.meas.num_shots, self._shots) + self.assertEqual(sum(result[0].data.meas.get_counts().values()), self._shots) + + @combine(backend=BACKENDS_V2) def test_primitive_job_status_done(self, backend): """test primitive job's status""" bell, _, _ = self._cases[1] @@ -497,7 +953,23 @@ def test_primitive_job_status_done(self, backend): _ = job.result() self.assertEqual(job.status(), JobStatus.DONE) - @combine(backend=BACKENDS) + @combine(backend=BACKENDS_V1) + def test_primitive_job_status_done_v1(self, backend): + """test primitive job's status""" + bell, _, _ = self._cases[1] + with self.assertWarnsRegex( + DeprecationWarning, + expected_regex="The `generate_preset_pass_manager` function will " + "stop supporting inputs of type `BackendV1`", + ): + pm = generate_preset_pass_manager(optimization_level=0, backend=backend) + bell = pm.run(bell) + sampler = BackendSamplerV2(backend=backend, options=self._options) + job = sampler.run([bell], shots=self._shots) + _ = job.result() + self.assertEqual(job.status(), JobStatus.DONE) + + @combine(backend=BACKENDS_V2) def test_circuit_with_unitary(self, backend): """Test for circuit with unitary gate.""" pm = generate_preset_pass_manager(optimization_level=0, backend=backend) @@ -528,7 +1000,43 @@ def test_circuit_with_unitary(self, backend): self.assertEqual(len(result), 1) self._assert_allclose(result[0].data.meas, np.array({1: self._shots})) - @combine(backend=BACKENDS) + @combine(backend=BACKENDS_V1) + def test_circuit_with_unitary_v1(self, backend): + """Test for circuit with unitary gate.""" + with self.assertWarnsRegex( + DeprecationWarning, + expected_regex="The `generate_preset_pass_manager` function will " + "stop supporting inputs of type `BackendV1`", + ): + pm = generate_preset_pass_manager(optimization_level=0, backend=backend) + + with self.subTest("identity"): + gate = UnitaryGate(np.eye(2)) + + circuit = QuantumCircuit(1) + circuit.append(gate, [0]) + circuit.measure_all() + circuit = pm.run(circuit) + + sampler = BackendSamplerV2(backend=backend, options=self._options) + result = sampler.run([circuit], shots=self._shots).result() + self.assertEqual(len(result), 1) + self._assert_allclose(result[0].data.meas, np.array({0: self._shots})) + + with self.subTest("X"): + gate = UnitaryGate([[0, 1], [1, 0]]) + + circuit = QuantumCircuit(1) + circuit.append(gate, [0]) + circuit.measure_all() + circuit = pm.run(circuit) + + sampler = BackendSamplerV2(backend=backend, options=self._options) + result = sampler.run([circuit], shots=self._shots).result() + self.assertEqual(len(result), 1) + self._assert_allclose(result[0].data.meas, np.array({1: self._shots})) + + @combine(backend=BACKENDS_V2) def test_circuit_with_multiple_cregs(self, backend): """Test for circuit with multiple classical registers.""" pm = generate_preset_pass_manager(optimization_level=0, backend=backend) @@ -608,7 +1116,92 @@ def test_circuit_with_multiple_cregs(self, backend): self.assertTrue(hasattr(data, creg.name)) self._assert_allclose(getattr(data, creg.name), np.array(target[creg.name])) - @combine(backend=BACKENDS) + @combine(backend=BACKENDS_V1) + def test_circuit_with_multiple_cregs_v1(self, backend): + """Test for circuit with multiple classical registers.""" + with self.assertWarnsRegex( + DeprecationWarning, + expected_regex="The `generate_preset_pass_manager` function will " + "stop supporting inputs of type `BackendV1`", + ): + pm = generate_preset_pass_manager(optimization_level=0, backend=backend) + cases = [] + + # case 1 + a = ClassicalRegister(1, "a") + b = ClassicalRegister(2, "b") + c = ClassicalRegister(3, "c") + + qc = QuantumCircuit(QuantumRegister(3), a, b, c) + qc.h(range(3)) + qc.measure([0, 1, 2, 2], [0, 2, 4, 5]) + qc = pm.run(qc) + target = {"a": {0: 5000, 1: 5000}, "b": {0: 5000, 2: 5000}, "c": {0: 5000, 6: 5000}} + cases.append(("use all cregs", qc, target)) + + # case 2 + a = ClassicalRegister(1, "a") + b = ClassicalRegister(5, "b") + c = ClassicalRegister(3, "c") + + qc = QuantumCircuit(QuantumRegister(3), a, b, c) + qc.h(range(3)) + qc.measure([0, 1, 2, 2], [0, 2, 4, 5]) + qc = pm.run(qc) + target = { + "a": {0: 5000, 1: 5000}, + "b": {0: 2500, 2: 2500, 24: 2500, 26: 2500}, + "c": {0: 10000}, + } + cases.append(("use only a and b", qc, target)) + + # case 3 + a = ClassicalRegister(1, "a") + b = ClassicalRegister(2, "b") + c = ClassicalRegister(3, "c") + + qc = QuantumCircuit(QuantumRegister(3), a, b, c) + qc.h(range(3)) + qc.measure(1, 5) + qc = pm.run(qc) + target = {"a": {0: 10000}, "b": {0: 10000}, "c": {0: 5000, 4: 5000}} + cases.append(("use only c", qc, target)) + + # case 4 + a = ClassicalRegister(1, "a") + b = ClassicalRegister(2, "b") + c = ClassicalRegister(3, "c") + + qc = QuantumCircuit(QuantumRegister(3), a, b, c) + qc.h(range(3)) + qc.measure([0, 1, 2], [5, 5, 5]) + qc = pm.run(qc) + target = {"a": {0: 10000}, "b": {0: 10000}, "c": {0: 5000, 4: 5000}} + cases.append(("use only c multiple qubits", qc, target)) + + # case 5 + a = ClassicalRegister(1, "a") + b = ClassicalRegister(2, "b") + c = ClassicalRegister(3, "c") + + qc = QuantumCircuit(QuantumRegister(3), a, b, c) + qc.h(range(3)) + qc = pm.run(qc) + target = {"a": {0: 10000}, "b": {0: 10000}, "c": {0: 10000}} + cases.append(("no measure", qc, target)) + + for title, qc, target in cases: + with self.subTest(title): + sampler = BackendSamplerV2(backend=backend, options=self._options) + result = sampler.run([qc], shots=self._shots).result() + self.assertEqual(len(result), 1) + data = result[0].data + self.assertEqual(len(data), 3) + for creg in qc.cregs: + self.assertTrue(hasattr(data, creg.name)) + self._assert_allclose(getattr(data, creg.name), np.array(target[creg.name])) + + @combine(backend=BACKENDS_V2) def test_circuit_with_aliased_cregs(self, backend): """Test for circuit with aliased classical registers.""" q = QuantumRegister(3, "q") @@ -644,6 +1237,47 @@ def test_circuit_with_aliased_cregs(self, backend): self.assertTrue(hasattr(data, creg_name)) self._assert_allclose(getattr(data, creg_name), np.array(creg)) + @combine(backend=BACKENDS_V1) + def test_circuit_with_aliased_cregs_v1(self, backend): + """Test for circuit with aliased classical registers.""" + q = QuantumRegister(3, "q") + c1 = ClassicalRegister(1, "c1") + c2 = ClassicalRegister(1, "c2") + + qc = QuantumCircuit(q, c1, c2) + qc.ry(np.pi / 4, 2) + qc.cx(2, 1) + qc.cx(0, 1) + qc.h(0) + qc.measure(0, c1) + qc.measure(1, c2) + qc.z(2).c_if(c1, 1) + qc.x(2).c_if(c2, 1) + qc2 = QuantumCircuit(5, 5) + qc2.compose(qc, [0, 2, 3], [2, 4], inplace=True) + cregs = [creg.name for creg in qc2.cregs] + target = { + cregs[0]: {0: 4255, 4: 4297, 16: 720, 20: 726}, + cregs[1]: {0: 5000, 1: 5000}, + cregs[2]: {0: 8500, 1: 1500}, + } + + sampler = BackendSamplerV2(backend=backend, options=self._options) + with self.assertWarnsRegex( + DeprecationWarning, + expected_regex="The `generate_preset_pass_manager` function will " + "stop supporting inputs of type `BackendV1`", + ): + pm = generate_preset_pass_manager(optimization_level=0, backend=backend) + qc2 = pm.run(qc2) + result = sampler.run([qc2], shots=self._shots).result() + self.assertEqual(len(result), 1) + data = result[0].data + self.assertEqual(len(data), 3) + for creg_name, creg in target.items(): + self.assertTrue(hasattr(data, creg_name)) + self._assert_allclose(getattr(data, creg_name), np.array(creg)) + @combine(backend=BACKENDS) def test_no_cregs(self, backend): """Test that the sampler works when there are no classical register in the circuit.""" @@ -670,7 +1304,7 @@ def test_empty_creg(self, backend): result = sampler.run([qc], shots=self._shots).result() self.assertEqual(result[0].data.c1.array.shape, (self._shots, 0)) - @combine(backend=BACKENDS) + @combine(backend=BACKENDS_V2) def test_diff_shots(self, backend): """Test of pubs with different shots""" pm = generate_preset_pass_manager(optimization_level=0, backend=backend) @@ -688,6 +1322,29 @@ def test_diff_shots(self, backend): self.assertEqual(result[1].data.meas.num_shots, shots2) self._assert_allclose(result[1].data.meas, np.array(target2)) + @combine(backend=BACKENDS_V1) + def test_diff_shots_v1(self, backend): + """Test of pubs with different shots""" + with self.assertWarnsRegex( + DeprecationWarning, + expected_regex="The `generate_preset_pass_manager` function will " + "stop supporting inputs of type `BackendV1`", + ): + pm = generate_preset_pass_manager(optimization_level=0, backend=backend) + + bell, _, target = self._cases[1] + bell = pm.run(bell) + sampler = BackendSamplerV2(backend=backend, options=self._options) + shots2 = self._shots + 2 + target2 = {k: v + 1 for k, v in target.items()} + job = sampler.run([(bell, None, self._shots), (bell, None, shots2)]) + result = job.result() + self.assertEqual(len(result), 2) + self.assertEqual(result[0].data.meas.num_shots, self._shots) + self._assert_allclose(result[0].data.meas, np.array(target)) + self.assertEqual(result[1].data.meas.num_shots, shots2) + self._assert_allclose(result[1].data.meas, np.array(target2)) + def test_job_size_limit_backend_v2(self): """Test BackendSamplerV2 respects backend's job size limit.""" diff --git a/test/python/providers/test_fake_backends.py b/test/python/providers/test_fake_backends.py index d743c4be5c53..6d8716359bcc 100644 --- a/test/python/providers/test_fake_backends.py +++ b/test/python/providers/test_fake_backends.py @@ -130,12 +130,15 @@ def test_circuit_on_fake_backend(self, backend, optimization_level): self.skipTest( f"Unable to run fake_backend {backend.configuration().backend_name} without qiskit-aer" ) - job = backend.run( - transpile( + with self.assertWarnsRegex( + DeprecationWarning, + expected_regex="The `transpile` function will " + "stop supporting inputs of type `BackendV1`", + ): + transpiled = transpile( self.circuit, backend, seed_transpiler=42, optimization_level=optimization_level - ), - seed_simulator=42, - ) + ) + job = backend.run(transpiled, seed_simulator=42) result = job.result() counts = result.get_counts() max_count = max(counts.items(), key=operator.itemgetter(1))[0] @@ -143,15 +146,18 @@ def test_circuit_on_fake_backend(self, backend, optimization_level): def test_qobj_failure(self): backend = BACKENDS[-1] - tqc = transpile(self.circuit, backend) with self.assertWarns(DeprecationWarning): + tqc = transpile(self.circuit, backend) qobj = assemble(tqc, backend) with self.assertRaises(QiskitError): backend.run(qobj) @data(*BACKENDS) def test_to_dict_properties(self, backend): - properties = backend.properties() + with warnings.catch_warnings(): + # The class QobjExperimentHeader is deprecated + warnings.filterwarnings("ignore", category=DeprecationWarning, module="qiskit") + properties = backend.properties() if properties: self.assertIsInstance(backend.properties().to_dict(), dict) else: @@ -220,7 +226,12 @@ def test_delay_circuit(self): qc.x(1) qc.delay(250, 1, unit="ns") qc.measure_all() - res = transpile(qc, backend) + with self.assertWarnsRegex( + DeprecationWarning, + expected_regex="The `transpile` function will " + "stop supporting inputs of type `BackendV1`", + ): + res = transpile(qc, backend) self.assertIn("delay", res.count_ops()) @data(0, 1, 2, 3) @@ -529,10 +540,10 @@ def test_filter_faulty_qubits_backend_v2_converter(self): """Test faulty qubits in v2 conversion.""" with self.assertWarns(DeprecationWarning): backend = Fake127QPulseV1() - # Get properties dict to make it easier to work with the properties API - # is difficult to edit because of the multiple layers of nesting and - # different object types - props_dict = backend.properties().to_dict() + # Get properties dict to make it easier to work with the properties API + # is difficult to edit because of the multiple layers of nesting and + # different object types + props_dict = backend.properties().to_dict() for i in range(62, 67): non_operational = { "date": datetime.datetime.now(datetime.timezone.utc), @@ -541,7 +552,8 @@ def test_filter_faulty_qubits_backend_v2_converter(self): "value": 0, } props_dict["qubits"][i].append(non_operational) - backend._properties = BackendProperties.from_dict(props_dict) + with self.assertWarns(DeprecationWarning): + backend._properties = BackendProperties.from_dict(props_dict) v2_backend = BackendV2Converter(backend, filter_faulty=True) for i in range(62, 67): for qarg in v2_backend.target.qargs: @@ -551,10 +563,10 @@ def test_filter_faulty_qubits_backend_v2_converter_with_delay(self): """Test faulty qubits in v2 conversion.""" with self.assertWarns(DeprecationWarning): backend = Fake127QPulseV1() - # Get properties dict to make it easier to work with the properties API - # is difficult to edit because of the multiple layers of nesting and - # different object types - props_dict = backend.properties().to_dict() + # Get properties dict to make it easier to work with the properties API + # is difficult to edit because of the multiple layers of nesting and + # different object types + props_dict = backend.properties().to_dict() for i in range(62, 67): non_operational = { "date": datetime.datetime.now(datetime.timezone.utc), @@ -563,7 +575,8 @@ def test_filter_faulty_qubits_backend_v2_converter_with_delay(self): "value": 0, } props_dict["qubits"][i].append(non_operational) - backend._properties = BackendProperties.from_dict(props_dict) + with self.assertWarns(DeprecationWarning): + backend._properties = BackendProperties.from_dict(props_dict) v2_backend = BackendV2Converter(backend, filter_faulty=True, add_delay=True) for i in range(62, 67): for qarg in v2_backend.target.qargs: @@ -602,9 +615,9 @@ def test_backend_v2_converter_with_meaningless_gate_config(self): """Test backend with broken gate config can be converted only with properties data.""" with self.assertWarns(DeprecationWarning): backend_v1 = Fake5QV1() - backend_v1.configuration().gates = [ - GateConfig(name="NotValidGate", parameters=[], qasm_def="not_valid_gate") - ] + backend_v1.configuration().gates = [ + GateConfig(name="NotValidGate", parameters=[], qasm_def="not_valid_gate") + ] backend_v2 = BackendV2Converter( backend=backend_v1, filter_faulty=True, @@ -620,10 +633,10 @@ def test_filter_faulty_qubits_and_gates_backend_v2_converter(self): """Test faulty gates and qubits.""" with self.assertWarns(DeprecationWarning): backend = Fake127QPulseV1() - # Get properties dict to make it easier to work with the properties API - # is difficult to edit because of the multiple layers of nesting and - # different object types - props_dict = backend.properties().to_dict() + # Get properties dict to make it easier to work with the properties API + # is difficult to edit because of the multiple layers of nesting and + # different object types + props_dict = backend.properties().to_dict() for i in range(62, 67): non_operational = { "date": datetime.datetime.now(datetime.timezone.utc), @@ -652,7 +665,8 @@ def test_filter_faulty_qubits_and_gates_backend_v2_converter(self): if tuple(gate["qubits"]) in invalid_cx_edges: gate["parameters"].append(non_operational_gate) - backend._properties = BackendProperties.from_dict(props_dict) + with self.assertWarns(DeprecationWarning): + backend._properties = BackendProperties.from_dict(props_dict) v2_backend = BackendV2Converter(backend, filter_faulty=True) for i in range(62, 67): for qarg in v2_backend.target.qargs: @@ -688,7 +702,8 @@ def test_filter_faulty_gates_v2_converter(self): if tuple(gate["qubits"]) in invalid_cx_edges: gate["parameters"].append(non_operational_gate) - backend._properties = BackendProperties.from_dict(props_dict) + with self.assertWarns(DeprecationWarning): + backend._properties = BackendProperties.from_dict(props_dict) v2_backend = BackendV2Converter(backend, filter_faulty=True) for i in range(62, 67): self.assertIn((i,), v2_backend.target.qargs) @@ -699,7 +714,7 @@ def test_filter_faulty_no_faults_v2_converter(self): """Test that faulty qubit filtering does nothing with all operational qubits and gates.""" with self.assertWarns(DeprecationWarning): backend = Fake127QPulseV1() - v2_backend = BackendV2Converter(backend, filter_faulty=True) + v2_backend = BackendV2Converter(backend, filter_faulty=True) for i in range(v2_backend.num_qubits): self.assertIn((i,), v2_backend.target.qargs) @@ -707,17 +722,19 @@ def test_filter_faulty_no_faults_v2_converter(self): def test_faulty_full_path_transpile_connected_cmap(self, opt_level): with self.assertWarns(DeprecationWarning): backend = Fake5QV1() + props = backend.properties().to_dict() + non_operational_gate = { "date": datetime.datetime.now(datetime.timezone.utc), "name": "operational", "unit": "", "value": 0, } - props = backend.properties().to_dict() for gate in props["gates"]: if tuple(sorted(gate["qubits"])) == (0, 1): gate["parameters"].append(non_operational_gate) - backend._properties = BackendProperties.from_dict(props) + with self.assertWarns(DeprecationWarning): + backend._properties = BackendProperties.from_dict(props) v2_backend = BackendV2Converter(backend, filter_faulty=True) qc = QuantumCircuit(5) for x, y in itertools.product(range(5), range(5)): diff --git a/test/python/providers/test_faulty_backend.py b/test/python/providers/test_faulty_backend.py index e1a3f9fa179e..bd8db856ec0b 100644 --- a/test/python/providers/test_faulty_backend.py +++ b/test/python/providers/test_faulty_backend.py @@ -26,15 +26,21 @@ class FaultyQubitBackendTestCase(QiskitTestCase): """Test operational-related methods of backend.properties() with Fake7QV1FaultyQ1, which is like Fake7QV1 but with a faulty 1Q""" + # These test can be removed with Fake7QV1FaultyQ1 + backend = Fake7QV1FaultyQ1() def test_operational_false(self): """Test operation status of the qubit. Q1 is non-operational""" - self.assertFalse(self.backend.properties().is_qubit_operational(1)) + with self.assertWarns(DeprecationWarning): + properties = self.backend.properties() + self.assertFalse(properties.is_qubit_operational(1)) def test_faulty_qubits(self): """Test faulty_qubits method.""" - self.assertEqual(self.backend.properties().faulty_qubits(), [1]) + with self.assertWarns(DeprecationWarning): + properties = self.backend.properties() + self.assertEqual(properties.faulty_qubits(), [1]) def test_convert_to_target_with_filter(self): """Test converting legacy data structure to V2 target model with faulty qubits. @@ -43,11 +49,13 @@ def test_convert_to_target_with_filter(self): even though instruction is not provided by the backend, since these are the necessary instructions that the transpiler may assume. """ + with self.assertWarns(DeprecationWarning): + properties = self.backend.properties() # Filter out faulty Q1 target = convert_to_target( configuration=self.backend.configuration(), - properties=self.backend.properties(), + properties=properties, add_delay=True, filter_faulty=True, ) @@ -57,10 +65,13 @@ def test_convert_to_target_with_filter(self): def test_convert_to_target_without_filter(self): """Test converting legacy data structure to V2 target model with faulty qubits.""" + with self.assertWarns(DeprecationWarning): + properties = self.backend.properties() + # Include faulty Q1 even though data could be incomplete target = convert_to_target( configuration=self.backend.configuration(), - properties=self.backend.properties(), + properties=properties, add_delay=True, filter_faulty=False, ) @@ -68,17 +79,20 @@ def test_convert_to_target_without_filter(self): self.assertTrue(target.instruction_supported(operation_name="delay", qargs=(1,))) # Properties are preserved + with self.assertWarns(DeprecationWarning): + properties = self.backend.properties() + self.assertEqual( target.qubit_properties[1].t1, - self.backend.properties().t1(1), + properties.t1(1), ) self.assertEqual( target.qubit_properties[1].t2, - self.backend.properties().t2(1), + properties.t2(1), ) self.assertEqual( target.qubit_properties[1].frequency, - self.backend.properties().frequency(1), + properties.frequency(1), ) @@ -90,12 +104,16 @@ class FaultyGate13BackendTestCase(QiskitTestCase): def test_operational_gate(self): """Test is_gate_operational method.""" - self.assertFalse(self.backend.properties().is_gate_operational("cx", [1, 3])) - self.assertFalse(self.backend.properties().is_gate_operational("cx", [3, 1])) + with self.assertWarns(DeprecationWarning): + properties = self.backend.properties() + self.assertFalse(properties.is_gate_operational("cx", [1, 3])) + self.assertFalse(properties.is_gate_operational("cx", [3, 1])) def test_faulty_gates(self): """Test faulty_gates method.""" - gates = self.backend.properties().faulty_gates() + with self.assertWarns(DeprecationWarning): + properties = self.backend.properties() + gates = properties.faulty_gates() self.assertEqual(len(gates), 2) self.assertEqual([gate.gate for gate in gates], ["cx", "cx"]) self.assertEqual(sorted(gate.qubits for gate in gates), [[1, 3], [3, 1]]) @@ -109,12 +127,16 @@ class FaultyGate01BackendTestCase(QiskitTestCase): def test_operational_gate(self): """Test is_gate_operational method.""" - self.assertFalse(self.backend.properties().is_gate_operational("cx", [0, 1])) - self.assertFalse(self.backend.properties().is_gate_operational("cx", [1, 0])) + with self.assertWarns(DeprecationWarning): + properties = self.backend.properties() + self.assertFalse(properties.is_gate_operational("cx", [0, 1])) + self.assertFalse(properties.is_gate_operational("cx", [1, 0])) def test_faulty_gates(self): """Test faulty_gates method.""" - gates = self.backend.properties().faulty_gates() + with self.assertWarns(DeprecationWarning): + properties = self.backend.properties() + gates = properties.faulty_gates() self.assertEqual(len(gates), 2) self.assertEqual([gate.gate for gate in gates], ["cx", "cx"]) self.assertEqual(sorted(gate.qubits for gate in gates), [[0, 1], [1, 0]]) @@ -129,9 +151,12 @@ class MissingPropertyQubitBackendTestCase(QiskitTestCase): def test_convert_to_target(self): """Test converting legacy data structure to V2 target model with missing qubit property.""" + with self.assertWarns(DeprecationWarning): + properties = self.backend.properties() + target = convert_to_target( configuration=self.backend.configuration(), - properties=self.backend.properties(), + properties=properties, add_delay=True, filter_faulty=True, ) @@ -139,9 +164,9 @@ def test_convert_to_target(self): self.assertIsNone(target.qubit_properties[1].t1) self.assertEqual( target.qubit_properties[1].t2, - self.backend.properties().t2(1), + properties.t2(1), ) self.assertEqual( target.qubit_properties[1].frequency, - self.backend.properties().frequency(1), + properties.frequency(1), ) diff --git a/test/python/pulse/test_builder.py b/test/python/pulse/test_builder.py index 563b83345496..72a6de11ae08 100644 --- a/test/python/pulse/test_builder.py +++ b/test/python/pulse/test_builder.py @@ -766,9 +766,13 @@ def get_sched(qubit_idx: [int], backend): qc = circuit.QuantumCircuit(2) for idx in qubit_idx: qc.append(circuit.library.U2Gate(0, pi / 2), [idx]) - return compiler.schedule( - compiler.transpile(qc, backend=backend, optimization_level=1), backend - ) + with self.assertWarnsRegex( + DeprecationWarning, + expected_regex="The `transpile` function will " + "stop supporting inputs of type `BackendV1`", + ): + transpiled = compiler.transpile(qc, backend=backend, optimization_level=1) + return compiler.schedule(transpiled, backend) with pulse.build(self.backend) as schedule: with pulse.align_sequential(): @@ -788,7 +792,12 @@ def get_sched(qubit_idx: [int], backend): # prepare and schedule circuits that will be used. single_u2_qc = circuit.QuantumCircuit(2) single_u2_qc.append(circuit.library.U2Gate(0, pi / 2), [1]) - single_u2_qc = compiler.transpile(single_u2_qc, self.backend, optimization_level=1) + with self.assertWarnsRegex( + DeprecationWarning, + expected_regex="The `transpile` function will " + "stop supporting inputs of type `BackendV1`", + ): + single_u2_qc = compiler.transpile(single_u2_qc, self.backend, optimization_level=1) single_u2_sched = compiler.schedule(single_u2_qc, self.backend) # sequential context @@ -813,7 +822,12 @@ def get_sched(qubit_idx: [int], backend): triple_u2_qc.append(circuit.library.U2Gate(0, pi / 2), [0]) triple_u2_qc.append(circuit.library.U2Gate(0, pi / 2), [1]) triple_u2_qc.append(circuit.library.U2Gate(0, pi / 2), [0]) - triple_u2_qc = compiler.transpile(triple_u2_qc, self.backend, optimization_level=1) + with self.assertWarnsRegex( + DeprecationWarning, + expected_regex="The `transpile` function will " + "stop supporting inputs of type `BackendV1`", + ): + triple_u2_qc = compiler.transpile(triple_u2_qc, self.backend, optimization_level=1) align_left_reference = compiler.schedule(triple_u2_qc, self.backend, method="alap") # measurement diff --git a/test/python/transpiler/test_calibrationbuilder.py b/test/python/transpiler/test_calibrationbuilder.py index cb7293049ef5..90676a38a586 100644 --- a/test/python/transpiler/test_calibrationbuilder.py +++ b/test/python/transpiler/test_calibrationbuilder.py @@ -267,6 +267,8 @@ def build_reverse( def test_rzx_calibration_cr_pulse_stretch(self, theta: float): """Test that cross resonance pulse durations are computed correctly.""" with self.assertWarns(DeprecationWarning): + # TODO this tests does not work with BackendV2/GenericBackendV2 + # https://github.com/Qiskit/qiskit/issues/12834 backend = Fake27QPulseV1() inst_map = backend.defaults().instruction_schedule_map cr_schedule = inst_map.get("cx", (0, 1)) @@ -514,7 +516,7 @@ def test_raises_error_when_rotation_angle_not_assigned(self): an unassigned Parameter, not a number. The QiskitError occurs while trying to typecast the Parameter into a float. """ - backend = GenericBackendV2(num_qubits=5) + backend = GenericBackendV2(num_qubits=5, seed=42) tp = RXCalibrationBuilder(backend.target) qubits = (0,) rx = RXGate(Parameter("theta")) @@ -526,7 +528,7 @@ def test_raises_error_when_rotation_angle_not_assigned(self): @data(0, np.pi / 3, (2 / 3) * np.pi) def test_pulse_schedule(self, theta: float): """Test that get_calibration() returns a schedule with correct amplitude.""" - backend = GenericBackendV2(num_qubits=5) + backend = GenericBackendV2(num_qubits=5, seed=42) dummy_target = Target() sx_amp, sx_beta, sx_sigma, sx_duration, sx_angle = 0.6, 2, 40, 160, 0.5 with builder.build(backend=backend) as dummy_sx_cal: @@ -577,7 +579,7 @@ def test_with_normalizerxangles(self): ) ism = InstructionScheduleMap() ism.add("sx", (0,), sched) - backend = GenericBackendV2(num_qubits=5, calibrate_instructions=ism) + backend = GenericBackendV2(num_qubits=5, calibrate_instructions=ism, seed=42) # NormalizeRXAngle pass should also be included because it's a required pass. pm = PassManager(RXCalibrationBuilder(backend.target)) diff --git a/test/python/transpiler/test_gates_in_basis_pass.py b/test/python/transpiler/test_gates_in_basis_pass.py index 06ce5e0f6702..0dd5e880e0c0 100644 --- a/test/python/transpiler/test_gates_in_basis_pass.py +++ b/test/python/transpiler/test_gates_in_basis_pass.py @@ -99,7 +99,7 @@ def test_all_gates_in_basis_after_translation(self): def test_all_gates_in_basis_with_target(self): """Test circuit with all gates in basis with target.""" - target = GenericBackendV2(num_qubits=5, basis_gates=["u", "cx"]).target + target = GenericBackendV2(num_qubits=5, basis_gates=["u", "cx"], seed=42).target basis_gates = ["cx", "u"] # not used property_set = {} analysis_pass = GatesInBasis(basis_gates, target=target) @@ -112,7 +112,7 @@ def test_all_gates_in_basis_with_target(self): def test_all_gates_not_in_basis_with_target(self): """Test circuit with not all gates in basis with target.""" - target = GenericBackendV2(num_qubits=5, basis_gates=["u", "cx"]).target + target = GenericBackendV2(num_qubits=5, basis_gates=["u", "cx"], seed=42).target basis_gates = ["cx", "h"] property_set = {} analysis_pass = GatesInBasis(basis_gates, target=target) @@ -125,7 +125,7 @@ def test_all_gates_not_in_basis_with_target(self): def test_all_gates_in_basis_not_on_all_qubits_with_target(self): """Test circuit with gate in global basis but not local basis.""" - target = GenericBackendV2(num_qubits=5, basis_gates=["u", "cx"]).target + target = GenericBackendV2(num_qubits=5, basis_gates=["u", "cx"], seed=42).target basis_gates = ["ecr", "cx", "h"] property_set = {} analysis_pass = GatesInBasis(basis_gates, target=target) @@ -138,7 +138,7 @@ def test_all_gates_in_basis_not_on_all_qubits_with_target(self): def test_all_gates_in_basis_empty_circuit_with_target(self): """Test circuit with no gates with target.""" - target = GenericBackendV2(num_qubits=5, basis_gates=["u", "cx"]).target + target = GenericBackendV2(num_qubits=5, basis_gates=["u", "cx"], seed=42).target basis_gates = ["cx", "u"] property_set = {} analysis_pass = GatesInBasis(basis_gates, target=target) @@ -191,7 +191,7 @@ def test_all_gates_not_in_ideal_sim_target(self): def test_all_gates_in_basis_after_translation_with_target(self): """Test circuit with gates in basis after conditional translation.""" - target = GenericBackendV2(num_qubits=5, basis_gates=["u", "cx"]).target + target = GenericBackendV2(num_qubits=5, basis_gates=["u", "cx"], seed=42).target basis_gates = ["cx", "u"] property_set = {} analysis_pass = GatesInBasis(basis_gates, target) diff --git a/test/python/transpiler/test_passmanager_run.py b/test/python/transpiler/test_passmanager_run.py index 3da6a042564c..96df928c6e21 100644 --- a/test/python/transpiler/test_passmanager_run.py +++ b/test/python/transpiler/test_passmanager_run.py @@ -85,7 +85,10 @@ def test_default_pass_manager_single(self): circuit.cx(qr[2], qr[3]) backend = GenericBackendV2( - num_qubits=20, coupling_map=ALMADEN_CMAP, basis_gates=["id", "u1", "u2", "u3", "cx"] + num_qubits=20, + coupling_map=ALMADEN_CMAP, + basis_gates=["id", "u1", "u2", "u3", "cx"], + seed=42, ) initial_layout = [None, qr[0], qr[1], qr[2], None, qr[3]] @@ -187,7 +190,10 @@ def test_default_pass_manager_two(self): initial_layout = [None, qr[0], qr[1], qr[2], None, qr[3]] backend = GenericBackendV2( - num_qubits=20, coupling_map=coupling_map, basis_gates=["id", "u1", "u2", "u3", "cx"] + num_qubits=20, + coupling_map=coupling_map, + basis_gates=["id", "u1", "u2", "u3", "cx"], + seed=42, ) pass_manager = level_1_pass_manager( diff --git a/test/python/transpiler/test_preset_passmanagers.py b/test/python/transpiler/test_preset_passmanagers.py index 3d11a5d55e93..58f6d35a20d5 100644 --- a/test/python/transpiler/test_preset_passmanagers.py +++ b/test/python/transpiler/test_preset_passmanagers.py @@ -39,7 +39,7 @@ from qiskit.transpiler.preset_passmanagers.builtin_plugins import OptimizationPassManager from test import QiskitTestCase # pylint: disable=wrong-import-order -from ..legacy_cmaps import MELBOURNE_CMAP, RUESCHLIKON_CMAP, LAGOS_CMAP, TOKYO_CMAP +from ..legacy_cmaps import MELBOURNE_CMAP, RUESCHLIKON_CMAP, LAGOS_CMAP, TOKYO_CMAP, BOGOTA_CMAP def mock_get_passmanager_stage( @@ -222,8 +222,12 @@ def test_alignment_constraints_called_with_by_default(self, level): circuit.h(q[0]) circuit.cz(q[0], q[1]) with unittest.mock.patch("qiskit.transpiler.passes.TimeUnitConversion.run") as mock: - with self.assertWarns(DeprecationWarning): - backend = Fake20QV1() + backend = GenericBackendV2( + num_qubits=20, + coupling_map=TOKYO_CMAP, + basis_gates=["id", "u1", "u2", "u3", "cx"], + seed=42, + ) transpile(circuit, backend=backend, optimization_level=level) mock.assert_not_called() @@ -238,15 +242,23 @@ def test_alignment_constraints_called_with_delay_in_circuit(self, level): with unittest.mock.patch( "qiskit.transpiler.passes.TimeUnitConversion.run", return_value=circuit_to_dag(circuit) ) as mock: - with self.assertWarns(DeprecationWarning): - backend = Fake20QV1() + backend = GenericBackendV2( + num_qubits=20, + coupling_map=TOKYO_CMAP, + basis_gates=["id", "u1", "u2", "u3", "cx"], + seed=42, + ) transpile(circuit, backend=backend, optimization_level=level) mock.assert_called_once() def test_unroll_only_if_not_gates_in_basis(self): """Test that the list of passes _unroll only runs if a gate is not in the basis.""" - with self.assertWarns(DeprecationWarning): - qcomp = Fake5QV1() + qcomp = GenericBackendV2( + num_qubits=5, + coupling_map=BOGOTA_CMAP, + basis_gates=["id", "u1", "u2", "u3", "cx"], + seed=42, + ) qv_circuit = QuantumVolume(3) gates_in_basis_true_count = 0 collect_2q_blocks_count = 0 @@ -278,8 +290,18 @@ class TestTranspileLevels(QiskitTestCase): circuit=[emptycircuit, circuit_2532], level=[0, 1, 2, 3], backend=[ - Fake5QV1(), - Fake20QV1(), + GenericBackendV2( + num_qubits=5, + coupling_map=BOGOTA_CMAP, + basis_gates=["id", "u1", "u2", "u3", "cx"], + seed=42, + ), + GenericBackendV2( + num_qubits=20, + coupling_map=TOKYO_CMAP, + basis_gates=["id", "u1", "u2", "u3", "cx"], + seed=42, + ), None, ], dsc="Transpiler {circuit.__name__} on {backend} backend at level {level}", @@ -290,6 +312,28 @@ def test(self, circuit, level, backend): result = transpile(circuit(), backend=backend, optimization_level=level, seed_transpiler=42) self.assertIsInstance(result, QuantumCircuit) + @combine( + circuit=[emptycircuit, circuit_2532], + level=[0, 1, 2, 3], + backend=[ + Fake5QV1(), + Fake20QV1(), + ], + dsc="Transpiler {circuit.__name__} on {backend} backend V1 at level {level}", + name="{circuit.__name__}_{backend}_level{level}", + ) + def test_v1(self, circuit, level, backend): + """All the levels with all the backends""" + with self.assertWarnsRegex( + DeprecationWarning, + expected_regex="The `transpile` function will " + "stop supporting inputs of type `BackendV1`", + ): + result = transpile( + circuit(), backend=backend, optimization_level=level, seed_transpiler=42 + ) + self.assertIsInstance(result, QuantumCircuit) + @ddt class TestPassesInspection(QiskitTestCase): @@ -787,8 +831,12 @@ def test_layout_2503(self, level): 19: ancilla[16], } - with self.assertWarns(DeprecationWarning): - backend = Fake20QV1() + backend = GenericBackendV2( + num_qubits=20, + coupling_map=TOKYO_CMAP, + basis_gates=["id", "u1", "u2", "u3", "cx"], + seed=42, + ) qc_b = transpile(qc, backend, initial_layout=initial_layout, optimization_level=level) self.assertEqual(qc_b._layout.initial_layout._p2v, final_layout) @@ -1044,8 +1092,12 @@ def test_trivial_layout(self, level): expected_layouts = [trivial_layout, trivial_layout] - with self.assertWarns(DeprecationWarning): - backend = Fake20QV1() + backend = GenericBackendV2( + num_qubits=20, + coupling_map=TOKYO_CMAP, + basis_gates=["id", "u1", "u2", "u3", "cx"], + seed=42, + ) result = transpile(qc, backend, optimization_level=level, seed_transpiler=42) self.assertEqual(result._layout.initial_layout._p2v, expected_layouts[level]) @@ -1078,8 +1130,12 @@ def test_initial_layout(self, level): 18: qr[9], } - with self.assertWarns(DeprecationWarning): - backend = Fake20QV1() + backend = GenericBackendV2( + num_qubits=20, + coupling_map=TOKYO_CMAP, + basis_gates=["id", "u1", "u2", "u3", "cx"], + seed=42, + ) result = transpile( qc, backend, optimization_level=level, initial_layout=initial_layout, seed_transpiler=42 ) @@ -1159,8 +1215,12 @@ def test_optimization_condition(self, level): cr = ClassicalRegister(1) qc = QuantumCircuit(qr, cr) qc.cx(0, 1).c_if(cr, 1) - with self.assertWarns(DeprecationWarning): - backend = Fake20QV1() + backend = GenericBackendV2( + num_qubits=20, + coupling_map=TOKYO_CMAP, + basis_gates=["id", "u1", "u2", "u3", "cx"], + seed=42, + ) circ = transpile(qc, backend, optimization_level=level) self.assertIsInstance(circ, QuantumCircuit) @@ -1226,7 +1286,12 @@ def test_with_backend(self, optimization_level): """Test a passmanager is constructed when only a backend and optimization level.""" with self.assertWarns(DeprecationWarning): backend = Fake20QV1() - pm = generate_preset_pass_manager(optimization_level, backend) + with self.assertWarnsRegex( + DeprecationWarning, + expected_regex="The `generate_preset_pass_manager` function will " + "stop supporting inputs of type `BackendV1`", + ): + pm = generate_preset_pass_manager(optimization_level, backend) self.assertIsInstance(pm, PassManager) def test_default_optimization_level(self): @@ -1597,9 +1662,12 @@ def test_invalid_methods_raise_on_control_flow(self, optimization_level): def test_unsupported_basis_gates_raise(self, optimization_level): """Test that trying to transpile a control-flow circuit for a backend that doesn't support the necessary operations in its `basis_gates` will raise a sensible error.""" - with self.assertWarns(DeprecationWarning): - backend = Fake20QV1() - + backend = GenericBackendV2( + num_qubits=20, + coupling_map=TOKYO_CMAP, + basis_gates=["id", "u1", "u2", "u3", "cx"], + seed=42, + ) qc = QuantumCircuit(1, 1) with qc.for_loop((0,)): pass diff --git a/test/python/transpiler/test_pulse_gate_pass.py b/test/python/transpiler/test_pulse_gate_pass.py index 539674609c26..07d6172264d4 100644 --- a/test/python/transpiler/test_pulse_gate_pass.py +++ b/test/python/transpiler/test_pulse_gate_pass.py @@ -57,6 +57,7 @@ def setUp(self): def test_transpile_with_bare_backend(self): """Test transpile without custom calibrations.""" with self.assertWarns(DeprecationWarning): + # TODO Move this test to backendV2 backend = Fake27QPulseV1() # Remove timing constraints to avoid triggering # scheduling passes. @@ -69,7 +70,12 @@ def test_transpile_with_bare_backend(self): qc.sx(1) qc.measure_all() - transpiled_qc = transpile(qc, backend, initial_layout=[0, 1]) + with self.assertWarnsRegex( + DeprecationWarning, + expected_regex="The `transpile` function will " + "stop supporting inputs of type `BackendV1`", + ): + transpiled_qc = transpile(qc, backend, initial_layout=[0, 1]) ref_calibration = {} self.assertDictEqual(transpiled_qc.calibrations, ref_calibration) @@ -78,9 +84,7 @@ def test_transpile_with_backend_target(self): """Test transpile without custom calibrations from target.""" target = GenericBackendV2( - num_qubits=5, - coupling_map=BOGOTA_CMAP, - calibrate_instructions=True, + num_qubits=5, coupling_map=BOGOTA_CMAP, calibrate_instructions=True, seed=42 ).target qc = circuit.QuantumCircuit(2) @@ -98,6 +102,7 @@ def test_transpile_with_backend_target(self): def test_transpile_with_custom_basis_gate(self): """Test transpile with custom calibrations.""" with self.assertWarns(DeprecationWarning): + # TODO Move this test to backendV2 backend = Fake27QPulseV1() backend.defaults().instruction_schedule_map.add("sx", (0,), self.custom_sx_q0) backend.defaults().instruction_schedule_map.add("sx", (1,), self.custom_sx_q1) @@ -112,7 +117,12 @@ def test_transpile_with_custom_basis_gate(self): qc.sx(1) qc.measure_all() - transpiled_qc = transpile(qc, backend, initial_layout=[0, 1]) + with self.assertWarnsRegex( + DeprecationWarning, + expected_regex="The `transpile` function will " + "stop supporting inputs of type `BackendV1`", + ): + transpiled_qc = transpile(qc, backend, initial_layout=[0, 1]) ref_calibration = { "sx": { @@ -156,6 +166,7 @@ def test_transpile_with_custom_basis_gate_in_target(self): def test_transpile_with_instmap(self): """Test providing instruction schedule map.""" with self.assertWarns(DeprecationWarning): + # TODO Move this test to backendV2 backend = Fake27QPulseV1() instmap = backend.defaults().instruction_schedule_map instmap.add("sx", (0,), self.custom_sx_q0) @@ -163,6 +174,7 @@ def test_transpile_with_instmap(self): # Inst map is renewed with self.assertWarns(DeprecationWarning): + # TODO Move this test to backendV2 backend = Fake27QPulseV1() # Remove timing constraints to avoid triggering # scheduling passes. @@ -175,7 +187,12 @@ def test_transpile_with_instmap(self): qc.sx(1) qc.measure_all() - transpiled_qc = transpile(qc, backend, inst_map=instmap, initial_layout=[0, 1]) + with self.assertWarnsRegex( + DeprecationWarning, + expected_regex="The `transpile` function will " + "stop supporting inputs of type `BackendV1`", + ): + transpiled_qc = transpile(qc, backend, inst_map=instmap, initial_layout=[0, 1]) ref_calibration = { "sx": { @@ -188,6 +205,7 @@ def test_transpile_with_instmap(self): def test_transpile_with_custom_gate(self): """Test providing non-basis gate.""" with self.assertWarns(DeprecationWarning): + # TODO Move this test to backendV2 backend = Fake27QPulseV1() backend.defaults().instruction_schedule_map.add( "my_gate", (0,), self.my_gate_q0, arguments=["P0"] @@ -197,9 +215,10 @@ def test_transpile_with_custom_gate(self): ) # Add gate to backend configuration backend.configuration().basis_gates.append("my_gate") - dummy_config = GateConfig( - name="my_gate", parameters=[], qasm_def="", coupling_map=[(0,), (1,)] - ) + with self.assertWarns(DeprecationWarning): + dummy_config = GateConfig( + name="my_gate", parameters=[], qasm_def="", coupling_map=[(0,), (1,)] + ) backend.configuration().gates.append(dummy_config) # Remove timing constraints to avoid triggering # scheduling passes. @@ -209,7 +228,12 @@ def test_transpile_with_custom_gate(self): qc.append(circuit.Gate("my_gate", 1, [1.0]), [0]) qc.append(circuit.Gate("my_gate", 1, [2.0]), [1]) - transpiled_qc = transpile(qc, backend, basis_gates=["my_gate"], initial_layout=[0, 1]) + with self.assertWarnsRegex( + DeprecationWarning, + expected_regex="The `transpile` function will " + "stop supporting inputs of type `BackendV1`", + ): + transpiled_qc = transpile(qc, backend, basis_gates=["my_gate"], initial_layout=[0, 1]) my_gate_q0_1_0 = self.my_gate_q0.assign_parameters({self.sched_param: 1.0}, inplace=False) my_gate_q1_2_0 = self.my_gate_q1.assign_parameters({self.sched_param: 2.0}, inplace=False) @@ -225,13 +249,17 @@ def test_transpile_with_custom_gate(self): def test_transpile_with_parameterized_custom_gate(self): """Test providing non-basis gate, which is kept parameterized throughout transpile.""" with self.assertWarns(DeprecationWarning): + # TODO convert this to BackendV2/Target backend = Fake27QPulseV1() backend.defaults().instruction_schedule_map.add( "my_gate", (0,), self.my_gate_q0, arguments=["P0"] ) # Add gate to backend configuration backend.configuration().basis_gates.append("my_gate") - dummy_config = GateConfig(name="my_gate", parameters=[], qasm_def="", coupling_map=[(0,)]) + with self.assertWarns(DeprecationWarning): + dummy_config = GateConfig( + name="my_gate", parameters=[], qasm_def="", coupling_map=[(0,)] + ) backend.configuration().gates.append(dummy_config) # Remove timing constraints to avoid triggering # scheduling passes. @@ -241,7 +269,12 @@ def test_transpile_with_parameterized_custom_gate(self): qc = circuit.QuantumCircuit(1) qc.append(circuit.Gate("my_gate", 1, [param]), [0]) - transpiled_qc = transpile(qc, backend, basis_gates=["my_gate"], initial_layout=[0]) + with self.assertWarnsRegex( + DeprecationWarning, + expected_regex="The `transpile` function will " + "stop supporting inputs of type `BackendV1`", + ): + transpiled_qc = transpile(qc, backend, basis_gates=["my_gate"], initial_layout=[0]) my_gate_q0_p = self.my_gate_q0.assign_parameters({self.sched_param: param}, inplace=False) @@ -255,13 +288,17 @@ def test_transpile_with_parameterized_custom_gate(self): def test_transpile_with_multiple_circuits(self): """Test transpile with multiple circuits with custom gate.""" with self.assertWarns(DeprecationWarning): + # TODO move this test to backendV2 backend = Fake27QPulseV1() backend.defaults().instruction_schedule_map.add( "my_gate", (0,), self.my_gate_q0, arguments=["P0"] ) # Add gate to backend configuration backend.configuration().basis_gates.append("my_gate") - dummy_config = GateConfig(name="my_gate", parameters=[], qasm_def="", coupling_map=[(0,)]) + with self.assertWarns(DeprecationWarning): + dummy_config = GateConfig( + name="my_gate", parameters=[], qasm_def="", coupling_map=[(0,)] + ) backend.configuration().gates.append(dummy_config) # Remove timing constraints to avoid triggering # scheduling passes. @@ -274,7 +311,12 @@ def test_transpile_with_multiple_circuits(self): qc.append(circuit.Gate("my_gate", 1, [param]), [0]) circs.append(qc) - transpiled_qcs = transpile(circs, backend, basis_gates=["my_gate"], initial_layout=[0]) + with self.assertWarnsRegex( + DeprecationWarning, + expected_regex="The `transpile` function will " + "stop supporting inputs of type `BackendV1`", + ): + transpiled_qcs = transpile(circs, backend, basis_gates=["my_gate"], initial_layout=[0]) for param, transpiled_qc in zip(params, transpiled_qcs): my_gate_q0_x = self.my_gate_q0.assign_parameters( @@ -286,13 +328,17 @@ def test_transpile_with_multiple_circuits(self): def test_multiple_instructions_with_different_parameters(self): """Test adding many instruction with different parameter binding.""" with self.assertWarns(DeprecationWarning): + # TODO Move this test to backendV2 backend = Fake27QPulseV1() backend.defaults().instruction_schedule_map.add( "my_gate", (0,), self.my_gate_q0, arguments=["P0"] ) # Add gate to backend configuration backend.configuration().basis_gates.append("my_gate") - dummy_config = GateConfig(name="my_gate", parameters=[], qasm_def="", coupling_map=[(0,)]) + with self.assertWarns(DeprecationWarning): + dummy_config = GateConfig( + name="my_gate", parameters=[], qasm_def="", coupling_map=[(0,)] + ) backend.configuration().gates.append(dummy_config) # Remove timing constraints to avoid triggering # scheduling passes. @@ -303,7 +349,12 @@ def test_multiple_instructions_with_different_parameters(self): qc.append(circuit.Gate("my_gate", 1, [2.0]), [0]) qc.append(circuit.Gate("my_gate", 1, [3.0]), [0]) - transpiled_qc = transpile(qc, backend, basis_gates=["my_gate"], initial_layout=[0]) + with self.assertWarnsRegex( + DeprecationWarning, + expected_regex="The `transpile` function will " + "stop supporting inputs of type `BackendV1`", + ): + transpiled_qc = transpile(qc, backend, basis_gates=["my_gate"], initial_layout=[0]) my_gate_q0_1_0 = self.my_gate_q0.assign_parameters({self.sched_param: 1.0}, inplace=False) my_gate_q0_2_0 = self.my_gate_q0.assign_parameters({self.sched_param: 2.0}, inplace=False) @@ -321,6 +372,7 @@ def test_multiple_instructions_with_different_parameters(self): def test_transpile_with_different_qubit(self): """Test transpile with qubit without custom gate.""" with self.assertWarns(DeprecationWarning): + # TODO Move this test to backendV2 backend = Fake27QPulseV1() backend.defaults().instruction_schedule_map.add("sx", (0,), self.custom_sx_q0) # Remove timing constraints to avoid triggering @@ -331,7 +383,12 @@ def test_transpile_with_different_qubit(self): qc.sx(0) qc.measure_all() - transpiled_qc = transpile(qc, backend, initial_layout=[3]) + with self.assertWarnsRegex( + DeprecationWarning, + expected_regex="The `transpile` function will " + "stop supporting inputs of type `BackendV1`", + ): + transpiled_qc = transpile(qc, backend, initial_layout=[3]) self.assertDictEqual(transpiled_qc.calibrations, {}) @@ -449,10 +506,7 @@ def test_transpile_with_instmap_with_v2backend_with_custom_gate(self, opt_level) qc.append(gate, [0]) qc.measure_all() - backend = GenericBackendV2( - num_qubits=5, - calibrate_instructions=True, - ) + backend = GenericBackendV2(num_qubits=5, calibrate_instructions=True, seed=42) transpiled_qc = transpile( qc, backend, @@ -475,10 +529,7 @@ def test_transpile_with_instmap_not_mutate_backend(self): This should not override the source object since the same backend may be used for future transpile without intention of instruction overriding. """ - backend = GenericBackendV2( - num_qubits=5, - calibrate_instructions=True, - ) + backend = GenericBackendV2(num_qubits=5, calibrate_instructions=True, seed=42) original_sx0 = backend.target["sx"][(0,)].calibration with self.assertWarns(DeprecationWarning): diff --git a/test/python/transpiler/test_sabre_layout.py b/test/python/transpiler/test_sabre_layout.py index 42ae3691c3ca..5ab8fe5c10b2 100644 --- a/test/python/transpiler/test_sabre_layout.py +++ b/test/python/transpiler/test_sabre_layout.py @@ -24,12 +24,12 @@ from qiskit.transpiler.exceptions import TranspilerError from qiskit.converters import circuit_to_dag from qiskit.compiler.transpiler import transpile -from qiskit.providers.fake_provider import Fake27QPulseV1, GenericBackendV2 +from qiskit.providers.fake_provider import GenericBackendV2 from qiskit.transpiler.passes.layout.sabre_pre_layout import SabrePreLayout from qiskit.transpiler.preset_passmanagers import generate_preset_pass_manager from test import QiskitTestCase # pylint: disable=wrong-import-order -from ..legacy_cmaps import ALMADEN_CMAP +from ..legacy_cmaps import ALMADEN_CMAP, MUMBAI_CMAP class TestSabreLayout(QiskitTestCase): @@ -195,8 +195,12 @@ def test_layout_with_classical_bits(self): rz(0) q4835[1]; """ ) - with self.assertWarns(DeprecationWarning): - backend = Fake27QPulseV1() + backend = GenericBackendV2( + num_qubits=27, + basis_gates=["id", "rz", "sx", "x", "cx", "reset"], + coupling_map=MUMBAI_CMAP, + seed=42, + ) res = transpile( qc, backend, layout_method="sabre", seed_transpiler=1234, optimization_level=1 ) @@ -249,8 +253,12 @@ def test_layout_many_search_trials(self): barrier q18585[5],q18585[2],q18585[8],q18585[3],q18585[6]; """ ) - with self.assertWarns(DeprecationWarning): - backend = Fake27QPulseV1() + backend = GenericBackendV2( + num_qubits=27, + basis_gates=["id", "rz", "sx", "x", "cx", "reset"], + coupling_map=MUMBAI_CMAP, + seed=42, + ) res = transpile( qc, backend, diff --git a/test/python/transpiler/test_sabre_swap.py b/test/python/transpiler/test_sabre_swap.py index 6650ca27c6f4..856b5ff09f5b 100644 --- a/test/python/transpiler/test_sabre_swap.py +++ b/test/python/transpiler/test_sabre_swap.py @@ -1393,7 +1393,7 @@ def test_random_circuit_no_control_flow_target(self, size): routing_method="sabre", layout_method="sabre", seed_transpiler=12342, - target=GenericBackendV2(num_qubits=27, coupling_map=MUMBAI_CMAP).target, + target=GenericBackendV2(num_qubits=27, coupling_map=MUMBAI_CMAP, seed=42).target, ) self.assert_valid_circuit(tqc) diff --git a/test/python/transpiler/test_unitary_synthesis.py b/test/python/transpiler/test_unitary_synthesis.py index 43acd4ef67af..4abf6511d8d2 100644 --- a/test/python/transpiler/test_unitary_synthesis.py +++ b/test/python/transpiler/test_unitary_synthesis.py @@ -65,6 +65,7 @@ from test.python.providers.fake_mumbai_v2 import ( # pylint: disable=wrong-import-order FakeMumbaiFractionalCX, ) +from ..legacy_cmaps import YORKTOWN_CMAP class FakeBackend2QV2(GenericBackendV2): @@ -674,8 +675,14 @@ def test_coupling_map_unequal_durations(self, opt): qr = QuantumRegister(2) circ = QuantumCircuit(qr) circ.append(random_unitary(4, seed=1), [1, 0]) - with self.assertWarns(DeprecationWarning): - backend = Fake5QV1() + backend = GenericBackendV2( + num_qubits=5, + coupling_map=YORKTOWN_CMAP, + basis_gates=["id", "rz", "sx", "x", "cx", "reset"], + calibrate_instructions=True, + pulse_channels=True, + seed=42, + ) tqc = transpile( circ, backend=backend, @@ -687,7 +694,7 @@ def test_coupling_map_unequal_durations(self, opt): self.assertTrue( all( ( - (0, 1) == (tqc_index[instr.qubits[0]], tqc_index[instr.qubits[1]]) + (1, 0) == (tqc_index[instr.qubits[0]], tqc_index[instr.qubits[1]]) for instr in tqc.get_instructions("cx") ) ) @@ -908,7 +915,7 @@ def test_single_qubit_with_target(self): qc = QuantumCircuit(1) qc.append(ZGate(), [qc.qubits[0]]) dag = circuit_to_dag(qc) - backend = GenericBackendV2(num_qubits=5) + backend = GenericBackendV2(num_qubits=5, seed=42) unitary_synth_pass = UnitarySynthesis(target=backend.target) result_dag = unitary_synth_pass.run(dag) result_qc = dag_to_circuit(result_dag) diff --git a/test/python/transpiler/test_vf2_post_layout.py b/test/python/transpiler/test_vf2_post_layout.py index e97ed279a8d8..5acdd3ba6ebc 100644 --- a/test/python/transpiler/test_vf2_post_layout.py +++ b/test/python/transpiler/test_vf2_post_layout.py @@ -26,7 +26,7 @@ from qiskit.transpiler.target import Target, InstructionProperties from test import QiskitTestCase # pylint: disable=wrong-import-order -from ..legacy_cmaps import LIMA_CMAP, YORKTOWN_CMAP +from ..legacy_cmaps import LIMA_CMAP, YORKTOWN_CMAP, BOGOTA_CMAP class TestVF2PostLayout(QiskitTestCase): @@ -183,29 +183,6 @@ def test_skip_3q_circuit_control_flow_v2(self): vf2_pass.property_set["VF2PostLayout_stop_reason"], VF2PostLayoutStopReason.MORE_THAN_2Q ) - def test_best_mapping_ghz_state_full_device_multiple_qregs(self): - """Test best mappings with multiple registers""" - with self.assertWarns(DeprecationWarning): - backend = Fake5QV1() - qr_a = QuantumRegister(2) - qr_b = QuantumRegister(3) - qc = QuantumCircuit(qr_a, qr_b) - qc.h(qr_a[0]) - qc.cx(qr_a[0], qr_a[1]) - qc.cx(qr_a[0], qr_b[0]) - qc.cx(qr_a[0], qr_b[1]) - qc.cx(qr_a[0], qr_b[2]) - qc.measure_all() - tqc = transpile(qc, backend, seed_transpiler=self.seed, layout_method="trivial") - initial_layout = tqc._layout - dag = circuit_to_dag(tqc) - cmap = CouplingMap(backend.configuration().coupling_map) - props = backend.properties() - pass_ = VF2PostLayout(coupling_map=cmap, properties=props, seed=self.seed) - pass_.run(dag) - self.assertLayout(dag, cmap, pass_.property_set) - self.assertNotEqual(pass_.property_set["post_layout"], initial_layout) - def test_2q_circuit_5q_backend(self): """A simple example, without considering the direction 0 - 1 @@ -217,7 +194,12 @@ def test_2q_circuit_5q_backend(self): qr = QuantumRegister(2, "qr") circuit = QuantumCircuit(qr) circuit.cx(qr[1], qr[0]) # qr1 -> qr0 - tqc = transpile(circuit, backend, layout_method="dense") + with self.assertWarnsRegex( + DeprecationWarning, + expected_regex="The `transpile` function will " + "stop supporting inputs of type `BackendV1`", + ): + tqc = transpile(circuit, backend, layout_method="dense") initial_layout = tqc._layout dag = circuit_to_dag(tqc) cmap = CouplingMap(backend.configuration().coupling_map) @@ -254,6 +236,40 @@ def test_2q_circuit_5q_backend_controlflow(self): self.assertNotEqual(pass_.property_set["post_layout"], initial_layout) def test_2q_circuit_5q_backend_max_trials(self): + """A simple example, without considering the direction + 0 - 1 + qr1 - qr0 + """ + max_trials = 11 + backend = GenericBackendV2( + num_qubits=5, + coupling_map=YORKTOWN_CMAP, + basis_gates=["id", "rz", "sx", "x", "cx", "reset"], + seed=1, + ) + + qr = QuantumRegister(2, "qr") + circuit = QuantumCircuit(qr) + circuit.cx(qr[1], qr[0]) # qr1 -> qr0 + tqc = transpile(circuit, backend, layout_method="dense") + initial_layout = tqc._layout + dag = circuit_to_dag(tqc) + cmap = CouplingMap(backend.coupling_map) + pass_ = VF2PostLayout(target=backend.target, seed=self.seed, max_trials=max_trials) + with self.assertLogs( + "qiskit.transpiler.passes.layout.vf2_post_layout", level="DEBUG" + ) as cm: + pass_.run(dag) + self.assertIn( + f"DEBUG:qiskit.transpiler.passes.layout.vf2_post_layout:Trial {max_trials} " + f"is >= configured max trials {max_trials}", + cm.output, + ) + print(pass_.property_set["VF2PostLayout_stop_reason"]) + self.assertLayout(dag, cmap, pass_.property_set) + self.assertNotEqual(pass_.property_set["post_layout"], initial_layout) + + def test_2q_circuit_5q_backend_max_trials_v1(self): """A simple example, without considering the direction 0 - 1 qr1 - qr0 @@ -265,7 +281,12 @@ def test_2q_circuit_5q_backend_max_trials(self): qr = QuantumRegister(2, "qr") circuit = QuantumCircuit(qr) circuit.cx(qr[1], qr[0]) # qr1 -> qr0 - tqc = transpile(circuit, backend, layout_method="dense") + with self.assertWarnsRegex( + DeprecationWarning, + expected_regex="The `transpile` function will " + "stop supporting inputs of type `BackendV1`", + ): + tqc = transpile(circuit, backend, layout_method="dense") initial_layout = tqc._layout dag = circuit_to_dag(tqc) cmap = CouplingMap(backend.configuration().coupling_map) @@ -287,7 +308,7 @@ def test_2q_circuit_5q_backend_max_trials(self): self.assertLayout(dag, cmap, pass_.property_set) self.assertNotEqual(pass_.property_set["post_layout"], initial_layout) - def test_best_mapping_ghz_state_full_device_multiple_qregs_v2(self): + def test_best_mapping_ghz_state_full_device_multiple_qregs(self): """Test best mappings with multiple registers""" backend = GenericBackendV2( num_qubits=5, @@ -634,6 +655,32 @@ def test_skip_3q_circuit_v2(self): ) def test_best_mapping_ghz_state_full_device_multiple_qregs(self): + """Test best mappings with multiple registers""" + backend = GenericBackendV2( + num_qubits=5, + coupling_map=YORKTOWN_CMAP, + basis_gates=["id", "rz", "sx", "x", "cx", "reset"], + seed=8, + ) + qr_a = QuantumRegister(2) + qr_b = QuantumRegister(3) + qc = QuantumCircuit(qr_a, qr_b) + qc.h(qr_a[0]) + qc.cx(qr_a[0], qr_a[1]) + qc.cx(qr_a[0], qr_b[0]) + qc.cx(qr_a[0], qr_b[1]) + qc.cx(qr_a[0], qr_b[2]) + qc.measure_all() + tqc = transpile(qc, seed_transpiler=self.seed, layout_method="trivial") + initial_layout = tqc._layout + dag = circuit_to_dag(tqc) + cmap = CouplingMap(backend.coupling_map) + pass_ = VF2PostLayout(target=backend.target, seed=self.seed, strict_direction=False) + pass_.run(dag) + self.assertLayout(dag, cmap, pass_.property_set) + self.assertNotEqual(pass_.property_set["post_layout"], initial_layout) + + def test_best_mapping_ghz_state_full_device_multiple_qregs_v1(self): """Test best mappings with multiple registers""" with self.assertWarns(DeprecationWarning): backend = Fake5QV1() @@ -646,7 +693,12 @@ def test_best_mapping_ghz_state_full_device_multiple_qregs(self): qc.cx(qr_a[0], qr_b[1]) qc.cx(qr_a[0], qr_b[2]) qc.measure_all() - tqc = transpile(qc, backend, seed_transpiler=self.seed, layout_method="trivial") + with self.assertWarnsRegex( + DeprecationWarning, + expected_regex="The `transpile` function will " + "stop supporting inputs of type `BackendV1`", + ): + tqc = transpile(qc, backend, seed_transpiler=self.seed, layout_method="trivial") initial_layout = tqc._layout dag = circuit_to_dag(tqc) cmap = CouplingMap(backend.configuration().coupling_map) @@ -659,6 +711,29 @@ def test_best_mapping_ghz_state_full_device_multiple_qregs(self): self.assertNotEqual(pass_.property_set["post_layout"], initial_layout) def test_2q_circuit_5q_backend(self): + """A simple example, without considering the direction + 0 - 1 + qr1 - qr0 + """ + backend = GenericBackendV2( + num_qubits=5, + coupling_map=BOGOTA_CMAP, + basis_gates=["id", "u1", "u2", "u3", "cx"], + seed=42, + ) + qr = QuantumRegister(2, "qr") + circuit = QuantumCircuit(qr) + circuit.cx(qr[1], qr[0]) # qr1 -> qr0 + tqc = transpile(circuit, backend, layout_method="dense") + initial_layout = tqc._layout + dag = circuit_to_dag(tqc) + cmap = CouplingMap(backend.coupling_map) + pass_ = VF2PostLayout(target=backend.target, seed=self.seed, strict_direction=False) + pass_.run(dag) + self.assertLayout(dag, cmap, pass_.property_set) + self.assertNotEqual(pass_.property_set["post_layout"], initial_layout) + + def test_2q_circuit_5q_backend_v1(self): """A simple example, without considering the direction 0 - 1 qr1 - qr0 @@ -669,7 +744,12 @@ def test_2q_circuit_5q_backend(self): qr = QuantumRegister(2, "qr") circuit = QuantumCircuit(qr) circuit.cx(qr[1], qr[0]) # qr1 -> qr0 - tqc = transpile(circuit, backend, layout_method="dense") + with self.assertWarnsRegex( + DeprecationWarning, + expected_regex="The `transpile` function will " + "stop supporting inputs of type `BackendV1`", + ): + tqc = transpile(circuit, backend, layout_method="dense") initial_layout = tqc._layout dag = circuit_to_dag(tqc) cmap = CouplingMap(backend.configuration().coupling_map) diff --git a/test/python/visualization/test_circuit_latex.py b/test/python/visualization/test_circuit_latex.py index 1be7ad7ce051..bcf5b77d51bd 100644 --- a/test/python/visualization/test_circuit_latex.py +++ b/test/python/visualization/test_circuit_latex.py @@ -20,7 +20,7 @@ from qiskit.visualization import circuit_drawer from qiskit import QuantumCircuit, QuantumRegister, ClassicalRegister, transpile -from qiskit.providers.fake_provider import Fake5QV1 +from qiskit.providers.fake_provider import GenericBackendV2 from qiskit.circuit.library import ( XGate, MCXGate, @@ -36,6 +36,7 @@ from qiskit.quantum_info.random import random_unitary from qiskit.utils import optionals from .visualization import QiskitVisualizationTestCase +from ..legacy_cmaps import YORKTOWN_CMAP pi = np.pi @@ -481,8 +482,12 @@ def test_partial_layout(self): See: https://github.com/Qiskit/qiskit-terra/issues/4757""" filename = self._get_resource_path("test_latex_partial_layout.tex") - with self.assertWarns(DeprecationWarning): - backend = Fake5QV1() + backend = GenericBackendV2( + num_qubits=5, + coupling_map=YORKTOWN_CMAP, + basis_gates=["id", "rz", "sx", "x", "cx", "reset"], + seed=42, + ) circuit = QuantumCircuit(3) circuit.h(1) diff --git a/test/utils/base.py b/test/utils/base.py index 6d0c917ace30..78d5aceb58f2 100644 --- a/test/utils/base.py +++ b/test/utils/base.py @@ -129,6 +129,15 @@ def setUpClass(cls): module=r"qiskit_aer(\.[a-zA-Z0-9_]+)*", ) + # Safe to remove once https://github.com/Qiskit/qiskit-aer/issues/2197 is in a release version + # of Aer. + warnings.filterwarnings( + "ignore", # If "default", it floods the CI output + category=DeprecationWarning, + message=r"The class ``qiskit\.providers\.models\..*`", + module=r"qiskit_aer(\.[a-zA-Z0-9_]+)*", + ) + # Safe to remove once https://github.com/Qiskit/qiskit-aer/issues/2065 is in a release version # of Aer. warnings.filterwarnings(