Skip to content

Commit

Permalink
Update docstrings for renamed scheduling passes (#7884) (#7951)
Browse files Browse the repository at this point in the history
* Update docstrings for renamed scheduling passes

In #7835 we renamed the passes used in the new scheduler pass workflow
to differentiate them from the existing legacy scheduling pass workflow
(which we restored pending a future deprecation in that PR). However,
while we updated the docstring for the legacy path to update them to
point to the new passes, we neglected to update the docstrings for the
renamed classes to reflect the new names. The examples in the docstrings
still worked because of the old passes, but it wasn't showing an example
of how to use the new workflow anymore. This commit corrects this
oversight so that they actually explain how to use them.

* Add scheduling section to top level transpiler doc

* Update reference

* Fix lint

* Fix typos

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

* Apply suggestions from code review

Co-authored-by: Kevin Hartman <kevin@hart.mn>

Co-authored-by: Naoki Kanazawa <nkanazawa1989@gmail.com>
Co-authored-by: Kevin Hartman <kevin@hart.mn>
Co-authored-by: mergify[bot] <37929162+mergify[bot]@users.noreply.github.com>
(cherry picked from commit a4edc11)

Co-authored-by: Matthew Treinish <mtreinish@kortar.org>
  • Loading branch information
mergify[bot] and mtreinish authored Apr 19, 2022
1 parent e653362 commit 095d2a4
Show file tree
Hide file tree
Showing 6 changed files with 250 additions and 189 deletions.
239 changes: 239 additions & 0 deletions qiskit/transpiler/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,8 @@
these ready-made routines.
.. _transpiler_supplemental:
Supplementary Information
=========================
Expand Down Expand Up @@ -354,6 +356,243 @@
<br>
.. 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
<br>
Transpiler API
==============
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand All @@ -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)
Expand All @@ -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)
Expand Down
4 changes: 2 additions & 2 deletions qiskit/transpiler/passes/scheduling/scheduling/alap.py
Original file line number Diff line number Diff line change
Expand Up @@ -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):
Expand Down
4 changes: 2 additions & 2 deletions qiskit/transpiler/passes/scheduling/scheduling/asap.py
Original file line number Diff line number Diff line change
Expand Up @@ -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):
Expand Down
Loading

0 comments on commit 095d2a4

Please sign in to comment.