Case Study: Compiling to a Native Gate Set
Executive Summary
You write qc.h(0) and qc.ccx(0,1,2). The hardware has never heard of either. A superconducting processor typically executes exactly four operations: $R_z(\theta)$, $\sqrt{X}$, $X$, and CNOT (or ECR). Everything else is a fiction maintained by the compiler.
This case study follows a small circuit through compilation, counting what each abstraction actually costs. The punchline is that the gate you write and the gate that runs can differ by a factor of twenty in error contribution, and that knowing the native set changes how you write circuits.
Skills applied
- Decomposing arbitrary single-qubit unitaries into the ZYZ/native form (§6.9).
- Counting the true cost of composite gates like Toffoli and SWAP (§6.11).
- Distinguishing virtual (free) from physical (costly) operations.
- Estimating circuit fidelity from a gate-count budget.
Background
The native set
A representative superconducting backend supports:
| Native operation | Cost | Error |
|---|---|---|
| $R_z(\theta)$ | 0 ns — virtual | ~0 |
| $\sqrt{X}$ (SX) | 35 ns | $2\times10^{-4}$ |
| $X$ | 35 ns | $2\times10^{-4}$ |
| CNOT / ECR | 300–500 ns | $6\times10^{-3}$ |
The first row is the surprise. $R_z$ costs nothing: a $z$ rotation is implemented by shifting the phase of all subsequent microwave pulses on that qubit — a bookkeeping change in the control software, not a physical operation. This is the "virtual Z" trick, and it is why the native set is built around $\sqrt X$ plus free $z$ rotations.
The second surprise is the ratio: a two-qubit gate is 30× more error-prone and ~10× slower than a single-qubit gate. Every optimization that matters is about reducing two-qubit gate count.
Phase 1: Single-qubit decomposition
Any single-qubit unitary decomposes as $U = R_z(\gamma)R_y(\beta)R_z(\alpha)$ (up to global phase). But there is no native $R_y$. Rewrite it using
$$R_y(\beta) = R_z(-\pi/2)\,R_x(\beta)\,R_z(\pi/2), \qquad R_x(\beta) = \sqrt{X}\,R_z(\beta)\,\sqrt{X} \ \ (\text{up to phase})$$
Combining, any single-qubit unitary becomes
$$U = R_z(\theta_1)\,\sqrt{X}\,R_z(\theta_2)\,\sqrt{X}\,R_z(\theta_3)$$
Two $\sqrt X$ pulses and three free rotations. That is the universal cost of an arbitrary single-qubit gate: 70 ns, error $\approx 4\times10^{-4}$.
Special cases are cheaper: - $H = R_z(\pi/2)\,\sqrt{X}\,R_z(\pi/2)$ — one $\sqrt X$, 35 ns. - $Z, S, T$ — zero pulses. Entirely virtual, entirely free. - $X$ — one native pulse.
Finding 1. $T$ gates are free on NISQ hardware. This is worth internalizing because it inverts the fault-tolerant intuition, where $T$ is the most expensive gate. The cost of $T$ depends entirely on which regime you are in.
Phase 2: The Toffoli
Now the expensive part. The standard decomposition of CCX into Clifford+T uses 6 CNOTs, 7 $T$/$T^\dagger$ gates, and 2 Hadamards.
On our backend: - 6 CNOTs × 300 ns = 1,800 ns, error $6\times6\times10^{-3} = 3.6\times10^{-2}$ - 7 $T$ gates: free - 2 $H$: 70 ns, negligible error
$$\text{Toffoli fidelity} \approx (1 - 0.006)^6 \approx 0.965$$
A single Toffoli costs about 3.5% error. Write ten of them and the circuit is at $0.965^{10} \approx 0.70$ — a coin-flip's worth of signal gone.
Finding 2.
qc.ccx()is one line of Python and six two-qubit gates. Any algorithm whose cost you estimated in Toffolis has a hardware cost six times larger in the currency that matters.
Phase 3: Connectivity — the hidden multiplier
The costs above assume the two qubits are physically coupled. They usually are not. On a heavy-hex lattice, most qubit pairs are not adjacent, and a CNOT between distant qubits requires SWAP chains to bring them together:
$$\text{SWAP} = 3\ \text{CNOTs}$$
A CNOT between qubits four hops apart needs roughly 3 SWAPs out and 3 back, or ~18 extra CNOTs, unless the compiler can route more cleverly.
Consider the Toffoli again, now on three qubits in a line (0–1–2 connected, 0 and 2 not):
| Layout | CNOTs | Error |
|---|---|---|
| All-to-all connectivity | 6 | 3.5% |
| Linear chain | 8–10 (with routing) | 5–6% |
| Distant qubits on a heavy-hex | 15–20 | 9–12% |
Finding 3. The same logical circuit can differ 3× in error depending on which physical qubits it is mapped to. Qubit selection is not a detail.
Phase 4: Running the compiler and reading the output
from qiskit import QuantumCircuit, transpile
from qiskit.providers.fake_provider import FakeBrisbane
qc = QuantumCircuit(3)
qc.h(0)
qc.ccx(0, 1, 2)
qc.h(0)
backend = FakeBrisbane()
for level in range(4):
t = transpile(qc, backend, optimization_level=level, seed_transpiler=42)
two_q = sum(1 for inst in t.data if inst.operation.num_qubits == 2)
print(f"level {level}: depth={t.depth():3d} total={len(t.data):3d} 2q={two_q:3d}")
Typical output:
level 0: depth= 78 total=116 2q= 18
level 1: depth= 54 total= 84 2q= 12
level 2: depth= 41 total= 66 2q= 9
level 3: depth= 38 total= 61 2q= 8
From 18 two-qubit gates down to 8 — a fidelity improvement from $0.996^{18} \approx 0.90$ to $0.996^{8} \approx 0.95$, for the cost of a compiler flag. Optimization level 3 is not free (compilation is slower and uses stochastic routing, so results vary with seed), but on hardware it is almost always worth it.
Phase 5: Writing circuits that compile well
Four practices that follow directly:
- Count two-qubit gates, not gates. It is the only number that predicts fidelity to first order.
- Prefer circuits that match the coupling map. A linear-chain algorithm on a linear device needs no routing. Nearest-neighbour formulations of an algorithm often beat "better" formulations that require all-to-all connectivity.
- Avoid Toffolis where a measurement will do. If a multi-controlled operation is followed by measurement anyway, the deferred-measurement trade from Chapter 4 sometimes runs in reverse — mid-circuit measurement plus classical control can replace a Toffoli entirely.
- Let $R_z$ be free. Do not "optimize away" $z$ rotations; they cost nothing. Optimize away CNOTs.
Discussion Questions
- Virtual $Z$ makes $R_z$ free on superconducting hardware. What property of the physical implementation allows this, and would you expect it on trapped ions?
- $T$ is free on NISQ hardware and the dominant cost in fault-tolerant architectures. Explain the reversal.
- Optimization level 3 uses stochastic routing, so two runs can produce different circuits. How should that affect how you benchmark?
- Given a 1% two-qubit error rate, estimate the maximum useful circuit depth in two-qubit gates. What does that imply for algorithms needing thousands?
Your Turn: Extensions
- Transpile a 5-qubit GHZ circuit at every optimization level for both a linear and a heavy-hex coupling map; tabulate two-qubit counts.
- Decompose a Toffoli by hand into Clifford+T and verify with
qiskit.quantum_info.Operator. - Write a helper that estimates circuit fidelity from a transpiled circuit's gate counts and the backend's reported error rates, and check it against a noisy simulation.
Key Takeaways
- Hardware runs a small native set; every other gate is a compiler fiction with a measurable price.
- $R_z$ is free (virtual), $\sqrt X$ is cheap, and CNOT is ~30× worse than a single-qubit gate. Optimize the CNOT count and nothing else, first.
- A Toffoli is six CNOTs; a SWAP is three. One line of Python is not one operation.
- Limited connectivity can triple a circuit's cost through routing — qubit mapping matters as much as gate count.
- $T$ is free now and expensive under error correction. Cost models do not transfer between regimes.