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:

  1. Count two-qubit gates, not gates. It is the only number that predicts fidelity to first order.
  2. 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.
  3. 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.
  4. Let $R_z$ be free. Do not "optimize away" $z$ rotations; they cost nothing. Optimize away CNOTs.

Discussion Questions

  1. 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?
  2. $T$ is free on NISQ hardware and the dominant cost in fault-tolerant architectures. Explain the reversal.
  3. Optimization level 3 uses stochastic routing, so two runs can produce different circuits. How should that affect how you benchmark?
  4. 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.