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)