Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix the output macros.measure with backendV2 #10135

Merged
merged 8 commits into from
Jun 7, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
22 changes: 8 additions & 14 deletions qiskit/pulse/macros.py
Original file line number Diff line number Diff line change
Expand Up @@ -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,
)
Expand Down Expand Up @@ -198,20 +193,14 @@ 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 '{}'. "
"Please provide another name using the 'measure_name' keyword "
"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


Expand All @@ -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(
Expand Down
Original file line number Diff line number Diff line change
@@ -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.

92 changes: 72 additions & 20 deletions test/python/pulse/test_macros.py
Original file line number Diff line number Diff line change
Expand Up @@ -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


Expand Down Expand Up @@ -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):
Expand All @@ -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):
Expand All @@ -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)

Expand All @@ -159,21 +145,87 @@ 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."""

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):
"""Test measure_all function."""
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)