English
Languages
English
Bengali
French
German
Japanese
Korean
Portuguese
Spanish
Tamil

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]:
../../_images/tutorials_circuits_advanced_07_pulse_scheduler_1_0.png

We’ll use the mocked backend, FakeHanoi, 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.providers.fake_provider import FakeHanoi

backend = FakeHanoi()

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]:
../../_images/tutorials_circuits_advanced_07_pulse_scheduler_5_0.png

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]:
../../_images/tutorials_circuits_advanced_07_pulse_scheduler_7_0.png

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]:
../../_images/tutorials_circuits_advanced_07_pulse_scheduler_9_0.png

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]:
../../_images/tutorials_circuits_advanced_07_pulse_scheduler_11_0.png

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]:
../../_images/tutorials_circuits_advanced_07_pulse_scheduler_13_0.png

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

Version Information

Qiskit SoftwareVersion
qiskit-terra0.23.3
qiskit-aer0.12.0
qiskit-ibmq-provider0.20.2
qiskit0.42.1
qiskit-nature0.5.2
qiskit-finance0.3.4
qiskit-optimization0.5.0
qiskit-machine-learning0.5.0
System information
Python version3.8.16
Python compilerGCC 11.3.0
Python builddefault, Jan 11 2023 00:28:51
OSLinux
CPUs2
Memory (Gb)6.781219482421875
Mon Mar 27 16:36:41 2023 UTC

This code is a part of Qiskit

© Copyright IBM 2017, 2023.

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.