> *"Entanglement is not a stronger correlation than any classical correlation. It is a different
Prerequisites
- 1
- 2
- 3
Learning Objectives
- Compose multi-qubit states with the tensor product, and reproduce Qiskit's amplitude ordering with numpy.kron.
- Apply CNOT and predict its effect on both basis states and superpositions, and write its matrix in Qiskit's little-endian convention.
- Build all four Bell states and distinguish them by the phases and correlations that measurement in the computational basis cannot see.
- Test whether a state is entangled by computing the reduced state of one qubit, and explain why an entangled qubit has no state of its own.
- Use CZ, SWAP, and Toffoli, and state each one's cost in two-qubit gates on real hardware.
- Build GHZ and W states on three or more qubits and explain how they differ under the loss of one qubit.
- Quantify how entangled-state fidelity degrades with qubit count on real hardware, and explain why.
In This Chapter
- Overview
- Learning Paths
- 4.1 Two Qubits, Four Amplitudes
- 4.2 CNOT
- 4.3 The Bell State
- 4.4 Is It Entangled? An Operational Test
- 4.5 The Other Three Bell States
- 4.6 The Rest of the Two-Qubit Vocabulary
- 4.7 Three Qubits and Up: GHZ and W
- 4.8 The Exponential Wall, Concretely
- 4.9 Entangled States on Hardware
- 4.10 Summary
Chapter 4: Multi-Qubit Programming
"Entanglement is not a stronger correlation than any classical correlation. It is a different kind of thing, and the difference is what you are about to spend a career exploiting."
Overview
One qubit is a curiosity. Two qubits is a computer.
That sounds like an exaggeration and it is close to literally true. Everything in Chapter 3 — every single-qubit state, every gate, the whole Bloch sphere — is efficiently simulable by a classical computer and always will be. Nothing there gives you any advantage over a laptop. The moment you add a second qubit and connect them, you get access to a state space that grows exponentially and to a kind of correlation with no classical counterpart, and that is where quantum computing actually begins.
This chapter builds that machinery. You will meet the tensor product, which is how multi-qubit states compose and where the $2^n$ comes from. You will meet CNOT, which is the entire two-qubit gate vocabulary in the sense that everything else can be built from it plus single-qubit gates. You will build the Bell state you ran in Chapter 2 and finally understand it — including the three siblings you have not met. And you will get an operational test for entanglement, which matters because "are these qubits entangled?" turns out to be a question you will ask constantly and which cannot be answered by looking at measurement outcomes alone.
The chapter closes on hardware, with a measurement you can reproduce: entangled-state fidelity as a function of qubit count, on a real device model, showing exactly how fast the wheels come off.
In this chapter, you will learn to:
- Compose states with the tensor product, and reproduce Qiskit's ordering with
numpy.kron. - Apply CNOT and predict its effect on basis states and — the interesting case — superpositions.
- Build all four Bell states, and distinguish them by properties measurement cannot see.
- Test for entanglement by computing a qubit's reduced state, and explain why an entangled qubit has no state of its own.
- Use CZ, SWAP, and Toffoli, and price each one in two-qubit gates.
- Build GHZ and W states, and explain how they differ under the loss of a qubit.
- Measure how entangled-state fidelity degrades with qubit count, and say why.
Learning Paths
How to read this chapter by track. - 🔰 Beginner — all of it. §4.4 (what entanglement is and is not) is the conceptual core and deserves a second read; §4.6 is reference you can skim and return to. - 🔬 Researcher — §4.4's reduced-state test is the tool you will use to verify entanglement claims. §4.7's GHZ-versus-W distinction matters for anything involving multipartite entanglement. - 🤖 Quantum ML — §4.2 and §4.4. Every variational ansatz is an alternation of single-qubit rotations and entangling layers, and §4.9's fidelity decay is why deep ansätze fail on hardware. - 🏗️ Quantum Engineer — §4.6's gate costs and §4.9's scaling are the practical heart. A SWAP costs three CNOTs and a Toffoli costs six; those two numbers will govern your design decisions from Chapter 10 onward. - 🔐 Security — §4.3 and §4.4 give you what you need to reason about entanglement-based key distribution; the rest can be skimmed until Chapter 38.
4.1 Two Qubits, Four Amplitudes
A single qubit needs two amplitudes. Two qubits need four — one for each of 00, 01, 10, 11.
from qiskit import QuantumCircuit
from qiskit.quantum_info import Statevector
qc = QuantumCircuit(2)
print(Statevector(qc).data.real)
[1. 0. 0. 0.]
Both qubits in $|0\rangle$, so all the amplitude sits on the 00 entry. Now flip qubit 0:
qc = QuantumCircuit(2)
qc.x(0)
print(Statevector(qc).data.real)
print(Statevector(qc).probabilities_dict())
[0. 1. 0. 0.]
{'01': 1.0}
The amplitude moved to index 1, and the label is '01'. Read that carefully. We flipped qubit
0, and the bitstring shows the 1 in the right-hand position. That is little-endian, as
Chapter 2 §2.7 promised, and it is about to have real consequences for how you write matrices.
The tensor product, in code
How do two single-qubit states combine into a two-qubit state? With the tensor product, written
$\otimes$ and implemented by numpy.kron:
import numpy as np
zero = np.array([1, 0])
one = np.array([0, 1])
print("q1=0, q0=1:", np.kron(zero, one))
print("q1=1, q0=0:", np.kron(one, zero))
q1=0, q0=1: [0 1 0 0]
q1=1, q0=0: [0 0 1 0]
Compare the first line to the qc.x(0) result above: identical. So Qiskit's amplitude ordering is
$$|\psi\rangle = |q_{n-1}\rangle \otimes \cdots \otimes |q_1\rangle \otimes |q_0\rangle$$
Qubit 0 goes last in the tensor product, which is exactly what "little-endian" means and is the reverse of the convention in most textbooks, including Nielsen and Chuang.
⚠️ Common Pitfall — The convention that will cost you an afternoon.
Most quantum computing textbooks write $|q_0 q_1 q_2\rangle$ with qubit 0 on the left. Qiskit puts it on the right.
This means that when you transcribe a matrix from a paper into Qiskit, or read a Qiskit result against a textbook's expectation, the basis ordering is reversed. For symmetric states like $|00\rangle + |11\rangle$ nothing goes wrong, which is precisely why the bug hides — it survives every test you write with a Bell state and then destroys your first Grover oracle.
Two defenses:
- Use
probabilities_dict()andStatevector.from_label(), which speak in bitstrings and are unambiguous, rather than raw index arithmetic.- When you must index by hand, write a test with an asymmetric state — $|01\rangle$, not $|00\rangle$ — because that is the only kind that catches the error.
Chapter 26 §26.5 is the full autopsy of this bug in a real algorithm. You will get there.
Product states
A state that factorizes as $|a\rangle \otimes |b\rangle$ is a product state. Both qubits have their own state; knowing one tells you nothing about the other.
qc = QuantumCircuit(2)
qc.h(0)
qc.h(1)
sv = Statevector(qc)
print(sv.data.real)
print({k: round(v, 4) for k, v in sv.probabilities_dict().items()})
[0.5 0.5 0.5 0.5]
{'00': 0.25, '01': 0.25, '10': 0.25, '11': 0.25}
Four equally likely outcomes. Note that this state is describable with four numbers total (two per qubit) even though it has four amplitudes — because the amplitudes are just products: $0.5 = 0.7071 \times 0.7071$ in every case.
That is the crucial economy. A product state of $n$ qubits needs only $2n$ numbers, and is therefore trivially simulable no matter how large $n$ is. The exponential cost only arrives when the state does not factorize — and making it not factorize is what CNOT is for.
📐 Math Aside — Why the tensor product multiplies, and how thin the product states are.
The tensor product of an $m$-dimensional space with an $n$-dimensional space has dimension $mn$, not $m + n$. The reason is the basis: if $\{|i\rangle\}$ spans the first and $\{|j\rangle\}$ spans the second, the products $|i\rangle \otimes |j\rangle$ span the combination, and there are $mn$ of those pairs. Two qubits give $2 \times 2 = 4$ basis states and therefore four amplitudes; ten give $2^{10} = 1{,}024$.
Addition is what the classical case does. Two classical bits have two settings each and you record two numbers; $n$ bits need $n$ numbers. The switch from $+$ to $\times$ is the entire difference between the two machines, and it happens right here, in the definition of how states compose.
Now count free parameters, which is where §4.1's economy becomes stark. An $n$-qubit pure state has $2^n$ complex amplitudes — that is $2^{n+1}$ real numbers — minus one for normalization and one for the physically irrelevant global phase. A product state needs two real parameters per qubit, the two angles of Chapter 3's Bloch sphere:
$$\text{general: } 2^{n+1} - 2 \qquad \text{versus} \qquad \text{product: } 2n$$
text n general state product state 2 6 4 10 2,046 20 50 2,251,799,813,685,246 100At two qubits the gap is two numbers, which sounds like a detail. At fifty it is fifteen orders of magnitude. The product states are a vanishingly thin sliver of the state space — formally a set of measure zero — which is the precise sense in which a state picked at random is entangled essentially always. Unentangled is the special case, not the default.
That is good news and bad news in the same sentence. The space a quantum computer works in is enormous; and reaching a generic point in it takes as much circuit as its description takes to write down. Part IV is largely the story of algorithms that get somewhere useful without paying that price.
4.2 CNOT
The controlled-NOT gate takes two qubits, a control and a target, and flips the target if and only if the control is 1.
On basis states it is simple bookkeeping:
Input q1 q0 |
Output after cx(0, 1) |
Why |
|---|---|---|
00 |
00 |
control (q0) is 0 → nothing |
01 |
11 |
control is 1 → flip target (q1) |
10 |
10 |
control is 0 → nothing |
11 |
01 |
control is 1 → flip target |
from qiskit.quantum_info import Statevector
for label in ("00", "01", "10", "11"):
qc = QuantumCircuit(2)
qc.initialize(Statevector.from_label(label))
qc.cx(0, 1)
out = Statevector(qc).probabilities_dict()
print(f" {label} -> {max(out, key=out.get)}")
00 -> 00
01 -> 11
10 -> 10
11 -> 01
Note the second row: input 01 (meaning $q_1=0$, $q_0=1$) becomes 11. The control $q_0$ was 1, so
the target $q_1$ flipped. Little-endian again.
The matrix
from qiskit.quantum_info import Operator
qc = QuantumCircuit(2)
qc.cx(0, 1)
print(Operator(qc).data.real)
[[1. 0. 0. 0.]
[0. 0. 0. 1.]
[0. 0. 1. 0.]
[0. 1. 0. 0.]]
If you were expecting the familiar textbook CNOT
$$\begin{pmatrix}1&0&0&0\\0&1&0&0\\0&0&0&1\\0&0&1&0\end{pmatrix}$$
you get that one from cx(1, 0) — control on qubit 1, target on qubit 0:
qc = QuantumCircuit(2)
qc.cx(1, 0)
print(Operator(qc).data.real)
[[1. 0. 0. 0.]
[0. 1. 0. 0.]
[0. 0. 0. 1.]
[0. 0. 1. 0.]]
Both matrices are correct CNOTs. They differ only in which qubit is the control, and the apparent discrepancy with the textbook is entirely the endianness convention. This is the single most confusing consequence of little-endian ordering and it is worth doing once by hand until it stops being surprising.
The interesting case: CNOT on a superposition
Basis states are bookkeeping. The gate becomes interesting when the control is in superposition, because then it acts on both branches at once:
qc = QuantumCircuit(2)
qc.h(0) # control into superposition
print("before cx:", Statevector(qc).data.real)
qc.cx(0, 1)
print("after cx: ", Statevector(qc).data.real)
before cx: [0.7071 0.7071 0. 0. ]
after cx: [0.7071 0. 0. 0.7071]
Before the CNOT: amplitude on indices 0 and 1, which are '00' and '01'. Qubit 0 is in
superposition, qubit 1 is firmly 0.
After the CNOT: amplitude on indices 0 and 3, which are '00' and '11'. That is
$\tfrac{1}{\sqrt2}(|00\rangle + |11\rangle)$ — the Bell state, in two gates.
⚠️ Common Pitfall — Which index lights up tells you which qubit, and it is easy to get backwards.
Compare the two single-Hadamard circuits:
python h0 = QuantumCircuit(2); h0.h(0) h1 = QuantumCircuit(2); h1.h(1) print("h(0):", Statevector(h0).data.real, Statevector(h0).probabilities_dict()) print("h(1):", Statevector(h1).data.real, Statevector(h1).probabilities_dict())
text h(0): [0.7071 0.7071 0. 0. ] {'00': 0.5, '01': 0.5} h(1): [0.7071 0. 0.7071 0. ] {'00': 0.5, '10': 0.5}
h(0)lights up index 1;h(1)lights up index 2. If you expected the reverse — and plenty of people carrying textbook conventions do — every subsequent index calculation you make will be wrong, silently, in a way that survives every test written with a symmetric state.Use
probabilities_dict()when the index needs a semantic reading. Bitstring labels cannot be misinterpreted; integer indices require you to redo endianness arithmetic correctly every single time. Reserve raw arrays for numerical work — inner products, fidelities, norms — where the index carries no meaning.⚛️ The Physics Underneath — Why CNOT entangles.
Before the CNOT, the state is $\tfrac{1}{\sqrt2}(|00\rangle + |01\rangle)$, which factorizes: it equals $|0\rangle_{q_1} \otimes \tfrac{1}{\sqrt2}(|0\rangle + |1\rangle)_{q_0}$. Qubit 1 is definitely 0; qubit 0 is in superposition. Two independent qubits.
CNOT acts linearly on that superposition, flipping $q_1$ only in the branch where $q_0 = 1$:
$$\tfrac{1}{\sqrt2}(|00\rangle + |01\rangle) \;\longrightarrow\; \tfrac{1}{\sqrt2}(|00\rangle + |11\rangle)$$
And that does not factorize. There is no pair of single-qubit states $|a\rangle, |b\rangle$ with $|a\rangle \otimes |b\rangle = \tfrac{1}{\sqrt2}(|00\rangle + |11\rangle)$ — try it: you would need $a_0 b_1 = 0$ and $a_1 b_0 = 0$ while $a_0 b_0 \neq 0$ and $a_1 b_1 \neq 0$, which is impossible.
That impossibility is entanglement. It is not a stronger correlation; it is a state that has no description as "this qubit is doing X and that one is doing Y."
4.3 The Bell State
Two gates, and the most important two-qubit state in quantum computing:
qc = QuantumCircuit(2)
qc.h(0)
qc.cx(0, 1)
print(qc.draw())
print(Statevector(qc).probabilities_dict())
┌───┐
q_0: ┤ H ├──■──
└───┘┌─┴─┐
q_1: ─────┤ X ├
└───┘
{'00': 0.4999999999999999, '11': 0.4999999999999999}
$|\Phi^+\rangle = \tfrac{1}{\sqrt2}(|00\rangle + |11\rangle)$. Half the time both qubits read 0, half the time both read 1, and never one of each.
The correlation is perfect and it is symmetric: measure either qubit first, in either order, and the other is immediately determined. There is no "first" — the qubits could be in different buildings.
What is and is not remarkable about this
The unremarkable part: perfect correlation is easy classically. Put two red balls in two boxes, ship them apart, open one, and you know the other. No physics required.
The remarkable part is that the correlation persists in every measurement basis, which classical correlation cannot do. That is Chapter 5's material and the foundation of Bell's theorem, and it is why $|\Phi^+\rangle$ is not just "two coins glued together."
For now, the operational version of the claim: measure both qubits in the $X$ basis (apply H to each before measuring) and you will still find perfect correlation. Do that to two classically correlated balls and the correlation vanishes.
qc = QuantumCircuit(2, 2)
qc.h(0)
qc.cx(0, 1)
qc.h(0) # rotate both into the X basis before measuring
qc.h(1)
qc.measure([0, 1], [0, 1])
# still only '00' and '11'
Try it. Then try it with qc.h(0) only on one qubit and watch the correlation break. §4.5 explains
which Bell state survives which basis change, and Chapter 5 §5.6 makes basis changes systematic.
4.4 Is It Entangled? An Operational Test
"Are these qubits entangled?" is a question you will ask constantly, and it cannot be answered from
measurement counts alone — the product state H⊗H and the Bell state both produce two or four
outcomes with equal probabilities, and telling them apart from counts requires measuring in more
than one basis.
There is a much better test available in simulation. Look at one qubit by itself.
If a two-qubit state factorizes, then qubit 0 has a state of its own and you can extract it. If the state is entangled, qubit 0 has no state of its own, and what you extract is a mixed state — a statistical mixture rather than a definite quantum state.
import numpy as np
from qiskit.quantum_info import Statevector, partial_trace, entropy
def entanglement_report(qc, label):
sv = Statevector(qc)
rho0 = partial_trace(sv, [1]) # trace out qubit 1, keep qubit 0
purity = float(np.real(np.trace(rho0.data @ rho0.data)))
ent = float(entropy(rho0))
paulis = [np.array([[0, 1], [1, 0]]),
np.array([[0, -1j], [1j, 0]]),
np.array([[1, 0], [0, -1]])]
bloch = [float(np.real(np.trace(rho0.data @ P))) for P in paulis]
print(f"{label:<24} purity {purity:.4f} entropy {ent:.4f} "
f"|Bloch| {np.linalg.norm(bloch):.4f}")
product = QuantumCircuit(2)
product.h(0)
product.h(1)
bell = QuantumCircuit(2)
bell.h(0)
bell.cx(0, 1)
entanglement_report(product, "product H(0) H(1)")
entanglement_report(bell, "entangled Bell")
product H(0) H(1) purity 1.0000 entropy 0.0000 |Bloch| 1.0000
entangled Bell purity 0.5000 entropy 1.0000 |Bloch| 0.0000
Three numbers, three ways of saying the same thing.
Purity 1.0 versus 0.5. Purity is $\mathrm{Tr}(\rho^2)$: it is 1 for a definite quantum state and drops to $1/d$ for a maximally mixed one. Qubit 0 of the product state is a definite state; qubit 0 of the Bell state is maximally mixed — 0.5 is the floor for a single qubit.
Entropy 0.0 versus 1.0. The entanglement entropy, in bits. Zero means "no entanglement"; 1.0 is the maximum for a single qubit. The Bell state is maximally entangled.
Bloch vector length 1.0 versus 0.0. This is the one to visualize. Chapter 3 §3.4 warned that the Bloch sphere fails for entangled states, and here is precisely how: qubit 0 of the Bell state has a Bloch vector of length zero. It is at the center of the sphere, pointing nowhere.
⚛️ The Physics Underneath — A qubit at the center of the Bloch sphere.
The surface of the Bloch sphere is the pure states. The interior is mixed states, which are probability distributions over pure states rather than states themselves. The exact center is the maximally mixed state: 50% $|0\rangle$, 50% $|1\rangle$, with no phase relationship at all.
Qubit 0 of a Bell state, considered on its own, is exactly that. It is not "in superposition" — superposition is a pure state with definite phases, and this has none. It is genuinely random.
And yet the pair is in a perfectly definite, pure, zero-entropy state. All the information is in the correlation and none of it is in the parts.
This is the single most counterintuitive fact in quantum information, and it is the actual content of the word "entangled." A joint state that is completely specified while both of its parts are completely undetermined has no classical analogue whatsoever.
The practical version
For everyday use, one number suffices:
def is_entangled(qc, tol=1e-9):
"""True if the two-qubit circuit's output state is entangled."""
return float(entropy(partial_trace(Statevector(qc), [1]))) > tol
You will want this constantly, and the Chapter 4 project checkpoint adds a general version that handles more than two qubits.
📐 Math Aside — ★ One number produces all three: the concurrence $C = 2|ad - bc|$.
Write a two-qubit pure state in Qiskit's ordering,
$$|\psi\rangle = a\,|00\rangle + b\,|01\rangle + c\,|10\rangle + d\,|11\rangle$$
and lay the amplitudes out as a matrix whose row index is $q_1$ and whose column index is $q_0$:
$$M = \begin{pmatrix} a & b \\ c & d \end{pmatrix}$$
Then the reduced state of qubit 1 is exactly $\rho_1 = M M^\dagger$, and qubit 0's is $(M^\dagger M)^{\mathsf T}$ — the two have the same eigenvalues, which is why §4.4's table does not care which qubit you keep. Let $s_1, s_2$ be the singular values of $M$. Normalization forces $s_1^2 + s_2^2 = 1$, and the eigenvalues of either reduced state are $s_1^2$ and $s_2^2$. So
$$\mathrm{Tr}(\rho^2) \;=\; s_1^4 + s_2^4 \;=\; (s_1^2 + s_2^2)^2 - 2 s_1^2 s_2^2 \;=\; 1 - 2\,(s_1 s_2)^2$$
and $s_1 s_2 = |\det M| = |ad - bc|$. Define the concurrence
$$C \;=\; 2\,|ad - bc|$$
and the three numbers measured above stop being three separate facts. They are one fact written three ways:
$$\text{purity} = 1 - \tfrac{C^2}{2}, \qquad |\vec r\,| = \sqrt{1 - C^2}, \qquad > \lambda_\pm = \tfrac{1 \pm \sqrt{1 - C^2}}{2}$$
with the entanglement entropy being the binary entropy of $\lambda_\pm$. Put $C = 0$ in and you get purity 1, Bloch length 1, entropy 0. Put $C = 1$ in and you get purity 0.5, Bloch length 0, entropy 1. Those are exactly the two rows printed above, now derived instead of measured.
Why a determinant? Because a product state's amplitude matrix is an outer product, $M = (\alpha, \beta)^{\mathsf T}(\gamma, \delta)$, which has rank one, so $\det M = 0$ identically. Entanglement is the failure of that determinant to vanish, and the concurrence measures how badly it fails.
Run §4.5's four Bell states through it and every one gives $|ad - bc| = 0.5$:
text state amplitudes (a, b, c, d) ad - bc C Phi+ [ 0.7071, 0.0000, 0.0000, 0.7071] +0.5000 1.0000 Phi- [ 0.7071, 0.0000, 0.0000, -0.7071] -0.5000 1.0000 Psi+ [ 0.0000, 0.7071, 0.7071, 0.0000] -0.5000 1.0000 Psi- [ 0.0000, -0.7071, 0.7071, 0.0000] +0.5000 1.0000All four are maximally entangled and the signs make no difference to $C$, which is the algebraic content of the claim §4.5 is about to make in words.
Two practical notes. First, the implementation is one line and you should keep it:
python def concurrence(sv): """Two-qubit PURE-state concurrence: 0 for any product state, 1 for any Bell state.""" a, b, c, d = np.asarray(sv) return float(2 * abs(a * d - b * c))Second — and this is the one piece of good news about little-endian in the entire chapter — $C$ is immune to the ordering convention. Relabelling which qubit is which swaps $b$ and $c$, and $ad - cb = ad - bc$. Of everything here, the entanglement measure is the single quantity you cannot get wrong by reading the bitstring backwards.
The formula is for pure states only. Once noise enters, the state is mixed, and the right generalization is Wootters' concurrence, which needs the eigenvalues of a spin-flipped product — more work, same name. On hardware you will not have the statevector anyway; use a witness instead, which is what Case Study 2 builds.
⚠️ Common Pitfall — Entanglement is not the same as correlation in the counts.
Two circuits, both producing exactly
{'00': 50%, '11': 50%}in the computational basis:```python
Entangled: no measurement anywhere; the correlation is quantum.
bell = QuantumCircuit(2, 2) bell.h(0) bell.cx(0, 1) bell.measure([0, 1], [0, 1])
NOT entangled: measure qubit 0, then classically flip qubit 1 to match.
classical = QuantumCircuit(2, 2) classical.h(0) classical.measure(0, 0) with classical.if_test((classical.clbits[0], 1)): # Ch. 9 covers this syntax classical.x(1) classical.measure(1, 1) ```
The second circuit contains no entanglement at all — the measurement destroyed the superposition, and everything after it is classical control. Yet the counts are identical:
text Z basis, entangled : {'00': 2074, '11': 2022} Z basis, classical : {'00': 2031, '11': 2065}The distinguishing experiment requires a second measurement basis. Insert
hon both qubits immediately before measuring, and the two circuits separate completely:
text X basis, entangled : {'00': 2074, '11': 2022} <- still perfectly correlated X basis, classical : {'00': 1039, '01': 1037, '10': 992, '11': 1028} <- correlation goneThat is the experiment. The Bell state's correlation survives the basis change; the classical one evaporates into uniform noise. This is the operational content of the claim in §4.3 that quantum correlation is a different kind of thing, and it is a two-line change to a circuit you have already written. Chapter 5 §5.6 makes basis changes systematic, and Chapter 30 turns this into a quantitative entanglement witness.
Never infer entanglement from computational-basis counts. It is the most common overclaim in student write-ups and it appears in some published work.
What a population table cannot see
The impostor above used a mid-circuit measurement, which lets the trick feel like a technicality — as
though a purely unitary circuit could not fool you the same way. It can, and the sharpest
demonstration is a pair of circuits that differ by exactly one gate. Both use only gates you already
have; cz is §4.6's, one section ahead.
uniform = QuantumCircuit(2)
uniform.h(0)
uniform.h(1)
twin = QuantumCircuit(2)
twin.h(0)
twin.h(1)
twin.cz(0, 1) # the only difference
circuit amplitudes populations
H(0) H(1) [ 0.5 0.5 0.5 0.5] all four outcomes at 0.25
H(0) H(1) CZ(0,1) [ 0.5 0.5 0.5 -0.5] all four outcomes at 0.25
Identical population tables, to every decimal place, at any shot count you could ever afford. Now apply the reduced-state test and the concurrence:
circuit C purity |Bloch| entropy
H(0) H(1) 0.0000 1.0000 1.0000 0.0000
H(0) H(1) CZ(0,1) 1.0000 0.5000 0.0000 1.0000
One of them is a product state and the other is maximally entangled — as entangled as
$|\Phi^+\rangle$, and indeed it is $|\Phi^+\rangle$ dressed in local Hadamards. The whole
difference is a minus sign on the 11 amplitude, and a population table cannot see a sign.
📊 What the Numbers Say — Why one basis can never be enough, counted exactly.
This is not bad luck about one pair of circuits. It is arithmetic, and the arithmetic is short.
A two-qubit pure state has $2^{2+1} - 2 = 6$ real parameters (§4.1's Math Aside). A computational-basis histogram gives you four probabilities constrained to sum to 1, so three independent numbers. Half of the state is invisible to that measurement, and no number of shots changes that — shots reduce the error bars on the three numbers you can see.
Look at where $C$ lives to see which half is missing. $C = 2|ad - bc|$ depends on the relative phases of the amplitudes, which is precisely what $|a|^2, |b|^2, |c|^2, |d|^2$ discards. Pin all four populations at $1/4$ and $C$ still sweeps its whole range: $(\tfrac12,\tfrac12,\tfrac12,\tfrac12)$ gives $ad - bc = \tfrac14 - \tfrac14 = 0$, and flipping a single sign to $(\tfrac12,\tfrac12,\tfrac12,-\tfrac12)$ gives $-\tfrac14 - \tfrac14 = -\tfrac12$, hence $C = 1$. The measurement is constant over the entire range of the thing being asked about.
An $X$-basis measurement buys three more numbers, which is exactly why the two-basis experiment in the pitfall above separates the circuits. Collecting all six is state tomography — $3^n$ measurement settings for $n$ qubits — and that exponential is why nobody tomographs anything large, and why entanglement witnesses exist at all. Case Study 2 builds one: $W = \langle ZZ\rangle + \langle XX\rangle$, which no separable state can push above 1, measured at 2.0000 for an ideal Bell state, 0.9966 for the impostor, and 1.9307 for a Bell state on a device-derived noise model. Twenty thousand random product states got no higher than 0.9980.
The general form is one of the most useful sentences in Part V: a measurement that cannot vary with the thing you are asking about is not evidence about it, and more of it is still not evidence. Chapter 27 §27.4 turns that into a testing discipline; you have now seen it at two qubits, which is the earliest it can possibly be shown.
🐛 Debug This — the equivalence check that could not fail.
This one is not hypothetical, and it is not a student's. It happened in this book's own source.
Chapter 17 §17.4 builds a Bell state from a trapped-ion native gate set and verifies it against the familiar
H+CNOTversion by comparing output populations:
python np.allclose(np.sort(p_logical), np.sort(p_native), atol=1e-6) # prints TrueIt printed
True. The circuit was wrong.
text circuit populations concurrence H + CNOT [0.5, 0.0, 0.0, 0.5] 1.0000 the "native equivalent" [0.5, 0.5, 0.0, 0.0] 0.0000$[0.5, 0, 0, 0.5]$ is a Bell state. $[0.5, 0.5, 0, 0]$ is qubit 0 in superposition with qubit 1 sitting in $|0\rangle$ — a product state, concurrence exactly zero. Those two states are about as different as two-qubit states get, and they sort to the same list.
np.sortkeeps how much weight there is and throws away which outcomes carry it, so the comparison was invariant under precisely the difference it was written to detect. Delete the sort and it fails on the first run.Two things went wrong and only one of them was the sort. The file's comment then attributed the mismatch to "a global/relative phase convention" — a plausible explanation that arrived before the check was audited, and stopped the search. The phases were fine. The entanglement was gone.
The fix is the one-liner from the Math Aside above:
python assert abs(concurrence(sv_native) - concurrence(sv_logical)) < 1e-9One number, computed from four amplitudes, and it separates the two states immediately. When you are checking that a circuit still does the thing it exists to do, assert on a quantity that changes when that thing breaks. A population comparison is a fine check for population bugs. It is not a check for entanglement, and it will keep passing, indefinitely and cheerfully, while the entanglement is missing.
4.5 The Other Three Bell States
$|\Phi^+\rangle$ has three siblings. All four are maximally entangled, all four are mutually orthogonal, and together they form a basis for the two-qubit space.
def bell_state(kind: str) -> QuantumCircuit:
"""kind in {'Phi+', 'Phi-', 'Psi+', 'Psi-'}"""
qc = QuantumCircuit(2)
if kind in ("Psi+", "Psi-"):
qc.x(1)
qc.h(0)
if kind in ("Phi-", "Psi-"):
qc.z(0)
qc.cx(0, 1)
return qc
for kind in ("Phi+", "Phi-", "Psi+", "Psi-"):
sv = Statevector(bell_state(kind))
probs = {k: round(v, 3) for k, v in sv.probabilities_dict().items()}
print(f"{kind}: {sv.data.real.round(4)} {probs}")
Phi+: [0.7071 0. 0. 0.7071] {'00': 0.5, '11': 0.5}
Phi-: [ 0.7071 0. 0. -0.7071] {'00': 0.5, '11': 0.5}
Psi+: [0. 0.7071 0.7071 0. ] {'01': 0.5, '10': 0.5}
Psi-: [ 0. -0.7071 0.7071 0. ] {'01': 0.5, '10': 0.5}
$$|\Phi^\pm\rangle = \tfrac{1}{\sqrt2}(|00\rangle \pm |11\rangle), \qquad |\Psi^\pm\rangle = \tfrac{1}{\sqrt2}(|01\rangle \pm |10\rangle)$$
$\Phi$ versus $\Psi$ is visible in the counts — same outcomes or opposite outcomes. The $\pm$ is not. $|\Phi^+\rangle$ and $|\Phi^-\rangle$ give identical computational-basis statistics and are orthogonal states, exactly as $|+\rangle$ and $|-\rangle$ were in Chapter 3.
This is Chapter 3 §3.5's lesson repeated one level up, and it matters more here. Distinguishing all four Bell states — a Bell measurement — requires undoing the entangling circuit before measuring:
def bell_measure(qc: QuantumCircuit) -> QuantumCircuit:
"""Append the inverse of the Bell preparation, so the four Bell states
map to the four computational basis states."""
qc.cx(0, 1)
qc.h(0)
return qc
Run each of the four Bell states through that and you get 00, 01, 10, 11 deterministically —
the four states become distinguishable because you rotated into the basis where they differ.
Bell measurement is a load-bearing primitive. It is how quantum teleportation works (Chapter 9 §9.3), how superdense coding works (§9.4), and how entanglement swapping works. The pattern — rotate into the basis where your states differ, then measure — is the same one from Chapter 3 §3.5 and it will keep recurring.
4.6 The Rest of the Two-Qubit Vocabulary
CZ — controlled-Z
Applies a phase of $-1$ to the $|11\rangle$ component and nothing else.
from qiskit.circuit.library import CZGate
import numpy as np
print(Operator(CZGate()).data.real)
print("symmetric:", np.allclose(Operator(CZGate()).data, Operator(CZGate()).data.T))
[[ 1. 0. 0. 0.]
[ 0. 1. 0. 0.]
[ 0. 0. 1. 0.]
[ 0. 0. 0. -1.]]
symmetric: True
CZ is symmetric — there is no distinction between control and target, which CNOT does not share.
That symmetry makes it the natural native gate on some hardware, and it is why you will meet devices
whose basis contains cz rather than cx or ecr.
The two are related by a basis change on the target:
qc = QuantumCircuit(2)
qc.h(1)
qc.cx(0, 1)
qc.h(1)
print("H(1) CX(0,1) H(1) == CZ:", Operator(qc).equiv(Operator(CZGate())))
H(1) CX(0,1) H(1) == CZ: True
Because $HXH = Z$ (Chapter 3 §3.8), conjugating the target of a CNOT by H turns the controlled-X into a controlled-Z. Sandwich identities like this one are the transpiler's bread and butter, and Chapter 10 shows the machinery.
SWAP — and its real price
from qiskit.circuit.library import SwapGate
qc = QuantumCircuit(2)
qc.cx(0, 1)
qc.cx(1, 0)
qc.cx(0, 1)
print("three CNOTs == SWAP:", Operator(qc).equiv(Operator(SwapGate())))
three CNOTs == SWAP: True
A SWAP costs three CNOTs. Memorize that number.
It matters far more than it looks, because you rarely write swap yourself. The transpiler inserts
SWAPs, automatically and invisibly, whenever your circuit needs a two-qubit gate between qubits that
are not physically connected — and on hardware with sparse connectivity, that is most of the time.
Every inserted SWAP costs three of your most expensive, noisiest operations.
This is the single largest hidden cost in quantum programming, and it is why Chapter 10 (routing) and Chapter 29 (layout) exist.
📐 Math Aside — Where the three comes from, and what it multiplies into downstream.
Why three works. Take a basis state $|q_1 q_0\rangle = |x\,y\rangle$ and follow it through
cx(0,1),cx(1,0),cx(0,1), writing the pair as $(q_1, q_0)$ at each step:$$(x,\; y) \;\to\; (x \oplus y,\; y) \;\to\; (x \oplus y,\; y \oplus x \oplus y) > \;\to\; (x \oplus y \oplus x,\; x) \;=\; (y,\; x)$$
That is the classical three-XOR swap — the trick you have written in C to exchange two integers without a temporary. The quantum SWAP is the same trick, and it is reversible for the same reason. Linearity carries it from basis states to every superposition, which is why checking the four rows is enough.
Why two does not work. On two qubits there are exactly two CNOTs available, so there are exactly four words of length two, and you can simply check all of them:
text cx(0,1) cx(0,1) == SWAP? False (they cancel — the identity) cx(0,1) cx(1,0) == SWAP? False cx(1,0) cx(0,1) == SWAP? False cx(1,0) cx(1,0) == SWAP? False (they cancel — the identity) cx(0,1) cx(1,0) cx(0,1) == SWAP? TrueAn exhaustive search over a four-element set is a proof, not a spot check, and it is Exercise 4.11(c). The stronger statement — that three CNOTs are needed even when you may interleave arbitrary single-qubit gates between them — is a real theorem rather than a case analysis, and it is what makes three a floor rather than merely the best decomposition anyone has published.
What it multiplies into. Two qubits that must interact but sit $d$ hops apart on the coupling graph have to be walked together first: $d - 1$ SWAPs to make them adjacent, and $2(d-1)$ if you also have to walk them home afterwards. In CNOTs, at three apiece:
text distance d SWAPs needed CNOTs (leave permuted) CNOTs (restore layout) 1 0 0 0 2 1 3 6 3 2 6 12 5 4 12 24Set that against the table below. A C4X costs 36 CNOTs — measured, but measured with
basis_gatesand no coupling map, which means any pair of the five qubits was allowed to interact. On a lattice of degree 3, five qubits cannot be mutually adjacent; a qubit has at most three neighbours. So some of those 36 CNOTs will inevitably connect non-neighbours, and the router will charge for each one. This predicts an on-device count above 36, by an amount that scales with the graph distances rather than with the gate — which is exactly why the table says lower bounds.The gate count you compute on a fully connected simulator is the optimistic half of the bill. Chapter 10 shows the router doing the arithmetic, and Chapter 29 shows how much of it a better starting layout saves.
Toffoli — and why three-qubit gates hurt
The Toffoli (CCX) flips its target when both controls are 1. It is universal for classical reversible computation, which makes it the workhorse of oracle construction in Chapter 19.
It is also expensive:
qc = QuantumCircuit(3)
qc.ccx(0, 1, 2)
for basis in (["cx", "u"], ["ecr", "rz", "sx", "x"]):
t = transpile(qc, basis_gates=basis, optimization_level=3)
print(f" {str(basis):<26} {dict(t.count_ops())} depth {t.depth()}")
['cx', 'u'] {'u': 8, 'cx': 6} depth 11
['ecr', 'rz', 'sx', 'x'] {'rz': 19, 'sx': 8, 'ecr': 6, 'x': 5} depth 26
One Toffoli costs six two-qubit gates. And that is with all-to-all connectivity assumed — on a real device where the three qubits are not mutually adjacent, routing adds SWAPs on top.
💰 Cost and Queue — The two-qubit budget, made concrete.
Chapter 1 §1.5 said your budget is a few hundred two-qubit gates. Here is what that buys:
Measured by transpiling each into a
["cx", "u"]basis at optimization level 3 — so these are lower bounds, assuming all-to-all connectivity:
Construct CNOTs Depth CNOT, CZ 1 1 SWAP 3 3 Toffoli (CCX) 6 11 3-controlled X (C3X) 14 28 4-controlled X (C4X) 36 65 any of the above, non-adjacent qubits + 3 per inserted SWAP + Look at that growth. Going from two controls to four multiplies the cost by six, and none of it includes routing. A Grover oracle for a 4-bit condition needs multi-controlled gates of exactly this kind, which is tens of two-qubit gates before the algorithm proper has started — against a budget of a few hundred.
This is why Chapter 19 says the oracle is the hard part, and it is the arithmetic behind every 🔬 Honest Assessment in Part IV. It is also why ancilla-based constructions matter: trading qubits for gates is usually the right trade on hardware where depth kills you first.
4.7 Three Qubits and Up: GHZ and W
Entanglement on three or more qubits is not one thing. There are genuinely different kinds, and the two representatives everyone uses are GHZ and W.
GHZ — the straightforward generalization
def ghz(n: int) -> QuantumCircuit:
qc = QuantumCircuit(n)
qc.h(0)
for i in range(n - 1):
qc.cx(i, i + 1)
return qc
print(Statevector(ghz(3)).probabilities_dict())
{'000': 0.4999999999999999, '111': 0.4999999999999999}
$|\mathrm{GHZ}_3\rangle = \tfrac{1}{\sqrt2}(|000\rangle + |111\rangle)$: all zeros or all ones, never anything else. The natural extension of the Bell state, and it scales to any $n$ with $n-1$ CNOTs.
W — a different kind of entanglement
$$|W_3\rangle = \tfrac{1}{\sqrt3}\bigl(|001\rangle + |010\rangle + |100\rangle\bigr)$$
Exactly one qubit is 1, and which one is undetermined.
import numpy as np
w = QuantumCircuit(3)
w.ry(2 * np.arccos(1 / np.sqrt(3)), 0)
w.ch(0, 1)
w.cx(1, 2)
w.cx(0, 1)
w.x(0)
print({k: round(v, 4) for k, v in Statevector(w).probabilities_dict().items()})
{'001': 0.3333, '010': 0.3333, '100': 0.3333}
Note the $\arccos(1/\sqrt3)$ — this is Chapter 3's half-angle machinery doing real work, splitting amplitude one-third/two-thirds so the subsequent controlled gates can distribute the rest evenly.
The difference that matters: losing a qubit
GHZ and W are both genuinely three-party entangled, and they are not convertible into each other by local operations. The cleanest way to see the difference is to ask what survives if you lose one qubit.
from qiskit.quantum_info import partial_trace, entropy
for label, qc in (("GHZ", ghz(3)), ("W", w)):
rho = partial_trace(Statevector(qc), [2]) # discard qubit 2
print(f" {label}: entropy of the remaining pair = {float(entropy(rho)):.4f}")
GHZ: entropy of the remaining pair = 1.0000
W: entropy of the remaining pair = 0.9183
Both non-zero, but the interesting fact is what the remaining pair can do, not the entropy number alone.
GHZ is fragile. Lose one qubit of a GHZ state and the remaining two are left in a classically correlated mixture — 50% $|00\rangle$, 50% $|11\rangle$ — with no entanglement between them at all. The three-way entanglement was all-or-nothing.
W is robust. Lose one qubit of a W state and the remaining two are still entangled, just less so. The entanglement is distributed pairwise rather than concentrated in a global correlation.
That trade-off is real and consequential. GHZ states are maximally sensitive, which makes them excellent for metrology and for detecting decoherence — and terrible for anything that must survive qubit loss. W states are the reverse. Chapter 30's benchmarks use GHZ states precisely because they are fragile: a fragile state is a sensitive instrument.
🧱 Project Checkpoint —
circuits.pyv1: the two-qubit entangling block.The project's ansatz gets its real shape. A variational ansatz alternates rotation layers (single-qubit, parameterized) with entangling layers (two-qubit, fixed):
python def two_qubit_ansatz(thetas=None) -> QuantumCircuit: """Rotation layer, entangling layer, rotation layer. Four parameters.""" thetas = ParameterVector("θ", 4) if thetas is None else thetas qc = QuantumCircuit(2, name="ansatz2") qc.ry(thetas[0], 0) qc.ry(thetas[1], 1) qc.cx(0, 1) # the entangling layer qc.ry(thetas[2], 0) qc.ry(thetas[3], 1) return qcWhy this shape? Because without the CNOT the two qubits stay in a product state forever, and a product-state ansatz can only represent product-state solutions — which for a molecular ground state is exactly wrong, since correlation between electrons is the entire problem VQE exists to solve.
The checkpoint file also adds
is_entangled(circuit), generalized to any number of qubits and any bipartition. You will use it to confirm that your ansatz can actually reach entangled states, which is the first thing to check when a VQE refuses to converge.
4.8 The Exponential Wall, Concretely
Chapter 1 §1.4 stated the $2^n$ scaling. Now you can see where it comes from.
Each qubit you add doubles the number of amplitudes, because the tensor product multiplies dimensions: $2 \times 2 \times \cdots$. There is no way around it for a general state.
for n in (1, 2, 10, 20, 30, 40, 50):
amps = 2 ** n
gib = amps * 16 / 2**30
print(f"{n:>3} qubits: {amps:>20,d} amplitudes {gib:>14,.3f} GiB")
1 qubits: 2 amplitudes 0.000 GiB
2 qubits: 4 amplitudes 0.000 GiB
10 qubits: 1,024 amplitudes 0.000 GiB
20 qubits: 1,048,576 amplitudes 0.016 GiB
30 qubits: 1,073,741,824 amplitudes 16.000 GiB
40 qubits: 1,099,511,627,776 amplitudes 16,384.000 GiB
50 qubits: 1,125,899,906,842,624 amplitudes 16,777,216.000 GiB
Sixteen bytes per amplitude, because a complex number is two 64-bit floats. Read the last three rows slowly. Thirty qubits fits in 16 GiB, which is a laptop. Forty needs 16 TiB, which is a cluster. Fifty needs 16 PiB, which is not a machine anyone will build for this purpose. Every ten qubits multiplies the memory by roughly a thousand, and the wall lands between 40 and 50 for any budget whatsoever — a supercomputer buys you a handful of qubits, not an order of magnitude.
But the crucial refinement, which Chapter 1 could not give you yet:
Product states do not pay this cost. An $n$-qubit product state needs $2n$ numbers, not $2^n$. Ten thousand unentangled qubits simulate on a phone.
The cost is entanglement. The exponential arrives exactly when the state stops factorizing, and it arrives in proportion to how much entanglement there is. That is not a hand-wave — it is the precise basis of matrix product state simulation, which represents a state by its entanglement structure and can therefore handle hundreds of qubits as long as the entanglement stays low. Chapter 11 §11.5 implements it.
The consequence is one of the most important framings in the field:
A quantum algorithm that does not generate substantial entanglement is classically simulable and therefore cannot provide a quantum advantage.
Entanglement is not decoration. It is the resource, and any claim of quantum advantage that does not involve creating a lot of it should be treated with suspicion.
4.9 Entangled States on Hardware
Now the measurement. How well does an entangled state survive a real device, as it grows?
from qiskit_ibm_runtime.fake_provider import FakeSherbrooke
from qiskit_ibm_runtime import SamplerV2 as Sampler
from qiskit.transpiler.preset_passmanagers import generate_preset_pass_manager
backend = FakeSherbrooke()
pm = generate_preset_pass_manager(optimization_level=1, backend=backend, seed_transpiler=42)
for n in range(2, 7):
qc = QuantumCircuit(n, n)
qc.h(0)
for i in range(n - 1):
qc.cx(i, i + 1)
qc.measure(range(n), range(n))
isa = pm.run(qc)
sampler = Sampler(mode=backend)
sampler.options.simulator.seed_simulator = 1234
counts = sampler.run([isa], shots=4096).result()[0].data.c.get_counts()
correct = counts.get("0" * n, 0) + counts.get("1" * n, 0)
print(f" GHZ n={n}: depth {isa.depth():>3} 2q gates {dict(isa.count_ops()).get('ecr', 0):>2}"
f" correct fraction {correct / 4096:.4f}")
Run it out to eight qubits and something happens that is worth the whole section:
n | opt level 1 | physical qubits used
---|-------------|----------------------------------
2 | 0.9561 | [0, 1]
3 | 0.9290 | [0, 1, 2]
4 | 0.9084 | [0, 1, 2, 3]
5 | 0.8813 | [0, 1, 2, 3, 4]
6 | 0.8127 | [0, 1, 2, 3, 4, 5]
7 | 0.2148 | [0, 1, 2, 3, 4, 5, 6] <-- ???
8 | 0.1091 | [0, 1, 2, 3, 4, 5, 6, 7]
Six qubits: a smooth, believable decay. Seven qubits: the floor gives out. From 81% to 21% for one extra qubit and one extra gate.
That is not scaling. Something is broken, and finding out what is a two-minute investigation that will change how you use this hardware.
target = backend.target
for q in range(8):
print(f" q{q}: readout error {target['measure'][(q,)].error:.4f}")
for pair in [(1, 0), (1, 2), (3, 2), (4, 3), (5, 4), (6, 5), (7, 6)]:
e = target["ecr"].get(pair)
if e:
print(f" ecr{pair}: error {e.error:.4f}")
q5: readout error 0.0605
q6: readout error 0.2573 <-- 20x worse than its neighbours
...
ecr(5, 4): error 0.0100
ecr(6, 5): error 1.0000 <-- a gate error of ONE
Physical qubit 6 is broken on this device snapshot. Its readout error is 26%, and the entangling gate connecting it to qubit 5 has an error of 1.0 — a completely uncalibrated operation.
And the transpiler walked straight into it, because optimization level 1 assigns qubits by position and not by quality. The instant our chain grew long enough to reach qubit 6, the whole computation was destroyed.
The fix, and the lesson
Optimization level 3 chooses a layout using the device's error data, not its numbering. Same circuit, same shots, same seed — only the layout differs:
n | opt 1 | qubits (opt 1) | opt 3 | qubits (opt 3)
---|---------|-----------------|---------|-----------------------------------
2 | 0.9561 | [0, 1] | 0.9827 | [124, 123]
3 | 0.9290 | [0, 1, 2] | 0.9736 | [124, 123, 122]
4 | 0.9084 | [0, 1, 2, 3] | 0.9585 | [125, 124, 123, 122]
5 | 0.8813 | [0 ... 4] | 0.9309 | [122, 123, 124, 125, 126]
6 | 0.8127 | [0 ... 5] | 0.8850 | [125, 124, 123, 122, 121, 120]
7 | 0.2148 | [0 ... 6] | 0.8906 | [122, 123, 124, 125, 126, 112, 108]
8 | 0.1091 | [0 ... 7] | 0.8569 | [124, 123, 122, 121, 120, 119, 118, 110]
At eight qubits: 10.9% versus 85.7%. An eightfold difference in the correctness of the answer, from a circuit that is character-for-character identical. The only thing that changed is which physical qubits the compiler chose.
📉 Noise Report — Four things to take from this table.
The decay is real but gentle when the qubits are good. With a noise-aware layout, 98.3% at two qubits down to 85.7% at eight. Each added qubit costs one more entangling gate and one more readout, and the losses compound multiplicatively — a per-qubit factor around 0.98 here.
Hardware is not uniform, and it is not uniformly working. A 127-qubit processor is not 127 equivalent qubits. It is a population with a distribution of quality, and on any given day some members of that population are dead. Treating "the device has 127 qubits" as a capability statement is exactly the error Chapter 1 §1.5 warned about, now with a number attached.
The default is not safe. Optimization level 1 is a perfectly reasonable default and it produced a catastrophically wrong answer here. This is the strongest possible argument for Chapter 29: layout selection is not a compiler detail, it is a correctness concern.
The "correct fraction" is still a generous metric. It counts only all-zeros and all-ones. It does not verify coherence — a device producing a classical 50/50 mixture of $|00\ldots0\rangle$ and $|11\ldots1\rangle$, with no entanglement whatsoever, would score 100% on this test. §4.4's pitfall applies at every scale.
That last point deserves emphasis because it is a real and common error in write-ups: "I got
000and111and nothing else, therefore I made a GHZ state" is not valid. You made something whose computational-basis statistics are consistent with a GHZ state. Chapter 5 §5.6 tells you how to earn the stronger claim, and Chapter 30 tells you how to quantify it.🔬 Honest Assessment — What entanglement on hardware currently costs.
Preparing entangled states works. Preparing large entangled states with high fidelity is the central engineering challenge of the field, and it is what error correction exists to solve.
Extrapolating the good-layout column at its measured per-qubit factor of 0.978 — and that is optimistic, since a linear CNOT chain also grows in depth, so decoherence contributes more at each step — a 20-qubit GHZ state lands near 0.65 and a 50-qubit one near 0.33. Published high-fidelity GHZ-state records on superconducting hardware are genuine research contributions precisely because the difficulty compounds so quickly, and because the extrapolation above is too kind.
The implication for algorithm design is direct and it recurs throughout Part IV: circuits that require large-scale entanglement across many qubits are not currently runnable. The algorithms that do run today — the variational family — keep entanglement local and shallow. That is not a coincidence; it is the design constraint that produced them.
And the second implication is the one this section actually discovered: before you conclude anything about scaling, check that your qubits are alive. An unexplained cliff in a fidelity curve is far more often a broken component than a law of nature. The two-minute calibration query above is the first thing to run, and Chapter 12 §12.2 makes it routine.
4.10 Summary
Multi-qubit states compose with the tensor product. $n$ qubits have $2^n$ amplitudes, indexed by
bitstring, and Qiskit orders them little-endian:
$|q_{n-1}\rangle \otimes \cdots \otimes |q_0\rangle$, with qubit 0 last. This is the reverse of most
textbooks, and it makes the CNOT matrix look unfamiliar. Use probabilities_dict() rather than
raw index arithmetic, and test with asymmetric states, because symmetric ones hide the bug.
CNOT flips its target when its control is 1. On basis states that is bookkeeping; on a superposition it acts on both branches at once and produces a state that does not factorize. That non-factorizability is entanglement — not a stronger correlation, but a state with no description as "this qubit is doing X and that one is doing Y."
h(0); cx(0, 1) builds the Bell state $|\Phi^+\rangle$. The four Bell states are mutually
orthogonal and form a basis; $\Phi$ versus $\Psi$ is visible in the counts and the $\pm$ is not.
Distinguishing all four requires a Bell measurement — running the preparation backward before
measuring — which is the primitive behind teleportation and superdense coding.
Test for entanglement by looking at one qubit alone. Trace out the other and check the reduced state: purity 1 and Bloch length 1 mean a product state; purity 0.5, entropy 1, and Bloch length 0 mean maximal entanglement. An entangled qubit sits at the center of the Bloch sphere, pointing nowhere — completely undetermined on its own while the pair is in a completely definite state. All the information is in the correlation and none is in the parts.
Those three numbers are one number. For a two-qubit pure state $a|00\rangle + b|01\rangle + c|10\rangle + d|11\rangle$, the **concurrence** $C = 2|ad - bc|$ gives purity $= 1 - C^2/2$ and Bloch length $= \sqrt{1 - C^2}$; it is 0 for every product state, 1 for all four Bell states whatever their phases, and — uniquely in this chapter — immune to the endianness convention, since relabelling the qubits swaps $b$ and $c$ and leaves $ad - bc$ alone.
Never infer entanglement from computational-basis counts. A classically conditioned circuit
produces identical counts with no entanglement at all. So does a purely unitary one: h(0); h(1)
and h(0); h(1); cz(0,1) both put 0.25 on all four outcomes, and one is a product state while the
other is maximally entangled. A two-qubit state has six real parameters and a Z-basis histogram
reports three of them.
Costs to memorize: SWAP = 3 CNOTs. Toffoli = 6 CNOTs. You rarely write SWAPs — the transpiler inserts them whenever two qubits that need to interact are not physically connected, and that hidden cost is the largest in quantum programming.
GHZ generalizes the Bell state and is fragile: lose one qubit and the rest are left with no entanglement. W distributes entanglement pairwise and is robust. They are inequivalent kinds of three-party entanglement, and the fragility of GHZ is exactly why it makes a good benchmark.
The exponential wall is entanglement's price. Product states cost $2n$ numbers; general states cost $2^n$. Therefore: an algorithm that does not generate substantial entanglement is classically simulable and cannot provide quantum advantage.
On hardware, GHZ fidelity decayed from 95.6% at two qubits to 81.3% at six on a device-derived model — steady, compounding, and enough to make large entangled states a research problem rather than a routine one.
Next: Chapter 5 — the other half of every quantum program. How many shots do you need, what does a bitstring actually mean, how do you measure in a basis other than the computational one, and how do you decide whether the distribution you got is the one you expected? Several claims deferred in this chapter get settled there.