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 scheduling units (backport #11782) #11817

Merged
merged 1 commit into from
Feb 16, 2024
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
11 changes: 9 additions & 2 deletions qiskit/circuit/duration.py
Original file line number Diff line number Diff line change
Expand Up @@ -78,8 +78,15 @@ def convert_durations_to_dt(qc: QuantumCircuit, dt_in_sec: float, inplace=True):
operation.duration = duration_in_dt(duration, dt_in_sec)
operation.unit = "dt"

if circ.duration is not None:
circ.duration = duration_in_dt(circ.duration, dt_in_sec)
if circ.duration is not None and circ.unit != "dt":
if not circ.unit.endswith("s"):
raise CircuitError(f"Invalid time unit: '{circ.unit}'")

duration = circ.duration
if circ.unit != "s":
duration = apply_prefix(duration, circ.unit)

circ.duration = duration_in_dt(duration, dt_in_sec)
circ.unit = "dt"

if not inplace:
Expand Down
6 changes: 6 additions & 0 deletions releasenotes/notes/fix-scheduling-units-59477912b47d3dc1.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
---
fixes:
- |
A bug has been fixed in :func:`.convert_durations_to_dt` where the function would blindly apply
a conversion from seconds to ``dt`` on circuit durations, independently of the original units of the attribute.
This could lead to wrong orders of magnitude in the reported circuit durations.
46 changes: 45 additions & 1 deletion test/python/circuit/test_scheduled_circuit.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,10 @@
from qiskit import QuantumCircuit, QiskitError
from qiskit import transpile, assemble
from qiskit.circuit import Parameter
from qiskit.providers.fake_provider import Fake27QPulseV1
from qiskit.circuit.duration import convert_durations_to_dt
from qiskit.providers.fake_provider import Fake27QPulseV1, GenericBackendV2
from qiskit.providers.basic_provider import BasicSimulator
from qiskit.scheduler import ScheduleConfig
from qiskit.transpiler.exceptions import TranspilerError
from qiskit.transpiler.instruction_durations import InstructionDurations
from test import QiskitTestCase # pylint: disable=wrong-import-order
Expand Down Expand Up @@ -300,6 +302,48 @@ def test_per_qubit_durations(self):
self.assertEqual(sc.qubit_start_time(*q), 300)
self.assertEqual(sc.qubit_stop_time(*q), 2400)

def test_convert_duration_to_dt(self):
"""Test that circuit duration unit conversion is applied only when necessary.
Tests fix for bug reported in PR #11782."""

backend = GenericBackendV2(num_qubits=3, calibrate_instructions=True, seed=10)
schedule_config = ScheduleConfig(
inst_map=backend.target.instruction_schedule_map(),
meas_map=backend.meas_map,
dt=backend.dt,
)

circ = QuantumCircuit(2)
circ.cx(0, 1)
circ.measure_all()

circuit_dt = transpile(circ, backend, scheduling_method="asap")
# reference duration and unit in dt
ref_duration = circuit_dt.duration
ref_unit = circuit_dt.unit

circuit_s = circuit_dt.copy()
circuit_s.duration *= backend.dt
circuit_s.unit = "s"

circuit_ms = circuit_s.copy()
circuit_ms.duration *= 1000
circuit_ms.unit = "ms"

for circuit in [circuit_dt, circuit_s, circuit_ms]:
with self.subTest(circuit=circuit):
converted_circ = convert_durations_to_dt(
circuit, dt_in_sec=schedule_config.dt, inplace=False
)
self.assertEqual(
converted_circ.duration,
ref_duration,
)
self.assertEqual(
converted_circ.unit,
ref_unit,
)

def test_change_dt_in_transpile(self):
qc = QuantumCircuit(1, 1)
qc.x(0)
Expand Down
Loading