---
title: Create a pass manager for dynamical decoupling
description: How to create a pass manager for dynamical decoupling in Qiskit.
source: https://eu-de.quantum.cloud.ibm.com/docs/en/guides/dynamical-decoupling-pass-manager
---

# Create a pass manager for dynamical decoupling

### Package versions

The code on this page was developed using the following requirements.
We recommend using these versions or newer.

```
qiskit[all]~=2.5.1
qiskit-ibm-runtime~=0.47.0
```

This page demonstrates how to use the [`PadDynamicalDecoupling`](/docs/api/qiskit/qiskit.transpiler.passes.PadDynamicalDecoupling) pass to add an error suppression technique called *dynamical decoupling* to the circuit.

Dynamical decoupling works by adding pulse sequences (known as *dynamical decoupling sequences*) to idle qubits to flip them around the Bloch sphere, which cancels the effect of noise channels, thereby suppressing decoherence. These pulse sequences are similar to refocusing pulses used in nuclear magnetic resonance. For a full description, see [A Quantum Engineer's Guide to Superconducting Qubits](https://arxiv.org/abs/1904.06560).

Because the `PadDynamicalDecoupling` pass only operates on scheduled circuits and involves gates that are not necessarily basis gates of our target, you will need the [`ALAPScheduleAnalysis`](/docs/api/qiskit/qiskit.transpiler.passes.ALAPScheduleAnalysis) and [`BasisTranslator`](/docs/api/qiskit/qiskit.transpiler.passes.BasisTranslator) passes as well.

Get the `target` information from the `backend` and save the operation names as `basis_gates` because the `target` will need to be modified to add timing information for the gates used in dynamical decoupling.

> **Note**
>
> The  `FakeSherbrooke` mock backend from `qiskit_ibm_runtime` is used in these examples, but you can try it on any Qiskit-compatible real or fake backend.  Your results might be different.

```python
from qiskit_ibm_runtime.fake_provider import FakeSherbrooke

backend = FakeSherbrooke()

target = backend.target
basis_gates = list(target.operation_names)
```

Create an `efficient_su2` circuit as an example. First, transpile the circuit to the backend because dynamical decoupling pulses need to be added after the circuit has been transpiled and scheduled. Dynamical decoupling often works best when there is a lot of idle time in the quantum circuits - that is, there are qubits that are not being used while others are active. This is the case in this circuit because the two-qubit `ecr` gates are applied sequentially in this ansatz.

```python
from qiskit.transpiler import generate_preset_pass_manager
from qiskit.circuit.library import efficient_su2

qc = efficient_su2(12, entanglement="circular", reps=1)
pm = generate_preset_pass_manager(1, target=target, seed_transpiler=12345)
qc_t = pm.run(qc)
qc_t.draw("mpl", fold=-1, idle_wires=False)
```

Output:

![Output of the previous code cell](https://eu-de.quantum.cloud.ibm.com/docs/images/guides/dynamical-decoupling-pass-manager/extracted-outputs/9479a60c-d5d0-45c7-a93e-a2a488ba8985-0.svg)

A dynamical decoupling sequence is a series of gates that compose to the identity and are spaced regularly in time. For example, start by creating a simple sequence called XY4 consisting of four gates.

```python
from qiskit.circuit.library import XGate, YGate

X = XGate()
Y = YGate()

dd_sequence = [X, Y, X, Y]
```

Because of the regular timing of dynamical decoupling sequences, information about the `YGate` must be added to the `target` because it is *not* a basis gate, whereas the `XGate` is. We know *a priori* that the `YGate` has the same duration and error as the `XGate`, however, so we can just retrieve those properties from the `target` and add them back for the `YGate` objects. This is also why the `basis_gates` were saved separately, since we are adding the `YGate` instruction to the `target` although it is not an actual basis gate of `ibm_fez`.

```python
from qiskit.transpiler import InstructionProperties

y_gate_properties = {}
for qubit in range(target.num_qubits):
    y_gate_properties.update(
        {
            (qubit,): InstructionProperties(
                duration=target["x"][(qubit,)].duration,
                error=target["x"][(qubit,)].error,
            )
        }
    )

target.add_instruction(YGate(), y_gate_properties)
```

Ansatz circuits such as `efficient_su2` are parameterized, so they must have value bound to them before being sent to the backend. Here, assign random parameters.

```python
import numpy as np

rng = np.random.default_rng(1234)
qc_t.assign_parameters(
    rng.uniform(-np.pi, np.pi, qc_t.num_parameters), inplace=True
)
```

Next, execute the custom passes. Instantiate the `PassManager` with `ALAPScheduleAnalysis` and `PadDynamicalDecoupling`.  Run `ALAPScheduleAnalysis` first to add timing information about the quantum circuit before the regularly-spaced dynamical decoupling sequences can be added. These passes are run on the circuit with `.run()`.

```python
from qiskit.transpiler import PassManager
from qiskit.transpiler.passes.scheduling import (
    ALAPScheduleAnalysis,
    PadDynamicalDecoupling,
)

dd_pm = PassManager(
    [
        ALAPScheduleAnalysis(target=target),
        PadDynamicalDecoupling(target=target, dd_sequence=dd_sequence),
    ]
)
qc_dd = dd_pm.run(qc_t)
```

Use the visualization tool [`timeline_drawer`](/docs/api/qiskit/qiskit.visualization.timeline_drawer) to see the circuit's timing and confirm that a regularly-spaced sequence of `XGate` objects and `YGate` objects appear in the circuit.

```python
from qiskit.visualization import timeline_drawer

timeline_drawer(qc_dd, idle_wires=False, target=target)
```

Output:

![Output of the previous code cell](https://eu-de.quantum.cloud.ibm.com/docs/images/guides/dynamical-decoupling-pass-manager/extracted-outputs/7a552621-a96f-4bb8-ae9b-4ab5a65bbb64-0.svg)

Lastly, because the `YGate` is not an actual basis gate of our backend, manually apply the `BasisTranslator` pass (this is a default pass, but it is executed before scheduling, so it needs to be applied again). The session equivalence library is a library of circuit equivalences that allows the transpiler to decompose circuits into basis gates, as also specified as an argument.

```python
from qiskit.circuit.equivalence_library import (
    SessionEquivalenceLibrary as sel,
)
from qiskit.transpiler.passes import BasisTranslator

qc_dd = BasisTranslator(sel, basis_gates)(qc_dd)
qc_dd.draw("mpl", fold=-1, idle_wires=False)
```

Output:

![Output of the previous code cell](https://eu-de.quantum.cloud.ibm.com/docs/images/guides/dynamical-decoupling-pass-manager/extracted-outputs/f0f4b29d-1c95-47d2-a7ad-8e130eaff74a-0.svg)

Now, `YGate` objects are absent from our circuit, and there is explicit timing information in the form of `Delay` gates. This transpiled circuit with dynamical decoupling is now ready to be sent to the backend.

## Next steps

> **Recommendations**
>
> - To learn how to use the `generate_preset_passmanager` function instead of writing your own passes, start with the [Transpilation default settings and configuration options](/docs/guides/defaults-and-configuration-options) topic.
> - Try the [Compare transpiler settings](/docs/guides/circuit-transpilation-settings#compare-transpiler-settings) guide.
> - See the [Transpile API documentation](https://docs.quantum-computing.ibm.com/api/qiskit/transpiler).
