The Pipeline
When you call transpile(), your circuit passes through a sequence of single-purpose transformation passes. Each pass receives the output of the previous one. The final stage is an optimization loop that wraps two inner passes and can be configured to run a fixed number of iterations or until the gate count stabilizes. This page walks through each stage in order, including what it does, why it exists, and what changes in the circuit as a result.
The full pipeline:
BasisTranslation → Layout → BasicSwapRouter → BasisTranslation → RemoveBarriers → OptimizationLoop
OptimizationLoop = (CancelAdjacent → MergeRotations) repeated N times or until gate count convergesPass 1: Basis Translation
The first thing Tessera does is decompose every gate in your circuit into the target backend's supported gate set. Different hardware supports different native gates. IBM supports cx, rz, sx, x, u. IonQ supports rx, ry, rz, cx. Rigetti supports rx, rz, cz. Any gate that isn't in the backend's basis set gets replaced with an equivalent sequence of gates that are.
This pass is single-pass. It walks the instruction list once and substitutes each non-basis gate using the backend's decomposition map. Decomposition map entries must produce only basis gate instructions, so no second pass is needed here.
Gates that are already in the basis set pass through unchanged. Measurements and barriers also pass through unchanged.
Pass 2: Layout
Your circuit is written in logical qubit space with qubit 0, qubit 1, qubit 2. Real hardware has a fixed topology where only certain qubit pairs are physically connected. LayoutPass maps each logical qubit to a physical qubit on the target device.
The actual placement logic lives in a layout algorithm. LayoutPass resolves whichever algorithm you selected from the registry (or a custom callable you passed) and delegates to it. Three algorithms ship with Tessera:
"dense"(default): greedy placement by interaction frequency"sabre": forward-backward trial routing for higher quality on routing-heavy circuits"trivial": direct logical-to-physical mapping, useful as a baseline
The result is stored in TesseraCircuit.layout as a dict mapping logical → physical qubit indices. For example {0: 3, 1: 5, 2: 6} means logical qubit 0 maps to physical qubit 3, and so on. All subsequent passes work in physical qubit space using this mapping.
For the details of each built-in algorithm and the custom-callable interface, see the Layout Algorithms page.
layout field on the circuit is populated.Pass 3: Swap Router
Even with a good layout, some two-qubit gates may still involve qubits that aren't directly connected on the hardware. BasicSwapRouter resolves this by applying the layout from Pass 2 and inserting SWAP gates to move qubits into adjacent positions before each non-adjacent operation.
The actual swap-selection logic lives in a routing algorithm. BasicSwapRouter resolves whichever algorithm you selected from the registry (or a custom pairwise callable you passed) and delegates to it. Three algorithms ship with Tessera:
"bfs"(default): pairwise breadth-first shortest path"a_star": pairwise A* shortest path with an admissible heuristic, ready for noise-aware weighted edges"sabre": whole-circuit swap selection with front-layer lookahead, often produces fewer total SWAPs
For pairwise algorithms, the router walks the instruction list once. For each two-qubit gate it checks whether the two involved physical qubits are connected in the coupling map. If they are, the gate is emitted as-is. If they aren't, the router finds a path between them using the selected algorithm, inserts SWAP gates along that path to bring them adjacent, and emits the gate. The routing state (which logical qubit is at which physical position) is updated after every SWAP so subsequent gates see the correct positions.
SABRE works differently. It maintains a front layer of executable gates and picks each swap by scoring candidates against a heuristic that considers both the immediate gates and a window of upcoming gates, then applies the swap and updates the front layer.
For the details of each built-in algorithm and the custom pairwise callable interface, see the Routing Algorithms page.
Pass 4: Basis Translation (Second Run)
The SWAP gates inserted by Pass 3 are not basis gates on most backends. A SWAP decomposes into three CX gates on IBM, or a longer sequence on Rigetti. This second run of BasisTranslationPass catches those newly introduced SWAPs and decomposes them into backend basis gates exactly the same way Pass 1 did.
Running basis translation a second time rather than baking SWAP decomposition into the router keeps the router simple and backend-agnostic. It only has to think about connectivity, not gate sets.
Pass 5: Remove Barriers
Barriers are structural hints that prevent gate reordering during circuit construction. They have no physical effect on hardware. Before the optimization passes run, RemoveBarriersPass strips all barrier instructions from the circuit so that CancelAdjacentPass and MergeRotationsPass can see across them and find cancellation and merging opportunities they would otherwise miss.
Pass 6: Optimization Loop
The final stage is an optimization loop that wraps two inner passes (Cancel Adjacent and Merge Rotations) and can run them more than once. A single round of these passes often unlocks new cancellation and merging opportunities for the other to find on the next round, so iterating can compound the savings.
The number of iterations is controlled by optimization_iterations:
1(default): a single pass through Cancel Adjacent and Merge Rotations. Matches pre-v1.1 behavior.- Any positive integer: run that many iterations regardless of whether the gate count is still changing.
-1: convergence mode. The loop runs until the gate count stops decreasing, capped atmax_iterations(default1000) as a safety valve against pathological circuits.
Inside the loop, the two inner passes run in order: Cancel Adjacent first, then Merge Rotations. Both inner passes can also be used standalone outside the loop if you want to compose your own pipeline.
Inner pass: Cancel Adjacent
Some gates are self-inverse. Applying the same gate twice returns the qubit to its original state, so the pair can be removed entirely. CancelAdjacentPass finds and removes these pairs.
The supported self-inverse gates are: x, cx, y, h, cz, swap.
This pass operates in two modes controlled by the strict parameter:
- Strict mode (default): only cancels gates that are directly adjacent in the instruction list.
X(q0) X(q0)cancels;X(q0) H(q1) X(q0)does not. - Commutative mode: cancels gates separated by instructions on non-overlapping qubits, since those instructions commute freely.
H(q0) X(q1) H(q0)cancels the H gates because nothing between them touches q0.
Inner pass: Merge Rotations
Consecutive rotation gates on the same qubit can be combined into a single rotation since rotation is additive: Rz(a)·Rz(b) = Rz(a+b). MergeRotationsPass finds these pairs and collapses them. If the merged angle is smaller than epsilon (default 1e-9), the gate is dropped entirely since it has negligible effect.
The supported mergeable gates are: rz, rx, ry.
Like CancelAdjacentPass, this pass operates in two modes:
- Strict mode (default): only merges gates that are directly adjacent. Three consecutive rotation gates will leave one unmerged in a single iteration of this pass; running the optimization loop more than once handles that case.
- Commutative mode: merges gates separated by instructions on non-overlapping qubits.
Rz(0.3, q0) Rx(0.5, q1) Rz(0.5, q0)becomesRz(0.8, q0) Rx(0.5, q1).