Download
Download this file as Jupyter notebook: program_basics.ipynb.
Program basics
A Program
contains a series of instructions
to be performed on control hardware without requiring communication with the
host computer.
Basic instructions and targets
The set of allowed instructions for a Program
includes abstract quantum operations such as single- or multi-qudit gates as well as
hardware operations such as RF waveforms or digitizer instructions for acquisitions.
While it is possible two combine both abstraction layers within a single program, for
the purposes of this tutorial we will treat them separately.
The instruction targets in a Program
can either be
Channels
or
Qudits
. The former is intended for use in waveform
programs while the latter is intended for abstract quantum programs. See
Introduction to linkers for more information for how to translate between these
layers of abstraction.
The following program contains two Gaussian pulses on two abstract AWG channels and two acquisition readouts on two digitizer channels, with the first readout using a constant acquisition window and the second one using an integrated filter.
[2]:
import keysight.qcs as qcs
# define channels representing two AWGs and two digitizers
awgs = qcs.Channels(range(2), "awgs")
digs = qcs.Channels(range(2), "digs")
# instantiate an empty program
program = qcs.Program()
# instantiate a pulse with two different amplitudes
amps = qcs.Array("amplitudes", value=[1, 0.8])
freqs = qcs.Array("frequencies", value=[1.0e8, 5.1e8])
gauss = qcs.RFWaveform(8e-8, qcs.GaussianEnvelope(), amps, freqs)
readout = qcs.RFWaveform(8e-8, qcs.GaussianEnvelope(2), 0.5, 4.8e8)
# add the pulses to the program
program.add_waveform(gauss, awgs)
# add an acquisition to the program
program.add_acquisition(readout, digs[0])
program.add_acquisition(8e-8, digs[1])
program.add_acquisition(readout, digs[1], pre_delay=5e-9)
# visualize the program using the draw method:
program.draw()
Program
Program
|
|||||||||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
Layer #0
Layer #0
|
|||||||||||||||||||||||
|
|
RFWaveform on ('awgs', 0)
Parameters
|
|||||||||||||||||||||
|
RFWaveform on ('awgs', 1)
Parameters
|
||||||||||||||||||||||
|
|
Acquisition on ('digs', 0)
Parameters
|
|||||||||||||||||||||
|
Acquisition on ('digs', 1)
Parameters
|
Delay on ('digs', 1)
Parameters
|
Acquisition on ('digs', 1)
Parameters
|
Hover over the operations in this visualization to view their specifications.
In this program, the first channel in awgs
plays the pulse with amplitude
0.8
and the second channel plays the pulse with amplitude 1.0
. Meanwhile,
the first channel in digs
rendered with a constant gate and the second channel
in digs
rendered with an integration filter, with amplitude 1.0
and
0.5
, respectively. This can be verified by visualizing the pulses using the
render()
method.
[3]:
program.render(channel_subplots=False, sample_rate=5e9)
Timing model
A Program
consists of a series of
Layer
s that represent instructions within a
fixed time interval. When a program is constructed, new operations are added to the
current layer if possible, otherwise a new Layer
is created. The example below creates a program with the same instructions as
before, but this time adds each to a new layer explicitly, causing them to be
executed sequentially.
[4]:
program = qcs.Program()
# instantiate a pulse with two different amplitudes
gauss = qcs.RFWaveform(100e-9, qcs.GaussianEnvelope(), amps, freqs)
# add the pulses to the program using explicit indexing this time
program.add_waveform(gauss[0], awgs[0])
# create a new layer for the next pulse by setting new_layer=True
program.add_waveform(gauss[1], awgs[1], new_layer=True)
# add the acquisition
program.add_acquisition(100e-9, digs[0], new_layer=True)
program.draw()
Program
Program
|
||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
Layer #0
Layer #0
|
Layer #1
Layer #1
|
Layer #2
Layer #2
|
||||||||||||||
|
|
RFWaveform on ('awgs', 0)
Parameters
|
||||||||||||||
|
RFWaveform on ('awgs', 1)
Parameters
|
|||||||||||||||
|
|
Acquisition on ('digs', 0)
Parameters
|
The instructions are now in separate layers. The duration of each layer is determined by the maximum duration of each operation in that layer, or, if there are multiple operations in each layer, the maximum of the sum of operation durations.
Quantum Programs
The Program
class also supports circuit-level
quantum programming where the targets are specified as
Qudits
and the operations are
:Gate
s. Multi-qudit targets can be created using
tuples of single-qudit targets.
[5]:
qudits1 = qcs.Qudits(range(2), "xy_qudits")
qudits2 = qcs.Qudits(2, "other")
prog = qcs.Program()
prog.add_gate(qcs.GATES.x, qudits1[0])
prog.add_gate(qcs.GATES.cx, (qudits1[0], qudits2[0]))
prog.add_gate(qcs.GATES.y, qudits2, new_layer=True)
prog.add_gate(qcs.GATES.cx, (qudits1[1], qudits2[0]))
prog.add_measurement(qudits1[1], new_layer=True)
prog.add_measurement(qudits2, new_layer=True)
prog.add_gate(qcs.GATES.x, qudits1[0])
prog.draw()
Program
Program
|
|||||||||||||||||||||||||||||||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
Layer #0
Layer #0
|
Layer #1
Layer #1
|
Layer #2
Layer #2
|
Layer #3
Layer #3
|
Layer #4
Layer #4
|
Layer #5
Layer #5
|
||||||||||||||||||||||||||||||||||||||||
|
|
X
Gate X on ('xy_qudits', 0)
Matrix:
|
CX
Gate CX on (('xy_qudits', 0), ('other', 2))
Matrix:
|
X
Gate X on ('xy_qudits', 0)
Matrix:
|
|||||||||||||||||||||||||||||||||||||||||
|
CX
Gate CX on (('xy_qudits', 1), ('other', 2))
Matrix:
|
Measure on ('xy_qudits', 1)
Parameters
|
|||||||||||||||||||||||||||||||||||||||||||
|
|
CX
Gate CX on (('other', 2), ('xy_qudits', 0))
Matrix:
|
Y
Gate Y on ('other', 2)
Matrix:
|
CX
Gate CX on (('other', 2), ('xy_qudits', 1))
Matrix:
|
Measure on ('other', 2)
Parameters
|
The available built-in gates can be viewed through the aliases
attribute:
[6]:
qcs.GATES.aliases
[6]:
{'cx',
'cy',
'cz',
'h',
'id',
'iswap',
'swap',
'x',
'x90',
'y',
'y90',
'z',
'z90'}
Users can also specify their own gates with a matrix.
Download
Download this file as Jupyter notebook: program_basics.ipynb.