Skip to content

Commit

Permalink
Treat Reset like Measure in ConstrainedReschedule (#11756)
Browse files Browse the repository at this point in the history
* fix mid-circuit measure problem

* Update qiskit/transpiler/passes/scheduling/base_scheduler.py

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

* Update releasenotes/notes/add-scheduler-warnings-da6968a39fd8e6e7.yaml

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

* Update qiskit/transpiler/passes/scheduling/base_scheduler.py

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

* Move runtime warning about reset and measurement durations outside of calibration if statement

* Replace raise with warn

* Switch import orders

---------

Co-authored-by: Naoki Kanazawa <nkanazawa1989@gmail.com>
  • Loading branch information
hunterkemeny and nkanazawa1989 committed Apr 25, 2024
1 parent 1dd7233 commit 7e44b6b
Show file tree
Hide file tree
Showing 3 changed files with 36 additions and 5 deletions.
7 changes: 4 additions & 3 deletions qiskit/transpiler/passes/scheduling/alignments/reschedule.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
from qiskit.circuit.gate import Gate
from qiskit.circuit.delay import Delay
from qiskit.circuit.measure import Measure
from qiskit.circuit.reset import Reset
from qiskit.dagcircuit import DAGCircuit, DAGOpNode, DAGOutNode
from qiskit.transpiler.basepasses import AnalysisPass
from qiskit.transpiler.exceptions import TranspilerError
Expand Down Expand Up @@ -121,7 +122,7 @@ def _push_node_back(self, dag: DAGCircuit, node: DAGOpNode):

if isinstance(node.op, Gate):
alignment = self.pulse_align
elif isinstance(node.op, Measure):
elif isinstance(node.op, (Measure, Reset)):
alignment = self.acquire_align
elif isinstance(node.op, Delay) or getattr(node.op, "_directive", False):
# Directive or delay. These can start at arbitrary time.
Expand All @@ -143,7 +144,7 @@ def _push_node_back(self, dag: DAGCircuit, node: DAGOpNode):
# Compute shifted t1 of this node separately for qreg and creg
new_t1q = this_t0 + node.op.duration
this_qubits = set(node.qargs)
if isinstance(node.op, Measure):
if isinstance(node.op, (Measure, Reset)):
# creg access ends at the end of instruction
new_t1c = new_t1q
this_clbits = set(node.cargs)
Expand All @@ -161,7 +162,7 @@ def _push_node_back(self, dag: DAGCircuit, node: DAGOpNode):
# Compute next node start time separately for qreg and creg
next_t0q = node_start_time[next_node]
next_qubits = set(next_node.qargs)
if isinstance(next_node.op, Measure):
if isinstance(next_node.op, (Measure, Reset)):
# creg access starts after write latency
next_t0c = next_t0q + clbit_write_latency
next_clbits = set(next_node.cargs)
Expand Down
23 changes: 21 additions & 2 deletions qiskit/transpiler/passes/scheduling/base_scheduler.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,11 +11,13 @@
# that they have been altered from the originals.

"""Base circuit scheduling pass."""
import warnings

from qiskit.transpiler import InstructionDurations
from qiskit.transpiler.basepasses import TransformationPass
from qiskit.transpiler.passes.scheduling.time_unit_conversion import TimeUnitConversion
from qiskit.dagcircuit import DAGOpNode, DAGCircuit
from qiskit.circuit import Delay, Gate
from qiskit.dagcircuit import DAGOpNode, DAGCircuit, DAGOutNode
from qiskit.circuit import Delay, Gate, Measure, Reset
from qiskit.circuit.parameterexpression import ParameterExpression
from qiskit.transpiler.exceptions import TranspilerError
from qiskit.transpiler.target import Target
Expand Down Expand Up @@ -269,6 +271,23 @@ def _get_node_duration(
else:
duration = node.op.duration

if isinstance(node.op, Reset):
warnings.warn(
"Qiskit scheduler assumes Reset works similarly to Measure instruction. "
"Actual behavior depends on the control system of your quantum backend. "
"Your backend may provide a plugin scheduler pass."
)
elif isinstance(node.op, Measure):
is_mid_circuit = not any(
isinstance(x, DAGOutNode) for x in dag.quantum_successors(node)
)
if is_mid_circuit:
warnings.warn(
"Qiskit scheduler assumes mid-circuit measurement works as a standard instruction. "
"Actual backend may apply custom scheduling. "
"Your backend may provide a plugin scheduler pass."
)

if isinstance(duration, ParameterExpression):
raise TranspilerError(
f"Parameterized duration ({duration}) "
Expand Down
11 changes: 11 additions & 0 deletions releasenotes/notes/add-scheduler-warnings-da6968a39fd8e6e7.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
fixes:
- |
Fixed an issue where the :class:`.ConstrainedReschedule` transpiler pass would previously error
if the circuit contained a :class:`~.circuit.Reset` instruction. This has been corrected so that the
pass no longer errors, however an actual hardware may behave differently from
what Qiskit scheduler assumes especially for
mid-circuit measurements and resets.
Qiskit scheduler raises ``RuntimeWarning`` if
it encounters circuit containing either.
Fixed `#10354 <https://github.com/Qiskit/qiskit/issues/10354>`__

0 comments on commit 7e44b6b

Please sign in to comment.