From b90c7a706f3848310fa1c0ddaaea5994b78ecfa4 Mon Sep 17 00:00:00 2001 From: Julien Gacon Date: Tue, 20 Aug 2024 17:54:19 +0200 Subject: [PATCH 1/2] Tiny follow up to #12983 (#12999) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * tiny follow up * Update releasenotes/notes/deprecate-StochasticSwap-451f46b273602b7b.yaml Co-authored-by: Elena Peña Tapia <57907331+ElePT@users.noreply.github.com> --------- Co-authored-by: Elena Peña Tapia <57907331+ElePT@users.noreply.github.com> --- .../passes/routing/stochastic_swap.py | 4 +- ...ecate-StochasticSwap-451f46b273602b7b.yaml | 58 ++++++++++--------- 2 files changed, 33 insertions(+), 29 deletions(-) diff --git a/qiskit/transpiler/passes/routing/stochastic_swap.py b/qiskit/transpiler/passes/routing/stochastic_swap.py index 8cb628501017..a3ebbd6cbdde 100644 --- a/qiskit/transpiler/passes/routing/stochastic_swap.py +++ b/qiskit/transpiler/passes/routing/stochastic_swap.py @@ -63,8 +63,8 @@ class StochasticSwap(TransformationPass): @deprecate_func( since="1.3", removal_timeline="in the 2.0 release", - additional_msg="The `StochasticSwap` transpilation pass is a suboptimal " - "routing algorithm and has been superseded by the :class:`.SabreSwap` pass.", + additional_msg="The StochasticSwap transpilation pass is a suboptimal " + "routing algorithm and has been superseded by the SabreSwap pass.", ) def __init__(self, coupling_map, trials=20, seed=None, fake_run=False, initial_layout=None): """StochasticSwap initializer. diff --git a/releasenotes/notes/deprecate-StochasticSwap-451f46b273602b7b.yaml b/releasenotes/notes/deprecate-StochasticSwap-451f46b273602b7b.yaml index 24ade535f294..c858dd6fe6ab 100644 --- a/releasenotes/notes/deprecate-StochasticSwap-451f46b273602b7b.yaml +++ b/releasenotes/notes/deprecate-StochasticSwap-451f46b273602b7b.yaml @@ -1,45 +1,49 @@ --- deprecations_transpiler: - | - Deprecated ``StochasticSwap`` which has been superseded by :class:`.SabreSwap`. + Deprecated :class:`.StochasticSwap` which has been superseded by :class:`.SabreSwap`. If the class is called from the transpile function, the change would be, for example:: + from qiskit import transpile + from qiskit.circuit import QuantumCircuit + from qiskit.transpiler import CouplingMap + from qiskit.providers.fake_provider import GenericBackendV2 + + + qc = QuantumCircuit(4) + qc.h(0) + qc.cx(0, range(1, 4)) + qc.measure_all() + + cmap = CouplingMap.from_heavy_hex(3) + backend = GenericBackendV2(num_qubits=cmap.size(), coupling_map=cmap) + tqc = transpile( - circuit, - routing_method="stochastic", - layout_method="dense", - seed_transpiler=12342, - target=GenericBackendV2( - num_qubits=27, - coupling_map=MUMBAI_CMAP, - ).target, - ) + qc, + routing_method="stochastic", + layout_method="dense", + seed_transpiler=12342, + target=backend.target + ) to:: tqc = transpile( - circuit, - routing_method="sabre", - layout_method="sabre", - seed_transpiler=12342, - target=GenericBackendV2( - num_qubits=27, - coupling_map=MUMBAI_CMAP, - ).target, - ) - - While for a pass mananager change:: - - qr = QuantumRegister(4, "q") - qc = QuantumCircuit(qr) + qc, + routing_method="sabre", + layout_method="sabre", + seed_transpiler=12342, + target=backend.target + ) + + While for a pass manager, the change would be:: + passmanager = PassManager(StochasticSwap(coupling, 20, 13)) new_qc = passmanager.run(qc) to:: - qr = QuantumRegister(5, "q") - qc = QuantumCircuit(qr) - passmanager = PassManager(SabreSwap(target, "basic")) + passmanager = PassManager(SabreSwap(backend.target, "basic")) new_qc = passmanager.run(qc) From 6107799ce19996ed125cb3f01663ad394e4eadbc Mon Sep 17 00:00:00 2001 From: Shravan Patel <78003234+shravanpatel30@users.noreply.github.com> Date: Wed, 21 Aug 2024 04:31:03 -0500 Subject: [PATCH 2/2] Extended the `from_backend` method of `InstructionDurations` to support both `BackendV1` and `BackendV2` (#12941) * Extended the `from_backend` method of `InstructionDurations` to support `GenericBackendV2` * Simplified the `from_backend` method to allow using `BackendV2`. Added a test and a releasenote. * Made changes to the releasenote. --- qiskit/transpiler/instruction_durations.py | 4 ++++ .../notes/fix-InstructionDurations-b47a9770b424d7a0.yaml | 5 +++++ test/python/transpiler/test_instruction_durations.py | 8 ++++++++ 3 files changed, 17 insertions(+) create mode 100644 releasenotes/notes/fix-InstructionDurations-b47a9770b424d7a0.yaml diff --git a/qiskit/transpiler/instruction_durations.py b/qiskit/transpiler/instruction_durations.py index 85d89bb16a18..56f8b5587c0c 100644 --- a/qiskit/transpiler/instruction_durations.py +++ b/qiskit/transpiler/instruction_durations.py @@ -18,6 +18,7 @@ from qiskit.circuit import Barrier, Delay, Instruction, ParameterExpression from qiskit.circuit.duration import duration_in_dt from qiskit.providers import Backend +from qiskit.providers.backend import BackendV2 from qiskit.transpiler.exceptions import TranspilerError from qiskit.utils.units import apply_prefix @@ -75,6 +76,9 @@ def from_backend(cls, backend: Backend): TranspilerError: If dt and dtm is different in the backend. """ # All durations in seconds in gate_length + if isinstance(backend, BackendV2): + return backend.target.durations() + instruction_durations = [] backend_properties = backend.properties() if hasattr(backend_properties, "_gates"): diff --git a/releasenotes/notes/fix-InstructionDurations-b47a9770b424d7a0.yaml b/releasenotes/notes/fix-InstructionDurations-b47a9770b424d7a0.yaml new file mode 100644 index 000000000000..ce8b789462de --- /dev/null +++ b/releasenotes/notes/fix-InstructionDurations-b47a9770b424d7a0.yaml @@ -0,0 +1,5 @@ +--- +fixes: + - | + Fixed a bug where :meth:`.InstructionDurations.from_backend` did not work for :class:`.BackendV2` backends. + Fixed `#12760 `. \ No newline at end of file diff --git a/test/python/transpiler/test_instruction_durations.py b/test/python/transpiler/test_instruction_durations.py index de68fbadf86a..c59d0ff2a6cc 100644 --- a/test/python/transpiler/test_instruction_durations.py +++ b/test/python/transpiler/test_instruction_durations.py @@ -16,6 +16,7 @@ from qiskit.circuit import Delay, Parameter from qiskit.providers.fake_provider import Fake27QPulseV1 +from qiskit.providers.fake_provider import GenericBackendV2 from qiskit.transpiler.exceptions import TranspilerError from qiskit.transpiler.instruction_durations import InstructionDurations from test import QiskitTestCase # pylint: disable=wrong-import-order @@ -92,3 +93,10 @@ def test_fail_if_get_unbounded_duration_with_unit_conversion_when_dt_is_not_prov parameterized_delay = Delay(param, "s") with self.assertRaises(TranspilerError): InstructionDurations().get(parameterized_delay, 0) + + def test_from_backend_with_backendv2(self): + """Test if `from_backend()` method allows using BackendV2""" + backend = GenericBackendV2(num_qubits=4, calibrate_instructions=True, seed=42) + inst_durations = InstructionDurations.from_backend(backend) + self.assertEqual(inst_durations, backend.target.durations()) + self.assertIsInstance(inst_durations, InstructionDurations)