Download

Download this file as Jupyter notebook: linker.ipynb.

Introduction to linkers

This guide provides a few examples that show how to initialize linkers in QCS, as well as to use a linker pass inside an executor to modify quantum programs.

In this example, Mapping from circuit to hardware, we will show how to map circuit-level instructions to pulses that can be executed on hardware.

Mapping from circuit to hardware

Consider the following program, which applies a Pauli-X gate to a qubit labelled 0 and subsequently measures the qubit in the computational basis.

[2]:
import keysight.qcs as qcs

# initialize a qubit and an array to hold results
qubit = qcs.Qudits([0])

# define a program
program_in = qcs.Program()
program_in.add_gate(qcs.GATES.x, qubit)
program_in.add_measurement(qubit)

program_in.draw()
keysight-logo-svg
Program
Program
Duration undefined
Layers 1
Targets 1
Repetitions
Layer #0
Layer #0
Duration undefined
qudits 0
X
Gate X on ('qudits', 0)

Matrix:
0 1
1 0
Measure on ('qudits', 0)

Parameters
Dim 2

We now define two linkers. The first linker maps the Pauli-X gate to a pulse executed on an AWG.

[3]:
# define the replacement in terms of a pulse and channel
pulse = qcs.RFWaveform(
    duration=8e-8, envelope=qcs.GaussianEnvelope(), amplitude=1, rf_frequency=5e9
)

channel = qcs.Channels(range(1), "control_channel")

replacement_gt = qcs.Program()
replacement_gt.add_waveform(pulse, channel)

# specify the instruction to be replaced and create the Linker
linker_gt = qcs.Linker(qcs.GATES.x, qubit, replacement_gt)

The second linker maps the measurement instruction to an acquisition.

[4]:
replacement_meas = qcs.Program()
integration_filter = qcs.IntegrationFilter(pulse)
classifier = qcs.Classifier([0.0, 1.0])
replacement_meas.add_acquisition(integration_filter, channel, classifier)

linker_meas = qcs.ParameterizedLinker(qcs.Measure(), qubit, replacement_meas)

Finally, we use the Executor to replace the circuit-level instructions with the new instructions.

[5]:
program_out = qcs.Executor(qcs.LinkerPass(linker_gt, linker_meas)).execute(program_in)

By plotting program_out, we can see that the circuit-level instructions have been correctly replaced.

[6]:
program_out.draw()
keysight-logo-svg
Program
Program
Duration 160 ns
Layers 1
Targets 1
Repetitions
Layer #0
Layer #0
Duration 160 ns
control_channel 0
RFWaveform on ('control_channel', 0)

Parameters
Duration 80 ns
Amplitude 1
Frequency 5 GHz
Envelope GaussianEnvelope(2.0)
Instantaneous Phase 0 rad
Post-phase 0 rad
Acquisition on ('control_channel', 0)

Parameters
Duration 80 ns
Integration Filter
RFWaveform

Parameters
Duration 80 ns
Amplitude 1
Frequency 5 GHz
Envelope GaussianEnvelope(2.0)
Instantaneous Phase 0 rad
Post-phase 0 rad
Classifier Classifier(Array(name=_implicit, shape=(2,), dtype=complex, unit=none))

Linking conditional operations

Rather than linking from a conditional operation to another conditional operation, we instead iterate through the possibile operations and link them all individually. Consider the case of active qubit reset.

[7]:
program = qcs.Program()
program.add_measurement(qubit, reset=True, repeat_reset=2)
program.draw()
keysight-logo-svg
Program
Program
Duration undefined
Layers 5
Targets 1
Repetitions
Layer #0
Layer #0
Duration undefined
Layer #1
Layer #1 (Data Transactions)
Duration 0 s
Transaction Source Measure on ('qudits', 0)
Transaction Destinations ('qudits', 0)
Layer #2
Layer #2
Duration undefined
Layer #3
Layer #3 (Data Transactions)
Duration 0 s
Transaction Source Measure on ('qudits', 0)
Transaction Destinations ('qudits', 0)
Layer #4
Layer #4
Duration undefined
qudits 0
Measure on ('qudits', 0)

Parameters
Dim 2
Register Register(name=qudits_results, num_bits=1, dim=2)
ConditionalOperation on ('qudits', 0)

Operations
Outcome 0
Gate ID

Matrix:
1 0
0 1
Outcome 1
Gate X

Matrix:
0 1
1 0

Register
Name qudits_results
Num Bits 1
Dim 2
Measure on ('qudits', 0)

Parameters
Dim 2
Register Register(name=qudits_results, num_bits=1, dim=2)
ConditionalOperation on ('qudits', 0)

Operations
Outcome 0
Gate ID

Matrix:
1 0
0 1
Outcome 1
Gate X

Matrix:
0 1
1 0

Register
Name qudits_results
Num Bits 1
Dim 2

Here, a conditional operation has been added after the measurement that will either perform a Pauli-X gate or the identity gate. To link this object properly, we add a linker for the identity gate in addition to the linker we already have.

[8]:
replacement_id = qcs.Program()
replacement_id.add_waveform(qcs.Delay(0), channel)

linker_id = qcs.Linker(qcs.GATES.id, qubit, replacement_id)

Applying the linkers, we see we get a new conditional operation except with a waveform and delay:

[9]:
program_out = qcs.LinkerPass(linker_gt, linker_id, linker_meas).apply(program)
program_out.draw()
keysight-logo-svg
Program
Program
Duration 320 ns
Layers 7
Targets 1
Repetitions
Layer #0
Layer #0
Duration 80 ns
Layer #1
Layer #1
Duration 0 s
Layer #2
Layer #2 (Data Transactions)
Duration 0 s
Transaction Source Acquisition on ('control_channel', 0)
Transaction Destinations ('control_channel', 0)
Layer #3
Layer #3
Duration 160 ns
Layer #4
Layer #4
Duration 0 s
Layer #5
Layer #5 (Data Transactions)
Duration 0 s
Transaction Source Acquisition on ('control_channel', 0)
Transaction Destinations ('control_channel', 0)
Layer #6
Layer #6
Duration 80 ns
control_channel 0
Acquisition on ('control_channel', 0)

Parameters
Duration 80 ns
Integration Filter
RFWaveform

Parameters
Duration 80 ns
Amplitude 1
Frequency 5 GHz
Envelope GaussianEnvelope(2.0)
Instantaneous Phase 0 rad
Post-phase 0 rad
Classifier Classifier(Array(name=_implicit, shape=(2,), dtype=complex, unit=none))
ConditionalOperation on ('control_channel', 0)

Operations
Outcome 0
Delay on None

Parameters
Duration 0 s
Outcome 1
RFWaveform

Parameters
Duration 80 ns
Amplitude 1
Frequency 5 GHz
Envelope GaussianEnvelope(2.0)
Instantaneous Phase 0 rad
Post-phase 0 rad

Register
Name qudits_results
Num Bits 1
Dim 2
Acquisition on ('control_channel', 0)

Parameters
Duration 80 ns
Integration Filter
RFWaveform

Parameters
Duration 80 ns
Amplitude 1
Frequency 5 GHz
Envelope GaussianEnvelope(2.0)
Instantaneous Phase 0 rad
Post-phase 0 rad
Classifier Classifier(Array(name=_implicit, shape=(2,), dtype=complex, unit=none))
ConditionalOperation on ('control_channel', 0)

Operations
Outcome 0
Delay on None

Parameters
Duration 0 s
Outcome 1
RFWaveform

Parameters
Duration 80 ns
Amplitude 1
Frequency 5 GHz
Envelope GaussianEnvelope(2.0)
Instantaneous Phase 0 rad
Post-phase 0 rad

Register
Name qudits_results
Num Bits 1
Dim 2

Download

Download this file as Jupyter notebook: linker.ipynb.

On this page