Download
Download this file as Jupyter notebook: parameterized_linker_msmt.ipynb.
Compiling measurements to waveforms and acquisitions
In this guide, we show how to use
ParameterizedLinker
s to compile
measurements to hardware instructions.
Creating the Linker
We first define all the targets in the system, together with the instruction to compile.
[2]:
import keysight.qcs as qcs
# set number of targets
n_targets = 4
# initialize qubit register and virtual channels
qubits = qcs.Qudits(range(n_targets))
readout_channels = qcs.Channels(range(n_targets), "readout_channels")
acquire_channels = qcs.Channels(range(n_targets), "acquire_channels")
# initialize a measurement operation to compile
measure = qcs.Measure()
Next, we define the program specifying the physical implementation of the measurement on hardware.
[3]:
# initialize the replacement program
replacement_program = qcs.Program()
# initialize the frequencies and amplitudes of the readout pulses
# these values will typically be imported from a calibration set
value = [8e9 + 50e6 * n for n in range(n_targets)]
readout_frequencies = qcs.Array("readout_frequencies", value=value, dtype=float)
readout_amplitudes = qcs.Array(
"readout_amplitudes", value=[0.4] * n_targets, dtype=float
)
readout_plateau_time = qcs.Scalar("readout_plateau_time", value=200e-9, dtype=float)
readout_rise_time = qcs.Scalar("readout_rise_time", value=30e-9, dtype=float)
readout_frequency_detuning = qcs.Scalar(
"readout_frequency_detuning", value=0, dtype=float
)
readout_phases = qcs.Array("readout_phases", value=[0] * n_targets, dtype=float)
readout_pulse_delay = qcs.Scalar("readout_pulse_delay", value=10e-9, dtype=float)
# initialize readout pulses
# the phases of the pulses are equal to intended axis of rotation
pulse = qcs.RFWaveform(
duration=2 * readout_rise_time,
envelope=qcs.GaussianEnvelope(),
amplitude=readout_amplitudes,
rf_frequency=readout_frequencies + readout_frequency_detuning,
instantaneous_phase=readout_phases,
)
delay_pulse = replacement_program.add_waveform(
qcs.Delay(readout_pulse_delay), readout_channels
)
# add the readout pulses to the readout channels
replacement_program.add_waveform(
pulse.to_flattop(readout_plateau_time), readout_channels
)
# create the integration filter for the acquisition
integration_envelope = qcs.ConstantEnvelope()
rf_pulse = qcs.RFWaveform(
500e-9, integration_envelope, 1.0, readout_frequencies + readout_frequency_detuning
)
integration_filter = qcs.IntegrationFilter(rf_pulse)
# create the classifier
iq_ref_pts = qcs.Array("ref_pts", value=[[1 + 1j, 1 - 1j]] * n_targets)
classifiers = qcs.Classifier(iq_ref_pts)
# specify the offset between AWG and digitizer
acquisition_delay = 10e-9
# add the acquisition concurrent with the readout pulses
replacement_program.add_acquisition(
integration_filter,
acquire_channels,
classifier=classifiers,
pre_delay=acquisition_delay,
)
replacement_program.draw()
Program
Program
|
|||||||||||||||||||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
Layer #0
Layer #0
|
|||||||||||||||||||||||||||||||||
|
|
Delay on ('readout_channels', 0)
Parameters
|
RFWaveform on ('readout_channels', 0)
Parameters
|
HOLD
Hold on ('readout_channels', 0)
Parameters
|
RFWaveform on ('readout_channels', 0)
Parameters
|
||||||||||||||||||||||||||||
|
Delay on ('readout_channels', 1)
Parameters
|
RFWaveform on ('readout_channels', 1)
Parameters
|
HOLD
Hold on ('readout_channels', 1)
Parameters
|
RFWaveform on ('readout_channels', 1)
Parameters
|
|||||||||||||||||||||||||||||
|
Delay on ('readout_channels', 2)
Parameters
|
RFWaveform on ('readout_channels', 2)
Parameters
|
HOLD
Hold on ('readout_channels', 2)
Parameters
|
RFWaveform on ('readout_channels', 2)
Parameters
|
|||||||||||||||||||||||||||||
|
Delay on ('readout_channels', 3)
Parameters
|
RFWaveform on ('readout_channels', 3)
Parameters
|
HOLD
Hold on ('readout_channels', 3)
Parameters
|
RFWaveform on ('readout_channels', 3)
Parameters
|
|||||||||||||||||||||||||||||
|
|
Delay on ('acquire_channels', 0)
Parameters
|
Acquisition on ('acquire_channels', 0)
Parameters
|
||||||||||||||||||||||||||||||
|
Delay on ('acquire_channels', 1)
Parameters
|
Acquisition on ('acquire_channels', 1)
Parameters
|
|||||||||||||||||||||||||||||||
|
Delay on ('acquire_channels', 2)
Parameters
|
Acquisition on ('acquire_channels', 2)
Parameters
|
|||||||||||||||||||||||||||||||
|
Delay on ('acquire_channels', 3)
Parameters
|
Acquisition on ('acquire_channels', 3)
Parameters
|
We now create a
ParameterizedLinker
to replace the measurement
instruction with replacement_program
.
[4]:
# initialize the linker for the measurement instruction
meas_linker = qcs.ParameterizedLinker(measure, qubits, replacement_program)
Using the Linker
We can use meas_linker
to replace any measurement in our programs on qubits
or on arbitrary subsets of it.
[5]:
# initialize a program that contains a measurement
program = qcs.Program()
program.add_measurement(qubits[[0, 2]])
# apply the linker pass
linker_pass = qcs.LinkerPass(meas_linker)
program_compiled = linker_pass.apply(program)
# apply the sequencer to the ``compiled_program`` and render
program_compiled.render(
channel_subplots=False,
lo_frequency=readout_frequencies.value.min() - 20e6,
sample_rate=qcs.SAMPLE_RATES[qcs.InstrumentEnum.M5300AWG],
)
When using linkers to replace Measure
s, the
measured qudits are mapped to channels. This mapping can be accessed from the
qudits()
property of the returned program.
The corresponding acquisition is added to a list stored in the corresponding key of
the channels()
property.
This allows results of one program to be identified with the results of another.
Download
Download this file as Jupyter notebook: parameterized_linker_msmt.ipynb.