Note

Using the Scheduler¶

The scheduler will translate a QuantumCircuit into a Pulse Schedule, using gate and measurement calibrations: an optimized pulse-level description of an operation on particular qubits.

Backends that are OpenPulse enabled will typically have calibrations defined for measurements and for each of its basis gates. Calibrations can also be defined or updated by the user.

Basic usage¶

To start, build a quantum circuit as you would normally. For our example below, we create a simple Bell state.

[1]:

from qiskit import QuantumCircuit

circ = QuantumCircuit(2, 2)
circ.h(0)
circ.cx(0, 1)
circ.measure([0, 1], [0, 1])

circ.draw('mpl')

[1]:


We’ll use the mocked backend, FakeAlmaden, to demonstrate how to use the scheduler. It contains default calibrations for measurement and for its basis gates. The Hadamard operation is not one of those basis gates, so we use the transpiler to compile our input circuit to an equivalent circuit in terms of the basis gates of the device.

[2]:

from qiskit import transpile, schedule as build_schedule

transpiled_circ = transpile(circ, backend)  # Undefined Hadamard is replaced by U1
schedule = build_schedule(transpiled_circ, backend)


Let’s see how our schedule schedule built from the circuit transpiled_circ looks.

[3]:

schedule.draw(plot_range=[0, 2000])

/home/runner/work/qiskit/qiskit/.tox/docs/lib/python3.8/site-packages/qiskit/pulse/schedule.py:1657: DeprecationWarning: Legacy pulse drawer is deprecated. Specified arguments plot_range are deprecated. Please check the API document of new pulse drawer qiskit.visualization.pulse_drawer_v2.
warnings.warn(

[3]:


That covers the basics! We used the transpiler to rewrite the circuit in terms of the basis gates, and then used the backend’s default calibrations to schedule the transpiled circuit. Next we will go through scheduling with calibrations we will build ourselves.

Scheduling with custom gate definitions¶

If your input circuit has calibrations defined, it will use those calibrations when scheduling your circuit.

[4]:

from qiskit import pulse

with pulse.build() as h_q0:
pulse.play(pulse.library.Gaussian(duration=256, amp=0.2, sigma=50, name='custom'),
pulse.DriveChannel(0))

schedule = build_schedule(circ, backend)
schedule.draw(plot_range=[0, 2000])

/home/runner/work/qiskit/qiskit/.tox/docs/lib/python3.8/site-packages/qiskit/pulse/schedule.py:1657: DeprecationWarning: Legacy pulse drawer is deprecated. Specified arguments plot_range are deprecated. Please check the API document of new pulse drawer qiskit.visualization.pulse_drawer_v2.
warnings.warn(

[4]:


Notice that the initial pulse on D0, the Hadamard gate, is now implemented with our custom pulse.

Scheduler methods¶

The scheduler can follow multiple routines. By default, it follows an as late as possible (ALAP) rule. Another scheduling method is as soon as possible, (ASAP). For both methods, the output schedule is minimal: in the longest-duration operation path of the input circuit, the start time of each operation is the end time of the proceeding operation. The methods determine how to schedule operations outside that longest path.

This is made clear through an example:

[5]:

circ = QuantumCircuit(2, 2)
circ.x(0)
circ.x(0)
circ.x(1)
circ.measure([0, 1], [0, 1])

[5]:

<qiskit.circuit.instructionset.InstructionSet at 0x7faab01acee0>


For our mocked backend, these $$X$$ gate operations are each the same duration (duration = 160 dt). For the schedule to be minimal, the two $$X$$ operations on qubit 0 will be scheduled back-to-back, and the measurement pulse will immediately follow the second of those pulses.

ALAP will choose the latest valid time to schedule lesser-constrained operations, so the $$X$$ gate on qubit 1 will play in sync with the second $$X$$ gate on qubit 0.

[6]:

schedule = build_schedule(circ, backend,
method="as_late_as_possible")
schedule.draw(channels=[pulse.DriveChannel(0), pulse.DriveChannel(1)])

/home/runner/work/qiskit/qiskit/.tox/docs/lib/python3.8/site-packages/qiskit/pulse/schedule.py:1657: DeprecationWarning: Legacy pulse drawer is deprecated. Specified arguments channels are deprecated. Please check the API document of new pulse drawer qiskit.visualization.pulse_drawer_v2.
warnings.warn(

[6]:


On the other hand, as the name suggests, ASAP will schedule operations as soon as its resources are free. Thus, the $$X$$ gate on qubit 1 will be scheduled at time=0, in sync with the first $$X$$ gate on qubit 0.

[7]:

schedule = build_schedule(circ, backend,
method="as_soon_as_possible")
schedule.draw(channels=[pulse.DriveChannel(0), pulse.DriveChannel(1)])

/home/runner/work/qiskit/qiskit/.tox/docs/lib/python3.8/site-packages/qiskit/pulse/schedule.py:1657: DeprecationWarning: Legacy pulse drawer is deprecated. Specified arguments channels are deprecated. Please check the API document of new pulse drawer qiskit.visualization.pulse_drawer_v2.
warnings.warn(

[7]:


ALAP is the default because it allows qubits to remain idle as long as possible. In this case, the difference between ALAP and ASAP may be negligible, but in ALAP, qubit 0 has no time to decay from the excited state before measurement.

[8]:

import qiskit.tools.jupyter
%qiskit_version_table

/home/runner/work/qiskit/qiskit/.tox/docs/lib/python3.8/site-packages/qiskit/aqua/__init__.py:86: DeprecationWarning: The package qiskit.aqua is deprecated. It was moved/refactored to qiskit-terra For more information see <https://github.com/Qiskit/qiskit-aqua/blob/main/README.md#migration-guide>
warn_package('aqua', 'qiskit-terra')


Version Information

Qiskit SoftwareVersion
qiskit-terra0.18.3
qiskit-aer0.9.1
qiskit-ignis0.6.0
qiskit-ibmq-provider0.17.0
qiskit-aqua0.9.5
qiskit0.31.0
qiskit-nature0.2.2
qiskit-finance0.2.1
qiskit-optimization0.2.3
qiskit-machine-learning0.2.1
System information
Python3.8.12 (default, Sep 13 2021, 08:28:12) [GCC 9.3.0]
OSLinux
CPUs2
Memory (Gb)6.790924072265625
Thu Oct 21 17:49:48 2021 UTC

This code is a part of Qiskit

[ ]: