Skip to main contentIBM Quantum Documentation
You are viewing the API reference for an old version of Qiskit SDK. Switch to latest version

Pulse

qiskit.pulse

Qiskit-Pulse is a pulse-level quantum programming kit. This lower level of programming offers the user more control than programming with QuantumCircuits.

Extracting the greatest performance from quantum hardware requires real-time pulse-level instructions. Pulse answers that need: it enables the quantum physicist user to specify the exact time dynamics of an experiment. It is especially powerful for error mitigation techniques.

The input is given as arbitrary, time-ordered signals (see: Instructions) scheduled in parallel over multiple virtual hardware or simulator resources (see: Channels). The system also allows the user to recover the time dynamics of the measured output.

This is sufficient to allow the quantum physicist to explore and correct for noise in a quantum system.


Instructions

qiskit.pulse.instructions

The instructions module holds the various Instructions which are supported by Qiskit Pulse. Instructions have operands, which typically include at least one Channel specifying where the instruction will be applied.

Every instruction has a duration, whether explicitly included as an operand or implicitly defined. For instance, a ShiftPhase instruction can be instantiated with operands phase and channel, for some float phase and a Channel channel:

ShiftPhase(phase, channel)

The duration of this instruction is implicitly zero. On the other hand, the Delay instruction takes an explicit duration:

Delay(duration, channel)

An instruction can be added to a Schedule, which is a sequence of scheduled Pulse Instruction s over many channels. Instruction s and Schedule s implement the same interface.

Acquire(duration, channel[, mem_slot, ...])The Acquire instruction is used to trigger the ADC associated with a particular qubit; e.g.
Call(subroutine[, value_dict, name])Pulse Call instruction.
Reference(name, *extra_keys)Pulse compiler directive that refers to a subroutine.
Delay(duration, channel[, name])A blocking instruction with no other effect.
Play(pulse, channel[, name])This instruction is responsible for applying a pulse on a channel.
RelativeBarrier(*channels[, name])Pulse RelativeBarrier directive.
SetFrequency(frequency, channel[, name])Set the channel frequency.
ShiftFrequency(frequency, channel[, name])Shift the channel frequency away from the current frequency.
SetPhase(phase, channel[, name])The set phase instruction sets the phase of the proceeding pulses on that channel to phase radians.
ShiftPhase(phase, channel[, name])The shift phase instruction updates the modulation phase of proceeding pulses played on the same Channel.
Snapshot(label[, snapshot_type, name])An instruction targeted for simulators, to capture a moment in the simulation.
TimeBlockade(duration, channel[, name])Pulse TimeBlockade directive.

These are all instances of the same base class:

qiskit.pulse.instructions.Instruction(operands, name=None) GitHub(opens in a new tab)

The smallest schedulable unit: a single instruction. It has a fixed duration and specified channels.

Instruction initializer.

Parameters


Pulse Library

qiskit.pulse.library

This library provides Pulse users with convenient methods to build Pulse waveforms.

A pulse programmer can choose from one of several Pulse Models such as Waveform and SymbolicPulse to create a pulse program. The Waveform model directly stores the waveform data points in each class instance. This model provides the most flexibility to express arbitrary waveforms and allows a rapid prototyping of new control techniques. However, this model is typically memory inefficient and might be hard to scale to large-size quantum processors. Several waveform subclasses are defined by Waveform Pulse Representation, but a user can also directly instantiate the Waveform class with samples argument which is usually a complex numpy array or any kind of array-like data.

In contrast, the SymbolicPulse model only stores the function and its parameters that generate the waveform in a class instance. It thus provides greater memory efficiency at the price of less flexibility in the waveform. This model also defines a small set of pulse subclasses in Parametric Pulse Representation which are commonly used in superconducting quantum processors. An instance of these subclasses can be serialized in the QPY Format while keeping the memory-efficient parametric representation of waveforms. Note that Waveform object can be generated from an instance of a SymbolicPulse which will set values for the parameters and sample the parametric expression to create the Waveform.

Pulse Models

Waveform(samples[, name, epsilon, ...])A pulse specified completely by complex-valued samples; each sample is played for the duration of the backend cycle-time, dt.
SymbolicPulse(pulse_type, duration[, ...])The pulse representation model with parameters and symbolic expressions.
ParametricPulse(duration[, name, ...])The abstract superclass for parametric pulses.

Waveform Pulse Representation

constant

qiskit.pulse.library.constant(duration, amp, name=None) GitHub(opens in a new tab)

Generates constant-sampled Waveform.

For A=A= amp, samples from the function:

f(x)=Af(x) = A
Deprecated since version 0.46.0

The function qiskit.pulse.library.discrete.constant() is deprecated as of qiskit 0.46.0. It will be removed in the Qiskit 1.0 release. The discrete pulses library, including constant() is deprecated. Instead, use the SymbolicPulse library to create the waveform with pulse.Constant(…).get_waveform(). Note that complex value support for the amp parameter is deprecated in the SymbolicPulse library. Use two float values for (amp, angle) instead of complex amp

Parameters

Return type

Waveform

zero

qiskit.pulse.library.zero(duration, name=None) GitHub(opens in a new tab)

Generates zero-sampled Waveform.

Samples from the function:

f(x)=0f(x) = 0
Deprecated since version 0.46.0

The function qiskit.pulse.library.discrete.zero() is deprecated as of qiskit 0.46.0. It will be removed in the Qiskit 1.0 release. The discrete pulses library, including zero() is deprecated. Instead, use the SymbolicPulse library to create the waveform with pulse.Constant(amp=0,…).get_waveform().

Parameters

Return type

Waveform

square

qiskit.pulse.library.square(duration, amp, freq=None, phase=0, name=None) GitHub(opens in a new tab)

Generates square wave Waveform.

For A=A= amp, T=T= period, and ϕ=\phi= phase, applies the midpoint sampling strategy to generate a discrete pulse sampled from the continuous function:

f(x)=Asign[sin(2πxT+2ϕ)]f(x) = A \text{sign}\left[ \sin\left(\frac{2 \pi x}{T} + 2\phi\right) \right]

with the convention sign(0)=1\text{sign}(0) = 1.

Deprecated since version 0.46.0

The function qiskit.pulse.library.discrete.square() is deprecated as of qiskit 0.46.0. It will be removed in the Qiskit 1.0 release. The discrete pulses library, including square() is deprecated. Instead, use the SymbolicPulse library to create the waveform with pulse.Square(…).get_waveform(). Note that pulse.Square() does not support complex values for amp, and that the phase is defined differently. See documentation.

Parameters

Return type

Waveform

sawtooth

qiskit.pulse.library.sawtooth(duration, amp, freq=None, phase=0, name=None) GitHub(opens in a new tab)

Generates sawtooth wave Waveform.

For A=A= amp, T=T= period, and ϕ=\phi= phase, applies the midpoint sampling strategy to generate a discrete pulse sampled from the continuous function:

f(x)=2A(g(x)12+g(x))f(x) = 2 A \left( g(x) - \left\lfloor \frac{1}{2} + g(x) \right\rfloor\right)

where g(x)=x/T+ϕ/πg(x) = x/T + \phi/\pi.

Deprecated since version 0.46.0

The function qiskit.pulse.library.discrete.sawtooth() is deprecated as of qiskit 0.46.0. It will be removed in the Qiskit 1.0 release. The discrete pulses library, including sawtooth() is deprecated. Instead, use the SymbolicPulse library to create the waveform with pulse.Sawtooth(…).get_waveform(). Note that pulse.Sawtooth() does not support complex values for amp. Instead, use two float values for (amp, angle). Also note that the phase is defined differently, such that 2*pi phase shifts by a full cycle.

Parameters

Return type

Waveform

Example

import matplotlib.pyplot as plt
from qiskit.pulse.library import sawtooth
import numpy as np
 
duration = 100
amp = 1
freq = 1 / duration
sawtooth_wave = np.real(sawtooth(duration, amp, freq).samples)
plt.plot(range(duration), sawtooth_wave)
plt.show()
../_images/pulse-1.png

triangle

qiskit.pulse.library.triangle(duration, amp, freq=None, phase=0, name=None) GitHub(opens in a new tab)

Generates triangle wave Waveform.

For A=A= amp, T=T= period, and ϕ=\phi= phase, applies the midpoint sampling strategy to generate a discrete pulse sampled from the continuous function:

f(x)=A(2sawtooth(x,A,T,ϕ)+1)f(x) = A \left(-2\left|\text{sawtooth}(x, A, T, \phi)\right| + 1\right)

This a non-sinusoidal wave with linear ramping.

Deprecated since version 0.46.0

The function qiskit.pulse.library.discrete.triangle() is deprecated as of qiskit 0.46.0. It will be removed in the Qiskit 1.0 release. The discrete pulses library, including triangle() is deprecated. Instead, use the SymbolicPulse library to create the waveform with pulse.Triangle(…).get_waveform(). Note that pulse.Triangle() does not support complex values for amp. Instead, use two float values for (amp, angle).

Parameters

Return type

Waveform

Example

import matplotlib.pyplot as plt
from qiskit.pulse.library import triangle
import numpy as np
 
duration = 100
amp = 1
freq = 1 / duration
triangle_wave = np.real(triangle(duration, amp, freq).samples)
plt.plot(range(duration), triangle_wave)
plt.show()
../_images/pulse-2.png

cos

qiskit.pulse.library.cos(duration, amp, freq=None, phase=0, name=None) GitHub(opens in a new tab)

Generates cosine wave Waveform.

For A=A= amp, ω=\omega= freq, and ϕ=\phi= phase, applies the midpoint sampling strategy to generate a discrete pulse sampled from the continuous function:

f(x)=Acos(2πωx+ϕ)f(x) = A \cos(2 \pi \omega x + \phi)
Deprecated since version 0.46.0

The function qiskit.pulse.library.discrete.cos() is deprecated as of qiskit 0.46.0. It will be removed in the Qiskit 1.0 release. The discrete pulses library, including cos() is deprecated. Instead, use the SymbolicPulse library to create the waveform with pulse.Cos(…).get_waveform(). Note that pulse.Cos() does not support complex values for amp. Instead, use two float values for (amp, angle).

Parameters

Return type

Waveform

sin

qiskit.pulse.library.sin(duration, amp, freq=None, phase=0, name=None) GitHub(opens in a new tab)

Generates sine wave Waveform.

For A=A= amp, ω=\omega= freq, and ϕ=\phi= phase, applies the midpoint sampling strategy to generate a discrete pulse sampled from the continuous function:

f(x)=Asin(2πωx+ϕ)f(x) = A \sin(2 \pi \omega x + \phi)
Deprecated since version 0.46.0

The function qiskit.pulse.library.discrete.sin() is deprecated as of qiskit 0.46.0. It will be removed in the Qiskit 1.0 release. The discrete pulses library, including sin() is deprecated. Instead, use the SymbolicPulse library to create the waveform with pulse.Sin(…).get_waveform(). Note that pulse.Sin() does not support complex values for amp. Instead, use two float values for (amp, angle).

Parameters

Return type

Waveform

gaussian

qiskit.pulse.library.gaussian(duration, amp, sigma, name=None, zero_ends=True) GitHub(opens in a new tab)

Generates unnormalized gaussian Waveform.

For A=A= amp and σ=\sigma= sigma, applies the midpoint sampling strategy to generate a discrete pulse sampled from the continuous function:

f(x)=Aexp((xμ2σ)2),f(x) = A\exp\left(\left(\frac{x - \mu}{2\sigma}\right)^2 \right),

with the center μ=\mu= duration/2.

If zero_ends==True, each output sample yy is modified according to:

yAyyAy,y \mapsto A\frac{y-y^*}{A-y^*},

where yy^* is the value of the endpoint samples. This sets the endpoints to 00 while preserving the amplitude at the center. If A=yA=y^*, yy is set to 11. By default, the endpoints are at x = -1, x = duration + 1.

Integrated area under the full curve is amp * np.sqrt(2*np.pi*sigma**2)

Deprecated since version 0.46.0

The function qiskit.pulse.library.discrete.gaussian() is deprecated as of qiskit 0.46.0. It will be removed in the Qiskit 1.0 release. The discrete pulses library, including gaussian() is deprecated. Instead, use the SymbolicPulse library to create the waveform with pulse.Gaussian(…).get_waveform(). Note that complex value support for the amp parameter is deprecated in the SymbolicPulse library. It is therefore recommended to use two float values for (amp, angle) instead of complex amp

Parameters

Return type

Waveform

gaussian_deriv

qiskit.pulse.library.gaussian_deriv(duration, amp, sigma, name=None) GitHub(opens in a new tab)

Generates unnormalized gaussian derivative Waveform.

For A=A= amp and σ=\sigma= sigma applies the midpoint sampling strategy to generate a discrete pulse sampled from the continuous function:

f(x)=A(xμ)σ2exp(12(xμσ)2)f(x) = -A\frac{(x - \mu)}{\sigma^2}\exp \left(-\frac{1}{2}\left(\frac{x - \mu}{\sigma}\right)^2 \right)

i.e. the derivative of the Gaussian function, with center μ=\mu= duration/2.

Deprecated since version 0.46.0

The function qiskit.pulse.library.discrete.gaussian_deriv() is deprecated as of qiskit 0.46.0. It will be removed in the Qiskit 1.0 release. The discrete pulses library, including gaussian_deriv() is deprecated. Instead, use the SymbolicPulse library to create the waveform with pulse.GaussianDeriv(…).get_waveform(). Note that pulse.GaussianDeriv() does not support complex values for amp. Instead, use two float values for (amp, angle).

Parameters

Return type

Waveform

sech

qiskit.pulse.library.sech(duration, amp, sigma, name=None, zero_ends=True) GitHub(opens in a new tab)

Generates unnormalized sech Waveform.

For A=A= amp and σ=\sigma= sigma, applies the midpoint sampling strategy to generate a discrete pulse sampled from the continuous function:

f(x)=Asech(xμσ)f(x) = A\text{sech}\left(\frac{x-\mu}{\sigma} \right)

with the center μ=\mu= duration/2.

If zero_ends==True, each output sample yy is modified according to:

yAyyAy,y \mapsto A\frac{y-y^*}{A-y^*},

where yy^* is the value of the endpoint samples. This sets the endpoints to 00 while preserving the amplitude at the center. If A=yA=y^*, yy is set to 11. By default, the endpoints are at x = -1, x = duration + 1.

Deprecated since version 0.46.0

The function qiskit.pulse.library.discrete.sech() is deprecated as of qiskit 0.46.0. It will be removed in the Qiskit 1.0 release. The discrete pulses library, including sech() is deprecated. Instead, use the SymbolicPulse library to create the waveform with pulse.Sech(…).get_waveform(). Note that pulse.Sech() does not support complex values for amp. Instead, use two float values for (amp, angle).

Parameters

Return type

Waveform

sech_deriv

qiskit.pulse.library.sech_deriv(duration, amp, sigma, name=None) GitHub(opens in a new tab)

Generates unnormalized sech derivative Waveform.

For A=A= amp, σ=\sigma= sigma, and center μ=\mu= duration/2, applies the midpoint sampling strategy to generate a discrete pulse sampled from the continuous function:

f(x)=ddx[Asech(xμσ)],f(x) = \frac{d}{dx}\left[A\text{sech}\left(\frac{x-\mu}{\sigma} \right)\right],

i.e. the derivative of sech\text{sech}.

Deprecated since version 0.46.0

The function qiskit.pulse.library.discrete.sech_deriv() is deprecated as of qiskit 0.46.0. It will be removed in the Qiskit 1.0 release. The discrete pulses library, including sech_deriv() is deprecated. Instead, use the SymbolicPulse library to create the waveform with pulse.SechDeriv(…).get_waveform(). Note that pulse.SechDeriv() does not support complex values for amp. Instead, use two float values for (amp, angle).

Parameters

Return type

Waveform

gaussian_square

qiskit.pulse.library.gaussian_square(duration, amp, sigma, risefall=None, width=None, name=None, zero_ends=True) GitHub(opens in a new tab)

Generates gaussian square Waveform.

For d=d= duration, A=A= amp, σ=\sigma= sigma, and r=r= risefall, applies the midpoint sampling strategy to generate a discrete pulse sampled from the continuous function:

f(x)={g(xr))xrArxdrg(x(dr))drxf(x) = \begin{cases} g(x - r) ) & x\leq r \\ A & r\leq x\leq d-r \\ g(x - (d - r)) & d-r\leq x \end{cases}

where g(x)g(x) is the Gaussian function sampled from in gaussian() with A=A= amp, μ=1\mu=1, and σ=\sigma= sigma. I.e. f(x)f(x) represents a square pulse with smooth Gaussian edges.

If zero_ends == True, the samples for the Gaussian ramps are remapped as in gaussian().

Deprecated since version 0.46.0

The function qiskit.pulse.library.discrete.gaussian_square() is deprecated as of qiskit 0.46.0. It will be removed in the Qiskit 1.0 release. The discrete pulses library, including gaussian_square() is deprecated. Instead, use the SymbolicPulse library to create the waveform with pulse.GaussianSquare(…).get_waveform(). Note that complex value support for the amp parameter is deprecated in the SymbolicPulse library. It is therefore recommended to use two float values for (amp, angle) instead of complex amp

Parameters

Raises

PulseError – If risefall and width arguments are inconsistent or not enough info.

Return type

Waveform

drag

qiskit.pulse.library.drag(duration, amp, sigma, beta, name=None, zero_ends=True) GitHub(opens in a new tab)

Generates Y-only correction DRAG Waveform for standard nonlinear oscillator (SNO) [1].

For A=A= amp, σ=\sigma= sigma, and β=\beta= beta, applies the midpoint sampling strategy to generate a discrete pulse sampled from the continuous function:

f(x)=g(x)+iβh(x),f(x) = g(x) + i \beta h(x),

where g(x)g(x) is the function sampled in gaussian(), and h(x)h(x) is the function sampled in gaussian_deriv().

If zero_ends == True, the samples from g(x)g(x) are remapped as in gaussian().

Deprecated since version 0.46.0

The function qiskit.pulse.library.discrete.drag() is deprecated as of qiskit 0.46.0. It will be removed in the Qiskit 1.0 release. The discrete pulses library, including drag() is deprecated. Instead, use the SymbolicPulse library to create the waveform with pulse.Drag(…).get_waveform(). Note that complex value support for the amp parameter is deprecated in the SymbolicPulse library. It is therefore recommended to use two float values for (amp, angle) instead of complex amp

References

  1. Gambetta, J. M., Motzoi, F., Merkel, S. T. & Wilhelm, F. K. “Analytic control methods for high-fidelity unitary operations in a weakly nonlinear oscillator.” Phys. Rev. A 83, 012308 (2011).(opens in a new tab)

Parameters

  • duration (int(opens in a new tab)) – Duration of pulse. Must be greater than zero.
  • amp (complex(opens in a new tab)) – Pulse amplitude at center duration/2.
  • sigma (float(opens in a new tab)) – Width (standard deviation) of pulse.
  • beta (float(opens in a new tab)) – Y correction amplitude. For the SNO this is β=λ124Δ2\beta=-\frac{\lambda_1^2}{4\Delta_2}. Where λ1\lambda_1 is the relative coupling strength between the first excited and second excited states and Δ2\Delta_2 is the detuning between the respective excited states.
  • name (str(opens in a new tab) | None) – Name of pulse.
  • zero_ends (bool(opens in a new tab)) – If True, zero ends at x = -1, x = duration + 1, but rescale to preserve amp.

Return type

Waveform

Parametric Pulse Representation

Constant(duration, amp[, angle, name, ...])A simple constant pulse, with an amplitude value and a duration:
Drag(duration, amp, sigma, beta[, angle, ...])The Derivative Removal by Adiabatic Gate (DRAG) pulse is a standard Gaussian pulse with an additional Gaussian derivative component and lifting applied.
Gaussian(duration, amp, sigma[, angle, ...])A lifted and truncated pulse envelope shaped according to the Gaussian function whose mean is centered at the center of the pulse (duration / 2):
GaussianSquare(duration, amp, sigma[, ...])A square pulse with a Gaussian shaped risefall on both sides lifted such that its first sample is zero.
GaussianSquareDrag(duration, amp, sigma, beta)A square pulse with a Drag shaped rise and fall
gaussian_square_echo(duration, amp, sigma[, ...])An echoed Gaussian square pulse with an active tone overlaid on it.
GaussianDeriv(duration, amp, sigma[, angle, ...])An unnormalized Gaussian derivative pulse.
Sin(duration, amp, phase[, freq, angle, ...])A sinusoidal pulse.
Cos(duration, amp, phase[, freq, angle, ...])A cosine pulse.
Sawtooth(duration, amp, phase[, freq, ...])A sawtooth pulse.
Triangle(duration, amp, phase[, freq, ...])A triangle wave pulse.
Square(duration, amp, phase[, freq, angle, ...])A square wave pulse.
Sech(duration, amp, sigma[, angle, name, ...])An unnormalized sech pulse.
SechDeriv(duration, amp, sigma[, angle, ...])An unnormalized sech derivative pulse.

Channels

qiskit.pulse.channels

Pulse is meant to be agnostic to the underlying hardware implementation, while still allowing low-level control. Therefore, our signal channels are virtual hardware channels. The backend which executes our programs is responsible for mapping these virtual channels to the proper physical channel within the quantum control hardware.

Channels are characterized by their type and their index. Channels include:

Novel channel types can often utilize the ControlChannel, but if this is not sufficient, new channel types can be created. Then, they must be supported in the PulseQobj schema and the assembler. Channels are characterized by their type and their index. See each channel type below to learn more.

DriveChannel(*args, **kwargs)Drive channels transmit signals to qubits which enact gate operations.
MeasureChannel(*args, **kwargs)Measure channels transmit measurement stimulus pulses for readout.
AcquireChannel(*args, **kwargs)Acquire channels are used to collect data.
ControlChannel(*args, **kwargs)Control channels provide supplementary control over the qubit to the drive channel.
RegisterSlot(*args, **kwargs)Classical resister slot channels represent classical registers (low-latency classical memory).
MemorySlot(*args, **kwargs)Memory slot channels represent classical memory storage.
SnapshotChannel(*args, **kwargs)Snapshot channels are used to specify instructions for simulators.

All channels are children of the same abstract base class:

qiskit.pulse.channels.Channel(*args, **kwargs) GitHub(opens in a new tab)

Base class of channels. Channels provide a Qiskit-side label for typical quantum control hardware signal channels. The final label -> physical channel mapping is the responsibility of the hardware backend. For instance, DriveChannel(0) holds instructions which the backend should map to the signal line driving gate operations on the qubit labeled (indexed) 0.

When serialized channels are identified by their serialized name <prefix><index>. The type of the channel is interpreted from the prefix, and the index often (but not always) maps to the qubit index. All concrete channel classes must have a prefix class attribute (and instances of that class have an index attribute). Base classes which have prefix set to None are prevented from being instantiated.

To implement a new channel inherit from Channel and provide a unique string identifier for the prefix class attribute.

Channel class.

Parameters

index – Index of channel.


Schedules

Schedules are Pulse programs. They describe instruction sequences for the control hardware. The Schedule is one of the most fundamental objects to this pulse-level programming module. A Schedule is a representation of a program in Pulse. Each schedule tracks the time of each instruction occuring in parallel over multiple signal channels.

Schedule(*schedules[, name, metadata])A quantum program schedule with exact time constraints for its instructions, operating over all input signal channels and supporting special syntaxes for building.
ScheduleBlock([name, metadata, ...])Time-ordered sequence of instructions with alignment context.

Pulse Transforms

qiskit.pulse.transforms

The pulse transforms provide transformation routines to reallocate and optimize pulse programs for backends.

Alignments

The alignment transforms define alignment policies of instructions in ScheduleBlock. These transformations are called to create Schedules from ScheduleBlocks.

AlignEquispaced(duration)Align instructions with equispaced interval within a specified duration.
AlignFunc(duration, func)Allocate instructions at position specified by callback function.
AlignLeft()Align instructions in as-soon-as-possible manner.
AlignRight()Align instructions in as-late-as-possible manner.
AlignSequential()Align instructions sequentially.

These are all subtypes of the abstract base class AlignmentKind.

qiskit.pulse.transforms.AlignmentKind(context_params) GitHub(opens in a new tab)

An abstract class for schedule alignment.

Create new context.

Canonicalization

The canonicalization transforms convert schedules to a form amenable for execution on OpenPulse backends.

add_implicit_acquires

qiskit.pulse.transforms.add_implicit_acquires(schedule, meas_map) GitHub(opens in a new tab)

Return a new schedule with implicit acquires from the measurement mapping replaced by explicit ones.

Warning

Since new acquires are being added, Memory Slots will be set to match the qubit index. This may overwrite your specification.

Parameters

Returns

A Schedule with the additional acquisition instructions.

Return type

Schedule

align_measures

qiskit.pulse.transforms.align_measures(schedules, inst_map=None, cal_gate='u3', max_calibration_duration=None, align_time=None, align_all=True) GitHub(opens in a new tab)

Return new schedules where measurements occur at the same physical time.

This transformation will align the first Acquire on every channel to occur at the same time.

Minimum measurement wait time (to allow for calibration pulses) is enforced and may be set with max_calibration_duration.

By default only instructions containing a AcquireChannel or MeasureChannel will be shifted. If you wish to keep the relative timing of all instructions in the schedule set align_all=True.

This method assumes that MeasureChannel(i) and AcquireChannel(i) correspond to the same qubit and the acquire/play instructions should be shifted together on these channels.

from qiskit import pulse
from qiskit.pulse import transforms
 
d0 = pulse.DriveChannel(0)
m0 = pulse.MeasureChannel(0)
a0 = pulse.AcquireChannel(0)
mem0 = pulse.MemorySlot(0)
 
sched = pulse.Schedule()
sched.append(pulse.Play(pulse.Constant(10, 0.5), d0), inplace=True)
sched.append(pulse.Play(pulse.Constant(10, 1.), m0).shift(sched.duration), inplace=True)
sched.append(pulse.Acquire(20, a0, mem0).shift(sched.duration), inplace=True)
 
sched_shifted = sched << 20
 
aligned_sched, aligned_sched_shifted = transforms.align_measures([sched, sched_shifted])
 
assert aligned_sched == aligned_sched_shifted

If it is desired to only shift acquisition and measurement stimulus instructions set the flag align_all=False:

aligned_sched, aligned_sched_shifted = transforms.align_measures(
    [sched, sched_shifted],
    align_all=False,
)
 
assert aligned_sched != aligned_sched_shifted

Parameters

Returns

The input list of schedules transformed to have their measurements aligned.

Raises

PulseError – If the provided alignment time is negative.

Return type

List(opens in a new tab)[Schedule]

block_to_schedule

qiskit.pulse.transforms.block_to_schedule(block) GitHub(opens in a new tab)

Convert ScheduleBlock to Schedule.

Parameters

block (ScheduleBlock) – A ScheduleBlock to convert.

Returns

Scheduled pulse program.

Raises

  • UnassignedDurationError – When any instruction duration is not assigned.
  • PulseError – When the alignment context duration is shorter than the schedule duration.

Return type

Schedule

Note

This transform may insert barriers in between contexts.

compress_pulses

qiskit.pulse.transforms.compress_pulses(schedules) GitHub(opens in a new tab)

Optimization pass to replace identical pulses.

Parameters

schedules (List(opens in a new tab)[Schedule]) – Schedules to compress.

Returns

Compressed schedules.

Return type

List(opens in a new tab)[Schedule]

flatten

qiskit.pulse.transforms.flatten(program) GitHub(opens in a new tab)

Flatten (inline) any called nodes into a Schedule tree with no nested children.

Parameters

program (Schedule) – Pulse program to remove nested structure.

Returns

Flatten pulse program.

Raises

PulseError – When invalid data format is given.

Return type

Schedule

inline_subroutines

qiskit.pulse.transforms.inline_subroutines(program) GitHub(opens in a new tab)

Recursively remove call instructions and inline the respective subroutine instructions.

Assigned parameter values, which are stored in the parameter table, are also applied. The subroutine is copied before the parameter assignment to avoid mutation problem.

Parameters

program (Schedule |ScheduleBlock) – A program which may contain the subroutine, i.e. Call instruction.

Returns

A schedule without subroutine.

Raises

PulseError – When input program is not valid data format.

Return type

Schedule | ScheduleBlock

pad

qiskit.pulse.transforms.pad(schedule, channels=None, until=None, inplace=False, pad_with=None) GitHub(opens in a new tab)

Pad the input Schedule with Delay``s on all unoccupied timeslots until ``schedule.duration or until if not None.

Parameters

Returns

The padded schedule.

Raises

PulseError – When non pulse instruction is set to pad_with.

Return type

Schedule

remove_directives

qiskit.pulse.transforms.remove_directives(schedule) GitHub(opens in a new tab)

Remove directives.

Parameters

schedule (Schedule) – A schedule to remove compiler directives.

Returns

A schedule without directives.

Return type

Schedule

remove_trivial_barriers

qiskit.pulse.transforms.remove_trivial_barriers(schedule) GitHub(opens in a new tab)

Remove trivial barriers with 0 or 1 channels.

Parameters

schedule (Schedule) – A schedule to remove trivial barriers.

Returns

A schedule without trivial barriers

Return type

schedule

DAG

The DAG transforms create DAG representation of input program. This can be used for optimization of instructions and equality checks.

block_to_dag

qiskit.pulse.transforms.block_to_dag(block) GitHub(opens in a new tab)

Convert schedule block instruction into DAG.

ScheduleBlock can be represented as a DAG as needed. For example, equality of two programs are efficiently checked on DAG representation.

with pulse.build() as sched1:
    with pulse.align_left():
        pulse.play(my_gaussian0, pulse.DriveChannel(0))
        pulse.shift_phase(1.57, pulse.DriveChannel(2))
        pulse.play(my_gaussian1, pulse.DriveChannel(1))
 
with pulse.build() as sched2:
    with pulse.align_left():
        pulse.shift_phase(1.57, pulse.DriveChannel(2))
        pulse.play(my_gaussian1, pulse.DriveChannel(1))
        pulse.play(my_gaussian0, pulse.DriveChannel(0))

Here the sched1 `` and ``sched2 are different implementations of the same program, but it is difficult to confirm on the list representation.

Another example is instruction optimization.

with pulse.build() as sched:
    with pulse.align_left():
        pulse.shift_phase(1.57, pulse.DriveChannel(1))
        pulse.play(my_gaussian0, pulse.DriveChannel(0))
        pulse.shift_phase(-1.57, pulse.DriveChannel(1))

In above program two shift_phase instructions can be cancelled out because they are consecutive on the same drive channel. This can be easily found on the DAG representation.

Parameters

block ("ScheduleBlock") – A schedule block to be converted.

Returns

Instructions in DAG representation.

Raises

PulseError – When the context is invalid subclass.

Return type

PyDAG(opens in a new tab)

Composite transform

A sequence of transformations to generate a target code.

target_qobj_transform

qiskit.pulse.transforms.target_qobj_transform(sched, remove_directives=True) GitHub(opens in a new tab)

A basic pulse program transformation for OpenPulse API execution.

Parameters

Returns

Transformed program for execution.

Return type

Schedule


Pulse Builder

Use the pulse builder DSL to write pulse programs with an imperative syntax.

Warning

The pulse builder interface is still in active development. It may have breaking API changes without deprecation warnings in future releases until otherwise indicated.

The pulse builder provides an imperative API for writing pulse programs with less difficulty than the Schedule API. It contextually constructs a pulse schedule and then emits the schedule for execution. For example, to play a series of pulses on channels is as simple as:

from qiskit import pulse
 
dc = pulse.DriveChannel
d0, d1, d2, d3, d4 = dc(0), dc(1), dc(2), dc(3), dc(4)
 
with pulse.build(name='pulse_programming_in') as pulse_prog:
    pulse.play([1, 1, 1, 0, 0, 1, 1, 1, 0, 1, 1, 1, 0, 1, 0, 1, 0, 1, 1, 1, 0, 1, 1, 1], d0)
    pulse.play([1, 0, 1, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 1, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0], d1)
    pulse.play([1, 0, 1, 0, 0, 0, 1, 0, 0, 1, 1, 1, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 1, 0], d2)
    pulse.play([1, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 1, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0], d3)
    pulse.play([1, 1, 1, 1, 0, 1, 1, 1, 0, 1, 1, 1, 0, 1, 0, 1, 0, 1, 1, 1, 0, 0, 1, 0], d4)
 
pulse_prog.draw()
../_images/pulse-3.png

To begin pulse programming we must first initialize our program builder context with build(), after which we can begin adding program statements. For example, below we write a simple program that play()s a pulse:

from qiskit import execute, pulse
 
d0 = pulse.DriveChannel(0)
 
with pulse.build() as pulse_prog:
    pulse.play(pulse.Constant(100, 1.0), d0)
 
pulse_prog.draw()
../_images/pulse-4.png

The builder initializes a pulse.Schedule, pulse_prog and then begins to construct the program within the context. The output pulse schedule will survive after the context is exited and can be executed like a normal Qiskit schedule using qiskit.execute(pulse_prog, backend).

Pulse programming has a simple imperative style. This leaves the programmer to worry about the raw experimental physics of pulse programming and not constructing cumbersome data structures.

We can optionally pass a Backend to build() to enable enhanced functionality. Below, we prepare a Bell state by automatically compiling the required pulses from their gate-level representations, while simultaneously applying a long decoupling pulse to a neighboring qubit. We terminate the experiment with a measurement to observe the state we prepared. This program which mixes circuits and pulses will be automatically lowered to be run as a pulse program:

import math
 
from qiskit import pulse
from qiskit.providers.fake_provider import FakeOpenPulse3Q
 
# TODO: This example should use a real mock backend.
backend = FakeOpenPulse3Q()
 
d2 = pulse.DriveChannel(2)
 
with pulse.build(backend) as bell_prep:
    pulse.u2(0, math.pi, 0)
    pulse.cx(0, 1)
 
with pulse.build(backend) as decoupled_bell_prep_and_measure:
    # We call our bell state preparation schedule constructed above.
    with pulse.align_right():
        pulse.call(bell_prep)
        pulse.play(pulse.Constant(bell_prep.duration, 0.02), d2)
        pulse.barrier(0, 1, 2)
        registers = pulse.measure_all()
 
decoupled_bell_prep_and_measure.draw()
../_images/pulse-5.png
Warning

Calling gates directly within the pulse builder namespace is deprecated as of qiskit 0.46.0.

With the pulse builder we are able to blend programming on qubits and channels. While the pulse schedule is based on instructions that operate on channels, the pulse builder automatically handles the mapping from qubits to channels for you.

In the example below we demonstrate some more features of the pulse builder:

import math
 
from qiskit import pulse, QuantumCircuit
from qiskit.pulse import library
from qiskit.providers.fake_provider import FakeOpenPulse2Q
 
backend = FakeOpenPulse2Q()
 
with pulse.build(backend) as pulse_prog:
    # Create a pulse.
    gaussian_pulse = library.gaussian(10, 1.0, 2)
    # Get the qubit's corresponding drive channel from the backend.
    d0 = pulse.drive_channel(0)
    d1 = pulse.drive_channel(1)
    # Play a pulse at t=0.
    pulse.play(gaussian_pulse, d0)
    # Play another pulse directly after the previous pulse at t=10.
    pulse.play(gaussian_pulse, d0)
    # The default scheduling behavior is to schedule pulses in parallel
    # across channels. For example, the statement below
    # plays the same pulse on a different channel at t=0.
    pulse.play(gaussian_pulse, d1)
 
    # We also provide pulse scheduling alignment contexts.
    # The default alignment context is align_left.
 
    # The sequential context schedules pulse instructions sequentially in time.
    # This context starts at t=10 due to earlier pulses above.
    with pulse.align_sequential():
        pulse.play(gaussian_pulse, d0)
        # Play another pulse after at t=20.
        pulse.play(gaussian_pulse, d1)
 
        # We can also nest contexts as each instruction is
        # contained in its local scheduling context.
        # The output of a child context is a context-schedule
        # with the internal instructions timing fixed relative to
        # one another. This is schedule is then called in the parent context.
 
        # Context starts at t=30.
        with pulse.align_left():
            # Start at t=30.
            pulse.play(gaussian_pulse, d0)
            # Start at t=30.
            pulse.play(gaussian_pulse, d1)
        # Context ends at t=40.
 
        # Alignment context where all pulse instructions are
        # aligned to the right, ie., as late as possible.
        with pulse.align_right():
            # Shift the phase of a pulse channel.
            pulse.shift_phase(math.pi, d1)
            # Starts at t=40.
            pulse.delay(100, d0)
            # Ends at t=140.
 
            # Starts at t=130.
            pulse.play(gaussian_pulse, d1)
            # Ends at t=140.
 
        # Acquire data for a qubit and store in a memory slot.
        pulse.acquire(100, 0, pulse.MemorySlot(0))
 
        # We also support a variety of macros for common operations.
 
        # Measure all qubits.
        pulse.measure_all()
 
        # Delay on some qubits.
        # This requires knowledge of which channels belong to which qubits.
        # delay for 100 cycles on qubits 0 and 1.
        pulse.delay_qubits(100, 0, 1)
 
        # Call a quantum circuit. The pulse builder lazily constructs a quantum
        # circuit which is then transpiled and scheduled before inserting into
        # a pulse schedule.
        # NOTE: Quantum register indices correspond to physical qubit indices.
        qc = QuantumCircuit(2, 2)
        qc.cx(0, 1)
        pulse.call(qc)
        # Calling a small set of standard gates and decomposing to pulses is
        # also supported with more natural syntax.
        pulse.u3(0, math.pi, 0, 0)
        pulse.cx(0, 1)
 
 
        # It is also be possible to call a preexisting schedule
        tmp_sched = pulse.Schedule()
        tmp_sched += pulse.Play(gaussian_pulse, d0)
        pulse.call(tmp_sched)
 
        # We also support:
 
        # frequency instructions
        pulse.set_frequency(5.0e9, d0)
 
        # phase instructions
        pulse.shift_phase(0.1, d0)
 
        # offset contexts
        with pulse.phase_offset(math.pi, d0):
            pulse.play(gaussian_pulse, d0)
Warning

Calling gates directly within the pulse builder namespace is deprecated as of qiskit 0.46.0.

The above is just a small taste of what is possible with the builder. See the rest of the module documentation for more information on its capabilities.

build

qiskit.pulse.builder.build(backend=None, schedule=None, name=None, default_alignment='left', default_transpiler_settings=None, default_circuit_scheduler_settings=None) GitHub(opens in a new tab)

Create a context manager for launching the imperative pulse builder DSL.

To enter a building context and starting building a pulse program:

from qiskit import transpile, pulse
from qiskit.providers.fake_provider import FakeOpenPulse2Q
 
backend = FakeOpenPulse2Q()
 
d0 = pulse.DriveChannel(0)
 
with pulse.build() as pulse_prog:
    pulse.play(pulse.Constant(100, 0.5), d0)

While the output program pulse_prog cannot be executed as we are using a mock backend. If a real backend is being used, executing the program is done with:

backend.run(transpile(pulse_prog, backend))
Deprecated since version 0.46.0

qiskit.pulse.builder.build()’s argument default_circuit_scheduler_settings is deprecated as of qiskit 0.46.0. It will be removed in the Qiskit 1.0 release. setting parameter default_circuit_scheduler_settings in build() was used for gate operations, which are deprecated. pulse schedules should only be used for gate calibrations as part of a quantum circuit, and not vice versa

Deprecated since version 0.46.0

qiskit.pulse.builder.build()’s argument default_transpiler_settings is deprecated as of qiskit 0.46.0. It will be removed in the Qiskit 1.0 release. setting parameter default_transpiler_settings in build() was used for gate operations, which are deprecated. pulse schedules should only be used for gate calibrations as part of a quantum circuit, and not vice versa

Parameters

Returns

A new builder context which has the active builder initialized.

Return type

ContextManager(opens in a new tab)[ScheduleBlock]

Channels

Methods to return the correct channels for the respective qubit indices.

from qiskit import pulse
from qiskit.providers.fake_provider import FakeArmonk
 
backend = FakeArmonk()
 
with pulse.build(backend) as drive_sched:
    d0 = pulse.drive_channel(0)
    print(d0)
DriveChannel(0)

acquire_channel

qiskit.pulse.builder.acquire_channel(qubit) GitHub(opens in a new tab)

Return AcquireChannel for qubit on the active builder backend.

Examples:

from qiskit import pulse
from qiskit.providers.fake_provider import FakeOpenPulse2Q
 
backend = FakeOpenPulse2Q()
 
with pulse.build(backend):
    assert pulse.acquire_channel(0) == pulse.AcquireChannel(0)
Note

Requires the active builder context to have a backend set.

Return type

AcquireChannel

control_channels

qiskit.pulse.builder.control_channels(*qubits) GitHub(opens in a new tab)

Return ControlChannel for qubit on the active builder backend.

Return the secondary drive channel for the given qubit – typically utilized for controlling multi-qubit interactions.

Examples:

from qiskit import pulse
from qiskit.providers.fake_provider import FakeOpenPulse2Q
 
backend = FakeOpenPulse2Q()
with pulse.build(backend):
    assert pulse.control_channels(0, 1) == [pulse.ControlChannel(0)]
Note

Requires the active builder context to have a backend set.

Parameters

qubits (Iterable(opens in a new tab)[int(opens in a new tab)]) – Tuple or list of ordered qubits of the form (control_qubit, target_qubit).

Returns

List of control channels associated with the supplied ordered list of qubits.

Return type

List(opens in a new tab)[ControlChannel]

drive_channel

qiskit.pulse.builder.drive_channel(qubit) GitHub(opens in a new tab)

Return DriveChannel for qubit on the active builder backend.

Examples:

from qiskit import pulse
from qiskit.providers.fake_provider import FakeOpenPulse2Q
 
backend = FakeOpenPulse2Q()
 
with pulse.build(backend):
    assert pulse.drive_channel(0) == pulse.DriveChannel(0)
Note

Requires the active builder context to have a backend set.

Return type

DriveChannel

measure_channel

qiskit.pulse.builder.measure_channel(qubit) GitHub(opens in a new tab)

Return MeasureChannel for qubit on the active builder backend.

Examples:

from qiskit import pulse
from qiskit.providers.fake_provider import FakeOpenPulse2Q
 
backend = FakeOpenPulse2Q()
 
with pulse.build(backend):
    assert pulse.measure_channel(0) == pulse.MeasureChannel(0)
Note

Requires the active builder context to have a backend set.

Return type

MeasureChannel

Instructions

Pulse instructions are available within the builder interface. Here’s an example:

from qiskit import pulse
from qiskit.providers.fake_provider import FakeArmonk
 
backend = FakeArmonk()
 
with pulse.build(backend) as drive_sched:
    d0 = pulse.drive_channel(0)
    a0 = pulse.acquire_channel(0)
 
    pulse.play(pulse.library.Constant(10, 1.0), d0)
    pulse.delay(20, d0)
    pulse.shift_phase(3.14/2, d0)
    pulse.set_phase(3.14, d0)
    pulse.shift_frequency(1e7, d0)
    pulse.set_frequency(5e9, d0)
 
    with pulse.build() as temp_sched:
        pulse.play(pulse.library.Gaussian(20, 1.0, 3.0), d0)
        pulse.play(pulse.library.Gaussian(20, -1.0, 3.0), d0)
 
    pulse.call(temp_sched)
    pulse.acquire(30, a0, pulse.MemorySlot(0))
 
drive_sched.draw()
../_images/pulse-6.png

acquire

qiskit.pulse.builder.acquire(duration, qubit_or_channel, register, **metadata) GitHub(opens in a new tab)

Acquire for a duration on a channel and store the result in a register.

Examples:

from qiskit import pulse
 
acq0 = pulse.AcquireChannel(0)
mem0 = pulse.MemorySlot(0)
 
with pulse.build() as pulse_prog:
    pulse.acquire(100, acq0, mem0)
 
    # measurement metadata
    kernel = pulse.configuration.Kernel('linear_discriminator')
    pulse.acquire(100, acq0, mem0, kernel=kernel)
Note

The type of data acquire will depend on the execution meas_level.

Parameters

Raises

exceptions.PulseError – If the register type is not supported.

barrier

qiskit.pulse.builder.barrier(*channels_or_qubits, name=None) GitHub(opens in a new tab)

Barrier directive for a set of channels and qubits.

This directive prevents the compiler from moving instructions across the barrier. Consider the case where we want to enforce that one pulse happens after another on separate channels, this can be done with:

from qiskit import pulse
from qiskit.providers.fake_provider import FakeOpenPulse2Q
 
backend = FakeOpenPulse2Q()
 
d0 = pulse.DriveChannel(0)
d1 = pulse.DriveChannel(1)
 
with pulse.build(backend) as barrier_pulse_prog:
    pulse.play(pulse.Constant(10, 1.0), d0)
    pulse.barrier(d0, d1)
    pulse.play(pulse.Constant(10, 1.0), d1)

Of course this could have been accomplished with:

from qiskit.pulse import transforms
 
with pulse.build(backend) as aligned_pulse_prog:
    with pulse.align_sequential():
        pulse.play(pulse.Constant(10, 1.0), d0)
        pulse.play(pulse.Constant(10, 1.0), d1)
 
barrier_pulse_prog = transforms.target_qobj_transform(barrier_pulse_prog)
aligned_pulse_prog = transforms.target_qobj_transform(aligned_pulse_prog)
 
assert barrier_pulse_prog == aligned_pulse_prog

The barrier allows the pulse compiler to take care of more advanced scheduling alignment operations across channels. For example in the case where we are calling an outside circuit or schedule and want to align a pulse at the end of one call:

import math
 
d0 = pulse.DriveChannel(0)
 
with pulse.build(backend) as pulse_prog:
    with pulse.align_right():
        pulse.x(1)
        # Barrier qubit 1 and d0.
        pulse.barrier(1, d0)
        # Due to barrier this will play before the gate on qubit 1.
        pulse.play(pulse.Constant(10, 1.0), d0)
        # This will end at the same time as the pulse above due to
        # the barrier.
        pulse.x(1)
Note

Requires the active builder context to have a backend set if qubits are barriered on.

Parameters

call

qiskit.pulse.builder.call(target, name=None, value_dict=None, **kw_params) GitHub(opens in a new tab)

Call the subroutine within the currently active builder context with arbitrary parameters which will be assigned to the target program.

Note

If the target program is a ScheduleBlock, then a Reference instruction will be created and appended to the current context. The target program will be immediately assigned to the current scope as a subroutine. If the target program is Schedule, it will be wrapped by the Call instruction and appended to the current context to avoid a mixed representation of ScheduleBlock and Schedule. If the target program is a QuantumCircuit it will be scheduled and the new Schedule will be added as a Call instruction.

Deprecated since version 0.46.0

QuantumCircuit type for the argument target is deprecated as of qiskit 0.46.0. It will be removed in the Qiskit 1.0 release. ScheduleBlock should only be used for gate calibrations in a quantum circuit. Thus, the called quantum circuit should be added to the main circuit instead of to the ScheduleBlock.

Examples

  1. Calling a schedule block (recommended)
from qiskit import circuit, pulse
from qiskit.providers.fake_provider import FakeBogotaV2
 
backend = FakeBogotaV2()
 
with pulse.build() as x_sched:
    pulse.play(pulse.Gaussian(160, 0.1, 40), pulse.DriveChannel(0))
 
with pulse.build() as pulse_prog:
    pulse.call(x_sched)
 
print(pulse_prog)
ScheduleBlock(
    ScheduleBlock(
        Play(
            Gaussian(duration=160, amp=(0.1+0j), sigma=40),
            DriveChannel(0)
        ),
        name="block0",
        transform=AlignLeft()
    ),
    name="block1",
    transform=AlignLeft()
)

The actual program is stored in the reference table attached to the schedule.

print(pulse_prog.references)
ReferenceManager:
  - ('block0', '634b3b50bd684e26a673af1fbd2d6c81'): ScheduleBlock(Play(Gaussian(...

In addition, you can call a parameterized target program with parameter assignment.

amp = circuit.Parameter("amp")
 
with pulse.build() as subroutine:
    pulse.play(pulse.Gaussian(160, amp, 40), pulse.DriveChannel(0))
 
with pulse.build() as pulse_prog:
    pulse.call(subroutine, amp=0.1)
    pulse.call(subroutine, amp=0.3)
 
print(pulse_prog)
ScheduleBlock(
    ScheduleBlock(
        Play(
            Gaussian(duration=160, amp=(0.1+0j), sigma=40),
            DriveChannel(0)
        ),
        name="block2",
        transform=AlignLeft()
    ),
    ScheduleBlock(
        Play(
            Gaussian(duration=160, amp=(0.3+0j), sigma=40),
            DriveChannel(0)
        ),
        name="block2",
        transform=AlignLeft()
    ),
    name="block3",
    transform=AlignLeft()
)

If there is a name collision between parameters, you can distinguish them by specifying each parameter object in a python dictionary. For example,

amp1 = circuit.Parameter('amp')
amp2 = circuit.Parameter('amp')
 
with pulse.build() as subroutine:
    pulse.play(pulse.Gaussian(160, amp1, 40), pulse.DriveChannel(0))
    pulse.play(pulse.Gaussian(160, amp2, 40), pulse.DriveChannel(1))
 
with pulse.build() as pulse_prog:
    pulse.call(subroutine, value_dict={amp1: 0.1, amp2: 0.3})
 
print(pulse_prog)
ScheduleBlock(
    ScheduleBlock(
        Play(Gaussian(duration=160, amp=(0.1+0j), sigma=40), DriveChannel(0)),
        Play(Gaussian(duration=160, amp=(0.3+0j), sigma=40), DriveChannel(1)),
        name="block4",
        transform=AlignLeft()
    ),
    name="block5",
    transform=AlignLeft()
)
  1. Calling a schedule
x_sched = backend.instruction_schedule_map.get("x", (0,))
 
with pulse.build(backend) as pulse_prog:
    pulse.call(x_sched)
 
print(pulse_prog)
ScheduleBlock(
    Call(
        Schedule(
            (
                0,
                Play(
                    Drag(
                        duration=160,
                        amp=(0.18989731546729305+0j),
                        sigma=40,
                        beta=-1.201258305015517,
                        name='drag_86a8'
                    ),
                    DriveChannel(0),
                    name='drag_86a8'
                )
            ),
            name="x"
        ),
        name='x'
    ),
    name="block6",
    transform=AlignLeft()
)

Currently, the backend calibrated gates are provided in the form of Schedule. The parameter assignment mechanism is available also for schedules. However, the called schedule is not treated as a reference.

Warning

Calling a circuit from a schedule is deprecated as of qiskit 0.46.0. The Qiskit execution model has migrating toward the pulse gate model, where schedules are attached to circuits through the QuantumCircuit.add_calibration() method. Thus, instead of calling a circuit into the schedule, it should instead be added to the main circuit.

Parameters

delay

qiskit.pulse.builder.delay(duration, channel, name=None) GitHub(opens in a new tab)

Delay on a channel for a duration.

Examples:

from qiskit import pulse
 
d0 = pulse.DriveChannel(0)
 
with pulse.build() as pulse_prog:
    pulse.delay(10, d0)

Parameters

play

qiskit.pulse.builder.play(pulse, channel, name=None) GitHub(opens in a new tab)

Play a pulse on a channel.

Examples:

from qiskit import pulse
 
d0 = pulse.DriveChannel(0)
 
with pulse.build() as pulse_prog:
    pulse.play(pulse.Constant(10, 1.0), d0)

Parameters

reference

qiskit.pulse.builder.reference(name, *extra_keys) GitHub(opens in a new tab)

Refer to undefined subroutine by string keys.

A Reference instruction is implicitly created and a schedule can be separately registered to the reference at a later stage.

from qiskit import pulse
 
with pulse.build() as main_prog:
    pulse.reference("x_gate", "q0")
 
with pulse.build() as subroutine:
    pulse.play(pulse.Gaussian(160, 0.1, 40), pulse.DriveChannel(0))
 
main_prog.assign_references(subroutine_dict={("x_gate", "q0"): subroutine})

Parameters

set_frequency

qiskit.pulse.builder.set_frequency(frequency, channel, name=None) GitHub(opens in a new tab)

Set the frequency of a pulse channel.

Examples:

from qiskit import pulse
 
d0 = pulse.DriveChannel(0)
 
with pulse.build() as pulse_prog:
    pulse.set_frequency(1e9, d0)

Parameters

set_phase

qiskit.pulse.builder.set_phase(phase, channel, name=None) GitHub(opens in a new tab)

Set the phase of a pulse channel.

Examples:

import math
 
from qiskit import pulse
 
d0 = pulse.DriveChannel(0)
 
with pulse.build() as pulse_prog:
    pulse.set_phase(math.pi, d0)

Parameters

shift_frequency

qiskit.pulse.builder.shift_frequency(frequency, channel, name=None) GitHub(opens in a new tab)

Shift the frequency of a pulse channel.

Examples:

from qiskit import pulse
 
d0 = pulse.DriveChannel(0)
 
with pulse.build() as pulse_prog:
    pulse.shift_frequency(1e9, d0)

Parameters

shift_phase

qiskit.pulse.builder.shift_phase(phase, channel, name=None) GitHub(opens in a new tab)

Shift the phase of a pulse channel.

Examples:

import math
 
from qiskit import pulse
 
d0 = pulse.DriveChannel(0)
 
with pulse.build() as pulse_prog:
    pulse.shift_phase(math.pi, d0)

Parameters

snapshot

qiskit.pulse.builder.snapshot(label, snapshot_type='statevector') GitHub(opens in a new tab)

Simulator snapshot.

Examples:

from qiskit import pulse
 
with pulse.build() as pulse_prog:
    pulse.snapshot('first', 'statevector')

Parameters

Contexts

Builder aware contexts that modify the construction of a pulse program. For example an alignment context like align_right() may be used to align all pulses as late as possible in a pulse program.

from qiskit import pulse
 
d0 = pulse.DriveChannel(0)
d1 = pulse.DriveChannel(1)
 
with pulse.build() as pulse_prog:
    with pulse.align_right():
        # this pulse will start at t=0
        pulse.play(pulse.Constant(100, 1.0), d0)
        # this pulse will start at t=80
        pulse.play(pulse.Constant(20, 1.0), d1)
 
pulse_prog.draw()
../_images/pulse-7.png

align_equispaced

qiskit.pulse.builder.align_equispaced(duration) GitHub(opens in a new tab)

Equispaced alignment pulse scheduling context.

Pulse instructions within this context are scheduled with the same interval spacing such that the total length of the context block is duration. If the total free duration cannot be evenly divided by the number of instructions within the context, the modulo is split and then prepended and appended to the returned schedule. Delay instructions are automatically inserted in between pulses.

This context is convenient to write a schedule for periodical dynamic decoupling or the Hahn echo sequence.

Examples:

from qiskit import pulse
 
d0 = pulse.DriveChannel(0)
x90 = pulse.Gaussian(10, 0.1, 3)
x180 = pulse.Gaussian(10, 0.2, 3)
 
with pulse.build() as hahn_echo:
    with pulse.align_equispaced(duration=100):
        pulse.play(x90, d0)
        pulse.play(x180, d0)
        pulse.play(x90, d0)
 
hahn_echo.draw()
../_images/pulse-8.png

Parameters

duration (int(opens in a new tab) |ParameterExpression) – Duration of this context. This should be larger than the schedule duration.

Yields

None

Return type

AlignmentKind

Notes

The scheduling is performed for sub-schedules within the context rather than channel-wise. If you want to apply the equispaced context for each channel, you should use the context independently for channels.

align_func

qiskit.pulse.builder.align_func(duration, func) GitHub(opens in a new tab)

Callback defined alignment pulse scheduling context.

Pulse instructions within this context are scheduled at the location specified by arbitrary callback function position that takes integer index and returns the associated fractional location within [0, 1]. Delay instruction is automatically inserted in between pulses.

This context may be convenient to write a schedule of arbitrary dynamical decoupling sequences such as Uhrig dynamical decoupling.

Examples:

import numpy as np
from qiskit import pulse
 
d0 = pulse.DriveChannel(0)
x90 = pulse.Gaussian(10, 0.1, 3)
x180 = pulse.Gaussian(10, 0.2, 3)
 
def udd10_pos(j):
    return np.sin(np.pi*j/(2*10 + 2))**2
 
with pulse.build() as udd_sched:
    pulse.play(x90, d0)
    with pulse.align_func(duration=300, func=udd10_pos):
        for _ in range(10):
            pulse.play(x180, d0)
    pulse.play(x90, d0)
 
udd_sched.draw()
../_images/pulse-9.png

Parameters

Yields

None

Return type

AlignmentKind

Notes

The scheduling is performed for sub-schedules within the context rather than channel-wise. If you want to apply the numerical context for each channel, you need to apply the context independently to channels.

align_left

qiskit.pulse.builder.align_left() GitHub(opens in a new tab)

Left alignment pulse scheduling context.

Pulse instructions within this context are scheduled as early as possible by shifting them left to the earliest available time.

Examples:

from qiskit import pulse
 
d0 = pulse.DriveChannel(0)
d1 = pulse.DriveChannel(1)
 
with pulse.build() as pulse_prog:
    with pulse.align_left():
        # this pulse will start at t=0
        pulse.play(pulse.Constant(100, 1.0), d0)
        # this pulse will start at t=0
        pulse.play(pulse.Constant(20, 1.0), d1)
pulse_prog = pulse.transforms.block_to_schedule(pulse_prog)
 
assert pulse_prog.ch_start_time(d0) == pulse_prog.ch_start_time(d1)

Yields

None

Return type

ContextManager(opens in a new tab)[None]

align_right

qiskit.pulse.builder.align_right() GitHub(opens in a new tab)

Right alignment pulse scheduling context.

Pulse instructions within this context are scheduled as late as possible by shifting them right to the latest available time.

Examples:

from qiskit import pulse
 
d0 = pulse.DriveChannel(0)
d1 = pulse.DriveChannel(1)
 
with pulse.build() as pulse_prog:
    with pulse.align_right():
        # this pulse will start at t=0
        pulse.play(pulse.Constant(100, 1.0), d0)
        # this pulse will start at t=80
        pulse.play(pulse.Constant(20, 1.0), d1)
pulse_prog = pulse.transforms.block_to_schedule(pulse_prog)
 
assert pulse_prog.ch_stop_time(d0) == pulse_prog.ch_stop_time(d1)

Yields

None

Return type

AlignmentKind

align_sequential

qiskit.pulse.builder.align_sequential() GitHub(opens in a new tab)

Sequential alignment pulse scheduling context.

Pulse instructions within this context are scheduled sequentially in time such that no two instructions will be played at the same time.

Examples:

from qiskit import pulse
 
d0 = pulse.DriveChannel(0)
d1 = pulse.DriveChannel(1)
 
with pulse.build() as pulse_prog:
    with pulse.align_sequential():
        # this pulse will start at t=0
        pulse.play(pulse.Constant(100, 1.0), d0)
        # this pulse will also start at t=100
        pulse.play(pulse.Constant(20, 1.0), d1)
pulse_prog = pulse.transforms.block_to_schedule(pulse_prog)
 
assert pulse_prog.ch_stop_time(d0) == pulse_prog.ch_start_time(d1)

Yields

None

Return type

AlignmentKind

circuit_scheduler_settings

qiskit.pulse.builder.circuit_scheduler_settings(**settings) GitHub(opens in a new tab)

Set the currently active circuit scheduler settings for this context.

Deprecated since version 0.46.0

The function qiskit.pulse.builder.circuit_scheduler_settings() is deprecated as of qiskit 0.46.0. It will be removed in the Qiskit 1.0 release. This function was used for gate operations, which are deprecated. pulse schedules should only be used for gate calibrations as part of a quantum circuit, and not vice versa

Examples:

from qiskit import pulse
from qiskit.providers.fake_provider import FakeOpenPulse2Q
 
backend = FakeOpenPulse2Q()
 
with pulse.build(backend):
    print(pulse.active_circuit_scheduler_settings())
    with pulse.circuit_scheduler_settings(method='alap'):
        print(pulse.active_circuit_scheduler_settings())
{}
{'method': 'alap'}

Return type

ContextManager(opens in a new tab)[None]

frequency_offset

qiskit.pulse.builder.frequency_offset(frequency, *channels, compensate_phase=False) GitHub(opens in a new tab)

Shift the frequency of inputs channels on entry into context and undo on exit.

Examples:

from qiskit import pulse
 
d0 = pulse.DriveChannel(0)
 
with pulse.build(backend) as pulse_prog:
    # shift frequency by 1GHz
    with pulse.frequency_offset(1e9, d0):
        pulse.play(pulse.Constant(10, 1.0), d0)
 
assert len(pulse_prog.instructions) == 3
 
with pulse.build(backend) as pulse_prog:
    # Shift frequency by 1GHz.
    # Undo accumulated phase in the shifted frequency frame
    # when exiting the context.
    with pulse.frequency_offset(1e9, d0, compensate_phase=True):
        pulse.play(pulse.Constant(10, 1.0), d0)
 
assert len(pulse_prog.instructions) == 4

Parameters

  • frequency (float(opens in a new tab)) – Amount of frequency offset in Hz.
  • channels (PulseChannel) – Channels to offset frequency of.
  • compensate_phase (bool(opens in a new tab)) – Compensate for accumulated phase accumulated with respect to the channels’ frame at its initial frequency.

Yields

None

Return type

ContextManager(opens in a new tab)[None]

phase_offset

qiskit.pulse.builder.phase_offset(phase, *channels) GitHub(opens in a new tab)

Shift the phase of input channels on entry into context and undo on exit.

Examples:

import math
 
from qiskit import pulse
 
d0 = pulse.DriveChannel(0)
 
with pulse.build() as pulse_prog:
    with pulse.phase_offset(math.pi, d0):
        pulse.play(pulse.Constant(10, 1.0), d0)
 
assert len(pulse_prog.instructions) == 3

Parameters

  • phase (float(opens in a new tab)) – Amount of phase offset in radians.
  • channels (PulseChannel) – Channels to offset phase of.

Yields

None

Return type

ContextManager(opens in a new tab)[None]

transpiler_settings

qiskit.pulse.builder.transpiler_settings(**settings) GitHub(opens in a new tab)

Set the currently active transpiler settings for this context.

Deprecated since version 0.46.0

The function qiskit.pulse.builder.transpiler_settings() is deprecated as of qiskit 0.46.0. It will be removed in the Qiskit 1.0 release. This function was used for gate operations, which are deprecated. pulse schedules should only be used for gate calibrations as part of a quantum circuit, and not vice versa

Examples:

from qiskit import pulse
from qiskit.providers.fake_provider import FakeOpenPulse2Q
 
backend = FakeOpenPulse2Q()
 
with pulse.build(backend):
    print(pulse.active_transpiler_settings())
    with pulse.transpiler_settings(optimization_level=3):
        print(pulse.active_transpiler_settings())
{}
{'optimization_level': 3}

Return type

ContextManager(opens in a new tab)[None]

Macros

Macros help you add more complex functionality to your pulse program.

from qiskit import pulse
from qiskit.providers.fake_provider import FakeArmonk
 
backend = FakeArmonk()
 
with pulse.build(backend) as measure_sched:
    mem_slot = pulse.measure(0)
    print(mem_slot)
MemorySlot(0)

measure

qiskit.pulse.builder.measure(qubits, registers=None) GitHub(opens in a new tab)

Measure a qubit within the currently active builder context.

At the pulse level a measurement is composed of both a stimulus pulse and an acquisition instruction which tells the systems measurement unit to acquire data and process it. We provide this measurement macro to automate the process for you, but if desired full control is still available with acquire() and play().

To use the measurement it is as simple as specifying the qubit you wish to measure:

from qiskit import pulse
from qiskit.providers.fake_provider import FakeOpenPulse2Q
 
backend = FakeOpenPulse2Q()
 
qubit = 0
 
with pulse.build(backend) as pulse_prog:
    # Do something to the qubit.
    qubit_drive_chan = pulse.drive_channel(0)
    pulse.play(pulse.Constant(100, 1.0), qubit_drive_chan)
    # Measure the qubit.
    reg = pulse.measure(qubit)

For now it is not possible to do much with the handle to reg but in the future we will support using this handle to a result register to build up ones program. It is also possible to supply this register:

with pulse.build(backend) as pulse_prog:
    pulse.play(pulse.Constant(100, 1.0), qubit_drive_chan)
    # Measure the qubit.
    mem0 = pulse.MemorySlot(0)
    reg = pulse.measure(qubit, mem0)
 
assert reg == mem0
Note

Requires the active builder context to have a backend set.

Parameters

Returns

The register the qubit measurement result will be stored in.

Return type

List(opens in a new tab)[StorageLocation] | StorageLocation

measure_all

qiskit.pulse.builder.measure_all() GitHub(opens in a new tab)

Measure all qubits within the currently active builder context.

A simple macro function to measure all of the qubits in the device at the same time. This is useful for handling device meas_map and single measurement constraints.

Examples:

from qiskit import pulse
from qiskit.providers.fake_provider import FakeOpenPulse2Q
 
backend = FakeOpenPulse2Q()
 
with pulse.build(backend) as pulse_prog:
    # Measure all qubits and return associated registers.
    regs = pulse.measure_all()
Note

Requires the active builder context to have a backend set.

Returns

The registers the qubit measurement results will be stored in.

Return type

List(opens in a new tab)[MemorySlot]

delay_qubits

qiskit.pulse.builder.delay_qubits(duration, *qubits) GitHub(opens in a new tab)

Insert delays on all of the channels.Channels that correspond to the input qubits at the same time.

Examples:

from qiskit import pulse
from qiskit.providers.fake_provider import FakeOpenPulse3Q
 
backend = FakeOpenPulse3Q()
 
with pulse.build(backend) as pulse_prog:
    # Delay for 100 cycles on qubits 0, 1 and 2.
    regs = pulse.delay_qubits(100, 0, 1, 2)
Note

Requires the active builder context to have a backend set.

Parameters

Utilities

The utility functions can be used to gather attributes about the backend and modify how the program is built.

from qiskit import pulse
 
from qiskit.providers.fake_provider import FakeArmonk
 
backend = FakeArmonk()
 
with pulse.build(backend) as u3_sched:
    print('Number of qubits in backend: {}'.format(pulse.num_qubits()))
 
    samples = 160
    print('There are {} samples in {} seconds'.format(
        samples, pulse.samples_to_seconds(160)))
 
    seconds = 1e-6
    print('There are {} seconds in {} samples.'.format(
        seconds, pulse.seconds_to_samples(1e-6)))
Number of qubits in backend: 1
There are 160 samples in 3.5555555555555554e-08 seconds
There are 1e-06 seconds in 4500 samples.

active_backend

qiskit.pulse.builder.active_backend() GitHub(opens in a new tab)

Get the backend of the currently active builder context.

Returns

The active backend in the currently active

builder context.

Return type

Backend

Raises

exceptions.BackendNotSet – If the builder does not have a backend set.

active_transpiler_settings

qiskit.pulse.builder.active_transpiler_settings() GitHub(opens in a new tab)

Return the current active builder context’s transpiler settings.

Deprecated since version 0.46.0

The function qiskit.pulse.builder.active_transpiler_settings() is deprecated as of qiskit 0.46.0. It will be removed in the Qiskit 1.0 release. This function was used for gate operations, which are deprecated. pulse schedules should only be used for gate calibrations as part of a quantum circuit, and not vice versa

Examples:

from qiskit import pulse
from qiskit.providers.fake_provider import FakeOpenPulse2Q
 
backend = FakeOpenPulse2Q()
 
transpiler_settings = {'optimization_level': 3}
 
with pulse.build(backend,
                 default_transpiler_settings=transpiler_settings):
    print(pulse.active_transpiler_settings())
{'optimization_level': 3}

Return type

Dict(opens in a new tab)[str(opens in a new tab), Any(opens in a new tab)]

active_circuit_scheduler_settings

qiskit.pulse.builder.active_circuit_scheduler_settings() GitHub(opens in a new tab)

Return the current active builder context’s circuit scheduler settings.

Deprecated since version 0.46.0

The function qiskit.pulse.builder.active_circuit_scheduler_settings() is deprecated as of qiskit 0.46.0. It will be removed in the Qiskit 1.0 release. This function was used for gate operations, which are deprecated. pulse schedules should only be used for gate calibrations as part of a quantum circuit, and not vice versa

Examples:

from qiskit import pulse
from qiskit.providers.fake_provider import FakeOpenPulse2Q
 
backend = FakeOpenPulse2Q()
 
circuit_scheduler_settings = {'method': 'alap'}
 
with pulse.build(
        backend,
        default_circuit_scheduler_settings=circuit_scheduler_settings):
    print(pulse.active_circuit_scheduler_settings())
{'method': 'alap'}

Return type

Dict(opens in a new tab)[str(opens in a new tab), Any(opens in a new tab)]

num_qubits

qiskit.pulse.builder.num_qubits() GitHub(opens in a new tab)

Return number of qubits in the currently active backend.

Examples:

from qiskit import pulse
from qiskit.providers.fake_provider import FakeOpenPulse2Q
 
backend = FakeOpenPulse2Q()
 
with pulse.build(backend):
    print(pulse.num_qubits())
2
Note

Requires the active builder context to have a backend set.

Return type

int(opens in a new tab)

qubit_channels

qiskit.pulse.builder.qubit_channels(qubit) GitHub(opens in a new tab)

Returns the set of channels associated with a qubit.

Examples:

from qiskit import pulse
from qiskit.providers.fake_provider import FakeOpenPulse2Q
 
backend = FakeOpenPulse2Q()
 
with pulse.build(backend):
    print(pulse.qubit_channels(0))
{MeasureChannel(0), ControlChannel(0), DriveChannel(0), AcquireChannel(0), ControlChannel(1)}
Note

Requires the active builder context to have a backend set.

Note

A channel may still be associated with another qubit in this list such as in the case where significant crosstalk exists.

Return type

Set(opens in a new tab)[Channel]

samples_to_seconds

qiskit.pulse.builder.samples_to_seconds(samples) GitHub(opens in a new tab)

Obtain the time in seconds that will elapse for the input number of samples on the active backend.

Parameters

samples (int(opens in a new tab) |ndarray(opens in a new tab)) – Number of samples to convert to time in seconds.

Returns

The time that elapses in samples.

Return type

float(opens in a new tab) | ndarray(opens in a new tab)

seconds_to_samples

qiskit.pulse.builder.seconds_to_samples(seconds) GitHub(opens in a new tab)

Obtain the number of samples that will elapse in seconds on the active backend.

Rounds down.

Parameters

seconds (float(opens in a new tab) |ndarray(opens in a new tab)) – Time in seconds to convert to samples.

Returns

The number of samples for the time to elapse

Return type

int(opens in a new tab) | ndarray(opens in a new tab)


Configuration

InstructionScheduleMap()Mapping from QuantumCircuit qiskit.circuit.Instruction names and qubits to Schedule s. In particular, the mapping is formatted as type::.

Exceptions

PulseError

qiskit.pulse.PulseError(*message) GitHub(opens in a new tab)

Errors raised by the pulse module.

Set the error message.

BackendNotSet

qiskit.pulse.BackendNotSet(*message) GitHub(opens in a new tab)

Raised if the builder context does not have a backend.

Set the error message.

NoActiveBuilder

qiskit.pulse.NoActiveBuilder(*message) GitHub(opens in a new tab)

Raised if no builder context is active.

Set the error message.

UnassignedDurationError

qiskit.pulse.UnassignedDurationError(*message) GitHub(opens in a new tab)

Raised if instruction duration is unassigned.

Set the error message.

UnassignedReferenceError

qiskit.pulse.UnassignedReferenceError(*message) GitHub(opens in a new tab)

Raised if subroutine is unassigned.

Set the error message.

Was this page helpful?
Report a bug or request content on GitHub.