Download
Download this file as Jupyter notebook: parameterized_linker_native_gates_mq.ipynb.
Compiling multi-qubit native gates to waveforms
In this guide, we build on on Compiling single-qubit native gates to waveforms to demonstrate how to create a linker for a typical multi-qubit gate. We define two linkers for a cross-resonance gate, a common entangling gate in superconducting systems. The first is a basic implementation, while the second adds an extra pulse for crosstalk suppression.
Here, we only consider one of two commuting subsets of multi-qubit gates assuming linear connectivity.
Creating the Linkers
We define the cross-resonance gate and a corresponding instruction. We work with all
phases in the gate being 0
for simplicity, resulting in a gate proportional to
\(ZX\) with angle \(\beta\).
[2]:
import keysight.qcs as qcs
import numpy as np
import math
n_targets = 4
qubits = qcs.Qudits(range(n_targets))
# the number of commuting multi-qubit gates
n_mq = math.floor(n_targets / 2)
# create the multi-qudit targets
mq_targets = qcs.MultiQudits.from_qudits((qubits[: 2 * n_mq : 2], qubits[1::2]))
zx = qcs.PAULIS.sigma_z & qcs.PAULIS.sigma_x
cr_gate = qcs.ParametricGate([zx], ["beta"])
angles = qcs.Array(name="beta", shape=(n_mq,), dtype=float)
cr_param_gate = qcs.ParameterizedGate(cr_gate, angles)
The first linker corresponds to the basic implementation. Here, we apply a pulse to to the control qubit with the resonant frequency of the target qubit, resulting in a rotation around \(Z\) for the control and around \(X\) for the target. Note that we use the same frequencies as those in Compiling single-qubit native gates to waveforms.
[3]:
channels = qcs.Channels(range(n_targets), name="xy_channels")
sq_freqs = [5e9 + 100e6 * n for n in range(n_targets)]
freqs = qcs.Array("single_qubit_frequencies", value=sq_freqs, dtype=float)
amps = qcs.Array("multi_qubit_amplitudes", value=[0.5] * n_mq, dtype=float)
dur = qcs.Scalar("multi_qubit_duration", value=30e-9, dtype=float)
pulse = qcs.RFWaveform(dur, qcs.GaussianEnvelope(), angles * amps, freqs[1::2])
cr_prog = qcs.Program()
cr_prog.add_waveform(pulse, channels[: 2 * n_mq : 2])
# create the linker
cr_linker = qcs.ParameterizedLinker(cr_param_gate, mq_targets, cr_prog)
cr_prog.draw()
Program
Program
|
||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
Layer #0
Layer #0
|
||||||||||||||
|
|
RFWaveform on ('xy_channels', 0)
Parameters
|
||||||||||||
|
RFWaveform on ('xy_channels', 2)
Parameters
|
We now extend the above linker to suppress crosstalk by playing a simultaneous pulse on the target qubit at the same frequency with a fraction of the amplitude \(\alpha\).
[4]:
alpha = qcs.Scalar("alpha", value=0.3, dtype=float)
pulse_supp = qcs.RFWaveform(
dur, qcs.GaussianEnvelope(), alpha * angles * amps, freqs[1::2]
)
cr_prog_supp = qcs.Program()
cr_prog_supp.add_waveform(pulse, channels[: 2 * n_mq : 2])
cr_prog_supp.add_waveform(pulse_supp, channels[1::2])
# create the linker
cr_linker_supp = qcs.ParameterizedLinker(cr_param_gate, mq_targets, cr_prog_supp)
cr_prog_supp.draw()
Program
Program
|
||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
Layer #0
Layer #0
|
||||||||||||||
|
|
RFWaveform on ('xy_channels', 0)
Parameters
|
||||||||||||
|
RFWaveform on ('xy_channels', 1)
Parameters
|
|||||||||||||
|
RFWaveform on ('xy_channels', 2)
Parameters
|
|||||||||||||
|
RFWaveform on ('xy_channels', 3)
Parameters
|
Using the Linkers
We can use either of the linkers defined above to replace cross-resonance gates. The first linker gives a single waveform.
[5]:
program = qcs.Program()
some_beta = qcs.Array("beta", value=[np.pi / 2])
program.add_parametric_gate(cr_gate, [some_beta], (qubits[0], qubits[1]))
linker_pass = qcs.LinkerPass(cr_linker)
program_compiled = linker_pass.apply(program)
program_compiled.render(
channel_subplots=False,
lo_frequency=5e9,
sample_rate=qcs.SAMPLE_RATES[qcs.InstrumentEnum.M5300AWG],
)
Reusing the same program to compile, the second linker renders two waveforms on different channels.
[6]:
linker_pass_supp = qcs.LinkerPass(cr_linker_supp)
program_compiled = linker_pass_supp.apply(program)
program_compiled.render(
channel_subplots=False,
lo_frequency=5e9,
sample_rate=qcs.SAMPLE_RATES[qcs.InstrumentEnum.M5300AWG],
)
Download
Download this file as Jupyter notebook: parameterized_linker_native_gates_mq.ipynb.