mirror of https://github.com/Qiskit/qiskit.git
160 lines
8.0 KiB
YAML
160 lines
8.0 KiB
YAML
---
|
|
features:
|
|
- |
|
|
Introduced a new transpiler pass workflow for building :class:`~.PassManager` objects
|
|
for scheduling :class:`~.QuantumCircuit` objects in the transpiler. In the new
|
|
workflow, scheduling and alignment passes are all :class:`~.AnalysisPass` objects that
|
|
only update the pass manager's property set, specifically a new property set item
|
|
``node_start_time``, which holds the absolute start time of each opnode. A separate
|
|
:class:`~.TransformationPass` such as :class:`~.PadDelay` is subsequently used
|
|
to apply scheduling to the DAG. This new workflow is both more efficient and can
|
|
correct for additional timing constraints exposed by a backend.
|
|
|
|
Previously, the pass chain would have been implemented as ``scheduling -> alignment``
|
|
which were both transform passes thus there were multiple :class:`~.DAGCircuit`
|
|
instances recreated during each pass. In addition, scheduling occurred in each pass
|
|
to obtain instruction start time. Now the required pass chain becomes
|
|
``scheduling -> alignment -> padding`` where the :class:`~.DAGCircuit` update only
|
|
occurs at the end with the ``padding`` pass.
|
|
|
|
For those who are creating custom :class:`~.PassManager` objects that involve
|
|
circuit scheduling you will need to adjust your :class:`~.PassManager`
|
|
to insert one of the :class:`~.BasePadding` passes (currently
|
|
either :class:`~.PadDelay` or :class:`~.PadDynamicalDecoupling` can be used)
|
|
at the end of the scheduling pass chain. Without the padding pass the scheduling
|
|
passes will not be reflected in the output circuit of the :meth:`~.PassManager.run`
|
|
method of your custom :class:`~.PassManager`.
|
|
|
|
For example, if you were previously building your :class:`~.PassManager`
|
|
with something like::
|
|
|
|
from qiskit.transpiler import PassManager
|
|
from qiskit.transpiler.passes import TimeUnitConversion, ALAPSchedule, ValidatePulseGates, AlignMeasures
|
|
|
|
pm = PassManager()
|
|
scheduling = [
|
|
ALAPSchedule(instruction_durations), PadDelay()),
|
|
ValidatePulseGates(granularity=timing_constraints.granularity, min_length=timing_constraints.min_length),
|
|
AlignMeasures(alignment=timing_constraints.acquire_alignment),
|
|
]
|
|
pm.append(scheduling)
|
|
|
|
you can instead use::
|
|
|
|
from qiskit.transpiler import PassManager
|
|
from qiskit.transpiler.passes import TimeUnitConversion, ALAPScheduleAnalysis, ValidatePulseGates, AlignMeasures, PadDelay
|
|
|
|
pm = PassManager()
|
|
scheduling = [
|
|
ALAPScheduleAnalysis(instruction_durations), PadDelay()),
|
|
ConstrainedReschedule(acquire_alignment=timing_constraints.acquire_alignment, pulse_alignment=timing_constraints.pulse_alignment),
|
|
ValidatePulseGates(granularity=timing_constraints.granularity, min_length=timing_constraints.min_length),
|
|
PadDelay()
|
|
]
|
|
pm.append(scheduling)
|
|
|
|
which will both be more efficient and also align instructions based on any hardware constraints.
|
|
- |
|
|
Added a new transpiler pass :class:`~.ConstrainedReschedule` pass.
|
|
The :class:`~.ConstrainedReschedule` pass considers both hardware
|
|
alignment constraints that can be definied in a :class:`.BackendConfiguration`
|
|
object, ``pulse_alignment`` and ``acquire_alignment``. This new class superscedes
|
|
the previously existing :class:`~.AlignMeasures` as it performs the same alignment
|
|
(via the property set) for measurement instructions in addition to general instruction
|
|
alignment. By setting the ``acquire_alignment`` constraint argument for the
|
|
:class:`~.ConstrainedReschedule` pass it is a drop-in replacement of
|
|
:class:`~.AlignMeasures` when paired with a new :class:`~.BasePadding` pass.
|
|
- |
|
|
Added two new transpiler passes :class:`~.ALAPScheduleAnalysis` and :class:`~.ASAPScheduleAnalysis`
|
|
which superscede the :class:`~.ALAPSchedule` and :class:`~.ASAPSchedule` as part of the
|
|
reworked transpiler workflow for scheduling. The new passes perform the same scheduling but
|
|
in the property set and relying on a :class:`~.BasePadding` pass to adjust the circuit
|
|
based on all the scheduling alignment analysis.
|
|
|
|
The standard behavior of these passes also aligns timing ordering with the topological
|
|
ordering of the DAG nodes. This change may affect the scheduling outcome if it includes
|
|
conditional operations, or simultaneously measuring two qubits with the same classical
|
|
register (edge-case). To reproduce conventional behavior, set ``clbit_write_latency``
|
|
identical to the measurement instruction length.
|
|
|
|
For example, consider scheduling an input circuit like:
|
|
|
|
.. code-block:: text
|
|
|
|
┌───┐┌─┐
|
|
q_0: ┤ X ├┤M├──────────────
|
|
└───┘└╥┘ ┌───┐
|
|
q_1: ──────╫────┤ X ├──────
|
|
║ └─╥─┘ ┌─┐
|
|
q_2: ──────╫──────╫─────┤M├
|
|
║ ┌────╨────┐└╥┘
|
|
c: 1/══════╩═╡ c_0=0x1 ╞═╩═
|
|
0 └─────────┘ 0
|
|
|
|
|
|
.. code-block::
|
|
|
|
from qiskit import QuantumCircuit
|
|
from qiskit.transpiler import InstructionDurations, PassManager
|
|
from qiskit.transpiler.passes import ALAPScheduleAnalysis, PadDelay, SetIOLatency
|
|
from qiskit.visualization.timeline import draw
|
|
|
|
circuit = QuantumCircuit(3, 1)
|
|
circuit.x(0)
|
|
circuit.measure(0, 0)
|
|
circuit.x(1).c_if(0, 1)
|
|
circuit.measure(2, 0)
|
|
|
|
durations = InstructionDurations([("x", None, 160), ("measure", None, 800)])
|
|
|
|
pm = PassManager(
|
|
[
|
|
SetIOLatency(clbit_write_latency=800, conditional_latency=0),
|
|
ALAPScheduleAnalysis(durations),
|
|
PadDelay(),
|
|
]
|
|
)
|
|
draw(pm.run(circuit))
|
|
|
|
As you can see in the timeline view, the measurement on ``q_2`` starts before
|
|
the conditional X gate on the ``q_1``, which seems to be opposite to the
|
|
topological ordering of the node. This is also expected behavior
|
|
because clbit write-access happens at the end edge of the measure instruction,
|
|
and the read-access of the conditional gate happens the begin edge of the instruction.
|
|
Thus topological ordering is preserved on the timeslot of the classical register,
|
|
which is not captured by the timeline view.
|
|
However, this assumes a paticular microarchitecture design, and the circuit is
|
|
not necessary scheduled like this.
|
|
|
|
By using the default configuration of passes, the circuit is schedule like below.
|
|
|
|
.. code-block::
|
|
|
|
from qiskit import QuantumCircuit
|
|
from qiskit.transpiler import InstructionDurations, PassManager
|
|
from qiskit.transpiler.passes import ALAPScheduleAnalysis, PadDelay
|
|
from qiskit.visualization.timeline import draw
|
|
|
|
circuit = QuantumCircuit(3, 1)
|
|
circuit.x(0)
|
|
circuit.measure(0, 0)
|
|
circuit.x(1).c_if(0, 1)
|
|
circuit.measure(2, 0)
|
|
|
|
durations = InstructionDurations([("x", None, 160), ("measure", None, 800)])
|
|
|
|
pm = PassManager([ALAPScheduleAnalysis(durations), PadDelay()])
|
|
draw(pm.run(circuit))
|
|
|
|
Note that clbit is locked throughout the measurement instruction interval.
|
|
This behavior is designed based on the Qiskit Pulse, in which the acquire instruction takes
|
|
``AcquireChannel`` and ``MemorySlot`` which are not allowed to overlap with other instructions,
|
|
i.e. simultaneous memory access from the different instructions is prohibited.
|
|
This also always aligns the timing ordering with the topological node ordering.
|
|
- |
|
|
Added a new transpiler pass :class:`~.PadDynamicalDecoupling`
|
|
which superscedes the :class:`~.DynamicalDecoupling` pass as part of the
|
|
reworked transpiler workflow for scheduling. This new pass will insert dynamical decoupling
|
|
sequences into the circuit per any scheduling and alignment analysis that occurred in earlier
|
|
passes.
|