Chapter 9 — Key Takeaways (Dynamic Circuits)

Teleportation, superdense coding, qubit reuse — and the cost depth() cannot see.

Feedforward syntax

with qc.if_test((qc.clbits[0], 1)):        # one bit equals 1
    qc.x(1)

with qc.if_test((creg, 3)):                # a whole register equals 3
    ...

with qc.if_test((qc.clbits[0], 1)) as else_:
    qc.x(1)
with else_:
    qc.z(1)

🗝️ c_if was removed in Qiskit 1.0. It could only condition a single gate on a register equality — the same limitation that made OpenQASM 2 unable to express dynamic circuits (Ch. 6 §6.4).

What dynamic circuits add: not computability — practicality. Qubit reuse, error correction, and protocols like teleportation in one circuit.

★ Teleportation

qc.ry(theta, 0); qc.rz(phi, 0)      # 1. the state (Alice does not know it)
qc.h(1); qc.cx(1, 2)                # 2. Bell pair: q1 Alice's, q2 Bob's
qc.cx(0, 1); qc.h(0)                # 3. Alice's BELL MEASUREMENT (Ch. 4 §4.5 backward)
qc.measure(0, m0); qc.measure(1, m1)
with qc.if_test((m1, 1)): qc.x(2)   # 4. Bob's correction
with qc.if_test((m0, 1)): qc.z(2)
$m_0$ $m_1$ Bob had Correction shots (of 8192)
0 0 $\lvert\psi\rangle$ none 2109
0 1 $X\lvert\psi\rangle$ $X$ 1998
1 0 $Z\lvert\psi\rangle$ $Z$ 2074
1 1 $ZX\lvert\psi\rangle$ $X$ then $Z$ 2011

Each about a quarter — Alice's outcome carries no information about the state. That single fact settles the faster-than-light question.

★★ Verify in all three bases

   basis |  ideal <P> |  teleported |  difference
       Z |    +0.7648 |     +0.7708 |      0.0059
       X |    +0.1723 |     +0.1768 |      0.0044
       Y |    +0.6207 |     +0.6240 |      0.0033
  worst 0.0059 vs sampling error 0.0110  ->  consistent

One basis proves almost nothing. An impostor that just prepares $R_y(\theta)|0\rangle$ — no entanglement, no teleportation — has an exactly identical $Z$ distribution, and fails catastrophically in $X$ (+0.65 vs +0.17) and $Y$ (+0.0007 vs +0.62).

Three Bloch components completely determine a single-qubit pure state. That is tomography, and it is the honest standard.

⚠️ Test with a state having all three Bloch components nonzero. An axis-aligned state hides phase errors exactly as palindromes hide ordering errors (Ch. 5 §5.3).

What teleportation does NOT do

Misconception Reality
violates no-cloning no — Alice's measurement destroys the original; two copies never coexist
beats light no — Bob's qubit is one of four states until the classical bits arrive; they travel classically
transports matter/energy no — only two classical bits move

Exact exchange rate: 1 entangled pair + 2 classical bits → 1 transmitted qubit state.

Superdense coding — the same trade reversed

qc.h(0); qc.cx(0, 1)                 # shared pair
if bits[1] == "1": qc.x(0)           # Alice touches ONLY her qubit
if bits[0] == "1": qc.z(0)
qc.cx(0, 1); qc.h(0)                 # Bob's Bell measurement
  Alice sends 00 -> Bob measures 00
  Alice sends 01 -> Bob measures 10    <-- reversed
  Alice sends 10 -> Bob measures 01    <-- reversed
  Alice sends 11 -> Bob measures 11

⚠️ Not a bug — little-endian ordering interacting with which bit drives the $X$ gate. Testing only 00 and 11 (both palindromes) would have hidden it.

Honest accounting: the pair had to be distributed, so total qubit traffic is 2 for 2 bits — no better than sending the bits. What it buys is a shift in timing: the expensive part happens in advance.

Reset and qubit reuse

qc.h(0); qc.measure(0, 0)
qc.reset(0)                          # back to |0>
qc.h(0); qc.measure(0, 1)            # -> 4 outcomes at ~25% each

Converts a width constraint into a depth constraint.

⚠️ Reuse has a ceiling, but a noiseless simulator cannot show you where it is. Case Study 2 once read 0.0029 → 0.0048 → 0.0068 as cumulative degradation; 200 unseeded repeats per row give 0.00657 → 0.00642 → 0.00558, falling to 0.00214 by eight flips — the opposite direction — and there was no noise model attached to degrade anything. The real ceiling is readout error, reset infidelity, and the $T_2$ budget of a $k$-times-longer circuit. Measure it on a noisy backend, not with a bin-count-dependent statistic.

★ Should this circuit be dynamic? Four questions

  1. Does any qubit finish early?      no -> stop, use static
  2. Is width the binding constraint?  no -> stop, use static
  3. Does the depth fit T2?            no -> stop, use static
  4. Can you tolerate the latency?     no -> stop, use static
                                       yes -> measure both

A VQE ansatz fails question 1 immediately — entangling layers exist to keep every qubit correlated. Measured anyway:

  variant     ISA depth    2q   measure   reset
  static             24     6         4       0
  dynamic            29     6         2       1     -> 1.21x deeper, nothing saved

What dynamic circuits cost

  circuit                   ISA depth   2q   if_else
  static GHZ                        9    2         0
  teleportation                    14    2         2
  teleportation + barriers         20    2         2

Over 50% more depth for the same two-qubit count. Barriers add six more (Ch. 8 §8.6) — keep them to read the diagram, strip them to run.

On the noisy model: teleported $P(0) = 0.8350$ against an ideal $0.8824$ — about five points degraded.

💰 The cost depth() cannot see. At each if_test the control system reads the result, decides, and issues pulses — while every other qubit sits idle and decoheres. Gates take tens of nanoseconds; that round trip takes hundreds to thousands.

Ask "how long do my qubits sit idle," not "how many extra gates."

Common pitfalls

  • Verifying teleportation in the computational basis only.
  • Choosing an axis-aligned test state, which hides phase errors.
  • Testing superdense coding only on 00 and 11.
  • Reading a dynamic circuit's cost from depth() alone.
  • Reaching for qubit reuse in a circuit whose qubits stay entangled.
  • Leaving stage barriers in before running.

Project piece added this chapter

vqelab/measure.py v1measure_with_reset() and why_not_mid_circuit(), plus a recorded negative result: VQE should use static circuits, measured at 1.21× depth for no saving.

Knowing why a technique does not apply is worth as much as knowing how to use one, and it is the more common situation. measure_with_reset() stays for the case it is actually for — when a Hamiltonian needs more measurement qubits than the device has. Not H₂; possibly LiH.