Programming your first quantum circuitsLesson 3 of 6

Two qubits and the Bell pair

The CNOT gate as a controlled flip, then the Bell pair, and how to read a two-bit string in Qiskit.

The Playground's Circuit panel: an H gate on q0, a CNOT from q0 down to q1, and a measurement on each qubit.

One qubit gave answers that were uncertain. Two qubits give answers that can be uncertain and still agree with each other, every time. This lesson builds the smallest circuit that does that, the Bell pair, and along the way teaches the one gate that makes qubits act together.

The answer now has two characters instead of one, and Qiskit writes them in an order that catches most people out the first time. This lesson covers it before the first tally arrives.

A gate that acts on two qubits

Every gate so far acted on one qubit. The CNOT acts on two: a control and a target. It looks at the control and flips the target only if the control is 1. With the control at 0 it does nothing at all.

On its own that is a plain conditional, the kind of thing an ordinary program does with an if. The difference from an if shows when the control is in superposition.

The CNOT does not pick one of the control's two options and act on that. It applies its rule to each option separately, inside the superposition: where the control is 0 the target stays 0, and where the control is 1 the target flips to 1.

So the target's options become tied to the control's: both 0 together, or both 1 together, and never one of each.

cx

The CNOT gate

cx(control, target). Flips the target if the control is 1, leaves it alone if the control is 0. Applied to a target at 0 while the control is in superposition, it makes the two qubits agree: measure them and you get 00 or 11, never 01 or 10.

00

Two-character answers

With two ordinary bits, classical bits in Qiskit's words, every shot reads two characters, one per bit. Qiskit writes bit 0, which here holds qubit 0, on the right: the string 10 means qubit 1 read 1 and qubit 0 read 0. Read the string from the right to read it in qubit order.

The circuit, then the code

Two wires, q0 and q1, both starting at 0. Qubit 0 passes through an H gate, then a CNOT joins the wires with a dot on q0 and a crossed circle on q1. Two meters, one per wire, drop into two bit wires. The answer is 00 or 11, half the time each.
The CNOT is drawn as a dot on the control and a crossed circle on the target, joined by a line. After it, the two wires carry the same two options, together.

The circuit is three gates and two measurements:

qc = QuantumCircuit(2, 2)     # two qubits, two ordinary bits
qc.h(0)                       # qubit 0 into superposition
qc.cx(0, 1)                   # CNOT: control qubit 0, target qubit 1
qc.measure([0, 1], [0, 1])    # qubit 0 into bit 0, qubit 1 into bit 1

The plumbing is lesson 1's, unchanged. The keys of the counts dict are two characters now, and the bar loop prints one line per string that was read.

two_qubits.py Python · PlaygroundOpen in Playground ↗
# 'backend' already exists when this runs: it is whatever you pick in the Run Experiment dialog.
from qiskit import QuantumCircuit
from qiskit.providers.jobstatus import JobStatus
import time
shots = 1000
1qc = QuantumCircuit(2, 2)
2qc.h(0)
3qc.cx(0, 1)
4qc.measure([0, 1], [0, 1])
print(qc)
job = backend.run(qc, shots=shots)
while job.status() not in (JobStatus.DONE, JobStatus.ERROR, JobStatus.CANCELLED):
    time.sleep(5)
counts = job.result().get_counts()
print(counts)
5for bits, n in sorted(counts.items()):
    print(f"{bits}: {n:4d}  {100 * n / shots:5.1f}%  {'█' * (50 * n // shots)}")
  1. 1two qubits, two ordinary bits
  2. 2qubit 0 into superposition, as in lesson 2
  3. 3the CNOT: flip qubit 1 if qubit 0 is 1, and it acts inside the superposition
  4. 4read both: qubit 0 into bit 0, qubit 1 into bit 1
  5. 5each key is now two characters: bit 1 on the left, bit 0 on the right

Run the circuit

Predict the tally first. Four strings are possible, 00, 01, 10 and 11. Which of them will you see, and in what shares? Then open the project, press Run on Qollab, choose IonQ Aria 1, and press Run. Then fork it, the way lesson 1 showed, so the edits below land in your own copy.

The run console: the two-qubit circuit drawn in text, the counts dict, two long bars for 00 and 11, and lines for 01 and 10 that show a few shots and no bar
Two of the four strings carry almost everything. The 01 and 10 lines show their counts but no bar, because a bar is fifty characters for the full shot count and four shots in a thousand round to none. Those four are the noise model, not the circuit.

Our run on 15 September 2026, on the Aria 1 noise model, came back {'00': 512, '01': 3, '10': 1, '11': 484}: 51.2% 00, 48.4% 11, and four shots in a thousand where the two qubits disagreed.

Half 00, half 11, and a sliver of 01 and 10. The sliver is the noise model; on a perfect simulator the pair never disagrees. If you predicted four strings at a quarter each, the reading below is for you.

Why the pair always agrees

Follow the circuit in order. After the Hadamard, qubit 0 carries two options, 0 and 1, with no value chosen. The CNOT then says: flip qubit 1 wherever qubit 0 is 1.

It applies that rule to both options at once. Where qubit 0 is 0, qubit 1 stays 0; where qubit 0 is 1, qubit 1 becomes 1.

So the circuit never holds 01 or 10 as an option, and measuring cannot produce them. What it holds is 00 or 11, weighted half and half, and the measurement picks one of those. Two qubits in that state are called a Bell pair, the smallest case of entanglement.

Assignment: make the CNOT copy a plain 1

  1. In your fork, replace qc.h(0) with qc.x(0), so qubit 0 is a definite 1 when the CNOT sees it. There is no superposition now, so the CNOT has one case to handle.
  2. Apply the gate row's rule, flip the target if the control is 1, and work out what each of the two measurements reads. Write the answer as a string with qubit 0 on the right.
  3. Run and compare.
Solution
qc = QuantumCircuit(2, 2)
qc.x(0)
qc.cx(0, 1)
qc.measure([0, 1], [0, 1])

Qubit 0 is 1, so the CNOT flips qubit 1 to 1. Both read 1 and every shot is 11. This is the CNOT as an ordinary conditional; the previous run was the same gate with a control that had not decided.

Which character is which qubit

The Bell pair hides the bit order, because 00 and 11 read the same either way. The next task does not: it produces a string where the order matters, and asks you to call it before you see it.

Assignment: find qubit 0 in the string

  1. Starting from the version with qc.x(0), change that line to qc.x(1) and leave the CNOT in.
  2. Work out two things before you run: whether the CNOT changes its target at all, now that its control, qubit 0, is never flipped; and which character the qubit that reads 1 is written in, by the gate row on two-character answers.
  3. Write down 01 or 10, then run.
Solution

Qubit 0 stays 0, so the CNOT does nothing to qubit 1, which keeps the 1 the X gate gave it. Qubit 1 is 1 and qubit 0 is 0, and Qiskit writes qubit 0 on the right: the string is 10.

If you expected 01, you read the string left to right in qubit order. Read the tally from the right, qubit 0 first.

Measuring is per qubit

The pair agrees when both qubits are measured. Measuring only one of them is a legal circuit too, and the tally still shows two characters, because there are still two bits. A bit that no measurement writes to stays at 0.

Assignment: read only one qubit of the pair

  1. Change qc.x(1) back to qc.h(0), so the circuit is the Bell pair again: qc.h(0), then the CNOT.
  2. Replace the measurement line with qc.measure(0, 0), so only qubit 0 is read.
  3. Work out what qubit 0 alone reads over many shots, given it was put into superposition, and what bit 1 holds when nothing ever writes to it.
  4. Put the two together into two-character strings, qubit 0 on the right, then run.
Solution
qc = QuantumCircuit(2, 2)
qc.h(0)
qc.cx(0, 1)
qc.measure(0, 0)

Qubit 0 reads 0 or 1, half each. Bit 1 stays 0. So the tally is 00 and 01, about half each. Qubit 1 was in the pair the whole time; you simply did not ask it. Ask both again and the agreement comes back.

Every gate so far was all or nothing: a full flip, a full spread, a full copy. The next lesson turns the gate into a dial.

Stay in the loop.

Get the latest tutorials, demos, and project showcases straight to your inbox. No noise, just the good stuff.