Quantum computing and AIMiddleLesson 3066 min read

Simulating a tiny quantum computer

A quantum state is a vector of amplitudes, and gates are matrices. Build Hadamard, X and CNOT in numpy, make a Bell state, and see why n qubits need 2ⁿ numbers.

Lesson in motion

In 60 seconds

Simulating a tiny quantum computer

A quantum state is a vector of amplitudes, and gates are matrices. Build Hadamard, X and CNOT in numpy, make a Bell state, and see why n qubits need 2ⁿ numbers.

1/4
In simple words
A recipe changes ingredients step by step: chop, mix, cook. A quantum circuit changes a list of numbers step by step. Each step is a gate, and each gate is a small table of numbers called a matrix. Multiply the list by the table, and you get the next list. That is all a simulator does.
A classical computer can simulate a small quantum computer exactly. We store the state vector, the list of all amplitudes, and apply each gate as a matrix multiplication. This is how researchers test ideas before running on real hardware.

Three gates

GateActs onWhat it doesMatrix
X (NOT)1 qubitSwaps |0⟩ and |1⟩, like a classical NOT[[0, 1], [1, 0]]
H (Hadamard)1 qubit|0⟩ → (|0⟩ + |1⟩)/√2 and |1⟩ → (|0⟩ − |1⟩)/√2[[1, 1], [1, −1]] / √2
CNOT2 qubitsFlips the second (target) qubit if the first (control) is 14 × 4, swaps the 10 and 11 amplitudes

Two qubits: order and the Kronecker product

For two qubits we list amplitudes in the order 00, 01, 10, 11. In this track the left bit is qubit 0 and the right bit is qubit 1. To apply a one-qubit gate to one qubit and do nothing to the other, we combine it with the identity matrix I using the Kronecker product, np.kron. For example, np.kron(H, I) applies H to qubit 0 and leaves qubit 1 alone.
Note
Different tools order qubits differently. Some put qubit 0 on the right. The physics is the same, but your vectors will look reversed. Always check which convention a tool uses.

Build a Bell state

  1. 1

    Start

    Both qubits in |0⟩: the vector [1, 0, 0, 0].
  2. 2

    Hadamard on qubit 0

    Now (|00⟩ + |10⟩)/√2.
  3. 3

    CNOT, control 0, target 1

    The |10⟩ part becomes |11⟩. Result: (|00⟩ + |11⟩)/√2.
Python: a Bell state from matricespython
import numpy as np

I = np.eye(2)
H = np.array([[1, 1], [1, -1]]) / np.sqrt(2)
CNOT = np.array([[1, 0, 0, 0],
                 [0, 1, 0, 0],
                 [0, 0, 0, 1],
                 [0, 0, 1, 0]])

state = np.array([1.0, 0, 0, 0])      # |00>
state = np.kron(H, I) @ state          # H on qubit 0
state = CNOT @ state                   # entangle
for label, amp in zip(["00", "01", "10", "11"], state):
    print(label, round(float(amp), 3), "prob", round(float(amp) ** 2, 3))

Why big simulations are hard

One qubit needs 2 amplitudes. Two need 4. Every extra qubit doubles the list. For n qubits you need 2ⁿ numbers, and each gate touches many of them. Run this to see how fast that grows:
Python: memory for a full state vectorpython
# Each amplitude stored as a complex number takes 16 bytes (complex128 in numpy).
for n in [10, 20, 30, 40, 50]:
    amplitudes = 2 ** n
    gigabytes = amplitudes * 16 / 1e9
    print(f"{n:2d} qubits: {amplitudes:>20,d} amplitudes, about {gigabytes:,.3f} GB")
Around 30 qubits already needs roughly 17 GB, more than most laptops have free. At 50 qubits the full vector would need millions of gigabytes. Clever methods can simulate some special circuits with more qubits, but for general circuits this doubling is a real wall. That wall is one reason people think quantum computers could do things classical computers cannot.
Watch out
The 2ⁿ amplitudes are not 2ⁿ answers you can read. Measuring n qubits still gives just n bits. The large state is only useful when an algorithm makes the amplitudes interfere so that the useful answer becomes likely.
Try this. In the Bell state code, add np.kron(I, X) (X on qubit 1) before the Hadamard. Which two outcomes appear now?

Watch and read more

Lab

A numpy simulator that builds a Bell state and a second entangled state from gate matrices, with their probabilities printed.

~30 min

The problem

Run this in the browser, or with Python 3 and numpy. Qubit 0 is the left bit.

  1. Make bell equal (|00⟩ + |11⟩)/√2 by applying H on qubit 0 and then CNOT to start. Use the matrices, not typed-in answers.
  2. Make other equal (|01⟩ + |10⟩)/√2, starting again from start. Hint: first apply X to one qubit.
  3. Print the probabilities of both states with show.
  4. Write one sentence: how many amplitudes would a 3-qubit version need?

Practice lab

Edit the code and run it. Python runs in your browser — nothing is sent to our server.

Output

No output. Add print(...) to see values.

You are done when

Hard questions

Try to answer before you reveal. If you can answer these, you understood the lesson.

Q1Extend the simulator to 3 qubits and make (|000⟩ + |111⟩)/√2. Which gates do you need?Reveal

Apply H to qubit 0 with np.kron(np.kron(H, I), I). Then apply CNOT from qubit 0 to qubit 1 with np.kron(CNOT, I), and CNOT from qubit 1 to qubit 2 with np.kron(I, CNOT). The state vector has 8 amplitudes, and only 000 and 111 are non-zero. This is often called a GHZ state.

Q2Our simulator builds full 4 × 4 or 8 × 8 matrices. Why do serious simulators avoid building a 2ⁿ × 2ⁿ matrix for each gate?Reveal

A full matrix for n qubits has 2ⁿ × 2ⁿ entries, far more than the state vector itself. Since each gate only touches one or two qubits, a simulator can update the state vector directly, pair by pair or in small groups of amplitudes, without ever building the big matrix. The memory needed is then about the size of the state vector, which is still 2ⁿ.

Please sign in to continue.

Questions people ask

Why are gates matrices?

Quantum mechanics says the changes you can make to a closed system (without measuring) are linear and keep the total probability equal to 1. Linear maps are matrices, and the "keep probability 1" rule means the matrices are unitary. X, H and CNOT are all unitary.

Is measurement also a matrix?

Not in the same way. Measurement is not a unitary gate: it picks a random outcome with the Born rule and then the state jumps to match the outcome. In our simulator we do this by sampling from the probabilities.

Are real quantum programs written like this?

People usually use a quantum programming library that builds circuits for them, and can send them to a simulator or real hardware. Under the hood, a simulator does what you did here. Writing it yourself once makes those libraries much easier to understand.

If simulation is so hard, how do we check big quantum computers are right?

This is a real challenge. Researchers check small parts that can be simulated, use special circuits whose answers are known, and use problems where a proposed answer is easy to verify, such as checking that two numbers multiply to give a third.

Lesson test

5 questions. Get 3 right (60%) to pass and complete this lesson.

Sign in to take the test and save your progress