Cross-resonance gate tuneup¶
In this reference notebook, you'll learn how to use LabOne Q's logical signals lines to perform simple tuneup of a cross-resonance two qubit gate. This functionality requires an SHFSG or SHFQC and relies on using the command table instead of playWave
commands.
0. General Imports and Definitions¶
0.1 Python Imports¶
In [ ]:
Copied!
# Helpers:
from laboneq.contrib.example_helpers.generate_device_setup import (
generate_device_setup_qubits,
)
from laboneq.contrib.example_helpers.plotting.plot_helpers import plot_simulation
# LabOne Q:
from laboneq.simple import *
# Helpers:
from laboneq.contrib.example_helpers.generate_device_setup import (
generate_device_setup_qubits,
)
from laboneq.contrib.example_helpers.plotting.plot_helpers import plot_simulation
# LabOne Q:
from laboneq.simple import *
1. Define Device Setup and Calibration¶
1.1 Define a Device Setup¶
We'll generate a device setup and some qubit objects using a set of pre-defined parameters in a helper function.
In [ ]:
Copied!
# specify the number of qubits you want to use
number_of_qubits = 2
# generate the device setup and the qubit objects using a helper function
device_setup, qubits = generate_device_setup_qubits(
number_qubits=number_of_qubits,
pqsc=[{"serial": "DEV10001"}],
hdawg=[
{
"serial": "DEV8001",
"zsync": 0,
"number_of_channels": 8,
"options": None,
}
],
shfqc=[
{
"serial": "DEV12001",
"zsync": 1,
"number_of_channels": 6,
"readout_multiplex": 6,
"options": None,
}
],
multiplex_drive_lines=True,
include_flux_lines=True,
server_host="localhost",
setup_name=f"my_{number_of_qubits}_tunable_qubit_setup",
)
q0, q1 = qubits[:2]
# specify the number of qubits you want to use
number_of_qubits = 2
# generate the device setup and the qubit objects using a helper function
device_setup, qubits = generate_device_setup_qubits(
number_qubits=number_of_qubits,
pqsc=[{"serial": "DEV10001"}],
hdawg=[
{
"serial": "DEV8001",
"zsync": 0,
"number_of_channels": 8,
"options": None,
}
],
shfqc=[
{
"serial": "DEV12001",
"zsync": 1,
"number_of_channels": 6,
"readout_multiplex": 6,
"options": None,
}
],
multiplex_drive_lines=True,
include_flux_lines=True,
server_host="localhost",
setup_name=f"my_{number_of_qubits}_tunable_qubit_setup",
)
q0, q1 = qubits[:2]
In [ ]:
Copied!
# use emulation mode - no connection to instruments
use_emulation = True
# create and connect to a session
session = Session(device_setup=device_setup)
session.connect(do_emulation=use_emulation)
# use emulation mode - no connection to instruments
use_emulation = True
# create and connect to a session
session = Session(device_setup=device_setup)
session.connect(do_emulation=use_emulation)
2. CR Gate Tune-up¶
Sweep the pulse length of a qubit drive pulse at the difference frequency of two qubits to determine the ideal parameters for a CR gate.
2.1 Define the Experiment¶
In [ ]:
Copied!
## define pulses
# qubit pi pulse for first excited state
x90 = pulse_library.drag(uid="x90", length=16e-9, amplitude=0.5, sigma=0.3, beta=0.2)
# pulse to be calibrated for CR gate - length will be swept
cr_pulse = pulse_library.gaussian(
uid="cr_pulse", length=32e-9, amplitude=0.7, sigma=0.3
)
# readout drive pulse
readout_pulse = pulse_library.const(uid="readout_pulse", length=400e-9, amplitude=0.2)
# readout integration weights
readout_weighting_function = pulse_library.const(
uid="readout_weighting_function", length=400e-9, amplitude=0.8
)
## define pulses
# qubit pi pulse for first excited state
x90 = pulse_library.drag(uid="x90", length=16e-9, amplitude=0.5, sigma=0.3, beta=0.2)
# pulse to be calibrated for CR gate - length will be swept
cr_pulse = pulse_library.gaussian(
uid="cr_pulse", length=32e-9, amplitude=0.7, sigma=0.3
)
# readout drive pulse
readout_pulse = pulse_library.const(uid="readout_pulse", length=400e-9, amplitude=0.2)
# readout integration weights
readout_weighting_function = pulse_library.const(
uid="readout_weighting_function", length=400e-9, amplitude=0.8
)
In [ ]:
Copied!
# set up sweep parameter - drive pulse length
start = 32e-9
stop = 640e-9
count = 20
length_sweep = LinearSweepParameter(uid="length", start=start, stop=stop, count=count)
# number of averages
average_exponent = 10 # used for 2^n averages, n=average_exponent, maximum: n = 17
# Create Experiment
exp_cr_gate = Experiment(
uid="cr Tuneup",
signals=[
ExperimentSignal("drive_0"),
ExperimentSignal("drive_1"),
ExperimentSignal("drive_cr"),
ExperimentSignal("measure_0"),
ExperimentSignal("acquire_0"),
ExperimentSignal("measure_1"),
ExperimentSignal("acquire_1"),
],
)
## experimental pulse sequence
# outer loop - real-time, cyclic averaging in standard integration mode
with exp_cr_gate.acquire_loop_rt(
uid="shots",
count=pow(2, average_exponent),
averaging_mode=AveragingMode.CYCLIC,
acquisition_type=AcquisitionType.INTEGRATION,
):
# inner loop - real-time sweep of qubit drive pulse amplitude
with exp_cr_gate.sweep(uid="sweep", parameter=length_sweep):
with exp_cr_gate.section(
uid="drive", alignment=SectionAlignment.RIGHT, length=stop + 2 * x90.length
):
# qubit excitation - assume something is done to both qubits
with exp_cr_gate.section(
uid="qubit_excitation",
on_system_grid=True,
alignment=SectionAlignment.RIGHT,
):
exp_cr_gate.play(signal="drive_0", pulse=x90)
exp_cr_gate.play(signal="drive_1", pulse=x90, amplitude=0.4)
# play CR pulse and sweep its length
with exp_cr_gate.section(
uid="cr_gate",
play_after="qubit_excitation",
on_system_grid=True,
alignment=SectionAlignment.LEFT,
):
exp_cr_gate.play(signal="drive_cr", pulse=cr_pulse, length=length_sweep)
# qubit readout pulses and data acquisition
with exp_cr_gate.section(uid="qubit_readout", play_after="drive"):
# play readout pulse
exp_cr_gate.play(signal="measure_0", pulse=readout_pulse)
exp_cr_gate.play(signal="measure_1", pulse=readout_pulse)
# signal data acquisition
exp_cr_gate.acquire(
signal="acquire_0",
handle="ac_0",
kernel=readout_weighting_function,
)
# signal data acquisition
exp_cr_gate.acquire(
signal="acquire_1",
handle="ac_1",
kernel=readout_weighting_function,
)
# relax time after readout - for signal processing and qubit relaxation to ground state
with exp_cr_gate.section(uid="relax", length=100e-9):
exp_cr_gate.reserve(signal="measure_0")
# set up sweep parameter - drive pulse length
start = 32e-9
stop = 640e-9
count = 20
length_sweep = LinearSweepParameter(uid="length", start=start, stop=stop, count=count)
# number of averages
average_exponent = 10 # used for 2^n averages, n=average_exponent, maximum: n = 17
# Create Experiment
exp_cr_gate = Experiment(
uid="cr Tuneup",
signals=[
ExperimentSignal("drive_0"),
ExperimentSignal("drive_1"),
ExperimentSignal("drive_cr"),
ExperimentSignal("measure_0"),
ExperimentSignal("acquire_0"),
ExperimentSignal("measure_1"),
ExperimentSignal("acquire_1"),
],
)
## experimental pulse sequence
# outer loop - real-time, cyclic averaging in standard integration mode
with exp_cr_gate.acquire_loop_rt(
uid="shots",
count=pow(2, average_exponent),
averaging_mode=AveragingMode.CYCLIC,
acquisition_type=AcquisitionType.INTEGRATION,
):
# inner loop - real-time sweep of qubit drive pulse amplitude
with exp_cr_gate.sweep(uid="sweep", parameter=length_sweep):
with exp_cr_gate.section(
uid="drive", alignment=SectionAlignment.RIGHT, length=stop + 2 * x90.length
):
# qubit excitation - assume something is done to both qubits
with exp_cr_gate.section(
uid="qubit_excitation",
on_system_grid=True,
alignment=SectionAlignment.RIGHT,
):
exp_cr_gate.play(signal="drive_0", pulse=x90)
exp_cr_gate.play(signal="drive_1", pulse=x90, amplitude=0.4)
# play CR pulse and sweep its length
with exp_cr_gate.section(
uid="cr_gate",
play_after="qubit_excitation",
on_system_grid=True,
alignment=SectionAlignment.LEFT,
):
exp_cr_gate.play(signal="drive_cr", pulse=cr_pulse, length=length_sweep)
# qubit readout pulses and data acquisition
with exp_cr_gate.section(uid="qubit_readout", play_after="drive"):
# play readout pulse
exp_cr_gate.play(signal="measure_0", pulse=readout_pulse)
exp_cr_gate.play(signal="measure_1", pulse=readout_pulse)
# signal data acquisition
exp_cr_gate.acquire(
signal="acquire_0",
handle="ac_0",
kernel=readout_weighting_function,
)
# signal data acquisition
exp_cr_gate.acquire(
signal="acquire_1",
handle="ac_1",
kernel=readout_weighting_function,
)
# relax time after readout - for signal processing and qubit relaxation to ground state
with exp_cr_gate.section(uid="relax", length=100e-9):
exp_cr_gate.reserve(signal="measure_0")
In [ ]:
Copied!
# define the signal map - playing cr gate pulse on qubit drive 0
map_q0 = {
"drive_0": q0.signals["drive"],
"drive_1": q1.signals["drive"],
"drive_cr": q0.signals["drive_ef"],
"measure_0": q0.signals["measure"],
"acquire_0": q0.signals["acquire"],
"measure_1": q1.signals["measure"],
"acquire_1": q1.signals["acquire"],
}
# .. and on qubit drive 1
map_q1 = {
"drive_0": q0.signals["drive"],
"drive_1": q1.signals["drive"],
"drive_cr": q1.signals["drive_ef"],
"measure_0": q0.signals["measure"],
"acquire_0": q0.signals["acquire"],
"measure_1": q1.signals["measure"],
"acquire_1": q1.signals["acquire"],
}
# define the signal map - playing cr gate pulse on qubit drive 0
map_q0 = {
"drive_0": q0.signals["drive"],
"drive_1": q1.signals["drive"],
"drive_cr": q0.signals["drive_ef"],
"measure_0": q0.signals["measure"],
"acquire_0": q0.signals["acquire"],
"measure_1": q1.signals["measure"],
"acquire_1": q1.signals["acquire"],
}
# .. and on qubit drive 1
map_q1 = {
"drive_0": q0.signals["drive"],
"drive_1": q1.signals["drive"],
"drive_cr": q1.signals["drive_ef"],
"measure_0": q0.signals["measure"],
"acquire_0": q0.signals["acquire"],
"measure_1": q1.signals["measure"],
"acquire_1": q1.signals["acquire"],
}
2.2 Run the Experiment and Plot the Pulse Sequence¶
In [ ]:
Copied!
# set signal map to qubit 0
exp_cr_gate.set_signal_map(map_q1)
# run experiment on qubit 0
compiled_exp_cr_gate = session.compile(exp_cr_gate)
cr_gate_results = session.run(compiled_exp_cr_gate)
# set signal map to qubit 0
exp_cr_gate.set_signal_map(map_q1)
# run experiment on qubit 0
compiled_exp_cr_gate = session.compile(exp_cr_gate)
cr_gate_results = session.run(compiled_exp_cr_gate)
In [ ]:
Copied!
# Plot simulated output signals
plot_simulation(compiled_exp_cr_gate, start_time=0, length=5e-6)
# Plot simulated output signals
plot_simulation(compiled_exp_cr_gate, start_time=0, length=5e-6)
In [ ]:
Copied!