Core Concepts
The Intermediate Representation
Tessera does not operate directly on Qiskit circuits. Instead it converts the input circuit into its own internal format, TesseraCircuit and TesseraInstruction. It processes it through the pipeline, and converts back at the end. This means every pass is completely independent of Qiskit internals and can be written, tested, and reasoned about without any knowledge of how Qiskit represents circuits internally.
TesseraInstruction represents a single gate or measurement. It has four fields:
| Field | Type | Description |
|---|---|---|
name | str | The gate name (e.g. "cx", "rz", "measure") |
qubits | list[int] | Qubit indices the gate acts on |
clbits | list[int] | Classical bit indices (for measurements) |
params | list[float] | Rotation angles or other gate parameters |
TesseraCircuit is an ordered list of instructions plus metadata:
| Field | Type | Description |
|---|---|---|
num_qubits | int | Number of qubits in the circuit |
num_clbits | int | Number of classical bits |
instructions | list[TesseraInstruction] | The ordered sequence of operations |
layout | dict[int, int] | Maps logical qubit indices to physical qubit indices. Empty until DenseLayoutPass runs. |
Passes
A pass is a single transformation step on a circuit. Every pass in Tessera follows the same contract: it takes a TesseraCircuit in and returns a TesseraCircuitout. That's it. A pass does exactly one thing, has no side effects, and knows nothing about what came before or after it in the pipeline.
All passes inherit from TranspilerPass and implement a single run() method:
from tessera.circuit import TesseraCircuit
from tessera.transpiler_pass import TranspilerPass
class MyPass(TranspilerPass):
def run(self, circuit: TesseraCircuit) -> TesseraCircuit:
# transform circuit here
return circuitThis design means any pass can be unit tested in complete isolation. Just construct a TesseraCircuit, call run(), and inspect the output. No pipeline setup required.
The Pass Manager
The TesseraPassManager chains passes together sequentially. Each pass receives the output of the previous one. The pipeline is just a list, and passes run in the order they were added, no branching, no conditionals.
from tessera.pass_manager import TesseraPassManager
manager = TesseraPassManager([PassA(), PassB(), PassC()])
result = manager.run(circuit)Passes can also be added incrementally after construction:
manager = TesseraPassManager()
manager.add_pass(PassA())
manager.add_pass(PassB())run() accepts optional before and after hook functions that fire around each pass. Both receive the pass instance and the current circuit. Tessera uses these internally to implement debug_on logging:
def log_before(pass_, circuit):
print(f"Running {pass_.name} | Gates: {len(circuit.instructions)}")
def log_after(pass_, circuit):
print(f"Finished {pass_.name} | Gates: {len(circuit.instructions)}")
result = manager.run(circuit, before=log_before, after=log_after)Logical vs Physical Qubits
When you write a circuit you work in logical qubit space with qubit 0, qubit 1, qubit 2, and so on. Real quantum hardware has a fixed number of physical qubits arranged in a specific topology, and not every qubit can interact with every other qubit directly.
DenseLayoutPass bridges this gap. It maps each logical qubit to a physical qubit on the target device, choosing positions that minimize the routing overhead for the interactions in your circuit. After it runs, TesseraCircuit.layout holds that mapping:
# Example: 3 logical qubits mapped to physical qubits on a 7-qubit device
circuit.layout # {0: 3, 1: 5, 2: 6}All subsequent passes: including BasicSwapRouter: work in physical qubit space using this mapping. When to_qiskit() converts the final circuit back, it uses layout to correctly size the output circuit to the physical qubit count rather than the logical count.
The Conversion Layer
Tessera uses two converter functions to bridge between Qiskit and its own IR. These are the only two places in the entire codebase where Qiskit is directly touched.
from_qiskit(qc) takes a Qiskit QuantumCircuit and returns a TesseraCircuit. It walks every instruction in the Qiskit circuit, extracts the gate name, qubit indices, classical bit indices, and parameters, and builds the equivalent TesseraInstruction list. The resulting TesseraCircuit has no layout: it represents the circuit in logical qubit space exactly as written.
to_qiskit(tc) takes a TesseraCircuit and returns a Qiskit QuantumCircuit. If a layout is present it sizes the output circuit to max(layout.values()) + 1 physical qubits. If no layout is present it falls back to num_qubits. It then appends each instruction back as a Qiskit gate using the gate library mapping.
Neither function does any transformation. They are pure format conversions. All circuit transformations happen in passes.
Philosophy
Every component in Tessera has a single responsibility and a clean boundary. Passes don't know about backends. The pass manager doesn't know what passes do. The IR doesn't know about Qiskit. The conversion layer is the only place Qiskit is touched. The backend registry is the only place gate sets and decompositions live.
The practical consequence is that you can work on any one piece of the system without touching any other. Adding a new optimization pass means writing one class and adding it to the pipeline. Nothing else changes. Adding a new backend means registering a gate set and a decomposition map with no pass code changes. Swapping out the routing algorithm means replacing one pass. The rest of the pipeline is unaffected.
This isn't just an architectural preference. It's what makes the codebase testable. Each boundary is a natural test seam. Each pass can be verified in isolation with a constructed input circuit and an expected output. Each backend can be verified without running the full pipeline. The modularity and the testability are the same thing.