diff --git a/qiskit/transpiler/__init__.py b/qiskit/transpiler/__init__.py index 19aafb51a1bc..8a3b61f17bc3 100644 --- a/qiskit/transpiler/__init__.py +++ b/qiskit/transpiler/__init__.py @@ -43,6 +43,8 @@ these ready-made routines. +.. _transpiler_supplemental: + Supplementary Information ========================= @@ -354,6 +356,243 @@
+.. dropdown:: Scheduling + :animate: fade-in-slide-down + + After the circuit has been translated to the target basis, mapped to the device, and optimized, + a scheduling phase can be applied to optionally account for all the idle time in the circuit. + At a high level the scheduling can be thought of as inserting delays into the circuit to account + for idle time on the qubits between the execution of instructions. For example, if we start with a + circuit such as: + + .. jupyter-execute:: + + from qiskit import QuantumCircuit, transpile + from qiskit.test.mock import FakeBoeblingen + backend = FakeBoeblingen() + + ghz = QuantumCircuit(5) + ghz.h(0) + ghz.cx(0,range(1,5)) + ghz.draw(output='mpl') + + we can then call :func:`~.transpile` on it with ``scheduling_method`` set: + + .. jupyter-execute:: + + circ = transpile(ghz, backend, scheduling_method="asap") + circ.draw(output='mpl') + + You can see here that the transpiler inserted :class:`~qiskit.circuit.Delay` instructions to + account for idle time on each qubit. To get a better idea of the timing of the circuit we can + also look at it with the :func:`.timeline.draw` function: + + .. jupyter-execute:: + + from qiskit.visualization.timeline import draw as timeline_draw + + timeline_draw(circ) + + The scheduling of a circuit involves two parts, analysis and constraint mapping followed by a + padding pass. The first part requires running a scheduling analysis pass such as + :class:`~.ALAPSchedulingAnalysis` or :class:`~.ASAPSchedulingAnalysis` which analyzes the circuit + and records the start time of each instruction in the circuit using a scheduling algorithm ("as late + as possible" for :class:`~.ALAPSchedulingAnalysis` and "as soon as possible" for + :class:`~.ASAPSchedulingAnalysis`) in the property set. Once the circuit has an initial scheduling + additional passes can be run to account for any timing constraints on the target backend, such + as alignment constraints. This is typically done with the + :class:`~.ConstrainedReschedule` pass which will adjust the scheduling + set in the property set to the contraints of the target backend. Once all + the scheduling and adjustments/rescheduling are finished a padding pass, + such as :class:`~.PadDelay` or :class:`~.PadDynamicalDecoupling` is run + to insert the instructions into the circuit, which completes the scheduling. + + Scheduling Anaylsis with control flow instructions: + + When scheduling analysis passes run there are additional constraints on classical conditions + and control flow instructions in a circuit. This section covers the details of these additional + constraints that any scheduling pass will need to account for. + + Policy of topological node ordering in scheduling: + + The DAG representation of ``QuantumCircuit`` respects the node ordering also in the + classical register wires, though theoretically two conditional instructions + conditioned on the same register are commute, i.e. read-access to the + classical register doesn't change its state. + + .. parsed-literal:: + + qc = QuantumCircuit(2, 1) + qc.delay(100, 0) + qc.x(0).c_if(0, True) + qc.x(1).c_if(0, True) + + The scheduler SHOULD comply with above topological ordering policy of the DAG circuit. + Accordingly, the `asap`-scheduled circuit will become + + .. parsed-literal:: + + ┌────────────────┐ ┌───┐ + q_0: ┤ Delay(100[dt]) ├───┤ X ├────────────── + ├────────────────┤ └─╥─┘ ┌───┐ + q_1: ┤ Delay(100[dt]) ├─────╫────────┤ X ├─── + └────────────────┘ ║ └─╥─┘ + ┌────╨────┐┌────╨────┐ + c: 1/══════════════════╡ c_0=0x1 ╞╡ c_0=0x1 ╞ + └─────────┘└─────────┘ + + Note that this scheduling might be inefficient in some cases, + because the second conditional operation can start without waiting the delay of 100 dt. + However, such optimization should be done by another pass, + otherwise scheduling may break topological ordering of the original circuit. + + Realistic control flow scheduling respecting for microarcitecture: + + In the dispersive QND readout scheme, qubit is measured with microwave stimulus to qubit (Q) + followed by resonator ring-down (depopulation). This microwave signal is recorded + in the buffer memory (B) with hardware kernel, then a discriminated (D) binary value + is moved to the classical register (C). + The sequence from t0 to t1 of the measure instruction interval might be modeled as follows: + + .. parsed-literal:: + + Q ░▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒░ + B ░░▒▒▒▒▒▒▒▒░░░░░░░░░ + D ░░░░░░░░░░▒▒▒▒▒▒░░░ + C ░░░░░░░░░░░░░░░░▒▒░ + + However, ``QuantumCircuit`` representation is not enough accurate to represent + this model. In the circuit representation, thus ``Qubit`` is occupied by the + stimulus microwave signal during the first half of the interval, + and ``Clbit`` is only occupied at the very end of the interval. + + This precise model may induce weird edge case. + + .. parsed-literal:: + + ┌───┐ + q_0: ───┤ X ├────── + └─╥─┘ ┌─┐ + q_1: ─────╫─────┤M├ + ┌────╨────┐└╥┘ + c: 1/╡ c_0=0x1 ╞═╩═ + └─────────┘ 0 + + In this example, user may intend to measure the state of ``q_1``, after ``XGate`` is + applied to the ``q_0``. This is correct interpretation from viewpoint of + the topological node ordering, i.e. x gate node come in front of the measure node. + However, according to the measurement model above, the data in the register + is unchanged during the stimulus, thus two nodes are simultaneously operated. + If one `alap`-schedule this circuit, it may return following circuit. + + .. parsed-literal:: + + ┌────────────────┐ ┌───┐ + q_0: ┤ Delay(500[dt]) ├───┤ X ├────── + └────────────────┘ └─╥─┘ ┌─┐ + q_1: ───────────────────────╫─────┤M├ + ┌────╨────┐└╥┘ + c: 1/══════════════════╡ c_0=0x1 ╞═╩═ + └─────────┘ 0 + + Note that there is no delay on ``q_1`` wire, and the measure instruction immediately + start after t=0, while the conditional gate starts after the delay. + It looks like the topological ordering between the nodes are flipped in the scheduled view. + This behavior can be understood by considering the control flow model described above, + + .. parsed-literal:: + + : Quantum Circuit, first-measure + 0 ░░░░░░░░░░░░▒▒▒▒▒▒░ + 1 ░▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒░ + + : In wire q0 + Q ░░░░░░░░░░░░░░░▒▒▒░ + C ░░░░░░░░░░░░▒▒░░░░░ + + : In wire q1 + Q ░▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒░ + B ░░▒▒▒▒▒▒▒▒░░░░░░░░░ + D ░░░░░░░░░░▒▒▒▒▒▒░░░ + C ░░░░░░░░░░░░░░░░▒▒░ + + Since there is no qubit register (Q0, Q1) overlap, the node ordering is determined by the + shared classical register C. As you can see, the execution order is still + preserved on C, i.e. read C then apply ``XGate``, finally store the measured outcome in C. + Because ``DAGOpNode`` cannot define different durations for associated registers, + the time ordering of two nodes is inverted anyways. + + This behavior can be controlled by ``clbit_write_latency`` and ``conditional_latency``. + The former parameter determines the delay of the register write-access from + the beginning of the measure instruction t0, and another parameter determines + the delay of conditional gate operation from t0 which comes from the register read-access. + These information might be found in the backend configuration and then should + be copied to the pass manager property set before the pass is called. + + By default latencies, the `alap`-scheduled circuit of above example may become + + .. parsed-literal:: + + ┌───┐ + q_0: ───┤ X ├────── + └─╥─┘ ┌─┐ + q_1: ─────╫─────┤M├ + ┌────╨────┐└╥┘ + c: 1/╡ c_0=0x1 ╞═╩═ + └─────────┘ 0 + + If the backend microarchitecture supports smart scheduling of the control flow, i.e. + it may separately schedule qubit and classical register, + insertion of the delay yields unnecessary longer total execution time. + + .. parsed-literal:: + : Quantum Circuit, first-xgate + 0 ░▒▒▒░░░░░░░░░░░░░░░ + 1 ░▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒░ + + : In wire q0 + Q ░▒▒▒░░░░░░░░░░░░░░░ + C ░░░░░░░░░░░░░░░░░░░ (zero latency) + + : In wire q1 + Q ░▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒░ + C ░▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒░ (zero latency, scheduled after C0 read-access) + + However this result is much more intuitive in the topological ordering view. + If finite conditional latency is provided, for example, 30 dt, the circuit + is scheduled as follows. + + .. parsed-literal:: + + ┌───────────────┐ ┌───┐ + q_0: ┤ Delay(30[dt]) ├───┤ X ├────── + ├───────────────┤ └─╥─┘ ┌─┐ + q_1: ┤ Delay(30[dt]) ├─────╫─────┤M├ + └───────────────┘┌────╨────┐└╥┘ + c: 1/═════════════════╡ c_0=0x1 ╞═╩═ + └─────────┘ 0 + + with the timing model: + + .. parsed-literal:: + : Quantum Circuit, first-xgate + 0 ░░▒▒▒░░░░░░░░░░░░░░░ + 1 ░░▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒░ + + : In wire q0 + Q ░░▒▒▒░░░░░░░░░░░░░░░ + C ░▒░░░░░░░░░░░░░░░░░░ (30dt latency) + + : In wire q1 + Q ░░▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒░ + C ░░▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒░ + + See https://arxiv.org/abs/2102.01682 for more details. + + .. raw:: html + +
+ Transpiler API ============== diff --git a/qiskit/transpiler/passes/scheduling/alignments/reschedule.py b/qiskit/transpiler/passes/scheduling/alignments/reschedule.py index ab22b0080a9d..af28fed1adb6 100644 --- a/qiskit/transpiler/passes/scheduling/alignments/reschedule.py +++ b/qiskit/transpiler/passes/scheduling/alignments/reschedule.py @@ -25,7 +25,7 @@ class ConstrainedReschedule(AnalysisPass): """Rescheduler pass that updates node start times to conform to the hardware alignments. This pass shifts DAG node start times previously scheduled with one of - the scheduling passes, e.g. :class:`ASAPSchedule` or :class:`ALAPSchedule`, + the scheduling passes, e.g. :class:`ASAPScheduleAnalysis` or :class:`ALAPScheduleAnalysis`, so that every instruction start time satisfies alignment constraints. Examples: diff --git a/qiskit/transpiler/passes/scheduling/padding/dynamical_decoupling.py b/qiskit/transpiler/passes/scheduling/padding/dynamical_decoupling.py index 828fb49f5bcf..d19727d469a1 100644 --- a/qiskit/transpiler/passes/scheduling/padding/dynamical_decoupling.py +++ b/qiskit/transpiler/passes/scheduling/padding/dynamical_decoupling.py @@ -53,7 +53,7 @@ class PadDynamicalDecoupling(BasePadding): from qiskit.circuit import QuantumCircuit from qiskit.circuit.library import XGate from qiskit.transpiler import PassManager, InstructionDurations - from qiskit.transpiler.passes import ALAPSchedule, DynamicalDecoupling + from qiskit.transpiler.passes import ALAPScheduleAnalysis, PadDynamicalDecoupling from qiskit.visualization import timeline_drawer circ = QuantumCircuit(4) circ.h(0) @@ -71,8 +71,8 @@ class PadDynamicalDecoupling(BasePadding): # balanced X-X sequence on all qubits dd_sequence = [XGate(), XGate()] - pm = PassManager([ALAPSchedule(durations), - DynamicalDecoupling(durations, dd_sequence)]) + pm = PassManager([ALAPScheduleAnalysis(durations), + PadDynamicalDecoupling(durations, dd_sequence)]) circ_dd = pm.run(circ) timeline_drawer(circ_dd) @@ -89,8 +89,8 @@ def uhrig_pulse_location(k): spacing.append(1 - sum(spacing)) pm = PassManager( [ - ALAPSchedule(durations), - DynamicalDecoupling(durations, dd_sequence, qubits=[0], spacing=spacing), + ALAPScheduleAnalysis(durations), + PadDynamicalDecoupling(durations, dd_sequence, qubits=[0], spacing=spacing), ] ) circ_dd = pm.run(circ) diff --git a/qiskit/transpiler/passes/scheduling/scheduling/alap.py b/qiskit/transpiler/passes/scheduling/scheduling/alap.py index e9a26b19e49e..9de6b162ec0b 100644 --- a/qiskit/transpiler/passes/scheduling/scheduling/alap.py +++ b/qiskit/transpiler/passes/scheduling/scheduling/alap.py @@ -20,8 +20,8 @@ class ALAPScheduleAnalysis(BaseScheduler): """ALAP Scheduling pass, which schedules the **stop** time of instructions as late as possible. - See :class:`~qiskit.transpiler.passes.scheduling.base_scheduler.BaseScheduler` for the - detailed behavior of the control flow operation, i.e. ``c_if``. + See the Scheduling section in :ref:`transpiler_supplemental` for + the detailed behavior of the control flow operation, i.e. ``c_if``. """ def run(self, dag): diff --git a/qiskit/transpiler/passes/scheduling/scheduling/asap.py b/qiskit/transpiler/passes/scheduling/scheduling/asap.py index e4ed656655a2..c37beb4f967e 100644 --- a/qiskit/transpiler/passes/scheduling/scheduling/asap.py +++ b/qiskit/transpiler/passes/scheduling/scheduling/asap.py @@ -20,8 +20,8 @@ class ASAPScheduleAnalysis(BaseScheduler): """ASAP Scheduling pass, which schedules the start time of instructions as early as possible.. - See :class:`~qiskit.transpiler.passes.scheduling.base_scheduler.BaseScheduler` for the - detailed behavior of the control flow operation, i.e. ``c_if``. + See Scheduling section in :ref:`transpiler_supplemental` for + the detailed behavior of the control flow operation, i.e. ``c_if``. """ def run(self, dag): diff --git a/qiskit/transpiler/passes/scheduling/scheduling/base_scheduler.py b/qiskit/transpiler/passes/scheduling/scheduling/base_scheduler.py index 5cedbd0e1ae5..8dacf45f1e83 100644 --- a/qiskit/transpiler/passes/scheduling/scheduling/base_scheduler.py +++ b/qiskit/transpiler/passes/scheduling/scheduling/base_scheduler.py @@ -25,185 +25,7 @@ class BaseScheduler(AnalysisPass): - """Base scheduler pass. - - Policy of topological node ordering in scheduling - - The DAG representation of ``QuantumCircuit`` respects the node ordering also in the - classical register wires, though theoretically two conditional instructions - conditioned on the same register are commute, i.e. read-access to the - classical register doesn't change its state. - - .. parsed-literal:: - - qc = QuantumCircuit(2, 1) - qc.delay(100, 0) - qc.x(0).c_if(0, True) - qc.x(1).c_if(0, True) - - The scheduler SHOULD comply with above topological ordering policy of the DAG circuit. - Accordingly, the `asap`-scheduled circuit will become - - .. parsed-literal:: - - ┌────────────────┐ ┌───┐ - q_0: ┤ Delay(100[dt]) ├───┤ X ├────────────── - ├────────────────┤ └─╥─┘ ┌───┐ - q_1: ┤ Delay(100[dt]) ├─────╫────────┤ X ├─── - └────────────────┘ ║ └─╥─┘ - ┌────╨────┐┌────╨────┐ - c: 1/══════════════════╡ c_0=0x1 ╞╡ c_0=0x1 ╞ - └─────────┘└─────────┘ - - Note that this scheduling might be inefficient in some cases, - because the second conditional operation can start without waiting the delay of 100 dt. - However, such optimization should be done by another pass, - otherwise scheduling may break topological ordering of the original circuit. - - Realistic control flow scheduling respecting for microarcitecture - - In the dispersive QND readout scheme, qubit is measured with microwave stimulus to qubit (Q) - followed by resonator ring-down (depopulation). This microwave signal is recorded - in the buffer memory (B) with hardware kernel, then a discriminated (D) binary value - is moved to the classical register (C). - The sequence from t0 to t1 of the measure instruction interval might be modeled as follows: - - .. parsed-literal:: - - Q ░▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒░ - B ░░▒▒▒▒▒▒▒▒░░░░░░░░░ - D ░░░░░░░░░░▒▒▒▒▒▒░░░ - C ░░░░░░░░░░░░░░░░▒▒░ - - However, ``QuantumCircuit`` representation is not enough accurate to represent - this model. In the circuit representation, thus ``Qubit`` is occupied by the - stimulus microwave signal during the first half of the interval, - and ``Clbit`` is only occupied at the very end of the interval. - - This precise model may induce weird edge case. - - .. parsed-literal:: - - ┌───┐ - q_0: ───┤ X ├────── - └─╥─┘ ┌─┐ - q_1: ─────╫─────┤M├ - ┌────╨────┐└╥┘ - c: 1/╡ c_0=0x1 ╞═╩═ - └─────────┘ 0 - - In this example, user may intend to measure the state of ``q_1``, after ``XGate`` is - applied to the ``q_0``. This is correct interpretation from viewpoint of - the topological node ordering, i.e. x gate node come in front of the measure node. - However, according to the measurement model above, the data in the register - is unchanged during the stimulus, thus two nodes are simultaneously operated. - If one `alap`-schedule this circuit, it may return following circuit. - - .. parsed-literal:: - - ┌────────────────┐ ┌───┐ - q_0: ┤ Delay(500[dt]) ├───┤ X ├────── - └────────────────┘ └─╥─┘ ┌─┐ - q_1: ───────────────────────╫─────┤M├ - ┌────╨────┐└╥┘ - c: 1/══════════════════╡ c_0=0x1 ╞═╩═ - └─────────┘ 0 - - Note that there is no delay on ``q_1`` wire, and the measure instruction immediately - start after t=0, while the conditional gate starts after the delay. - It looks like the topological ordering between the nodes are flipped in the scheduled view. - This behavior can be understood by considering the control flow model described above, - - .. parsed-literal:: - - : Quantum Circuit, first-measure - 0 ░░░░░░░░░░░░▒▒▒▒▒▒░ - 1 ░▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒░ - - : In wire q0 - Q ░░░░░░░░░░░░░░░▒▒▒░ - C ░░░░░░░░░░░░▒▒░░░░░ - - : In wire q1 - Q ░▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒░ - B ░░▒▒▒▒▒▒▒▒░░░░░░░░░ - D ░░░░░░░░░░▒▒▒▒▒▒░░░ - C ░░░░░░░░░░░░░░░░▒▒░ - - Since there is no qubit register (Q0, Q1) overlap, the node ordering is determined by the - shared classical register C. As you can see, the execution order is still - preserved on C, i.e. read C then apply ``XGate``, finally store the measured outcome in C. - Because ``DAGOpNode`` cannot define different durations for associated registers, - the time ordering of two nodes is inverted anyways. - - This behavior can be controlled by ``clbit_write_latency`` and ``conditional_latency``. - The former parameter determines the delay of the register write-access from - the beginning of the measure instruction t0, and another parameter determines - the delay of conditional gate operation from t0 which comes from the register read-access. - These information might be found in the backend configuration and then should - be copied to the pass manager property set before the pass is called. - - By default latencies, the `alap`-scheduled circuit of above example may become - - .. parsed-literal:: - - ┌───┐ - q_0: ───┤ X ├────── - └─╥─┘ ┌─┐ - q_1: ─────╫─────┤M├ - ┌────╨────┐└╥┘ - c: 1/╡ c_0=0x1 ╞═╩═ - └─────────┘ 0 - - If the backend microarchitecture supports smart scheduling of the control flow, i.e. - it may separately schedule qubit and classical register, - insertion of the delay yields unnecessary longer total execution time. - - .. parsed-literal:: - : Quantum Circuit, first-xgate - 0 ░▒▒▒░░░░░░░░░░░░░░░ - 1 ░▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒░ - - : In wire q0 - Q ░▒▒▒░░░░░░░░░░░░░░░ - C ░░░░░░░░░░░░░░░░░░░ (zero latency) - - : In wire q1 - Q ░▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒░ - C ░▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒░ (zero latency, scheduled after C0 read-access) - - However this result is much more intuitive in the topological ordering view. - If finite conditional latency is provided, for example, 30 dt, the circuit - is scheduled as follows. - - .. parsed-literal:: - - ┌───────────────┐ ┌───┐ - q_0: ┤ Delay(30[dt]) ├───┤ X ├────── - ├───────────────┤ └─╥─┘ ┌─┐ - q_1: ┤ Delay(30[dt]) ├─────╫─────┤M├ - └───────────────┘┌────╨────┐└╥┘ - c: 1/═════════════════╡ c_0=0x1 ╞═╩═ - └─────────┘ 0 - - with the timing model: - - .. parsed-literal:: - : Quantum Circuit, first-xgate - 0 ░░▒▒▒░░░░░░░░░░░░░░░ - 1 ░░▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒░ - - : In wire q0 - Q ░░▒▒▒░░░░░░░░░░░░░░░ - C ░▒░░░░░░░░░░░░░░░░░░ (30dt latency) - - : In wire q1 - Q ░░▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒░ - C ░░▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒░ - - See https://arxiv.org/abs/2102.01682 for more details. - - """ + """Base scheduler pass.""" CONDITIONAL_SUPPORTED = (Gate, Delay)