Download

Download this file as Jupyter notebook: qubit_dynamical_decoupling.ipynb.

Dynamical decoupling

Dynamical decoupling is a simple error suppression strategy in quantum computing systems in which a series of pulses with certain intervals are applied to the qubits to effectively “decouple” them from their environment, thus improving decoherence times.

The type of interaction with the environment typically determines what kind of decoupling sequence will work best, for example, if the qubits are coupled to their environment through a purely dephasing interaction, a single-axis pulse sequence is effective in mitigating that interaction. If there are other terms in the interaction, multi-axis pulse sequences tend to perform better.

Keysight’s Quantum Control System offers a series of commonly used decoupling sequences that can be defined through the total sequence length, number of pulses and/or the pulse interval. We provide the DynamicalDecouplingExperiment class as an easy entrance point for testing out the sequences. The typical use case for those sequences is to integrate them into a longer program (whenever certain qubits are idle for a longer period of time), which we demonstrate at the end of this guide.

[2]:
import keysight.qcs as qcs

We start by initializing a qubit and defining an empty channel mapper to create a new instance of the DynamicalDecouplingExperiment class. We load a pre-defined CalibrationSet that contains a configuration for up to 10 qubits and linkers for the X and Y gates.

[3]:
from keysight.qcs.experiments import (
    DynamicalDecouplingExperiment,
    make_calibration_set,
)

from keysight.qcs.quantum import make_decoupling_sequence, SequenceType

n_qubits = 1
qubits = qcs.Qudits(range(n_qubits))

# generate an empty channel mapper
mapper = qcs.ChannelMapper("ip_addr")

# create a default calibration set for n_qubits
calibration_set = make_calibration_set(n_qubits)

# in its simplest form, this class generates a constant decoupling sequence with two
# pulses
dd_experiment = DynamicalDecouplingExperiment(
    mapper,
    calibration_set,
    qubits,
    total_duration=200e-9,
)

dd_experiment.program.draw()
dd_experiment.compiled_program.render()
keysight-logo-svg
Program
Program
Duration undefined
Layers 1
Targets 1
Repetitions Repeat with 100 repetitions
Layer #0
Layer #0
Duration undefined
qudits 0
Delay on ('qudits', 0)

Parameters
Duration 50 ns
X
Gate X on ('qudits', 0)

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

Parameters
Duration 100 ns
X
Gate X on ('qudits', 0)

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

Parameters
Duration 50 ns

This creates a program that contains two X pulses and has a total duration of 200 ns. The finite pulse width is not taken into account by default, but can be added by specifying the pulse_duration argument, which will adjust the pulse interval accordingly.

To customize the sequence, users can specify the following arguments:

  • total_duration to set the total sequence duration

  • number_of_pulses to set the number of pulses

  • pulse_interval to specify the time between pulses

  • sequence_type to specify which decoupling sequence should be used

Note that not all arguments are compatible with each other, e.g. specifying all three parameters for total duration, pulse number and pulse interval will result in an error.

Available dynamical decoupling sequences

The DynamicalDecouplingExperiment supports the following sequence types:

  • "DD": constant dynamical decoupling, implemented via the

    constant_decoupling_sequence() function,

  • "CPMG": the Carr-Purcell-Meiboom-Gill (CPMG) sequence, implemented via the

    cpmg_sequence() function,

  • "UHRIG": the Uhrig (or quadratic) sequence, implemented via the

    uhrig_sequence() function,

  • "XY4": the XY4 sequence, implemented via the

    xy4_sequence() function, and

  • "CDD": a concatenated decoupling sequence, implemented via the

    concatenated_decoupling_sequence() function that uses the XY4 sequence as a base sequence. Other base sequences can be specified when using this function directly.

These strings can be passed to the decoupling experiment to use other sequences. For example, the following creates a Uhrig decoupling sequence with 10 pulses:

[4]:
dd_experiment = DynamicalDecouplingExperiment(
    mapper,
    calibration_set,
    qubits,
    total_duration=200e-9,
    number_of_pulses=10,
    sequence_type=SequenceType.UHRIG,
)

dd_experiment.program.draw()
dd_experiment.compiled_program.render()
keysight-logo-svg
Program
Program
Duration undefined
Layers 1
Targets 1
Repetitions Repeat with 100 repetitions
Layer #0
Layer #0
Duration undefined
qudits 0
Delay on ('qudits', 0)

Parameters
Duration 2.8463 ns
X
Gate X on ('qudits', 0)

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

Parameters
Duration 8.3083 ns
X
Gate X on ('qudits', 0)

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

Parameters
Duration 13.0972 ns
X
Gate X on ('qudits', 0)

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

Parameters
Duration 16.8251 ns
X
Gate X on ('qudits', 0)

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

Parameters
Duration 19.1899 ns
X
Gate X on ('qudits', 0)

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

Parameters
Duration 20 ns
X
Gate X on ('qudits', 0)

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

Parameters
Duration 19.1899 ns
X
Gate X on ('qudits', 0)

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

Parameters
Duration 16.8251 ns
X
Gate X on ('qudits', 0)

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

Parameters
Duration 13.0972 ns
X
Gate X on ('qudits', 0)

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

Parameters
Duration 8.3083 ns
X
Gate X on ('qudits', 0)

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

Parameters
Duration 2.8463 ns

Integrating dynamical decoupling into another experiment

Dynamical decoupling can be used as an error suppression tool within other programs and are typically integrated whenever there are long idle times for certain qubits. Using the DynamicalDecouplingExperiment class in this use case is not practical, it is better to use the built-in functions for creating single sequences as listed above, and then insert those into the program layers directly.

For example, let’s consider the following program which has a two-qubit gates on qubits 1 and 2, leaving qubit 0 idle for a longer amount of time:

[5]:
qubits = qcs.Qudits(range(3))

prog = qcs.Program()
prog.add_gate(qcs.GATES.x, qubits[0])
prog.add_gate(qcs.GATES.h, qubits[1], new_layer=True)
prog.add_gate(qcs.GATES.cx, (qubits[1], qubits[2]))
prog.add_measurement(qubits)

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

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

Parameters
Dim 2
1
H
Gate H on ('qudits', 1)

Matrix:
0.71 0.71
0.71 -0.71
CX
Gate CX on (('qudits', 1), ('qudits', 2))

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

Parameters
Dim 2
2
CX
Gate CX on (('qudits', 2), ('qudits', 1))

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

Parameters
Dim 2

We can insert a list of operations, e.g. a decoupling sequence into the second layer of the program. If the duration of the CX gate is known, we can use this to determine the decoupling sequence length.

[6]:
decoupling_duration = 150e-9

prog[2].insert(
    qubits[0],
    make_decoupling_sequence(
        decoupling_duration, number_of_pulses=2, sequence_type=SequenceType.CPMG
    ),
)
prog.draw()
keysight-logo-svg
Program
Program
Duration undefined
Layers 4
Targets 3
Repetitions
Layer #0
Layer #0
Duration undefined
Layer #1
Layer #1
Duration undefined
Layer #2
Layer #2
Duration undefined
Layer #3
Layer #3
Duration undefined
qudits 0
X
Gate X on ('qudits', 0)

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

Parameters
Duration 37.5 ns
X
Gate X on ('qudits', 0)

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

Parameters
Duration 75 ns
X
Gate X on ('qudits', 0)

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

Parameters
Duration 37.5 ns
Measure on ('qudits', 0)

Parameters
Dim 2
1
H
Gate H on ('qudits', 1)

Matrix:
0.71 0.71
0.71 -0.71
CX
Gate CX on (('qudits', 1), ('qudits', 2))

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

Parameters
Dim 2
2
CX
Gate CX on (('qudits', 2), ('qudits', 1))

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

Parameters
Dim 2

Download

Download this file as Jupyter notebook: qubit_dynamical_decoupling.ipynb.

On this page