An interactive essay

Quantum computing,
slowly.

A quantum computer is not a parallel-universe oracle. It is a machine that steers probability amplitudes — numbers a lot like probabilities, but allowed to be negative — so that wrong answers cancel out and right answers add. Everything else, from Shor's algorithm to error correction, is choreography on that one idea.

Two amplitudes for the same outcome can cancel. Probabilities can't. That is the whole story, the rest is detail.


2 · What is a qubit?

A classical bit is a switch: 0 or 1. A qubit is something stranger — an arrow inside a sphere. The arrow can point at the north pole (call it $|0\rangle$), the south pole ($|1\rangle$), or anywhere on the surface in between. The surface holds every possible in‑between state a single qubit can be in.

Mathematically a pure qubit state is a unit vector in $\mathbb{C}^2$: $$|\psi\rangle = \alpha|0\rangle + \beta|1\rangle, \qquad |\alpha|^2 + |\beta|^2 = 1.$$ Two complex numbers, four real parameters, minus normalization, minus a physically‑unobservable global phase, leaves two real angles — a polar $\theta$ and an azimuthal $\varphi$ — mapping every pure state to one point on a sphere: $$|\psi\rangle = \cos\tfrac{\theta}{2}|0\rangle + e^{i\varphi}\sin\tfrac{\theta}{2}|1\rangle.$$

The factor of $\theta/2$ rather than $\theta$ is the geometric subtlety that the Bloch sphere demands. Orthogonal qubit states — $|0\rangle$ and $|1\rangle$ — sit on opposite poles, 180° apart, not 90° apart. Drag the arrow below and watch the amplitudes update.

Bloch sphere

Drag the arrow. Watch $(\theta,\varphi)$, the Dirac form, and the measurement probabilities.

$\theta$0.00rad
$\varphi$0.00rad
$|\psi\rangle = |0\rangle$
$P(0)$
1.000
$P(1)$
0.000

Recap: the north pole is $|0\rangle$, the south pole is $|1\rangle$, the equator holds equal‑weight superpositions, and the only thing a measurement returns is one bit.


3 · Superposition & interference

The word superposition gets misused constantly. A qubit in state $\tfrac{1}{\sqrt 2}(|0\rangle + |1\rangle)$ is not “both 0 and 1 at once”. It is a definite state whose amplitudes — the two complex numbers attached to the two basis labels — happen to be equal in magnitude.

Amplitudes look a lot like probabilities, with one crucial difference: they are allowed to be negative, or complex. And when two different amplitudes contribute to the same outcome, they add. Equal-magnitude opposite‑sign amplitudes cancel. Probabilities can never do this.

The cleanest example: apply the Hadamard gate twice to $|0\rangle$. $$H|0\rangle = \tfrac{1}{\sqrt 2}(|0\rangle + |1\rangle),\qquad H\cdot H|0\rangle = |0\rangle.$$ Naively you might think the second Hadamard makes things even “more uncertain”. It doesn't. The two paths from $|0\rangle$ to $|1\rangle$ carry amplitudes $+\tfrac12$ and $-\tfrac12$. They cancel. The two paths to $|0\rangle$ both carry $+\tfrac12$. They add to 1.

Double Hadamard: interference made visible

Step through $|0\rangle \to H \to H \to |0\rangle$ and watch the four paths combine. Toggle “classical” mode to see what probabilities (no signs) would do.

Recap: in quantum mode, the $|1\rangle$ outcome ends up with amplitude $\tfrac12 - \tfrac12 = 0$, probability 0. In classical mode the same probabilities just add, $\tfrac14 + \tfrac14 = \tfrac12$, and you can never cancel anything. That difference is the engine of every quantum speedup.


4 · Measurement: same state, different basis, different bits

The Born rule is the contract between the quantum world and the classical one: a state $|\psi\rangle = \sum_x \alpha_x|x\rangle$, measured in the basis $\{|x\rangle\}$, yields outcome $x$ with probability $|\alpha_x|^2$, and afterwards the state is $|x\rangle$. One bit out per qubit, no peeking at the amplitudes themselves.

The choice of basis matters more than people expect. $|+\rangle$ measured in the $Z$ basis gives 0 or 1 with equal probability. The same state measured in the $X$ basis gives 0 every single time. Same physical state, different question, different statistics.

Pick a state, pick a basis, run 1000 shots

The state on the slider is $\cos(\theta/2)|0\rangle + \sin(\theta/2)|1\rangle$. Press a basis button to draw 1000 samples.

Recap: the histogram is what the Born rule actually predicts, sampled finitely. Slide $\theta$ to $\pi/2$ — that's $|+\rangle$ — and notice how it behaves drastically differently in $Z$ versus $X$.


5 · Entanglement: information that lives in a relationship

A two‑qubit state is separable if you can write it as $|a\rangle\otimes|b\rangle$ — one definite single‑qubit state for each qubit. Most two‑qubit states aren't separable. The famous Bell state $$|\Phi^+\rangle = \tfrac{1}{\sqrt 2}(|00\rangle + |11\rangle)$$ has perfect $00/11$ correlations, and yet looking at either qubit alone gives you a featureless 50/50 mixture. The information lives in the relationship, not in either party.

Building one is a two‑gate recipe: $H$ on qubit 0, then $\text{CNOT}$ from qubit 0 to qubit 1. Below, the circuit runs in your browser — amplitudes, probabilities, and 1000 sampled shots all computed live.

Bell pair generator

Apply the circuit gate by gate. The four bars are the amplitudes on $|00\rangle, |01\rangle, |10\rangle, |11\rangle$. Then run 1000 shots and see the resulting histogram.

Recap: only $|00\rangle$ and $|11\rangle$ appear in the histogram — perfectly correlated when measured in the Z basis. A Bell-inequality test would also confirm correlations in rotated bases, but that requires a basis selector this widget doesn't expose. The non-classical fingerprint is that the entangled correlations survive a basis change while classical coin‑flip correlations don't — which is what Bell's inequalities measure.

Bell test: the $2\sqrt 2$ violation

There is a sharp, experimental way to prove the correlations above are genuinely non‑classical. Alice and Bob share the Bell pair $|\Phi^+\rangle$, but instead of always measuring in $Z$, each of them picks (randomly, on each shot) between two measurement angles: Alice picks $a_0$ or $a_1$, Bob picks $b_0$ or $b_1$. Each measurement returns $\pm 1$. Repeat thousands of times and estimate the four correlations $E(a_i, b_j) = \langle a_i b_j\rangle$.

The CHSH statistic is the combination $$S = E(a_0, b_0) - E(a_0, b_1) + E(a_1, b_0) + E(a_1, b_1).$$ Any local hidden-variable theory — any model where the outcomes were predetermined and just revealed by measurement — satisfies $|S|\leq 2$. Quantum mechanics, applied to $|\Phi^+\rangle$ with the correlation $E(\theta_A, \theta_B) = \cos(\theta_A - \theta_B)$, can reach $|S| = 2\sqrt 2 \approx 2.828$ (Tsirelson's bound), achieved when Alice picks $0$ and $\pi/2$ and Bob picks $\pi/4$ and $3\pi/4$ — one of several geometrically equivalent optimal configurations.

CHSH compass · live $S$

Drag the four arrows to set Alice's two and Bob's two measurement angles. The CHSH value $S$ updates live. Use the “sample 1000 shots” button to draw empirical outcomes from the quantum probabilities.

Recap: at the optimal angles, $S = 2\sqrt 2 \approx 2.828$. The classical bound is $2$. No local hidden-variable theory can explain that. It's been verified experimentally since the 1980s, most stringently in the 2015 loophole-free tests at Delft, NIST, and Vienna.


6 · Gates and circuits

A quantum gate is a small, fixed transformation on one or two qubits. Each gate is a unitary matrix — norm-preserving, reversible. A circuit is a sequence of gates: read it left to right like sheet music, each gate applied in turn, ending in a measurement.

The first set you should know by name and shape: $X$ (NOT, north-pole to south-pole), $Z$ (flip the phase of $|1\rangle$), $H$ (build a superposition), $S$ and $T$ (small phase rotations), and $\text{CNOT}$ (the workhorse two-qubit gate that creates entanglement).

A profound fact: $\{\text{CNOT}, H, T\}$ — just three gates — is universal. Every unitary can be approximated to arbitrary accuracy by sequences from this set (Solovay–Kitaev). Click gates below to build a 2-qubit circuit and watch the amplitude vector update live.

2-qubit circuit composer

Click gates to add them. Drop one in to apply it. The state vector on the right updates after each gate.

Examples:

Recap: gates are unitaries, circuits compose them by multiplication, and a tiny universal set spans the whole space. The Bell circuit above is the simplest non‑trivial example: two gates, one entangled pair.


7 · Phase kickback — how oracles encode answers as phases

Every oracle-based quantum algorithm — Deutsch–Jozsa, Grover, Shor's order-finding — uses the same trick. The oracle $U_f$ implements $$U_f \,|x\rangle|y\rangle \;\mapsto\; |x\rangle\,|y \oplus f(x)\rangle.$$ By itself that just XOR‑flips a target bit. But if you prepare the target in the state $|-\rangle = (|0\rangle - |1\rangle)/\sqrt 2$, the XOR flips the sign of the whole expression when $f(x)=1$, and the sign gets kicked back onto the input register.

Compute it directly: $$U_f \,|x\rangle |{-}\rangle = \tfrac{1}{\sqrt 2}\bigl(|x\rangle|0 \oplus f(x)\rangle - |x\rangle|1 \oplus f(x)\rangle\bigr) = (-1)^{f(x)}\,|x\rangle\,|{-}\rangle.$$ The ancilla is untouched. The input register picked up a phase that depends on $f(x)$. That phase is invisible to any single measurement, but the second wall of Hadamards turns the pattern of phases into interference: amplitudes for one outcome add, amplitudes for another cancel. Phase kickback is how a quantum oracle injects information into the amplitude vector.

The widget below lets you define the oracle by clicking. Pick any Boolean function $f: \{0,1\}^4 \to \{0,1\}$ — click squares to toggle $f(x)$ between $0$ (blue) and $1$ (orange). Then step through the Deutsch–Jozsa circuit: Hadamard wall, oracle, Hadamard wall. Watch the amplitudes; if you started with a constant $f$, all amplitude lands on $|0000\rangle$. If $f$ is balanced (exactly 8 of 16 inputs marked), the amplitude on $|0000\rangle$ is exactly zero. One quantum query distinguishes the two; classically you might need nine.

Deutsch–Jozsa on 4 input qubits, live

Toggle the oracle. Step through the algorithm. The bars are the real-valued amplitudes on each of the 16 basis states of the input register.

Recap: when $f$ is constant, all 16 amplitudes carry the same sign and the second Hadamard wall constructively interferes them onto $|0000\rangle$ with amplitude $\pm 1$. When $f$ is balanced, the signs are split exactly half‑and‑half and the $|0000\rangle$ amplitude is the inner product of $(+1,\ldots,+1)$ with a vector of equal parts $+1$ and $-1$ — zero. That is the Deutsch–Jozsa algorithm. One quantum query, two possible outcomes, perfect discrimination of constant vs. balanced.


8 · Grover's algorithm: a rotation, not an amplifier

Suppose you have an unsorted list of $N$ items and a black-box function $f$ that returns 1 on the one item you want and 0 on the rest. Classically you have to try roughly $N/2$ items on average. Grover's algorithm finds it in about $\tfrac{\pi}{4}\sqrt N$ queries — a quadratic speedup, provably optimal for any quantum oracle algorithm.

The picture is geometric. The state lives in a 2D plane spanned by “the marked answer” and “everything else”. Each Grover iterate $G = D\cdot O$ rotates the state by a small angle $2\theta$ toward the marked axis, with $\sin\theta = \sqrt{1/N}$. After $k$ steps the marked probability is $\sin^2((2k+1)\theta)$. Iterate too few times, you haven't reached the answer; iterate too many, you spin past it.

The widget below runs the real Grover circuit on $N=16$ items in your browser — it computes the oracle $U_\omega = I - 2|m\rangle\langle m|$ and the diffusion operator $D = 2|s\rangle\langle s| - I$ directly on the 16‑amplitude state vector. The numbers match the Python toy 03_grover_search.py to four decimal places.

Grover on 16 items, live

Click a bar to choose the marked item. Press “Step” to apply one Grover iterate. Keep stepping to see the overshoot.

Iter $k$$P(\text{marked})$Note

Recap: probability rises, peaks at $k=3$ around 96.13%, then falls. Grover is a rotation, not a one-way amplifier. Knowing when to stop is part of the algorithm.


9 · The Quantum Fourier Transform: making periodicity visible

Don't think of the QFT as “an FFT, but faster”. You can never read out the output coefficients individually — you only get to measure, and that gives you one Fourier-basis state. The job the QFT is good at is this: given a quantum state with a periodic amplitude pattern, concentrate all of the amplitude onto the multiples of $N/r$ where $r$ is the period. Periodicity, in $O(\log^2 N)$ gates, becomes measurable.

The widget below builds a “comb” state on a 64-position register with adjustable period $r$, then applies the $64\times 64$ DFT in your browser. For $r = 4$, the output is concentrated on $\{0, 16, 32, 48\}$; for $r = 8$, on $\{0, 8, 16, \ldots\}$. The peaks are real, and they are exactly $N/r$ apart.

QFT of a comb

Slide the period $r$. The top plot is the input amplitudes, the bottom is the QFT output.

Recap: the QFT does not give you the Fourier spectrum, it gives you a state whose measurement statistics reveal periodicity. Combine that with continued fractions and you have the engine of Shor's algorithm.

Note: this widget computes the forward DFT. The inverse QFT used in Shor's algorithm has the conjugate phase but produces the same peak structure for real-valued input combs.


10 · Shor: from factoring to a comb in a register

The 1994 paper that woke the world up. To factor $N$, Shor reduces the problem to finding the order $r$ of a random base $a$ modulo $N$ — the smallest $r>0$ with $a^r \equiv 1 \pmod N$. Once you know $r$ (and as long as $r$ is even and $a^{r/2} \not\equiv -1$), the factors fall out of $\gcd(a^{r/2}\pm 1,\, N)$.

The function $f(x) = a^x \bmod N$ is classically easy to evaluate but its period is hard to find when $N$ is huge. A quantum computer prepares a uniform superposition on the input register, applies the modular-exponentiation oracle to entangle input with output, measures the output (which collapses the input to a comb with spacing $r$), and applies the inverse QFT. The peaks of the output are at multiples of $M/r$ where $M = 2^n$ is the input-register size. Continued fractions on $k/M$ recovers $r$.

The flow, in one diagram

The widget below runs the full pipeline live in your browser for $N = 15$, $a = 7$. The QFT, the measurement collapse, and the continued-fraction post-processing are all computed in JS — the numbers track the Python toy 04_period_finding.py exactly (period $r=4$, peaks at $\{0, 64, 128, 192\}$, factors 3 and 5).

Shor pipeline, live

Pick $N$ and $a$, then step through the algorithm. Each step computes its result on the fly.

Recap: factoring 15 is small enough that the “quantum” part runs in milliseconds on your laptop. The real wins come at $N$ with hundreds of digits, where the modular exponentiation step is the bottleneck and classical algorithms still take subexponential time.


11 · Build it from scratch A Karpathy-style notebook thread: a working quantum simulator in ~400 lines.

Six cells. The first five compute their own numbers live in your browser — they are real ports of the Python in code/workshop/, not pre‑recorded output. The last cell shows the output of the 256×256 inverse QFT for Shor on $N=15$ (static, because the QFT matrix is heavy enough to defer). Click Run on each cell to watch the state vector evolve, the amplitudes interfere, and the algorithms turn into ordinary NumPy.

A qubit is just a vector. Two complex numbers, unit norm. Gates are 2×2 unitary matrices — you apply them by multiplication. Apply $H$ once to $|0\rangle$ and watch the amplitudes.

In [1]:
import numpy as np

KET_0 = np.array([1+0j, 0+0j])
KET_1 = np.array([0+0j, 1+0j])

I = np.eye(2, dtype=complex)
X = np.array([[0, 1], [1, 0]], dtype=complex)
Z = np.array([[1, 0], [0, -1]], dtype=complex)
H = (1/np.sqrt(2)) * np.array([[1, 1], [1, -1]], dtype=complex)

def apply(gate, state):
    return gate @ state

state = KET_0.copy()
print("Before H: ", state)
state = apply(H, state)
print("After  H: ", state)
computes H·|0⟩ live in JS
Out [1]:
(click Run)
One $H$ makes a superposition. The amplitudes $(+0.707,\,+0.707)$ are equal — the qubit is on the equator of the Bloch sphere, 50/50 under a $Z$‑measurement.

Two Hadamards cancel. Apply $H$ a second time and the $|1\rangle$ amplitude vanishes — not because of randomness, but because two paths to $|1\rangle$ carry equal-magnitude, opposite-sign amplitudes and add to zero.

In [2]:
state = KET_0.copy()
state = apply(H, state)        # |0> -> (|0> + |1>)/sqrt(2)
state = apply(H, state)        # second H: |1> amplitudes cancel

# What just happened:
#   |0> --H--> (+1/sqrt2)|0> --H--> (+1/2)|0> + (+1/2)|1>
#   |0> --H--> (+1/sqrt2)|1> --H--> (+1/2)|0> + (-1/2)|1>
#   sum |1>:  +1/2  +  (-1/2)  =  0          # interference!
print("After HH:", state)
step-by-step path summation
Out [2]:
(click Run)
This is interference. Probabilities can't do this — they can only add, never cancel. This is the engine of every quantum speedup.

A Bell pair from $H$ and CNOT. Take two qubits, apply $H$ to the first, then CNOT with the first as control. The result has amplitude only on $|00\rangle$ and $|11\rangle$ — perfect correlation.

In [3]:
def kron(*ops):
    out = ops[0]
    for op in ops[1:]:
        out = np.kron(out, op)
    return out

I2 = np.eye(2, dtype=complex)
CNOT = np.array([[1,0,0,0],
                 [0,1,0,0],
                 [0,0,0,1],
                 [0,0,1,0]], dtype=complex)

state = kron(KET_0, KET_0)        # |00>
state = kron(H, I2) @ state       # H on qubit 0
state = CNOT @ state              # entangle
print("state =", state)           # (|00> + |11>) / sqrt(2)

# Sample 1000 shots in the Z basis:
p = np.abs(state)**2
counts = np.random.multinomial(1000, p)
for label, c in zip(["|00>","|01>","|10>","|11>"], counts):
    print(f"  P({label}) ~ {c/1000:.3f}   ({c} shots)")
amplitudes + 1000 shots
Out [3]:
(click Run)
Two qubits, perfectly correlated, individually uncertain. That's entanglement. Notice that $|01\rangle$ and $|10\rangle$ never appear.

The reduced density matrix shows the entanglement. Trace out qubit 1 from the Bell pair and look at qubit 0 on its own. If the result is $I/2$, qubit 0 alone is a fair coin — all the information lives in the relationship.

In [4]:
def reduced_qubit0(state):
    # state is length 4; reshape to (2,2): axis 0 = qubit 0, axis 1 = qubit 1.
    psi = state.reshape(2, 2)
    return psi @ psi.conj().T

rho_0 = reduced_qubit0(state)
print("rho_0 =")
print(rho_0.real)
print("eigenvalues:", np.linalg.eigvalsh(rho_0).round(3))
print("purity tr(rho_0^2) =", np.trace(rho_0 @ rho_0).real)
computes the 2×2 partial trace
Out [4]:
(click Run)
Each qubit alone is maximally mixed (purity $1/2$). The joint state is pure (purity $1$). The information is in the entanglement, not in either qubit.

Grover, in eight lines of NumPy. Phase-flip the marked amplitude; reflect about the uniform superposition; repeat. Print $P(\text{marked})$ after each iteration and watch it rise, peak, and overshoot.
The Python below relies on the helpers defined in earlier cells (the $H$ matrix and the apply_H_all function). Copying just this snippet into a fresh Python file won't run — see code/workshop/03_grover_search.py for the standalone version.

In [5]:
n, N, marked = 4, 16, 11

def apply_H_all(state):
    H_all = H
    for _ in range(n-1):
        H_all = np.kron(H_all, H)
    return H_all @ state

def oracle(state, m):              # phase-flip marked basis state
    s = state.copy(); s[m] *= -1; return s

def diffuser(state):               # H_all, flip-sign-of-zero, H_all
    s = apply_H_all(state)
    s = -s; s[0] = -s[0]
    return apply_H_all(s)

state = apply_H_all(np.eye(N, dtype=complex)[0])
for k in range(7):
    p_m = abs(state[marked])**2
    print(f"iter {k}:  P(marked) = {p_m:.4f}")
    state = diffuser(oracle(state, marked))
computes iter 0..6 on a 16-dim state vector
Out [5]:
(click Run)
Grover is a rotation. At $k=3$ we hit $0.9613$; at $k=6$ we are back to $0.0204$. Stop at the right step or you spin past the answer.

Period finding for $N=15$. Build the comb of $7^x \bmod 15$, apply the $256\times 256$ inverse QFT, measure, run continued fractions, extract the factors. This cell is static — the QFT matrix is heavy enough that we show the numbers the real Python prints. The four equal peaks at multiples of $64$ are the period $r=4$ made visible.

In [6]:
import math
from fractions import Fraction

N, A = 15, 7
n_in = 8;  M = 2**n_in        # input register: 256 values

# 1. Build the joint state in (M, M_out) shape and apply U_f.
joint = np.zeros((M, 16), dtype=complex)
for x in range(M):
    joint[x, pow(A, x, N)] = 1.0 / np.sqrt(M)

# 2. (For analysis) measure the output register -> input collapses to a comb.
y = np.random.choice(16, p=(np.abs(joint)**2).sum(axis=0))
comb = joint[:, y]; comb = comb / np.linalg.norm(comb)

# 3. Inverse QFT on the input register.
omega = np.exp(2j * np.pi / M)
QFT = omega ** (np.arange(M)[:,None] * np.arange(M)[None,:]) / np.sqrt(M)
after = QFT.conj().T @ comb

# 4. Top outcomes:
probs = np.abs(after)**2
for k in np.argsort(probs)[::-1][:4]:
    print(f"  k = {k:3d}    P = {probs[k]:.4f}    k/M = {k/M:.4f}")

# 5. Continued fractions + factor extraction.
k = 192
r = Fraction(k, M).limit_denominator(N).denominator
x = pow(A, r//2, N)
print(f"r = {r};  7^(r/2) mod 15 = {x}")
print(f"factors: {math.gcd(x-1, N)} and {math.gcd(x+1, N)}")
static — runs in 0.3s in real Python 256×256 QFT, deferred from the browser
Out [6]:
Period 4 $\to$ factors 3 and 5. The quantum part: finding that period via the QFT. The classical part: continued fractions and gcd. Together: Shor's algorithm on $N=15$.

All the math above is real. Cells 1–5 compute their own amplitudes in JS using the same matrices the Python toy uses. Cell 6's numbers are the actual output of python3 code/workshop/04_period_finding.py. No magic, no SDK — about 400 lines of NumPy is enough to run a quantum computer.


12 · Anatomy — how the parts fit

Three field-guide plates of the central concepts.

Plate I

Anatomy of a Qubit

exploded view · single qubit on the Bloch sphere
Dirac form \(|\psi\rangle = \cos(\theta/2)|0\rangle + e^{i\varphi}\sin(\theta/2)|1\rangle\)
1 |0⟩ — the “ground” state, +z pole.
2 |1⟩ — the “excited” state, −z pole.
3 |+⟩ on the equator — equal superposition, measured 50/50.
4 θ — the amplitude (polar) angle.
5 φ — the phase (azimuthal) angle, invisible to a single Z measurement.
θ = 0°   φ = 0°
Plate I · Bloch sphere · drawn from the +x viewer
Plate II

Anatomy of an Entangled Pair

assembly diagram · |00⟩ → H → CNOT → Bell pair
1 qubit A's reduced state — lives at the center of its sphere in a Bell pair: individually maximally uncertain.
2 qubit B's reduced state — same story: maximally mixed when looked at alone.
3 entanglement ribbon — ≠ classical correlation, survives a basis change.
4 amplitude bars on |00⟩, |01⟩, |10⟩, |11⟩ — in the Bell state, only |00⟩ and |11⟩ are non-zero.
5 Bell-test schematic — a shared source, measured at distance by Alice and Bob at varying angles.
stage: |00⟩ — two unentangled qubits
I · |00⟩
II · H on A
III · CNOT
IV · Bell pair
Plate II · Bell pair · the morph is the heart of this plate
Plate III

Anatomy of Shor's Algorithm

exploded engineering schematic · classical gears · quantum jewel
1 pick random a < N — classical, the seed of the run.
2 gcd(a, N) — got a factor already? lucky day.
3 build f(x) = aˣ mod N — the interface to the quantum chip.
4 quantum core — superposition, modular-exp oracle, inverse QFT, measure.
5 continued fractions on k/M → r.
6 if r is even: factors fall out of gcd(aʳ/² ± 1, N).
7 if r is odd or fails: restart with a new a.
click a gear to jump to that step.
I
II
III
IV
V
VI
VII
Step 1 — Classical preprocessing: pick a random base a, with 1 < a < N.
Plate III · Shor's algorithm · one quantum jewel, six classical gears

13 · Error correction in action — the surface code, live

Physical qubits are noisy. Each gate has a $0.1$–$1\%$ chance of an error. With billions of operations in a Shor‑scale computation, raw qubits would degrade to noise in microseconds. The fix is not better hardware alone — it's encoding. We spread each logical qubit across many physical qubits in a careful entanglement pattern, then continually measure parities of small groups (syndromes) to spot errors without disturbing the encoded data.

The surface code is the leading approach today — a 2D lattice of data qubits with two kinds of stabilizer ancillas interleaved between them. Google's Willow chip demonstrated this below threshold in 2024: increasing the code's distance suppressed the logical error rate by $2.14\times$ per $+2$ increment in distance — the first hardware where adding more physical qubits made the encoded qubit cleaner, not noisier.

Below is a distance-3 surface code drawn on a $3\times 3$ grid of data qubits. Two kinds of ancillas, drawn as diamonds, sit between them: Z‑stabilizers measure $Z\!Z\!Z\!Z$ on their four data‑neighbours (and fire when an $X$ error has flipped one of those neighbours), while X‑stabilizers measure $X\!X\!X\!X$ (and fire on $Z$ errors). A single $X$, $Z$, or $Y$ error on any data qubit lights up exactly the neighbouring stabilizers of the right type — a syndrome the decoder can match to a unique inferred correction.

Click any data qubit to inject an $X$, $Z$, or $Y$ error. Watch the syndromes light up. Press Decode to run a minimum‑weight matching on the syndrome and see the inferred correction. Try injecting two errors far apart, then three — eventually you'll see the decoder fail with a logical error: a string of errors long enough to be confused with a logical $X$ or $Z$ operator on the encoded qubit. That is the code distance being exceeded.

Surface code · error injection & MWPM decode

Click a data qubit to choose its error. Stabilizers turn solid when their parity flips. The decode button runs minimum-weight matching and overlays the inferred correction.

Recap: when the physical error rate is below the code's threshold, increasing the code distance suppresses the logical error rate exponentially. Google's 2024 Willow chip demonstrated this empirically with a distance-7 surface code achieving the $2.14\times$ suppression per $+2$ distance increment. Error correction is no longer a theory result — it is a working hardware primitive.


14 · Where we are, in 2026

The first watershed moment was Shor's paper in 1994; the second was Grover's in 1996. Then a long, often discouraging climb — 30 years of decoherence, error‑correction theorems, and platform shoot‑outs — until December 2024, when Google's Willow chip became the first hardware to show error-corrected logical qubits clearly outperforming their physical counterparts. 2025 and 2026 saw the first multi-dozen logical qubit demonstrations.

Click a dot to read the milestone.

Click a dot above to see what happened that year.

Where things stand

In 2026 the field has changed shape. Logical qubits are real but few; fault-tolerant resource estimates for breaking RSA-2048 have come down to roughly $2 \times 10^7$ physical qubits and a few hours of wall time — still many years from existing hardware, but no longer an open-ended fantasy. Post‑quantum cryptography (Kyber, Dilithium, SPHINCS+) was standardized by NIST in 2024 and is being rolled out into TLS and PKI now, mostly out of fear of harvest-now-decrypt-later attacks on long-lived secrets.

What we still don't know: which hardware modality wins, what the first useful application is (chemistry? optimization? something nobody has written down yet?), and whether NISQ devices — quantum machines too small to error-correct — have any path to advantage at all. The honest answer is that we are at the bottom of a long climb, and the most interesting decade for the field is the next one.