Part V. Practical Software · Chapter 40
Transpilation and Hardware-Aware Compilation
The circuit you drew is not the circuit that runs. Between them sits the transpiler, rewriting your gates into the native set, routing around missing connections, and quietly deciding whether your algorithm fits the hardware's error budget.
In this chapter 12 sections
Compile against a declared native gate set and coupling graph, record initial and final layouts, inserted SWAPs, direction fixes, depth, duration, and two-qubit count, then verify the compiled circuit against the abstract unitary or a complete small-instance oracle.
A routed circuit is a proof obligation with a cost ledger. The compiler must show which logical state occupies each physical site after every move and why the output still means what the input circuit meant.
The target is a graph plus an instruction set
Start with an abstract circuit and a target contract. Vertices are physical qubit locations; directed or undirected edges identify allowed two-qubit operations; the instruction set names native one- and two-qubit gates. Add operation durations in seconds and calibration-specific error probabilities only when their protocol, scope, and date are known. Transpilation maps a circuit into such a target, and SDK compiler interfaces expose target-specific behavior [Qiskit transpiler documentation] [Cirq transformer documentation].
OpenQASM can express a program while leaving physical placement and target cost unresolved [OpenQASM 3 specification]. The compiler input must therefore include logical circuit, coupling graph, native entangler direction, initial layout policy, optimization objective, and whether measurements are reverse-mapped.
Route one distant CNOT on a line
On physical line 0—1—2—3, logical CNOT(q0,q3) is unavailable at the initial layout [q0,q1,q2,q3]. The transparent teaching router moves q0 right twice: SWAP(0,1), SWAP(1,2), then CNOT(2,3). The physical operation trace is short, but the logical layout is now [q1,q2,q0,q3]. If the output is read as the original layout, a correct physical run becomes a wrong logical result.
The route is not claimed optimal. A production compiler may move the target, exploit direction, commute gates, or choose a different initial placement. Its result must still expose enough layout and target data to reproduce the cost.
Expand SWAPs before comparing native cost
A SWAP is not usually a primitive entangler. Under a bidirectional CNOT basis, the familiar decomposition uses three CNOTs, so the teaching trace expands from two SWAPs plus one CNOT to seven CNOTs before single-qubit direction corrections. On a directed coupling graph, a reverse CNOT may itself require basis changes around an allowed-direction entangler. Reporting “three operations” would therefore mix an abstract routing instruction with native hardware instructions.
The ledger should retain both levels. Logical operations explain intent; routing operations explain movement; native instructions support duration and calibration lookup. These rows must not be summed until each operation has been lowered to the same instruction set. The expansion also changes depth: some one-qubit gates can overlap, while the CNOT chain sharing the moved qubit cannot.
Prove the routed operation means the same thing
For five small logical bits, enumerate all 32 basis inputs. Simulate the abstract CNOT. Simulate every routed SWAP and CNOT on physical positions. Convert the final physical bit vector back through the final layout, then compare. This catches a correct-looking gate trace with a stale measurement map.
A basis oracle is complete for this classical reversible fragment. General quantum circuits need a unitary comparison up to global phase, process comparison, or a trusted simulator over a sufficiently complete test set. The semantic test and resource test are separate: a compiler can preserve the unitary while regressing depth badly.
For unitary matrices and , a small-instance check can estimate the phase from a nonzero entry of and test . Comparing entries directly would reject a physically identical circuit that differs only by global phase. Once measurement, reset, or classical control appears, there may be no single unitary; compare the resulting channels or an exhaustive branch oracle instead.
Measurement mapping deserves its own assertion. If logical q0 finishes at physical p2, the classical bit receiving p2 must be labeled q0 in the normalized result. Test this with asymmetric basis inputs after routing. A Bell circuit is insufficient because symmetric outcomes can conceal a stale final layout just as they conceal a reversed display convention.
Nearest-neighbor routing trace and equivalence table
| step | physical operation | layout after | two-qubit count |
|---|---|---|---|
| 0 | input | q0 q1 q2 q3 | 0 |
| 1 | SWAP p0,p1 | q1 q0 q2 q3 | 1 SWAP |
| 2 | SWAP p1,p2 | q1 q2 q0 q3 | 2 SWAP |
| 3 | CNOT p2,p3 | q1 q2 q0 q3 | 2 SWAP + 1 CNOT |
def route(control=0, target=3, sites=4):
if (type(sites) is not int or sites < 2 or control == target or
control not in range(sites) or target not in range(sites)):
raise ValueError("control and target must be distinct physical sites")
layout = list(range(sites)); ops = []
while abs(layout.index(control)-layout.index(target)) > 1:
p = layout.index(control); step = 1 if layout.index(target) > p else -1
q = p + step
layout[p], layout[q] = layout[q], layout[p]
ops.append(("SWAP", p, q, tuple(layout)))
ops.append(("CNOT", layout.index(control), layout.index(target), tuple(layout)))
return ops
ops = route()
reverse_ops = route(3, 0)
adjacent_ops = route(1, 2)
invalid_rejected = False
try:
route(0, 0)
except ValueError:
invalid_rejected = True
assert [op[0] for op in ops] == ["SWAP", "SWAP", "CNOT"]
assert abs(ops[-1][1]-ops[-1][2]) == 1
assert sorted(ops[-1][3]) == [0,1,2,3]
assert [op[0] for op in reverse_ops] == ["SWAP", "SWAP", "CNOT"]
assert [op[0] for op in adjacent_ops] == ["CNOT"] and invalid_rejected
print(f"PASS: 40 routing forward_ops={len(ops)} reverse_ops={len(reverse_ops)} adjacent_ops={len(adjacent_ops)}")
Existing fixture: cd labs && python -m unittest tests.test_companion_models.CompanionModelTests.test_line_router_exposes_swap_cost_and_layout -v.
Count gates, layers, duration, and error separately
Gate count is a count. Depth is a schedule length in layers under a stated parallelism rule. Duration is seconds computed from target-specific instruction times. Error is a protocol-defined probability per operation or circuit. Do not multiply a vendor average error by a gate count and call it success probability without an independence model, leakage policy, and calibration match. Modern benchmarking guidance treats these as non-equivalent axes [benchmarking review].
| metric | abstract | routed teaching trace | unit/assumption |
|---|---|---|---|
| two-qubit operations | 1 CNOT | 2 SWAP + 1 CNOT | operation counts; SWAP decomposition not expanded |
| depth | 1 | 3 | serial layers |
| duration | unknown | 2tswap+tcx | seconds after calibration supplied |
| error | unknown | unknown | requires operation-level model |
Suppose a calibrated target declares 240 ns for each native CNOT and 35 ns for each required Hadamard. Seven serial CNOTs alone imply 1.68 μs; direction fixes add their scheduled one-qubit layers. That arithmetic is a target-specific duration estimate, not a fidelity estimate. A cost record must include the calibration identifier and the exact schedule from which the critical path was summed.
An error ledger is more delicate. The product is defensible only under a stated independent stochastic model with matched per-instruction error probabilities. Coherent error, crosstalk, leakage, and temporal drift violate that shortcut. Preserve raw calibration fields and label any composed number as a model output rather than measured circuit success.
Calibration turns one circuit into many schedules
A layout favorable yesterday may cross a weak edge today. Direction fixes, dynamical constraints, readout assignment, and concurrent-crosstalk exclusions change the schedule. Full-stack performance couples compiler decisions to control and topology [full-stack review]. Store target and calibration identifiers, compiler version/options, and transpiled hash. Compiled evidence expires even when the logical circuit does not.
This is why optimization should be multiobjective and auditable. Minimizing two-qubit count may choose a slower edge; minimizing nominal duration may concentrate work on a drifting qubit; minimizing an error-model score may lengthen the critical path beyond a coherence budget. Record the objective and the values of the alternatives considered. A compiler seed is part of the evidence because stochastic placement can otherwise make a regression appear and disappear between runs.
Compiler regression fixtures
Maintain three classes: semantic fixtures compare outputs after reverse mapping; structural fixtures assert every operation is native and every entangler uses an allowed edge/direction; cost fixtures use explicit ceilings or relative non-regression thresholds. Never hard-code one exact route unless route stability itself is the API. Report improvements and regressions in counts, layers, and seconds independently.
Add metamorphic cases: relabel the physical graph and initial layout together, reverse a line target, or insert canceling one-qubit gates before optimization. The compiled text may change, but normalized semantics and appropriately relabeled costs should not. These tests detect hidden dependence on vertex numbering and compiler passes that silently discard or duplicate operations.
The five-site exercise has 32 inputs because the transparent verifier carries five logical bits even though the routed CNOT names only two. For each row, it initializes physical positions from the initial layout, applies every SWAP and directed CNOT, then reconstructs logical order from the final layout. Comparing before reverse mapping would test a different output convention and can falsely condemn a correct route.
Report the route trace as state transitions, not only a final permutation. After every SWAP, assert that the layout remains a bijection over logical labels; after every entangler, assert adjacency and direction in the target graph. Those local invariants identify the first illegal step. A final truth-table mismatch alone says only that something somewhere in routing or measurement mapping went wrong.
Cost ceilings should tolerate equivalent routing choices while detecting regression. For a named target and seed, one policy might require semantic equality, native-only operations, at most a declared two-qubit count, and duration no worse than the recorded baseline by more than a stated percentage. If calibration changes, create a new baseline record rather than comparing seconds computed from different target data.
Finally, keep compiler optimization claims scoped. Reducing a symbolic depth from ten to eight layers says nothing about wall time until scheduling applies instruction durations and constraints. Reducing seven native entanglers to six says nothing about fidelity without a matched error model. The compiler has several ledgers because optimization can improve one while harming another.
The publishable record links those ledgers through one transpiled-circuit hash. Counts, schedule seconds, layout trace, and semantic verification must all describe that exact artifact, not neighboring compiler runs.
Five-site route audit
Prompt: Route CNOT(q0,q4) on a five-site line, verify every computational-basis input, and compare it with an all-to-all target.
Deliverable: Operation trace, final layout, exhaustive truth table, and before/after resource table with counts, layers, and assumed durations.
Pass condition: All 32 basis inputs agree after reverse mapping, every resource column has units, and the report does not infer physical error from gate count alone.
Reference route
Format: Generated trace/CSV and a reference reverse-layout verifier.
Verification: Unit tests regenerate the trace, assert semantic equality, validate layout permutations, and check resource-table totals.
A transparent route moves one endpoint through three adjacent SWAPs before the CNOT and preserves the resulting final layout for reverse mapping. All 32 inputs agree with the abstract operation. The all-to-all case uses one two-qubit layer; duration remains symbolic until target operation times are supplied.
Companion work
Artifacts for this chapter
These entries resolve to checked-in local source. Commands are reproduced exactly from the chapter manifest, and source-embedded fixtures are exported as direct downloads.
Reproduce or test
python3 tools/validate_briefs.py --briefs data/editorial_briefs_36_63.json --from 36 --through 63 --check-rewritten-sources --execute-artifacts
Provenance
Sources and review
- IBM Quantum. Qiskit documentation. IBM. 2026official documentation
- Google Quantum AI. Cirq documentation. Google. 2026official documentation
- OpenQASM Technical Steering Committee. OpenQASM 3 specification. Linux Foundation Joint Development Foundation. 2026official technical specification
- Lieven M. K. Vandersypen et al.. A look at the full stack. Nature Reviews Physics. 2021peer-reviewed perspective
- Timothy Proctor et al.. Benchmarking quantum computers. Nature Reviews Physics. 2025peer-reviewed perspective
The load-bearing claims in the chapter are mapped inline to this registered source set. A citation supports only the bounded claim beside it.