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

Extended the from_backend method of InstructionDurations to support both BackendV1 and BackendV2 #12941

Merged
merged 3 commits into from
Aug 21, 2024
Merged
Changes from 1 commit
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
64 changes: 46 additions & 18 deletions qiskit/transpiler/instruction_durations.py
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand Down Expand Up @@ -62,7 +63,7 @@ def __str__(self):
return string

@classmethod
def from_backend(cls, backend: Backend):
def from_backend(cls, backend: Backend | BackendV2):
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Backend includes BackendV2 so we don't need an extra type here 🙂

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think we could just solve this as

def from_backend(cls, backend):
    if isinstance(backend, BackendV2):
        return backend.target.durations()
        
    # old code goes here as it is

"""Construct an :class:`InstructionDurations` object from the backend.

Args:
Expand All @@ -76,24 +77,51 @@ def from_backend(cls, backend: Backend):
"""
# All durations in seconds in gate_length
instruction_durations = []
backend_properties = backend.properties()
if hasattr(backend_properties, "_gates"):
for gate, insts in backend_properties._gates.items():
for qubits, props in insts.items():
if "gate_length" in props:
gate_length = props["gate_length"][0] # Throw away datetime at index 1
instruction_durations.append((gate, qubits, gate_length, "s"))
for q, props in backend.properties()._qubits.items():
if "readout_length" in props:
readout_length = props["readout_length"][0] # Throw away datetime at index 1
instruction_durations.append(("measure", [q], readout_length, "s"))
if hasattr(backend, "properties"):
backend_properties = backend.properties()
if hasattr(backend_properties, "_gates"):
for gate, insts in backend_properties._gates.items():
for qubits, props in insts.items():
if "gate_length" in props:
gate_length = props["gate_length"][0] # Throw away datetime at index 1
instruction_durations.append((gate, qubits, gate_length, "s"))
for q, props in backend.properties()._qubits.items():
if "readout_length" in props:
readout_length = props["readout_length"][
0
] # Throw away datetime at index 1
instruction_durations.append(("measure", [q], readout_length, "s"))

try:
dt = backend.configuration().dt
except AttributeError:
dt = None

return cls(instruction_durations, dt=dt)

elif isinstance(backend, BackendV2):
for gate, insts in backend.target.items():
for qb, inst_prop in insts.items():
# `duration` and `error` are defined as `None` for `delay` and `reset` in
# `GenericBackendV2`and due to that the `update()` method from `InstructionDurations`
# raises an error, so here we will skip adding instructions whose duration is `None`.
# Also, the `target` of `GenericBackendV2` includes the duration of `measure` so
# there is no need to access `readout_length` separately (like above).
if inst_prop.duration is not None:
gate_length = inst_prop.duration
instruction_durations.append((gate, qb, gate_length, "s"))

try:
dt = backend.target.dt
except AttributeError:
dt = None

return cls(instruction_durations, dt=dt)

try:
dt = backend.configuration().dt
except AttributeError:
dt = None

return cls(instruction_durations, dt=dt)
else:
raise TranspilerError(
"Unsupported backend type. The backend has to to be either a backend V1 or a backend V2"
)

def update(self, inst_durations: "InstructionDurationsType" | None, dt: float = None):
"""Update self with inst_durations (inst_durations overwrite self).
Expand Down
Loading