Skip to content

Commit

Permalink
Dispatch a builder with backendV1 and backendV2 (Qiskit#10150)
Browse files Browse the repository at this point in the history
* fix measure_v2

* modify measure_all

* dispatch backend

* add test of the builder with backendV2

* reconfigure test codes and some func

* refactoring

* add reno

* fix _measure_v2

* fix backend.meas_map in measure_v2

* fix reno

* delete get_qubit_channels from utils

* add get_qubits_channels in qubit_channels

* recostruct test about the builder with backendV2

* fix descriptions of test_macros

* fix descriptions of test_macros again

* delete import of backendV2 in utils

* revert no need to modify code

* Update releasenotes/notes/fix-dispatching-backends-28aff96f726ca9c5.yaml

Co-authored-by: Naoki Kanazawa <nkanazawa1989@gmail.com>

* Update a commnet in qiskit/pulse/builder.py

Co-authored-by: Naoki Kanazawa <nkanazawa1989@gmail.com>

* remove import TYPE_CHECKING

* removed test_builder.py utils.py and test_analyzation.py from pull request

---------

Co-authored-by: Naoki Kanazawa <nkanazawa1989@gmail.com>
  • Loading branch information
2 people authored and thspreetham98 committed Jun 19, 2023
1 parent cb52fce commit e5ad00d
Show file tree
Hide file tree
Showing 4 changed files with 420 additions and 8 deletions.
66 changes: 60 additions & 6 deletions qiskit/pulse/builder.py
Original file line number Diff line number Diff line change
Expand Up @@ -495,6 +495,7 @@
library,
transforms,
)
from qiskit.providers.backend import BackendV2
from qiskit.pulse.instructions import directives
from qiskit.pulse.schedule import Schedule, ScheduleBlock
from qiskit.pulse.transforms.alignments import AlignmentKind
Expand Down Expand Up @@ -677,6 +678,9 @@ def get_context(self) -> ScheduleBlock:
@_requires_backend
def num_qubits(self):
"""Get the number of qubits in the backend."""
# backendV2
if isinstance(self.backend, BackendV2):
return self.backend.num_qubits
return self.backend.configuration().n_qubits

@property
Expand Down Expand Up @@ -1105,6 +1109,8 @@ def num_qubits() -> int:
.. note:: Requires the active builder context to have a backend set.
"""
if isinstance(active_backend(), BackendV2):
return active_backend().num_qubits
return active_backend().configuration().n_qubits


Expand All @@ -1120,6 +1126,12 @@ def seconds_to_samples(seconds: Union[float, np.ndarray]) -> Union[int, np.ndarr
Returns:
The number of samples for the time to elapse
"""
# backendV2
if isinstance(active_backend(), BackendV2):
if isinstance(seconds, np.ndarray):
return (seconds / active_backend().dt).astype(int)
else:
return int(seconds / active_backend().dt)
if isinstance(seconds, np.ndarray):
return (seconds / active_backend().configuration().dt).astype(int)
return int(seconds / active_backend().configuration().dt)
Expand All @@ -1135,6 +1147,9 @@ def samples_to_seconds(samples: Union[int, np.ndarray]) -> Union[float, np.ndarr
Returns:
The time that elapses in ``samples``.
"""
# backendV2
if isinstance(active_backend(), BackendV2):
return samples * active_backend().dt
return samples * active_backend().configuration().dt


Expand Down Expand Up @@ -1163,6 +1178,31 @@ def qubit_channels(qubit: int) -> Set[chans.Channel]:
such as in the case where significant crosstalk exists.
"""

# implement as the inner function to avoid API change for a patch release in 0.24.2.
def get_qubit_channels_v2(backend: BackendV2, qubit: int):
r"""Return a list of channels which operate on the given ``qubit``.
Returns:
List of ``Channel``\s operated on my the given ``qubit``.
"""
channels = []

# add multi-qubit channels
for node_qubits in backend.coupling_map:
if qubit in node_qubits:
control_channel = backend.control_channel(node_qubits)
if control_channel:
channels.extend(control_channel)

# add single qubit channels
channels.append(backend.drive_channel(qubit))
channels.append(backend.measure_channel(qubit))
channels.append(backend.acquire_channel(qubit))
return channels

# backendV2
if isinstance(active_backend(), BackendV2):
return set(get_qubit_channels_v2(active_backend(), qubit))
return set(active_backend().configuration().get_qubit_channels(qubit))


Expand Down Expand Up @@ -1648,7 +1688,11 @@ def frequency_offset(
finally:
if compensate_phase:
duration = builder.get_context().duration - t0
dt = active_backend().configuration().dt
# backendV2
if isinstance(active_backend(), BackendV2):
dt = active_backend().dt
else:
dt = active_backend().configuration().dt
accumulated_phase = 2 * np.pi * ((duration * dt * frequency) % 1)
for channel in channels:
shift_phase(-accumulated_phase, channel)
Expand All @@ -1675,6 +1719,9 @@ def drive_channel(qubit: int) -> chans.DriveChannel:
.. note:: Requires the active builder context to have a backend set.
"""
# backendV2
if isinstance(active_backend(), BackendV2):
return active_backend().drive_channel(qubit)
return active_backend().configuration().drive(qubit)


Expand All @@ -1695,6 +1742,9 @@ def measure_channel(qubit: int) -> chans.MeasureChannel:
.. note:: Requires the active builder context to have a backend set.
"""
# backendV2
if isinstance(active_backend(), BackendV2):
return active_backend().measure_channel(qubit)
return active_backend().configuration().measure(qubit)


Expand All @@ -1715,6 +1765,9 @@ def acquire_channel(qubit: int) -> chans.AcquireChannel:
.. note:: Requires the active builder context to have a backend set.
"""
# backendV2
if isinstance(active_backend(), BackendV2):
return active_backend().acquire_channel(qubit)
return active_backend().configuration().acquire(qubit)


Expand Down Expand Up @@ -1745,6 +1798,9 @@ def control_channels(*qubits: Iterable[int]) -> List[chans.ControlChannel]:
List of control channels associated with the supplied ordered list
of qubits.
"""
# backendV2
if isinstance(active_backend(), BackendV2):
return active_backend().control_channel(qubits)
return active_backend().configuration().control(qubits=qubits)


Expand Down Expand Up @@ -2428,11 +2484,9 @@ def measure(
registers = list(registers)
except TypeError:
registers = [registers]

measure_sched = macros.measure(
qubits=qubits,
inst_map=backend.defaults().instruction_schedule_map,
meas_map=backend.configuration().meas_map,
backend=backend,
qubit_mem_slots={qubit: register.index for qubit, register in zip(qubits, registers)},
)

Expand Down Expand Up @@ -2478,10 +2532,10 @@ def measure_all() -> List[chans.MemorySlot]:
backend = active_backend()
qubits = range(num_qubits())
registers = [chans.MemorySlot(qubit) for qubit in qubits]

measure_sched = macros.measure(
qubits=qubits,
inst_map=backend.defaults().instruction_schedule_map,
meas_map=backend.configuration().meas_map,
backend=backend,
qubit_mem_slots={qubit: qubit for qubit in qubits},
)

Expand Down
5 changes: 3 additions & 2 deletions qiskit/pulse/macros.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
from qiskit.pulse import channels, exceptions, instructions, utils
from qiskit.pulse.instruction_schedule_map import InstructionScheduleMap
from qiskit.pulse.schedule import Schedule
from qiskit.providers.backend import BackendV2


if TYPE_CHECKING:
Expand Down Expand Up @@ -62,7 +63,7 @@ def measure(
"""

# backend is V2.
if hasattr(backend, "target"):
if isinstance(backend, BackendV2):

return _measure_v2(
qubits=qubits,
Expand Down Expand Up @@ -216,7 +217,7 @@ def measure_all(backend) -> Schedule:
A schedule corresponding to the inputs provided.
"""
# backend is V2.
if hasattr(backend, "target"):
if isinstance(backend, BackendV2):
qubits = list(range(backend.num_qubits))
else:
qubits = list(range(backend.configuration().n_qubits))
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
---
fixes:
- |
Fixed an failure of the pulse builder when the context is initialized with :class:`.BackendV2`.
Loading

0 comments on commit e5ad00d

Please sign in to comment.