Quantum Computation & Cryptography · Lecture 7

Lecture 7
Quantum Circuits, Reversible Computation and Universality

Week 4  |  every classical function fits inside a quantum computer, if you clean up after yourself  |  reading: Watrous §3.1 and Ch. 6

Cartoon: a cook who washes upA stick figure stands at a counter holding out a finished plate. Behind the figure are a pot and a tall stack of dirty bowls. A speech bubble says: serve the dish, then wash every bowl, or the next recipe will not work. serve the dish, then washevery bowl, or the nextrecipe will not work. garbage
compute, copy the answer, uncompute: leftover work qubits spoil later interference
In this lecture
  1. The circuit model and its costs
  2. Classical logic must become reversible
  3. The standard oracle
  4. Garbage, and how to uncompute it
  5. Universal gate sets
  6. What a Toffoli really costs
  7. Try it in code
  8. Summary and exercises

Lectures 3 to 6 built the vocabulary: states, gates, entanglement, measurement. This lecture turns the vocabulary into a model of computation. By the end you should be able to measure the size and depth of a circuit, explain why classical logic has to be made reversible before a quantum computer can run it, write down the standard oracle \(U_f\) for any function \(f\), explain why leftover "garbage" qubits wreck quantum algorithms and how Bennett's trick removes them, and say precisely what it means for a gate set to be universal and why the \(T\) gate is the expensive one.

1 — The circuit model and its costs

We have been drawing circuits since Lecture 4. Here is the official version.

definition 7.1 — quantum circuit, size, depth

A quantum circuit on \(n\) qubits is a finite sequence of gates, each a unitary acting on one, two or a few named qubits, possibly followed by measurements. Its width is \(n\). Its size is the number of gates. Its depth is the smallest number of layers into which the gates can be grouped, where the gates in a layer act on disjoint qubits (so they can run at the same time) and the layers are applied in order.

A four-qubit circuit applies, in this order, h(0), cx(0, 1), cx(1, 2), cx(2, 3), h(0). What are its size and depth?

Size counts gates. For depth, place each gate in the first layer after the last gate that used any of its qubits.
Size 5. The CNOTs form a chain of layers 2, 3, 4 (each shares a qubit with the previous one), and the second \(H\) fits into layer 3 beside cx(1, 2), so the depth is 4.
Size and depth of a three-qubit circuitA circuit on qubits q0, q1, q2 drawn with q0 on top. Layer 1 (shaded) holds three H gates, one on each qubit. Layer 2 holds a CNOT with control q0 and target q1. Layer 3 holds a CNOT with control q1 and target q2 and, in parallel, a T gate on q0. The circuit has size 6 (six gates) and depth 3 (three layers).layer 1layer 2layer 3q0Hq1Hq2HTsize = 6 gatesdepth = 3 layerstwo-qubit gates = 2T-count = 1
Example 7.1 as a circuit. The \(T\) gate on qubit 0 does not share a qubit with cx(1, 2), so the two run in the same layer. Qiskit's size() and depth() methods return 6 and 3.
example 7.1 — counting

The circuit in the figure applies \(H\) to qubits 0, 1 and 2, then cx(0, 1), then cx(1, 2), then \(T\) on qubit 0. Find its size, depth, number of two-qubit gates, and number of \(T\) gates.

There are six gates, so the size is 6. The three \(H\) gates act on different qubits and form layer 1. cx(0, 1) needs qubits 0 and 1, which are free after layer 1, so it forms layer 2. cx(1, 2) must wait for cx(0, 1) to release qubit 1, so it goes in layer 3, and the \(T\) on qubit 0 also waits for cx(0, 1), so it goes in layer 3 as well. Depth 3. Two gates act on two qubits, and there is one \(T\) gate.

The order of the last two gates in the gate list does not matter: gates on disjoint qubits commute (Lecture 5), so the depth counts only the chains of gates that genuinely wait for each other.

idea — four ways to measure cost

Size is total work. Depth is running time, and on today's hardware it also sets how long qubits must survive before they decohere. The two-qubit gate count matters because two-qubit gates are the noisiest operations (Lecture 6). The \(T\)-count, the number of \(T\) and \(T^\dagger\) gates, is the currency of fault-tolerant machines (Section 5). A good compiler trades these against each other; no single number captures "cost".

2 — Classical logic must become reversible

Quantum algorithms constantly need classical subroutines: adding numbers, comparing strings, evaluating a cipher. Can a quantum computer run a classical circuit? Not directly. Every gate is unitary, hence invertible, but the AND gate is not: it sends three different inputs \(00,01,10\) to the same output 0, so the input cannot be recovered from the output. Information is destroyed.

There is also a physical reason to care. Landauer's principle says that erasing one bit of information in an environment at temperature \(\mathcal T\) dissipates at least \(k_B\mathcal T\ln2\) of energy as heat. Reversible computation erases nothing, so in principle it has no such floor. For us the point is simpler: unitaries cannot erase, so we must compute without erasing.

Tick every map on two bits \((a,b)\) that could be the action of a quantum gate on the four basis states \(|a,b\rangle\).

A gate is unitary, hence invertible, so on basis states it must be a permutation: no two inputs may share an output. Look for a collision.
\((a\oplus b,b)\) is a CNOT and \((b,a)\) is SWAP, both permutations. The other two send two different inputs to the same output, which no unitary can do.

The standard fix keeps the inputs and writes the answer into a fresh bit.

definition 7.2 — the Toffoli gate

The Toffoli (controlled-controlled-NOT) gate acts on three qubits, flipping the target exactly when both controls are 1. With controls \(a,b\) and target \(c\),

$$|a,\,b,\,c\rangle\;\longmapsto\;|a,\,b,\,c\oplus ab\rangle .$$

In Qiskit it is ccx(c1, c2, t). With controls on qubits 0 and 1 and the target on qubit 2, it exchanges \(|011\rangle\) and \(|111\rangle\) (written \(|q_2q_1q_0\rangle\), basis vectors 3 and 7) and fixes the other six basis states.

proposition 7.1 — Toffoli is a reversible AND

The Toffoli gate is a permutation of the eight basis states, it is its own inverse, and with the target initialised to 0 it computes \(a\wedge b\) while keeping \(a\) and \(b\).

Applying it twice gives \(|a,b,c\oplus ab\oplus ab\rangle=|a,b,c\rangle\), so it is its own inverse; a map that has an inverse is a bijection, so it permutes the basis states, and its matrix is a permutation matrix, which is unitary. With \(c=0\) the target becomes \(0\oplus ab=ab=a\wedge b\).

Qubits 0 and 1 are both in \(|+\rangle\) and qubit 2 is in \(|0\rangle\). After ccx(0, 1, 2), qubit 2 is measured. What is the probability of outcome 1?

Expand \(|+\rangle|+\rangle\) into the four basis states \(|q_1q_0\rangle\), each with amplitude \(\tfrac12\). In which of them does the Toffoli flip the target?
The target becomes \(q_0\wedge q_1\), which is 1 only on \(|11\rangle\): probability \(\tfrac14\). The Toffoli computes AND on every branch of the superposition at once.
The Toffoli gate and an OR gate built from itLeft: the Toffoli gate ccx(0, 1, 2) with controls on q0 = a and q1 = b and target q2 = c, mapping |c b a> to |c xor ab, b, a>. A truth table below lists the eight inputs; only the rows a = b = 1 change the target. Right: the OR circuit of Example 7.2: X gates on a and b, then a Toffoli into c, then X on c, then X gates on a and b again, which outputs c xor (a or b).q0 = aq1 = bq2 = cabc xor abtruth table, written abc -> abc'000->000001->001010->010011->011100->100101->101110->111111->110Example 7.2: OR from Toffoliab|0>XXXXXaba OR bNOT a AND NOT b is 1 exactly when a = b = 0;negating it gives a OR b (De Morgan).The last two X gates restore a and b.
Left: the Toffoli gate and its truth table; only the two rows with \(a=b=1\) change. Right: an OR gate built from one Toffoli and five \(X\) gates (Example 7.2).
example 7.2 — OR from a Toffoli

Build a reversible circuit that maps \(|a,b,0\rangle\) to \(|a,b,a\vee b\rangle\) using one Toffoli and \(X\) gates.

De Morgan's law says \(a\vee b=\neg(\neg a\wedge\neg b)\). So: apply \(X\) to \(a\) and \(b\) (now they hold \(\neg a,\neg b\)); apply the Toffoli, which writes \(\neg a\wedge\neg b\) into the target; apply \(X\) to the target, giving \(\neg(\neg a\wedge\neg b)=a\vee b\); finally apply \(X\) to \(a\) and \(b\) again to restore them. Checking all eight inputs \(|a,b,c\rangle\) confirms the circuit maps them to \(|a,b,c\oplus(a\vee b)\rangle\) (verify_L07.py does this). The last two \(X\) gates are a tiny first example of uncomputation: undoing work we no longer need, so the inputs come out as they went in.

AND, OR and NOT (a single \(X\)) are not quite enough to run every classical circuit: classical circuits also copy bits (FANOUT), and copying an unknown bit must also be done reversibly. HW4 asks you to build NOT and FANOUT from Toffoli gates with constant inputs, which shows that the Toffoli gate by itself is universal for reversible classical computation.

3 — The standard oracle

Everything in Unit 2 of the course, from Deutsch–Jozsa to Grover to Shor, accesses a function \(f\) through one standard gate.

definition 7.3 — standard oracle

For a function \(f:\{0,1\}^n\to\{0,1\}^m\), the standard oracle is the gate on \(n+m\) qubits defined on basis states by

$$U_f\,|x\rangle|y\rangle=|x\rangle\,|y\oplus f(x)\rangle ,$$

where \(x\) is an \(n\)-bit input register, \(y\) an \(m\)-bit output register, and \(\oplus\) is bitwise XOR. Extended by linearity, it acts on superpositions of inputs.

proposition 7.2 — every standard oracle is unitary

For every function \(f\), however irreversible, \(U_f\) is a permutation matrix and \(U_f^2=I\). In particular \(U_f\) is unitary.

Applying \(U_f\) twice gives \(|x\rangle|y\oplus f(x)\oplus f(x)\rangle=|x\rangle|y\rangle\), because \(z\oplus z=0\) bitwise. So \(U_f\) is its own inverse, hence a bijection of the \(2^{n+m}\) basis states, hence a permutation matrix. Permutation matrices have orthonormal columns, so they are unitary.

Let \(f(x_1x_0)=x_1\vee x_0\) (OR) with a one-bit output. The standard oracle sends \(|x\rangle|y\rangle=|10\rangle|1\rangle\) to \(|10\rangle\) followed by .

Compute \(f(10)\) first, then \(y\oplus f(x)\), not \(f(x)\) alone.
\(f(10)=1\) and \(1\oplus1=0\). The output register is XORed, never overwritten; that is what makes \(U_f\) reversible.

Several gates we already know are standard oracles. CNOT cx(0, 1) is \(U_f\) for the one-bit identity \(f(x)=x\); \(X\) on the output qubit is \(U_f\) for the constant \(f(x)=1\); and the Toffoli is \(U_f\) for \(f(a,b)=a\wedge b\). Notice that \(U_f\) is reversible even though \(f\) need not be: the trick is that it keeps \(x\).

The output register can also be prepared in \(|-\rangle\) instead of a basis state. Then the oracle changes nothing but a sign, which is exactly phase kickback from Lecture 6.

proposition 7.3 — the phase oracle

For \(f:\{0,1\}^n\to\{0,1\}\) and every input \(x\),

$$U_f\,|x\rangle|-\rangle=(-1)^{f(x)}\,|x\rangle|-\rangle .$$

So on a superposition, \(U_f\big(\sum_x\alpha_x|x\rangle\big)|-\rangle=\big(\sum_x(-1)^{f(x)}\alpha_x|x\rangle\big)|-\rangle\): the function value is written into the phases of the input register.

If \(f(x)=0\), \(U_f\) does nothing. If \(f(x)=1\), it applies \(X\) to the output qubit, and \(X|-\rangle=-|-\rangle\). Both cases are \((-1)^{f(x)}|x\rangle|-\rangle\). The superposition statement follows by linearity.

How big is \(U_f\) as a circuit? If \(f\) has a classical circuit, not much bigger.

theorem 7.4 — classical circuits become reversible circuits

If \(f\) is computed by a classical circuit with \(g\) gates (AND, OR, NOT, FANOUT), then there is a circuit of \(O(g)\) Toffoli, CNOT and \(X\) gates, using \(O(g)\) extra qubits initialised to \(|0\rangle\), that maps

$$|x\rangle\,|0\cdots0\rangle\;\longmapsto\;|x\rangle\,|f(x)\rangle\,|\mathrm{garbage}(x)\rangle ,$$

where the garbage register holds the intermediate values of the classical computation.

Replace each classical gate by its reversible version writing into a fresh qubit that starts at 0: AND by a Toffoli, OR as in Example 7.2, NOT by a CNOT into a fresh 0 followed by \(X\) on that qubit, and FANOUT by a CNOT into a fresh 0 (on basis states a CNOT into \(|0\rangle\) copies a bit). Each classical wire becomes a qubit that holds its value at the end, so the intermediate wires are the garbage. Each replacement uses a constant number of gates, which gives the \(O(g)\) bound.

4 — Garbage, and how to uncompute it

Theorem 7.4 computes \(f\), but it leaves garbage behind. For a classical computer that would be harmless. For a quantum algorithm it is fatal, because the garbage depends on \(x\), so it becomes entangled with the input register, and entanglement with anything that records \(x\) destroys interference between different values of \(x\). Here is the smallest example.

example 7.3 — garbage destroys interference

Take \(f(x)=x\) on one bit, with the input \(x\) on qubit 0 and the output on qubit 1 prepared in \(|-\rangle\). Apply \(H\) to \(x\), then the phase oracle (a CNOT), then \(H\) again, and measure \(x\). Compare with a sloppy oracle that also leaves a copy of \(x\) in a garbage qubit \(g\).

Clean oracle. After the first \(H\), \(x\) is in \(|+\rangle\). By Proposition 7.3 the oracle turns \(\tfrac{1}{\sqrt2}(|0\rangle+|1\rangle)\) into \(\tfrac{1}{\sqrt2}(|0\rangle-|1\rangle)=|-\rangle\), and the final \(H\) turns that into \(|1\rangle\). The measurement gives \(x=1\) with certainty: the two "paths" \(x=0\) and \(x=1\) interfered completely.

Sloppy oracle. Now the oracle also copies \(x\) into \(g\), which starts in \(|0\rangle\). Before the final \(H\) the input and garbage are in

$$\frac{1}{\sqrt2}\Big(|0\rangle_x|0\rangle_g-|1\rangle_x|1\rangle_g\Big),$$

an entangled state (the output qubit stays \(|-\rangle\) and plays no further role). Apply \(H\) to \(x\):

$$\begin{aligned}&\frac12\Big((|0\rangle+|1\rangle)|0\rangle_g-(|0\rangle-|1\rangle)|1\rangle_g\Big)\\[4pt] &\quad=\frac12\Big(|0\rangle|0\rangle_g+|1\rangle|0\rangle_g-|0\rangle|1\rangle_g+|1\rangle|1\rangle_g\Big).\end{aligned}$$

By Rule 6.2, \(P(x=0)=\big|\tfrac12\big|^2+\big|{-\tfrac12}\big|^2=\tfrac12\). The two terms that should have cancelled carry different garbage values, \(|0\rangle_g\) and \(|1\rangle_g\), so they are orthogonal and cannot cancel. The garbage holds "which-path" information, and a path that has been recorded cannot interfere.

Repair. Apply the copying CNOT a second time before the final \(H\). It returns \(g\) to \(|0\rangle\) for both values of \(x\), the garbage factors out, and the answer \(x=1\) is certain again.

A reversible circuit computes \(f(x)\) cleanly but leaves one extra qubit in the basis state \(|g(x)\rangle\). Tick every choice of \(g\) for which interference between different inputs \(x\) still works as if there were no extra qubit.

The extra qubit is harmless exactly when it factors out of the sum over \(x\): when \(|g(x)\rangle\) is the same state for every \(x\).
Constant garbage, \(|0\rangle\) or \(|1\rangle\), factors out of \(\sum_x\alpha_x|x\rangle|g\rangle\). What destroys interference is garbage that records something about \(x\), whatever its value.

The repair generalises. Bennett's trick runs the computation, copies out the answer, and then runs the computation backwards.

Compute, copy, uncomputeThree registers: input x on top, a work register starting in |0> in the middle, and an output register starting in |y> at the bottom. A box labelled C computes f(x) and garbage g(x) into the work register. CNOT gates copy f(x) into the output register. A box labelled C-inverse runs the computation backwards, returning the work register to |0>. State labels between the stages read: |x>|0>|y>, then |x>|f(x) g(x)>|y>, then |x>|f(x) g(x)>|y xor f(x)>, then |x>|0>|y xor f(x)>.xworkout|x>|0>|y>Ccopy f(x)C^-1|x>|0>|y xor f(x)>|x>|0>|y>|x>|f,g>|y>|x>|f,g>|y+f>|x>|0>|y+f>f = wanted output, g = garbage; y+f means y xor f(x)
Compute, copy, uncompute. \(C\) is the reversible circuit of Theorem 7.4. The CNOTs copy the answer into the output register by XOR, and \(C^{-1}\) (the same gates in reverse order, each replaced by its inverse) returns the work register to \(|0\rangle\).
theorem 7.5 — compute, copy, uncompute (Bennett)

Let \(C\) be a reversible circuit with \(C|x\rangle|0\rangle=|x\rangle|f(x),\mathrm{garbage}(x)\rangle\), and let \(\mathrm{COPY}\) be \(m\) CNOTs from the \(f(x)\) part of the work register into an \(m\)-qubit output register. Then \(C^{-1}\,\mathrm{COPY}\,C\) implements the clean oracle:

$$|x\rangle|0\rangle|y\rangle\;\longmapsto\;|x\rangle|0\rangle|y\oplus f(x)\rangle .$$

It uses twice the gates of \(C\) plus \(m\) CNOTs, and the work qubits can be reused afterwards.

Follow a basis state. \(C\) produces \(|x\rangle|f(x),\mathrm{garbage}(x)\rangle|y\rangle\). The copy step changes only the output register, to \(|y\oplus f(x)\rangle\), and leaves the other two registers exactly as \(C\) produced them. So \(C^{-1}\), which acts only on the first two registers, sees exactly the state that \(C\) created and undoes it, returning \(|x\rangle|0\rangle\). The output register is untouched by \(C^{-1}\). By linearity the same holds for every superposition of inputs, with no garbage entangled with \(x\).

A reversible circuit \(C\) of 40 gates computes a 3-bit value \(f(x)\) plus garbage. How many gates does the clean oracle \(C^{-1}\,\mathrm{COPY}\,C\) of Theorem 7.5 use?

\(C^{-1}\) has as many gates as \(C\) (each gate is replaced by its inverse), and COPY uses one CNOT per output bit.
\(40+3+40=83\). Cleaning up roughly doubles the cost, which is the price of interference-safe oracles.
example 7.4 — an equality oracle, computed in place

Build the oracle \(|a\rangle|b\rangle|y\rangle\mapsto|a\rangle|b\rangle|y\oplus[a=b]\rangle\) for single bits \(a\) (qubit 0), \(b\) (qubit 1) and output \(y\) (qubit 2), where \([a=b]\) is 1 if \(a=b\) and 0 otherwise. Use no extra work qubits.

Compute in place. cx(0, 1) replaces \(b\) by \(a\oplus b\), which is 0 exactly when \(a=b\); then x(1) makes qubit 1 hold \(\neg(a\oplus b)=[a=b]\). Qubit 1 has served as its own work register, and \(b\) itself is temporarily lost: that is the garbage.

Copy. cx(1, 2) XORs \([a=b]\) into \(y\).

Uncompute. Undo the first two gates in reverse order: x(1), then cx(0, 1). Qubit 1 returns to \(b\). Five gates in all, and the truth table in Section 7 confirms every row. Without the last two gates, qubit 1 would be left holding \([a=b]\) instead of \(b\), and any later interference between inputs that differ in \(b\) would suffer exactly as in Example 7.3.

Reversible circuit lab

Build a classical reversible circuit on four bits, \(q_0\) to \(q_3\), from \(X\), CNOT and Toffoli gates. The table lists every input, written \(q_3q_2q_1q_0\), with its output; changed bits are highlighted. The presets load Example 7.2, Example 7.4 with and without the uncompute step, and Theorem 7.5 in miniature: OR computed into a work qubit \(q_3\) that starts in 0, copied into \(q_2\), then uncomputed. When a work qubit is chosen, only inputs with that qubit 0 are listed. The check at the bottom reports whether the circuit is a clean oracle, i.e. whether every qubit other than the chosen output ends as it began, and if so prints the truth table of \(f\).

5 — Universal gate sets

Real hardware offers a small menu of native gates, and every circuit must be compiled into it. When is a menu big enough?

definition 7.4 — universal gate set

A finite set \(\mathcal G\) of gates is universal if for every \(n\), every unitary \(U\) on \(n\) qubits and every \(\varepsilon>0\), some circuit built from gates in \(\mathcal G\) (acting on any of the qubits) implements a unitary within distance \(\varepsilon\) of \(U\), up to a global phase.

"Within \(\varepsilon\)" is unavoidable. A finite gate set generates only countably many circuits, while there are uncountably many unitaries, so exact universality with finitely many gates is impossible. For single-qubit gates we measure distance up to phase by \(d(U,V)=\sqrt{1-|\mathrm{tr}(U^\dagger V)|/2}\), which is 0 exactly when \(V=e^{i\theta}U\).

How far is the \(T\) gate from doing nothing? Compute \(d(I,T)\) to three decimal places.

\(\mathrm{tr}(I^\dagger T)=1+e^{i\pi/4}\), and \(|1+e^{i\varphi}|=2\cos(\varphi/2)\).
\(|\mathrm{tr}\,T|/2=\cos(\pi/8)\approx0.924\), so \(d(I,T)=\sqrt{1-\cos(\pi/8)}\approx0.276\), about twice the distance from \(I\) to \(P(\pi/8)\) in the figure below.
facts 7.6 — universality results (stated without proof)
  1. Exact universality with continuous gates. All single-qubit gates together with CNOT generate every unitary exactly (Barenco et al., 1995). Lecture 4's Z-Y-Z decomposition handles one qubit; the work is in reducing \(n\)-qubit unitaries to two-level pieces.
  2. Clifford + T. The finite set \(\{H,T,\mathrm{CNOT}\}\) is universal. The key point is that \(H\) and \(T\) generate a rotation of the Bloch sphere by an angle that is an irrational multiple of \(\pi\), whose powers come arbitrarily close to every rotation about its axis; conjugating by \(H\) gives the same for a second, non-parallel axis, and rotations about two such axes compose to every rotation (Lecture 4's Z-Y-Z idea).
  3. Solovay–Kitaev. For any universal set closed under inverses, every single-qubit gate can be approximated within \(\varepsilon\) by \(O\big(\log^{c}(1/\varepsilon)\big)\) gates, with \(c\approx3.97\) in the standard construction (Dawson–Nielsen). For Clifford + T specifically, number-theoretic algorithms (Ross–Selinger) approximate a \(z\)-rotation with about \(3\log_2(1/\varepsilon)\) \(T\) gates.
  4. Most unitaries are expensive. A counting argument shows that almost every \(n\)-qubit unitary needs a number of gates exponential in \(n\) to approximate (Nielsen–Chuang §4.5.4). Universality says every computation can be compiled; it says nothing about doing so efficiently. Efficient quantum algorithms are the rare exceptions.
  5. Gottesman–Knill. Circuits made only of the Clifford gates \(H\), \(S\), CNOT (plus Pauli gates and standard-basis measurements), started from \(|0\cdots0\rangle\), can be simulated efficiently on a classical computer, even when they create large entangled states. So Clifford circuits alone give no computational speedup over classical computers; a non-Clifford gate such as \(T\) is needed. (Clifford-only protocols can still be useful, for instance BB84 in Lecture 20.)

Which of these circuits, started from \(|0\cdots0\rangle\) and measured in the standard basis, is guaranteed to be efficiently simulable on a classical computer?

Gottesman–Knill (Fact 5) is about which gates appear, not about how entangled the state gets.
Clifford-only circuits are classically simulable however many qubits and however much entanglement; a non-Clifford gate such as \(T\) or Toffoli is what breaks this.

The approximation in Fact 2 can be watched directly. The figure searches every product of \(H\) and \(T\) gates up to a given length for the best approximation of the phase gate \(P(\pi/8)=\mathrm{diag}(1,e^{i\pi/8})\), the "square root of \(T\)" that the quantum Fourier transform needs (Lecture 13).

Approximating the gate P(pi/8) by words in H and TStep plot of the smallest distance, up to global phase, between P(pi/8) and any product of at most L gates H and T, for L from 0 to 42. The distance stays at 0.139 (the identity is the best choice) up to L = 10, drops to 0.112 at L = 11, to 0.040 at L = 19, to 0.026 at L = 37 and to 0.024 at L = 42. Annotations give the number of distinct gates searched: 266 at L = 10, 3,400 at L = 19 and about 1.4 million at L = 42.0.000.050.100.1506121824303642maximum number of gates Ldistance to P(pi/8)266 gates3,400 gates377,571 gates1.4 million gates
Exhaustive search for \(P(\pi/8)\) among products of at most \(L\) gates \(H\) and \(T\), counting distinct gates up to global phase (computed in ht_search.py). Up to \(L=10\) nothing beats doing nothing (distance \(0.139\)); the improvements come at \(L=11\) (6 \(T\) gates), \(L=19\) (11), \(L=37\) (23) and \(L=42\) (24). The number of distinct gates roughly doubles every three steps, so brute force is hopeless for high precision, which is why Solovay–Kitaev and Ross–Selinger matter.
idea — why T is the expensive gate

Fault-tolerant quantum computers (Lecture 23) can perform Clifford gates on encoded qubits relatively cheaply, but by Gottesman–Knill those alone are classically simulable. The \(T\) gate is the missing ingredient, and on error-corrected hardware it is typically made by a costly procedure called magic-state distillation. That is why resource estimates for Shor's algorithm (Lecture 17) are quoted in \(T\) gates or Toffoli gates, and why compilers work hard to minimise the \(T\)-count.

6 — What a Toffoli really costs

Hardware does not offer a three-qubit Toffoli gate, so the compiler must decompose it. Qiskit's transpile does this for any target gate set. Here are the results for a single ccx(0, 1, 2), recorded from a run of the code in Section 7 with qiskit 2.5 (optimisation level 1).

target gate setgate countssizedepth
IBM-style: cx, rz, sx, x10 rz, 6 cx, 2 sx1813
Clifford + T: h, t, tdg, cx4 t, 3 tdg, 6 cx, 2 h1511

The Clifford + T version is the textbook ancilla-free decomposition: six CNOTs and a \(T\)-count of 7. (With an extra qubit and a measurement, cleverer constructions reduce the \(T\)-count to 4.) One Toffoli costs as much as fifteen elementary gates, and a classical circuit with \(g\) AND gates, made reversible by Theorem 7.4 and cleaned by Theorem 7.5, needs about \(2g\) Toffolis, so about \(14g\) \(T\) gates. Arithmetic is expensive on a quantum computer.

A circuit contains 3 Toffoli gates, 2 \(T\) gates, 1 \(T^\dagger\) gate and some Clifford gates. What is its \(T\)-count after each Toffoli is replaced by the ancilla-free Clifford + T decomposition above?

Each Toffoli contributes 7 to the \(T\)-count (4 \(T\) and 3 \(T^\dagger\)); \(T^\dagger\) gates count too; Clifford gates count zero.
\(3\cdot7+2+1=24\). The Toffolis dominate, which is why reversible arithmetic drives the \(T\)-count of algorithms such as Shor's.
crypto connection — a cipher is just another oracle

A block cipher such as AES is a classical circuit that maps a key \(k\) and a known plaintext \(m\) to a ciphertext \(E_k(m)\). By Theorems 7.4 and 7.5 it becomes a clean quantum oracle, and so does the test "does key \(k\) encrypt \(m\) to the ciphertext we intercepted?". Grover's algorithm (Lectures 11–12) searches over keys with such an oracle. Every call runs the whole cipher reversibly, twice. The first detailed resource estimate (Grassl, Langenberg, Roetteler and Steinwandt, 2016) built exactly such reversible AES circuits. Their oracle runs AES on \(r=3\) known plaintext–ciphertext pairs at once (one pair does not pin down a 128-bit key uniquely), and Grover needs about \(\tfrac\pi4\cdot2^{64}\approx1.4\times10^{19}\) oracle calls. Their totals for the whole attack:

key sizelogical qubits\(T\) gates\(T\)-depth
AES-1282,953\(1.19\cdot2^{86}\)\(1.06\cdot2^{80}\)
AES-1924,449\(1.81\cdot2^{118}\)\(1.21\cdot2^{112}\)
AES-2566,681\(1.41\cdot2^{151}\)\(1.44\cdot2^{144}\)

The qubit counts are modest; the depth is not. A \(T\)-depth of \(1.06\cdot2^{80}\) sequential layers would take about 40 million years even at a billion layers per second (and today's error-corrected \(T\) gates are far slower than that), and Grover's iterations cannot be split across many machines without losing most of the quadratic speedup. Later papers have trimmed these numbers considerably, but not enough to change the picture: this is why Grover is a much weaker threat to symmetric cryptography than Shor is to RSA (Lecture 12, Lab 3), and why the standard advice is simply to prefer 256-bit keys.

7 — Try it in code

tool — transpiling a Toffoli (tested with qiskit 2.5)
from qiskit import QuantumCircuit, transpile

tof = QuantumCircuit(3)
tof.ccx(0, 1, 2)                              # controls q0, q1; target q2

for basis in (["cx", "rz", "sx", "x"], ["h", "t", "tdg", "cx"]):
    t = transpile(tof, basis_gates=basis, optimization_level=1, seed_transpiler=1)
    print(basis, dict(t.count_ops()), "depth", t.depth())
['cx', 'rz', 'sx', 'x'] {'rz': 10, 'cx': 6, 'sx': 2} depth 13
['h', 't', 'tdg', 'cx'] {'cx': 6, 't': 4, 'tdg': 3, 'h': 2} depth 11

Different Qiskit versions, optimisation levels or target devices can give different counts, so record your own rather than trusting a table. Real IBM devices currently use cz or ecr as their two-qubit gate; backend.target lists what a device supports.

tool — the equality oracle of Example 7.4, checked on every input
from qiskit import QuantumCircuit
from qiskit.quantum_info import Statevector

eq = QuantumCircuit(3)                        # a = q0, b = q1, output y = q2
eq.cx(0, 1); eq.x(1)                          # compute: b <- NOT(a xor b) = [a == b]
eq.cx(1, 2)                                   # copy the answer into y
eq.x(1); eq.cx(0, 1)                          # uncompute: restore b

for i in range(8):
    label = format(i, "03b")                  # the basis state |y b a>
    p = Statevector.from_label(label).evolve(eq).probabilities_dict()
    print(label, "->", max(p, key=p.get), end="   " if i % 4 < 3 else "\n")
000 -> 100   001 -> 001   010 -> 010   011 -> 111
100 -> 000   101 -> 101   110 -> 110   111 -> 011

Labels are \(|y\,b\,a\rangle\). Exactly the inputs with \(a=b\) (\(000,011,100,111\)) have their \(y\) bit flipped, and \(a,b\) always come out unchanged.

tool — Example 7.3: garbage and interference
from qiskit import QuantumCircuit
from qiskit.quantum_info import Statevector

def run(garbage, uncompute):
    qc = QuantumCircuit(3)                    # x = q0, target = q1, garbage = q2
    qc.x(1); qc.h(1)                          # target in |->
    qc.h(0)                                   # x in |+>
    if garbage: qc.cx(0, 2)                   # a sloppy oracle also copies x into q2
    qc.cx(0, 1)                               # the phase oracle for f(x) = x
    if garbage and uncompute: qc.cx(0, 2)     # clean up the garbage
    qc.h(0)
    p = Statevector.from_instruction(qc).probabilities([0])
    return p.round(4)

print("clean oracle       P(x=0), P(x=1):", run(False, False))
print("garbage left       P(x=0), P(x=1):", run(True, False))
print("garbage uncomputed P(x=0), P(x=1):", run(True, True))
clean oracle       P(x=0), P(x=1): [0. 1.]
garbage left       P(x=0), P(x=1): [0.5 0.5]
garbage uncomputed P(x=0), P(x=1): [0. 1.]

8 — Summary and exercises

summary

Next time: what quantum information cannot do (no-cloning), and what entanglement can do: teleportation and superdense coding. Lab 2 launches. HW4 is due at the start of Week 5.

exercises 7
  1. Find the size, depth, two-qubit gate count and \(T\)-count of the four-qubit circuit h(0), h(1), cx(0, 2), cx(1, 3), cx(2, 3), x(0), and list its layers.
  2. Let \(f(x)=1-x\) on one bit, with input on qubit 0 and output on qubit 1. Give two different circuits for \(U_f\), one with three gates and one with two.
  3. Let \(f(x_1x_0)=x_1\oplus x_0\). Show that \(U_f\), with the output on qubit 2, is cx(0, 2) followed by cx(1, 2). Why is no Toffoli needed?
  4. Instead of uncomputing the garbage qubit in Example 7.3, why not just measure it and throw away the result? Compute \(P(x=0)\) in that case.
  5. Show that \(S\), \(Z\), \(S^\dagger\) and \(T^\dagger\) are powers of \(T\), and that \(X=HT^4H\). Conclude that circuits of \(H\) and \(T\) can produce all four Pauli matrices up to phase.
  6. Use Proposition 7.3 to show that a Toffoli whose target is in \(|-\rangle\) multiplies \(|a\rangle|b\rangle\) by \((-1)^{ab}\). Which familiar two-qubit gate does it then act as on the controls?
  1. Size 6. Layer 1: h(0), h(1). Layer 2: cx(0, 2), cx(1, 3) (disjoint qubits). Layer 3: cx(2, 3), which needs qubits 2 and 3, and x(0), which waits for cx(0, 2). Depth 3, three two-qubit gates, \(T\)-count 0.
  2. \(U_f|x\rangle|y\rangle=|x\rangle|y\oplus1\oplus x\rangle\). Three gates: x(0), cx(0, 1), x(0) (flip the control, CNOT, flip it back). Two gates: cx(0, 1) then x(1), since \(y\oplus x\oplus1\) is the CNOT followed by a NOT on the output.
  3. The two CNOTs map \(|x_1x_0\rangle|y\rangle\) to \(|x_1x_0\rangle|y\oplus x_0\oplus x_1\rangle=|x_1x_0\rangle|y\oplus f(x)\rangle\). XOR is already reversible (it is what CNOT computes), and XOR-ing into the output register is linear, so no AND, and hence no Toffoli, is involved.
  4. Measuring \(g\) collapses the state \(\tfrac{1}{\sqrt2}(|0\rangle_x|0\rangle_g-|1\rangle_x|1\rangle_g)\) to \(|0\rangle|0\rangle_g\) or \(|1\rangle|1\rangle_g\) (Rule 6.2), each with probability \(\tfrac12\). Either way \(x\) is now a basis state, and \(H\) turns it into \(|\pm\rangle\), so \(P(x=0)=\tfrac12\), exactly as with the garbage left in place. Measuring the garbage reveals \(x\); it does not un-reveal it. Only uncomputation, which returns \(g\) to the same state for every \(x\), erases the record.
  5. \(T=\mathrm{diag}(1,e^{i\pi/4})\), so \(T^k=\mathrm{diag}(1,e^{ik\pi/4})\): \(S=T^2\), \(Z=T^4\), \(S^\dagger=T^6\), \(T^\dagger=T^7\), and \(T^8=I\). Then \(HT^4H=HZH=X\). Finally \(Y=iXZ\), so \(Y\) is \(XZ\) up to the phase \(i\), and the identity is the empty circuit.
  6. With \(f(a,b)=a\wedge b=ab\), the Toffoli is \(U_f\), so Proposition 7.3 gives \(|a\rangle|b\rangle|-\rangle\mapsto(-1)^{ab}|a\rangle|b\rangle|-\rangle\). On the two controls this is \(\mathrm{diag}(1,1,1,-1)\), the CZ gate of Lecture 6.

Reading and sources

all numbers and figures in these notes are computed in python (verify_L07.py, ht_search.py) and follow the page theme