Programming your first quantum circuitsLesson 5 of 6

Interference and your first algorithm

Make a hidden phase visible, then run a two-qubit Grover search.

The Playground's Circuit panel: qubit q0 runs through H, then Rz(0.5π), then H, into a measurement.

Interference is two paths through a circuit meeting again: where they agree they add up, where they disagree they cancel, and the tally shows which. Lesson 4 spun a fresh qubit around the measurement axis and nothing showed, because a single path has nothing to differ from.

A Hadamard on each side of the spin makes the phase show in the tally, and Grover's search, later in this lesson, uses the same effect.

Two paths, and whether they agree

The first Hadamard spreads a qubit at 0 over two paths, which here means the two weighted options of lesson 2, 0 and 1. The RZ gate turns the phase of one path by phi.

A phase is the continuous version of the sign a weight carried in lesson 2, and turning it changes nothing a measurement can see.

The second Hadamard brings the two paths back together: paths with the same phase add up, and paths with opposite phases cancel.

Two panels. A qubit at 0 is split by H into path 0 and path 1, a phase box sits on path 1, and a second H merges the paths. With the phase at 0 every shot reads 0; with the phase at pi every shot reads 1.
The two panels differ only in the phase. At φ = 0 the two paths add on 0 and every shot reads 0. At φ = π they cancel on 0, add on 1, and every shot reads 1. In between, the phase sets the odds and each shot is still a draw.

The rule is lesson 4's with the phase in place of the angle: after h, rz(phi), h on a fresh qubit, the share of shots that read 1 is sin²(φ/2).

At phi = 0 nothing is turned and every shot reads 0; at phi = pi every shot reads 1; at pi / 2 it is the even split.

h · rz · h

Hadamard, RZ, Hadamard

Hadamard, phase rotation, Hadamard. The first H splits the qubit into two paths, RZ turns the phase of one, and the second H recombines them so they add or cancel. The share of 1 after it is sin²(φ/2), the RY rule with the phase in place of the angle.

The circuit, then the code

The circuit is one qubit and three gates, with the phase at the top of the file:

phi = pi / 2

qc = QuantumCircuit(1, 1)
qc.h(0)                       # two paths
qc.rz(phi, 0)                 # turn one of them
qc.h(0)                       # bring them back together
qc.measure(0, 0)

The plumbing is lesson 4's: the measured share of 1 beside what the rule says.

interference.py Python · PlaygroundOpen in Playground ↗
# 'backend' already exists when this runs: it is whatever you pick in the Run on Qollab dialog.
from math import pi, sin
from qiskit import QuantumCircuit
from qiskit.providers.jobstatus import JobStatus
import time
​
shots = 1000
1phi = pi / 2
​
qc = QuantumCircuit(1, 1)
2qc.h(0)
3qc.rz(phi, 0)
4qc.h(0)
qc.measure(0, 0)
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)
measured = counts.get("1", 0) / shots
5expected = sin(phi / 2) ** 2
print(f"phi = {phi:.4f}   share of 1: measured {measured:.3f}   rule says {expected:.3f}")
  1. 1the phase RZ sets. On its own it is invisible; change it and press Run
  2. 2spread the qubit over 0 and 1, two paths
  3. 3turn the invisible dial on one of them
  4. 4fold the two paths back together: they add, or they cancel
  5. 5the same rule as RY, now driven by a phase

Run the circuit, three times

Predict the share of 1 for pi / 2 first. Then open the project, press Run on Qollab, choose IonQ Aria 1, and press Run. Then fork it, as in lesson 1, and in your fork set phi to 0 and to pi, one press each.

Our three presses on 15 September 2026, on the Aria 1 noise model:

phicountsmeasured share of 1rule says
0{'0': 1000}0.0000.000
pi / 2{'0': 474, '1': 526}0.5260.500
pi{'1': 1000}1.0001.000

In lesson 4 rz changed nothing visible. Between two Hadamards the same gate moves the share from all 0 to all 1.

Assignment: take the second Hadamard away

  1. Keep phi = pi and delete the second qc.h(0). The circuit is then a Hadamard, a phase and a measurement.
  2. Predict the tally: lesson 4 showed that a phase on its own leaves the share of 1 where it was, so ask where the first Hadamard left it.
  3. Press Run on Qollab and choose IonQ Aria 1.
  4. Change phi to anything else and press again. The rule line keeps printing sin²(φ/2), which no longer applies to this circuit; the tally is the answer.
Solution

The circuit is h then rz(pi) then measure: an even split with a phase on one path and no gate after it to turn the phase into a share.

qc.h(0)
qc.rz(phi, 0)
qc.measure(0, 0)

The share of 1 is one half, whatever phi is, because the measurement reads the split the first Hadamard made and cannot see the phase.

Grover's search on two qubits

The search uses two qubits. Hadamards on both spread them evenly over four candidates, 00, 01, 10 and 11, a quarter each: four weights of one half, since a share is a weight's size squared.

An oracle is the part of a search that checks the condition and marks whatever passes it. Here the condition is fixed, "both qubits are 1", and the marking is a CZ gate.

cz

The controlled-Z gate

cz(a, b). Flips the sign of the weight on the state where both qubits are 1, and does nothing anywhere else. A sign is a phase, so a CZ on its own is as invisible as an RZ: after it the tally still shows four quarters.

The diffusion step turns the mark into a change in the tally. It does the second Hadamard's job for four candidates instead of two paths: it reflects every weight about their average. Each weight moves to the same distance on the other side of the average, so the new value is twice the average minus the old one.

After the oracle the three unmarked weights are one half each and the marked one is minus one half, so the average is one quarter.

Twice one quarter is one half, and one half minus one half is zero, so each unmarked weight goes to zero. For the marked weight, one half minus a negative one half is one, so it goes to a full one; the gates below produce that reflection with a minus sign in front, which measurement cannot see. After one round of oracle and diffusion, the marked answer is the only one left.

The five lines below are that reflection written in gates; the diffuser section of the interference article shows how they do it, and you can use them without re-deriving them. The oracle encodes the problem and the diffusion step never changes, so the same five lines find whatever a different oracle marks.

Two wires, q0 and q1, both starting at 0. An H gate on each wire spreads the two qubits over four candidates. A CZ, drawn as a dot on each wire joined by a line, is the oracle that marks 11 with a sign. Then the diffusion step: H, X, CZ, X and H on both wires. Two meters drop into two bit wires. The answer is 11 on every shot.
The search circuit. The two H gates spread the two qubits over the four candidates, the CZ marks 11 with a sign, and the five gates after it are the diffusion step. On a perfect simulator both meters read 1 on every shot.
grover.py Python · PlaygroundOpen in Playground ↗
# 'backend' already exists when this runs: it is whatever you pick in the Run on Qollab dialog.
from qiskit import QuantumCircuit
from qiskit.providers.jobstatus import JobStatus
import time
​
shots = 1000
​
qc = QuantumCircuit(2, 2)
1qc.h([0, 1])
2qc.cz(0, 1)
3qc.h([0, 1])
qc.x([0, 1])
qc.cz(0, 1)
qc.x([0, 1])
qc.h([0, 1])
qc.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)
for bits, n in sorted(counts.items()):
    print(f"{bits}: {n:4d}  {100 * n / shots:5.1f}%  {'█' * (50 * n // shots)}")
  1. 1all four answers at once, a quarter each
  2. 2the oracle: flip the sign of 11 and nothing else. Invisible on its own
  3. 3the diffusion step, five lines: it turns that hidden sign into probability

Predict the tally, then open the search project and run it on IonQ Aria 1. Fork the search project too; the last two assignments edit it.

The run console after the Grover search: the counts dict {'11': 1000} and one full-length bar at 11
In the text drawing, the first pair of H gates spreads the two qubits over the four candidates and the CZ after them is the oracle; the block after that is the diffusion step. On a perfect simulator every shot reads 11; on this press the noise model put no shots elsewhere either.

Our press on 15 September 2026, on the Aria 1 noise model, came back {'11': 1000}: the marked answer on all 1,000 shots. The noise model can put a few shots elsewhere on another press; the ideal is all 1,000.

Changing the oracle

The CZ marks 11. To mark a different string, surround it with X gates on the qubits that should read 0 in that string. An X before the CZ turns that qubit's 0 into a 1 for the CZ to see, and an X after it turns it back. The diffusion step stays exactly as it is.

With exactly four candidates one round lands the marked answer on 100%. With more candidates it takes more rounds: the count grows with the square root of their number, about 0.8 times that root, and Grover's speed-up comes from that square root. Grover's search on Qollab runs it on eight candidates, where two rounds are needed.

Assignment: mark a different answer

  1. In your fork of the search, work out which qubit reads 0 in the string 10. Remember which character is qubit 0.
  2. Put an X gate on that qubit immediately before the first qc.cz(0, 1) and another immediately after it, as the section above describes. Do not touch the diffusion step.
  3. Predict the tally.
  4. Press Run on Qollab and choose IonQ Aria 1.
Solution
qc.h([0, 1])
qc.x(0)
qc.cz(0, 1)
qc.x(0)
qc.h([0, 1])
qc.x([0, 1])
qc.cz(0, 1)
qc.x([0, 1])
qc.h([0, 1])

The oracle now marks 10, and the diffusion step finds it: 10 on every shot, apart from the tail.

Assignment: search without the diffusion step

  1. Put the oracle back to 11 by removing the two X lines you added around the first CZ.
  2. Delete the five diffusion lines, the block from the second qc.h([0, 1]) down to the last one, so only the opening Hadamards, the CZ and the measurements remain.
  3. Predict the tally: after the oracle the mark is a sign, and a sign is a phase, so ask what a tally looks like when no gate after the phase turns it into a share.
  4. Press Run on Qollab and choose IonQ Aria 1.
Solution

All four strings come up, a quarter each, apart from the tail. The oracle marked 11, and without the diffusion step the mark stays invisible.

qc.h([0, 1])
qc.cz(0, 1)
qc.measure([0, 1], [0, 1])

Some presses in this course came back with a small tail of wrong answers. Lesson 6 measures that tail on the noise models of four IonQ machines, then looks at the real machines in the same dialog.

Stay in the loop.

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