Note
This page was generated from tutorials/circuits_advanced/07_pulse_scheduler.ipynb.
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
from qiskit.test.mock import FakeAlmaden
backend = FakeAlmaden()
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()
[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))
circ.add_calibration('h', [0], h_q0)
schedule = build_schedule(circ, backend)
schedule.draw()
[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])
circ.draw("mpl")
[5]:

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.filter(channels=[pulse.DriveChannel(0), pulse.DriveChannel(1)]).draw()
[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.filter(channels=[pulse.DriveChannel(0), pulse.DriveChannel(1)]).draw()
[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
%qiskit_copyright
/home/computertreker/git/qiskit/qiskit/.tox/docs/lib/python3.7/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 Software | Version |
---|---|
qiskit-terra | 0.18.2 |
qiskit-aer | 0.8.2 |
qiskit-ignis | 0.6.0 |
qiskit-ibmq-provider | 0.16.0 |
qiskit-aqua | 0.9.5 |
qiskit | 0.29.1 |
qiskit-nature | 0.2.2 |
qiskit-finance | 0.3.0 |
qiskit-optimization | 0.2.3 |
qiskit-machine-learning | 0.2.1 |
System information | |
Python | 3.7.12 (default, Nov 22 2021, 14:57:10) [GCC 11.1.0] |
OS | Linux |
CPUs | 32 |
Memory (Gb) | 125.71650314331055 |
Tue Jan 04 11:07:40 2022 EST |
This code is a part of Qiskit
© Copyright IBM 2017, 2022.
This code is licensed under the Apache License, Version 2.0. You may
obtain a copy of this license in the LICENSE.txt file in the root directory
of this source tree or at http://www.apache.org/licenses/LICENSE-2.0.
Any modifications or derivative works of this code must retain this
copyright notice, and modified files need to carry a notice indicating
that they have been altered from the originals.
[ ]: