Moving a qubit you are forbidden to copy.
Teleportation is the most over-sold word in quantum computing. It conjures Star Trek transporters and faster-than-light messaging, and almost every popular account quietly implies you end up with a copy of the original. You do not. Quantum teleportation moves an unknown quantum state from one qubit to another while destroying the original, and that destruction is not an incidental detail. It is the mechanism that keeps the protocol on the right side of the no-cloning theorem.
This whole protocol is haunted by the no-cloning theorem: there is no operation that copies an arbitrary unknown quantum state. I worked through the proof and its consequences in a recent post, The No-Cloning Theorem in Quantum Computing: Why You Can’t Copy a Qubit, so I will not re-derive it here.
The single fact we need going forward: you cannot deterministically duplicate an unknown qubit. The qualifiers matter, because teleportation lives in the gaps between them. The theorem forbids copying unknown states (a known state you can re-prepare at will), it forbids deterministic, perfect copies, and it is a statement about unitary operations — and measurement, which teleportation leans on at the decisive moment, is not unitary.
Here is the distinction in one sentence: cloning would leave |ψ⟩ in two places; teleportation leaves it in exactly one.
Partway through the protocol, Alice’s message qubit is measured. Measurement collapses it into a classical basis state — a plain |0⟩ or |1⟩ carrying none of the original amplitudes. By the time Bob’s qubit holds |ψ⟩, Alice’s qubit demonstrably does not. The state was relocated, and the accounting is exact: one copy in, one copy out. No moment ever exists where two qubits both carry |ψ⟩, so there is nothing for the no-cloning theorem to object to.
Here is the whole protocol in a single circuit. Read it left to right; the amber dashed dividers mark the three stages. The message qubit q0 starts in the unknown state |ψ⟩, while q1 and q2 both start in |0⟩.
Stage 1 — Bell pair. Alice and Bob share an entangled pair: an H on q1 followed by a CNOT from q1 onto q2 prepares (|00⟩ + |11⟩)/√2 across the two halves.
Stage 2 — Alice measures. Alice folds her message into the pair (a CNOT from q0 onto q1, then an H on q0) and measures both of her qubits, collapsing them to two classical bits.
Stage 3 — Bob corrects. Depending on those two bits, Bob applies an X and/or a Z to q2 — the X controlled by Alice’s q1 bit, the Z by her q0 bit — and q2 emerges as |ψ⟩. The next section is the algebra that fixes exactly which correction each outcome needs.
Now the algebra behind that circuit. Three qubits: q0 carries |ψ⟩ = α|0⟩ + β|1⟩ (Alice), q1 is Alice’s half of the Bell pair, and q2 is Bob’s half. They pre-share |Φ+⟩ = (|00⟩ + |11⟩)/√2 on q1 q2.
Step 1 — the starting state. Tensor the message against the Bell pair:
|ψ⟩ ⊗ |Φ+⟩ = (α|0⟩ + β|1⟩) ⊗ (|00⟩ + |11⟩)/√2
= (1/√2) [ α|000⟩ + α|011⟩ + β|100⟩ + β|111⟩ ]
Step 2 — Alice’s CNOT (control q0, target q1):
= (1/√2) [ α|000⟩ + α|011⟩ + β|110⟩ + β|101⟩ ]
Step 3 — Alice’s Hadamard on q0. Substitute |0⟩ → (|0⟩+|1⟩)/√2 and |1⟩ → (|0⟩−|1⟩)/√2, then collect by the value of (q0 q1):
= (1/2) [ |00⟩ (α|0⟩ + β|1⟩) ← case A
+ |01⟩ (α|1⟩ + β|0⟩) ← case B
+ |10⟩ (α|0⟩ − β|1⟩) ← case C
+ |11⟩ (α|1⟩ − β|0⟩) ] ← case D
Each bracketed q2 state is the original |ψ⟩ acted on by a known Pauli. Alice measures, gets one of four outcomes (each with probability 1/4), sends the two bits to Bob, and Bob undoes the Pauli. The Case column ties each row back to the matching line in Step 3:
|ψ⟩Bob applies Zm0 Xm1 — an X if m1 = 1, then a Z if m0 = 1 — and every branch lands back on α|0⟩ + β|1⟩ = |ψ⟩.
This version measures mid-circuit and uses real classical conditioning via if_test, the honest picture of the protocol. The verification trick: rather than read out Bob’s state, apply the inverse of the preparation to q2. If teleportation worked, that must collapse q2 to |0⟩ on every shot.
from qiskit import QuantumCircuit, QuantumRegister, ClassicalRegister, transpile
from qiskit.circuit.library import StatePreparation
from qiskit.quantum_info import random_statevector
from qiskit_aer import AerSimulator
# Unknown state to teleport (StatePreparation is unitary -> invertible)
psi = random_statevector(2)
prep = StatePreparation(psi)
q = QuantumRegister(3, “q”) # q0 message, q1 Alice, q2 Bob
mz = ClassicalRegister(1, “mz”) # q0 result -> drives Z
mx = ClassicalRegister(1, “mx”) # q1 result -> drives X
out = ClassicalRegister(1, “out”) # verification bit
qc = QuantumCircuit(q, mz, mx, out)
qc.append(prep, [0]); qc.barrier() # 1. load |ψ⟩ onto q0
qc.h(1); qc.cx(1, 2); qc.barrier() # 2. Bell pair on (q1,q2)
qc.cx(0, 1); qc.h(0) # 3. Alice’s basis change
qc.measure(0, mz); qc.measure(1, mx); qc.barrier()
with qc.if_test((mx, 1)): # 4. Bob’s corrections
qc.x(2)
with qc.if_test((mz, 1)):
qc.z(2)
qc.barrier()
qc.append(prep.inverse(), [2]) # 5. un-prepare on Bob: must read 0
qc.measure(2, out)
counts = AerSimulator().run(transpile(qc, AerSimulator()), shots=4000).result().get_counts()
clean = all(k.split()[0] == “0” for k in counts) # leftmost bit = out
print(counts); print(“Teleportation verified:”, clean)
out bit comes back 0 on 100% of shots regardless of the random (mx, mz) branch — exactly the claim that Bob reconstructs |ψ⟩ in every case.Before Bob learns (m0, m1), his qubit is an equal mixture of the four branch states. Averaging the four projectors gives the Pauli twirl:
+ Z|ψ⟩⟨ψ|Z + XZ|ψ⟩⟨ψ|ZX ) = I/2 for every |ψ⟩
for any |ψ⟩. Bob’s local state is identical no matter what Alice sent, so no information has reached him yet. The classical bits are not a formality — they are the only thing that carries the state across, and they travel no faster than light.
Quantum Series 2026 · Built with Qiskit 1.x
✦ This article was generated with the assistance of Claude by Anthropic ✦
Share this:
- Share on X (Opens in new window) X
- Share on Facebook (Opens in new window) Facebook
- Print (Opens in new window) Print
- Email a link to a friend (Opens in new window) Email
- Share on LinkedIn (Opens in new window) LinkedIn
- Share on Reddit (Opens in new window) Reddit
- Share on Tumblr (Opens in new window) Tumblr
- Share on Threads (Opens in new window) Threads
- Share on Pinterest (Opens in new window) Pinterest
- Share on Telegram (Opens in new window) Telegram
- Share on WhatsApp (Opens in new window) WhatsApp
- Share on Bluesky (Opens in new window) Bluesky