Chapter 28 — Key Takeaways (Circuit Optimization)

Every optimization is a claim that two circuits are equivalent — which is why this follows Chapter 27 rather than preceding it.

The claim holds

   level 0: depth 13  2q 7  process_fidelity 1.000000000000  PRESERVED
   level 1: depth 12  2q 7  process_fidelity 1.000000000000  PRESERVED
   level 2: depth 12  2q 7  process_fidelity 1.000000000000  PRESERVED
   level 3: depth 12  2q 7  process_fidelity 1.000000000000  PRESERVED

Exact at every level, verified with Chapter 26's Operator.from_circuit — which applies the initial layout and the routing permutation. Without it you get Chapter 26 Case Study 2's 0.001406.

Put this in the suite (~13 ms, Ch. 27 §27.8). Not because the transpiler is buggy, but because your configuration is what is likely wrong: a bad initial_layout, a missing basis gate, a level that removed something you needed.

⚠️ On a 127-qubit backend the operator cannot be built. Verify on a small backend with similar coupling, then apply the settings.

The levels

   QFT(5)                  L0: 310/56    L1: 137/38    L2: 136/31    L3: 136/31
   Grover-ish(5)           L0: 2484/423  L1: 931/273   L2: 1080/257  L3: 1080/257
   EfficientSU2(5,r=3)     L0: 112/12    L1: 40/12     L2: 32/12     L3: 32/12
                                                            (depth / 2q gates)

Level 0 does not optimize — it only makes the circuit runnable. Level 1 is where the win is, and it costs milliseconds.

★ The proxies disagree

   Grover-ish(5)   level 1:  depth  931   2q 273
                   level 2:  depth 1080   2q 257

Level 2 is 16% deeper with 6% fewer two-qubit gates.

   DEPTH     -> DECOHERENCE   (must finish inside T1/T2)
   2Q COUNT  -> GATE ERROR    (Ch. 12: median ecr ~8e-3, 288x spread)

Both real. Opposite directions. Only running both settles it.

★★ And the answer is: neither

8 transpiler seeds × 20,000 shots on a noise model:

    level   depth mean   ecr mean   P(top) mean      std     best
        1        956.4      279.8        0.0917   0.0119   0.1031
        2       1098.6      254.0        0.0945   0.0140   0.1072

    difference (L2 - L1) = +0.0028 +/- 0.0065    NOT SIGNIFICANT at 2 sigma

🔬 A gate-count improvement is not a performance claim. "Level 2 reduced two-qubit gates by 9%" is true, is what almost every optimization report says, and here corresponds to no measurable change in the answer. Report the fidelity with an error bar, or report that you did not measure it.

What IS significant:

   level 0:  6.5% of the noiseless signal retained
   level 1: 12.9%
   level 2: 12.9%

Level 0 → 1 roughly doubles it. Everything above level 1 is refinement.

And keep the absolute number in view: 12.9%. Optimization is a constant-factor improvement to an exponentially decaying quantity. Worth having; not a strategy. Ch. 25 §25.9 is why.

★ Levels 2 and 3 — and a correction

An earlier draft found byte-identical output on QFT(5) and Grover-ish(5) and concluded the levels were unified. Widening:

   QFT(5)           differed in 0/8 seeds        Grover-ish(7)   differed in 8/8
   QFT(8)           differed in 6/8 seeds        EffSU2(6,r=4)   differed in 0/8
   Grover-ish(5)    differed in 0/8 seeds
   TOTAL: 14/40.  Of those, L3 better 12, L2 better 2.

The pass lists differ genuinely:

   L1: Optimize1qGatesDecomposition, InverseCancellation, ...
   L2: + TwoQubitPeepholeOptimization, RemoveIdentityEquivalent,
         CommutativeCancellation
   L3: same, but MinimumPoint instead of FixedPoint (return the BEST circuit seen,
       not the first fixed point), plus VF2PostLayout + ApplyLayout

⚠️ Concluding "always" from two examples. The circuits where two configurations agree are, by definition, the ones that cannot tell them apart — Ch. 27's blind-input problem in different clothes, and Ch. 26 measured structured test cases blind 41% of the time. Vary the circuit as well as the seed.

The passes

Original: {'cx': 4, 'rz': 4, 'h': 2, 'x': 2}, depth 8.

   InverseCancellation(H,CX,X)    {'rz': 4}                            depth 4  fid 1.000000
   Optimize1qGatesDecomposition   {'cx': 4, 'u1': 1}                   depth 4  fid 1.000000
   CommutativeCancellation        {'rz': 1}                            depth 1  fid 1.000000
   RemoveIdentityEquivalent       {'cx': 4, 'rz': 4, 'h': 2, 'x': 2}   depth 8  fid 1.000000

   ALL FOUR, forward              {'u1': 1}                            depth 1
   ALL FOUR, reversed             {'rz': 1}                            depth 1

CommutativeCancellation alone does the whole job — it knows an RZ commutes through a CX control, where the non-obvious cancellations live. RemoveIdentityEquivalent did nothing (the RZs sum to zero only collectively) — a pass that does nothing on your circuit is not broken. Order changes the output basis, which is why preset managers use a convergence loop.

★ What optimization destroys

   H H (no barrier)  ->  {}                        depth 0   ANNIHILATED
   H barrier H       ->  {'h': 2, 'barrier': 1}    depth 2

Barrier anything whose timing rather than unitary is the point: Ch. 13's ZNE folds, dynamical decoupling, Ch. 25's noise slots.

But barriers are weaker than they look:

   Ch.25 noise slot, barriered, level 1:  {'barrier': 2, 'measure': 1}

⚠️ The barriers survived and the id was still deleted. A barrier stops gates commuting across it; it does not stop a removable gate between two barriers from being removed. "Wrap it in barriers" is the standard advice and it does not work here. Ch. 25's fix — optimization_level=0 plus an assertion on the count — remains the only reliable one.

★★ Approximation

   approximation_degree   2q gates   depth   process fidelity
                    1.0         19      36           1.000000
                   0.99         15      29           0.925328
                   0.95          8      13           0.657023
                    0.9          0       3           0.455317
                    0.5          0       3           0.117562

🔬 approximation_degree is not a fidelity and is not gentle. 0.99 gave 0.925. And between 0.95 and 0.9 the circuit goes from 8 two-qubit gates to none at all — the entangling structure synthesized away, leaving 46% overlap with what you asked for.

Never set it without measuring the fidelity you traded. And on a 127-qubit backend that measurement is impossible — so do the study small, then apply the setting.

Where hand optimization still wins

  • Choosing a decomposition — Ch. 19's plain MCXGate with spare qubits beat a hand-specified v-chain. Leaving the transpiler room is a hand optimization.
  • Knowing your ancillas are free — a qubits-for-depth trade only you can make.
  • Exploiting problem structure — Ch. 22's AQFT cutoff is a numerical argument, not a circuit identity. No peephole optimizer finds it.
  • $T$ count — the transpiler does not optimize it. Ch. 15's estimates were $T$-dominated and Ch. 25 §25.10 explains why. Depth and 2q count are pre-fault-tolerant metrics; $T$ count is the post-fault-tolerant one.

The policy

   1. Always at least level 1 -- doubles surviving signal, costs milliseconds.
   2. Verify equivalence with Operator.from_circuit, on a small backend, in CI.
   3. Diff count_ops() before and after.
   4. Prefer level 3 over 2 (won 12 of 14 differing trials); expect no difference
      on small circuits.
   5. Never report a gate-count improvement as a result. Run both on a noise
      model and give a standard error.
   6. Barrier anything timing-sensitive -- then assert it survived.
   7. approximation_degree only with a measured fidelity beside it.
   8. Optimize T count separately, and only for fault tolerance.

Common pitfalls

  • Reporting a proxy metric as a result.
  • Quoting a difference without an error bar.
  • Checking one objective and not the one moving against it.
  • Concluding "always" from two circuits.
  • Trusting barriers to protect a removable gate.
  • Reading approximation_degree as a fidelity.
  • Validating against a simulation of the approximated circuit rather than the logical one.
  • Optimizing past a good default without measuring how good the default was.

Project piece added this chapter

vqelab/optimization.pyprofile, two_qubit_count, count_ops_delta, slots_survived; OptimizationReport.better_than that RAISES without measured fidelity on both sides; significantly_better returning False inside 2σ rather than reporting the sign of the mean; verify_equivalence applying the layout and raising past the operator limit; and approximation_sweep that refuses to run where the traded fidelity cannot be measured. 23 tests pass, including test_better_than_REFUSES_to_decide_from_gate_counts, test_a_difference_inside_the_error_bars_is_not_better, test_barriers_do_NOT_protect_an_id_gate, and test_approximation_degree_falls_off_a_cliff.