From c3617e8bd9d7b4e8cd799670a43a0095cd07ca25 Mon Sep 17 00:00:00 2001 From: "mergify[bot]" <37929162+mergify[bot]@users.noreply.github.com> Date: Wed, 7 Jun 2023 14:09:37 +0000 Subject: [PATCH] Fix the output macros.measure with backendV2 (#10135) (#10241) * fix measure_v2 * modify measure_all * fix meas_map input in measure_v2 * add reno * fix reno * Update reno. Co-authored-by: Naoki Kanazawa * fix reno again --------- Co-authored-by: Naoki Kanazawa (cherry picked from commit f91136654b8934e618c895173504c8063251ef8c) Co-authored-by: Kento Ueda <38037695+to24toro@users.noreply.github.com> --- qiskit/pulse/macros.py | 22 ++--- ...utputs-of-measure_v2-8959ebbbf5f87294.yaml | 7 ++ test/python/pulse/test_macros.py | 92 +++++++++++++++---- 3 files changed, 87 insertions(+), 34 deletions(-) create mode 100644 releasenotes/notes/fix-outputs-of-measure_v2-8959ebbbf5f87294.yaml diff --git a/qiskit/pulse/macros.py b/qiskit/pulse/macros.py index d4ba4768ef57..357f5979fbd4 100644 --- a/qiskit/pulse/macros.py +++ b/qiskit/pulse/macros.py @@ -63,16 +63,11 @@ def measure( # backend is V2. if hasattr(backend, "target"): - try: - meas_map = backend.configuration().meas_map - except AttributeError: - # TODO add meas_map to Target in 0.25 - meas_map = [list(range(backend.num_qubits))] return _measure_v2( qubits=qubits, target=backend.target, - meas_map=meas_map, + meas_map=meas_map or backend.meas_map, qubit_mem_slots=qubit_mem_slots or dict(zip(qubits, range(len(qubits)))), measure_name=measure_name, ) @@ -198,12 +193,7 @@ def _measure_v2( channels.AcquireChannel(measure_qubit), ] ) - else: - default_sched = target.get_calibration(measure_name, (measure_qubit,)).filter( - channels=[ - channels.AcquireChannel(measure_qubit), - ] - ) + schedule += _schedule_remapping_memory_slot(default_sched, qubit_mem_slots) except KeyError as ex: raise exceptions.PulseError( "We could not find a default measurement schedule called '{}'. " @@ -211,7 +201,6 @@ def _measure_v2( "argument. For assistance, the instructions which are defined are: " "{}".format(measure_name, target.instructions) ) from ex - schedule += _schedule_remapping_memory_slot(default_sched, qubit_mem_slots) return schedule @@ -226,7 +215,12 @@ def measure_all(backend) -> Schedule: Returns: A schedule corresponding to the inputs provided. """ - return measure(qubits=list(range(backend.configuration().n_qubits)), backend=backend) + # backend is V2. + if hasattr(backend, "target"): + qubits = list(range(backend.num_qubits)) + else: + qubits = list(range(backend.configuration().n_qubits)) + return measure(qubits=qubits, backend=backend) def _schedule_remapping_memory_slot( diff --git a/releasenotes/notes/fix-outputs-of-measure_v2-8959ebbbf5f87294.yaml b/releasenotes/notes/fix-outputs-of-measure_v2-8959ebbbf5f87294.yaml new file mode 100644 index 000000000000..0699d854a1de --- /dev/null +++ b/releasenotes/notes/fix-outputs-of-measure_v2-8959ebbbf5f87294.yaml @@ -0,0 +1,7 @@ +--- +fixes: + - | + Fixed the output of pulse :func:`~qiskit.pulse.macros.measure` and + :func:`~qiskit.pulse.macros.measure_all` when functions are called + with the :class:`.BackendV2` backend. + diff --git a/test/python/pulse/test_macros.py b/test/python/pulse/test_macros.py index a3869fd11b7d..8c82e0c569be 100644 --- a/test/python/pulse/test_macros.py +++ b/test/python/pulse/test_macros.py @@ -24,7 +24,7 @@ ) from qiskit.pulse import macros from qiskit.pulse.exceptions import PulseError -from qiskit.providers.fake_provider import FakeOpenPulse2Q, FakeHanoiV2 +from qiskit.providers.fake_provider import FakeOpenPulse2Q, FakeHanoi, FakeHanoiV2 from qiskit.test import QiskitTestCase @@ -95,13 +95,8 @@ def test_measure_v2(self): """Test macro - measure with backendV2.""" sched = macros.measure(qubits=[0], backend=self.backend_v2) expected = self.backend_v2.target.get_calibration("measure", (0,)).filter( - channels=[ - MeasureChannel(0), - ] + channels=[MeasureChannel(0), AcquireChannel(0)] ) - measure_duration = expected.filter(instruction_types=[Play]).duration - for qubit in range(self.backend_v2.num_qubits): - expected += Acquire(measure_duration, AcquireChannel(qubit), MemorySlot(qubit)) self.assertEqual(sched.instructions, expected.instructions) def test_measure_v2_sched_with_qubit_mem_slots(self): @@ -113,15 +108,7 @@ def test_measure_v2_sched_with_qubit_mem_slots(self): ] ) measure_duration = expected.filter(instruction_types=[Play]).duration - for qubit in range(self.backend_v2.num_qubits): - if qubit == 0: - expected += Acquire(measure_duration, AcquireChannel(qubit), MemorySlot(2)) - elif qubit == 1: - expected += Acquire(measure_duration, AcquireChannel(qubit), MemorySlot(0)) - elif qubit == 2: - expected += Acquire(measure_duration, AcquireChannel(qubit), MemorySlot(1)) - else: - expected += Acquire(measure_duration, AcquireChannel(qubit), MemorySlot(qubit)) + expected += Acquire(measure_duration, AcquireChannel(0), MemorySlot(2)) self.assertEqual(sched.instructions, expected.instructions) def test_measure_v2_sched_with_meas_map(self): @@ -138,8 +125,7 @@ def test_measure_v2_sched_with_meas_map(self): ] ) measure_duration = expected.filter(instruction_types=[Play]).duration - for qubit in range(self.backend_v2.num_qubits): - expected += Acquire(measure_duration, AcquireChannel(qubit), MemorySlot(qubit)) + expected += Acquire(measure_duration, AcquireChannel(0), MemorySlot(0)) self.assertEqual(sched_with_meas_map_list.instructions, expected.instructions) self.assertEqual(sched_with_meas_map_dict.instructions, expected.instructions) @@ -159,10 +145,58 @@ def test_multiple_measure_v2(self): measure_duration = expected.filter(instruction_types=[Play]).duration expected += Acquire(measure_duration, AcquireChannel(0), MemorySlot(0)) expected += Acquire(measure_duration, AcquireChannel(1), MemorySlot(1)) - for qubit in range(2, self.backend_v2.num_qubits): - expected += Acquire(measure_duration, AcquireChannel(qubit), MemorySlot(qubit)) self.assertEqual(sched.instructions, expected.instructions) + def test_output_with_measure_v1_and_measure_v2(self): + """Test make outputs of measure_v1 and measure_v2 consistent.""" + sched_measure_v1 = macros.measure(qubits=[0, 1], backend=FakeHanoi()) + sched_measure_v2 = macros.measure(qubits=[0, 1], backend=self.backend_v2) + self.assertEqual(sched_measure_v1.instructions, sched_measure_v2.instructions) + + def test_output_with_measure_v1_and_measure_v2_sched_with_qubit_mem_slots(self): + """Test make outputs of measure_v1 and measure_v2 with custom qubit_mem_slots consistent.""" + sched_measure_v1 = macros.measure(qubits=[0], backend=FakeHanoi(), qubit_mem_slots={0: 2}) + sched_measure_v2 = macros.measure( + qubits=[0], backend=self.backend_v2, qubit_mem_slots={0: 2} + ) + self.assertEqual(sched_measure_v1.instructions, sched_measure_v2.instructions) + + def test_output_with_measure_v1_and_measure_v2_sched_with_meas_map(self): + """Test make outputs of measure_v1 and measure_v2 + with custom meas_map as list and dict consistent.""" + num_qubits_list_measure_v1 = list(range(FakeHanoi().configuration().num_qubits)) + num_qubits_list_measure_v2 = list(range(self.backend_v2.num_qubits)) + sched_with_meas_map_list_v1 = macros.measure( + qubits=[0], backend=FakeHanoi(), meas_map=[num_qubits_list_measure_v1] + ) + sched_with_meas_map_dict_v1 = macros.measure( + qubits=[0], + backend=FakeHanoi(), + meas_map={0: num_qubits_list_measure_v1, 1: num_qubits_list_measure_v1}, + ) + sched_with_meas_map_list_v2 = macros.measure( + qubits=[0], backend=self.backend_v2, meas_map=[num_qubits_list_measure_v2] + ) + sched_with_meas_map_dict_v2 = macros.measure( + qubits=[0], + backend=self.backend_v2, + meas_map={0: num_qubits_list_measure_v2, 1: num_qubits_list_measure_v2}, + ) + self.assertEqual( + sched_with_meas_map_list_v1.instructions, + sched_with_meas_map_list_v2.instructions, + ) + self.assertEqual( + sched_with_meas_map_dict_v1.instructions, + sched_with_meas_map_dict_v2.instructions, + ) + + def test_output_with_multiple_measure_v1_and_measure_v2(self): + """Test macro - consistent output of multiple qubit measure with backendV1 and backendV2.""" + sched_measure_v1 = macros.measure(qubits=[0, 1], backend=FakeHanoi()) + sched_measure_v2 = macros.measure(qubits=[0, 1], backend=self.backend_v2) + self.assertEqual(sched_measure_v1.instructions, sched_measure_v2.instructions) + class TestMeasureAll(QiskitTestCase): """Pulse measure all macro.""" @@ -170,6 +204,7 @@ class TestMeasureAll(QiskitTestCase): def setUp(self): super().setUp() self.backend = FakeOpenPulse2Q() + self.backend_v2 = FakeHanoiV2() self.inst_map = self.backend.defaults().instruction_schedule_map def test_measure_all(self): @@ -177,3 +212,20 @@ def test_measure_all(self): sched = macros.measure_all(self.backend) expected = Schedule(self.inst_map.get("measure", [0, 1])) self.assertEqual(sched.instructions, expected.instructions) + + def test_measure_all_v2(self): + """Test measure_all function with backendV2.""" + backend_v1 = FakeHanoi() + sched = macros.measure_all(self.backend_v2) + expected = Schedule( + backend_v1.defaults().instruction_schedule_map.get( + "measure", list(range(backend_v1.configuration().num_qubits)) + ) + ) + self.assertEqual(sched.instructions, expected.instructions) + + def test_output_of_measure_all_with_backend_v1_and_v2(self): + """Test make outputs of measure_all with backendV1 and backendV2 consistent.""" + sched_measure_v1 = macros.measure_all(backend=FakeHanoi()) + sched_measure_v2 = macros.measure_all(backend=self.backend_v2) + self.assertEqual(sched_measure_v1.instructions, sched_measure_v2.instructions)