Transpile with pass managers
The recommended way to transpile a circuit is to create a staged pass manager and then execute its run
method with the circuit as input. This page explains how to transpile quantum circuits this way.
What is a (staged) pass manager?
In the context of the Qiskit SDK, transpilation refers to the process of transforming an input circuit into a form that is suitable for execution on a quantum device. Transpilation typically occurs in a sequence of steps called transpiler passes. The circuit is processed by each transpiler pass in sequence, with the output of one pass becoming the input to the next. For example, one pass could go through the circuit and merge all consecutive sequences of single-qubit gates, and then the next pass could synthesize these gates into the basis set of the target device. The transpiler passes included with Qiskit are located in the qiskit.transpiler.passes module.
A pass manager is an object that stores a list of transpiler passes and can execute them on a circuit. Create a pass manager by initializing a PassManager
with a list of transpiler passes. To run the transpilation on a circuit, call the run
method with a circuit as input.
A staged pass manager is a special kind of pass manager that represents a level of abstraction above that of a normal pass manager. While a normal pass manager is composed of several transpiler passes, a staged pass manager is composed of several pass managers. This is a useful abstraction because transpilation typically happens in discrete stages, as described in Transpiler stages, with each stage being represented by a pass manager. Staged pass managers are represented by the StagedPassManager
class. The rest of this page describes how to create and customize (staged) pass managers.
Generate a preset staged pass manager
To create a preset staged pass manager with reasonable defaults, use the generate_preset_pass_manager
function:
from qiskit.transpiler.preset_passmanagers import generate_preset_pass_manager
from qiskit_ibm_runtime import QiskitRuntimeService
service = QiskitRuntimeService()
backend = service.backend("ibm_brisbane")
pass_manager = generate_preset_pass_manager(optimization_level=3, backend=backend)
To transpile a circuit or list of circuits with a pass manager, pass the circuit or list of circuits to the run
method. Let's do this on a two-qubit circuit consisting of a Hadamard followed by two adjacent CX gates:
from qiskit import QuantumRegister, QuantumCircuit
# Create a circuit
qubits = QuantumRegister(2, name="q")
circuit = QuantumCircuit(qubits)
a, b = qubits
circuit.h(a)
circuit.cx(a, b)
circuit.cx(b, a)
# Transpile it by calling the run method of the pass manager
transpiled = pass_manager.run(circuit)
# Draw it, excluding idle qubits from the diagram
transpiled.draw("mpl", idle_wires=False)
Output:
See Transpilation defaults and configuration options for a description of the possible arguments to the generate_preset_pass_manager
function. The arguments to generate_preset_pass_manager
match the arguments to the transpile
function.
Having trouble remembering pass manager details? Try asking Qiskit Code Assistant.
# Create a pass manager with the highest optimization level
# Transpile 'circuit' with the highest optimization level
New to the code assistant? See Qiskit Code Assistant for installation and usage. Note this is an experimental feature and only available to IBM Quantum™ Premium Plan users.
If the preset pass managers don't fulfill your needs, customize transpilation by creating (staged) pass managers or even transpilation passes. The rest of this page describes how to create pass managers. For instructions on how to create transpilation passes, see Write your own transpiler pass.
Create your own pass manager
The qiskit.transpiler.passes module includes many transpiler passes that can be used to create pass managers. To create a pass manager, initialize a PassManager
with a list of passes. For example, the following code creates a transpiler pass that merges adjacent two-qubit gates and then synthesizes them into a basis of , , and , gates.
from qiskit.transpiler import PassManager
from qiskit.transpiler.passes import (
Collect2qBlocks,
ConsolidateBlocks,
UnitarySynthesis,
)
basis_gates = ["rx", "ry", "rxx"]
translate = PassManager(
[
Collect2qBlocks(),
ConsolidateBlocks(basis_gates=basis_gates),
UnitarySynthesis(basis_gates),
]
)
To demonstrate this pass manager in action, test it on a two-qubit circuit consisting of a Hadamard followed by two adjacent CX gates:
[4] :from qiskit import QuantumRegister, QuantumCircuit
qubits = QuantumRegister(2, name="q")
circuit = QuantumCircuit(qubits)
a, b = qubits
circuit.h(a)
circuit.cx(a, b)
circuit.cx(b, a)
circuit.draw("mpl")
Output:
To run the pass manager on the circuit, call the run
method.
translated = translate.run(circuit)
translated.draw("mpl")
Output:
For a more advanced example that shows how to create a pass manager to implement the error suppression technique known as dynamical decoupling, see Create a pass manager for dynamical decoupling.
Create a staged pass manager
A StagedPassManager
is a pass manager that is composed of individual stages, where each stage is defined by a PassManager
instance. You can create a StagedPassManager
by specifying the desired stages. For example, the following code creates a staged pass manager with two stages, init
and translation
. The translation
stage is defined by the pass manager that was created previously.
from qiskit.transpiler import PassManager, StagedPassManager
from qiskit.transpiler.passes import UnitarySynthesis, Unroll3qOrMore
basis_gates = ["rx", "ry", "rxx"]
init = PassManager([UnitarySynthesis(basis_gates, min_qubits=3), Unroll3qOrMore()])
staged_pm = StagedPassManager(
stages=["init", "translation"], init=init, translation=translate
)
There is no limit on the number of stages you can put in a staged pass manager.
Another useful way to create a staged pass manager is to begin with a preset staged pass manager and then swap out some of the stages. For example, the following code generates a preset pass manager with optimization level 3, and then specifies a custom pre_layout
stage.
import numpy as np
from qiskit.circuit.library import HGate, PhaseGate, RXGate, TdgGate, TGate
from qiskit.transpiler.passes import CXCancellation, InverseCancellation
pass_manager = generate_preset_pass_manager(3, backend)
inverse_gate_list = [
HGate(),
(RXGate(np.pi / 4), RXGate(-np.pi / 4)),
(PhaseGate(np.pi / 4), PhaseGate(-np.pi / 4)),
(TGate(), TdgGate()),
]
logical_opt = PassManager(
[
CXCancellation(),
InverseCancellation(inverse_gate_list),
]
)
# Add pre-layout stage to run extra logical optimization
pass_manager.pre_layout = logical_opt
The stage generator functions might be useful for constructing custom pass managers.
They generate stages that provide common functionality used in many pass managers.
For example, generate_embed_passmanager
can be used to generate a stage
to "embed" a selected initial Layout
from a layout pass to the specified target device.
Next steps
- Write a custom transpiler pass.
- Create a pass manager for dynamical decoupling.
- To learn more about the
generate_preset_passmanager
function, see the Transpilation default settings and configuration options topic. - Try the Submit transpiled circuits tutorial.
- See the Transpile API documentation.