Understanding Quantum Measurement
Measurement does not read a value off a qubit, it produces one. Why a single run tells you nothing, and why the question you ask changes the answer.
About the author
There is no print(qubit). No debugger, no stepping through to watch one change. The only way to get anything out of a qubit is to measure it, and measurement does hand you a single 0 or 1.
The catch is where that 0 or 1 comes from. Measurement does not find an answer sitting in the qubit; it produces one. Before you measure there is nothing in there to print, which is why no such function exists.
Quantum code feels alien for that reason. You write a program, run it, get back a tally of bitstrings, and everything you actually wanted to know has to be inferred from that tally.
Four things follow, and each shows up the first time you write a circuit. You can sample a qubit but never read it. Which answer you get depends on which question you ask. Asking is one-way, so whatever the qubit held before is gone. And the instrument doing the asking can be wrong in its own right, separately from all of that.
The smallest measurement you can make
One qubit is enough to see the whole problem. Put it into a state that has no fixed value, read it, and count what comes back.
# 'backend' is pre-created for you in the Qollab Playground.
from qiskit import QuantumCircuit
1qc = QuantumCircuit(1, 1)
2qc.h(0)
3qc.measure(0, 0)
4one = backend.run(qc, shots=1).result().get_counts()
5many = backend.run(qc, shots=1000).result().get_counts()
print(one, many)
- 1One qubit to do the quantum work, and one ordinary bit to read the answer into.
- 2A Hadamard puts the qubit into superposition: not
0, not 1, and not secretly one of them either. It has no value to read. - 3The only way to get anything out. It forces the qubit to one definite answer and writes that answer to the bit.
- 4Run the circuit once. You get
{'0': 1} or {'1': 1} — one answer, with nothing to say whether the other was equally likely or nearly impossible. - 5Run it a thousand times. Now the pattern shows: roughly 500 each. A shot is one complete run, and the odds only exist across a pile of them.
Eight lines, and every difficulty is in them. The qubit held something before line three, the measurement turned it into a 0 or a 1, and what it held cannot be recovered from what you got.
Run the same program twice and the thousand-shot tally comes back roughly the same, while the single shot flips between runs. Neither number is more true than the other. One is a sample and the other is a pattern in a thousand samples.
Superposition is the word for what the qubit had before the measurement. It does not mean the qubit is secretly a 0 or a 1 and we have not looked yet. There is no answer in there to find; the measurement is what produces one.
All you get is counts
Every quantum program ends the same way: a dictionary mapping bitstrings to how many times each came up. Nothing else comes back.
# Counts from an ideal Bell-state experiment: only correlated outcomes,
# roughly 50/50 between 00 and 11
1ideal = {"00": 512, "11": 488}
plot_histogram(ideal, filename="ideal.svg")
# The same experiment on noisy hardware leaks shots into 01 and 10.
# plot_histogram overlays multiple experiments for direct comparison.
2noisy = {"00": 462, "01": 27, "10": 31, "11": 480}
plot_histogram(
[ideal, noisy],
legend=["ideal simulator", "noisy device"],
filename="ideal_vs_noisy.svg",
3)
- 1A thousand shots of a Bell pair. Not a state, not amplitudes: a tally.
- 2The same circuit on real hardware.
01 and 10 should be impossible for this state, and 58 shots out of a thousand landed there anyway. - 3Two runs on one chart. Comparing distributions is most of what reading quantum results consists of.
Notice what a single shot would have told you here: one bitstring, 00 or 11, with no way to know whether the other was equally likely or nearly impossible. Only a pile of a thousand has a pattern in it at all.
The gates in these circuits
Four gates and one instruction cover every excerpt below.
Hadamard
Takes a qubit sitting at 0 and leaves it with no fixed value: measure it and you get 0 or 1 with equal probability.
The Hadamard is also its own undo. Two of them in a row put the qubit back exactly where it started, which is the trick the next section is built on.
Leaves a qubit exactly as likely to read 0 or 1 as it already was, and flips the sign in front of the 1 half of the state.
A sign is not something a measurement reports, so a z is invisible in the counts. The change is real all the same, and the next section is about how to see it.
A rotation. The angle comes before the qubit and sets how likely a qubit starting at 0 is to read 1.
At 0 it is certain to read 0, at π certain to read 1, and at π/2 it gives the same even split the Hadamard does. Anything in between is a bias you pick, which is how a circuit gets odds other than fifty-fifty.
Couples two qubits by an angle. Unlike the others it does not change how often either qubit reads 0 or 1 on its own.
The coupling changes the relationship between the two instead, which is why Entangled Body's couplings entangle the state and still leave no trace in its counts.
Reads a qubit into an ordinary bit and forces it to a definite 0 or 1. It is the one irreversible step: whatever the qubit held before is gone once you look.
So a single run tells you one outcome and nothing about the odds behind it, which is why every circuit here is run many times over.
Which question you ask
Measuring is not reading a value off a dial. It is putting a question to the qubit, and 0-or-1 is only one of the questions available.
The cheapest way to see that is to build two qubits that give the same counts, and then ask them something else.
# 'backend' is pre-created for you in the Qollab Playground.
from qiskit import QuantumCircuit
def counts(add_z, ask_after_h):
qc = QuantumCircuit(1, 1)
1 qc.h(0)
if add_z:
2 qc.z(0)
if ask_after_h:
3 qc.h(0)
qc.measure(0, 0)
return backend.run(qc, shots=1000).result().get_counts()
4print("h asked directly :", counts(False, False))
5print("h,z asked directly :", counts(True, False))
6print("h asked after an h:", counts(False, True))
7print("h,z asked after an h:", counts(True, True))
- 1Both states start the same way, with the Hadamard from the first listing.
- 2The only difference between the two states. A
z leaves the qubit just as undecided as it was; all it does is flip the sign in front of the 1 half of it. - 3This one is not part of the state. It lands after the state is finished and just before the measurement, and switching it on is what changes the question.
- 4Roughly 500 each, the same even split as the first listing.
- 5Roughly 500 each again. Nothing in this tally can tell the two states apart.
- 6Every shot reads
0. Two Hadamards cancel, so the qubit is back where it started. - 7Every shot reads
1. The same two states as the rows above, and now the answers are opposites.
| prepared with | asked directly | asked after an h |
|---|---|---|
h | ~500 0, ~500 1 | 1000 0 |
h then z | ~500 0, ~500 1 | 1000 1 |
Read the table down the first column and the two states are identical. Read it down the second and they are opposites. The z did something real to the qubit, and the first question had no way to report it.
A basis is the question. Measuring straight away asks one; putting a Hadamard in front of the measurement asks a different one. Nothing about the qubit changed between the two columns, only what you asked it.
A quantum state carries more than any single measurement can hand back. Ask the wrong question and the interesting half of your circuit is not in the output, and nothing about the output says so.
Each of those four rows needed its own run and its own fresh qubit. The measurement is the last line of the function every time, because there is no version of this where you ask one question, look, and then ask the other. That is the one-way part: you get one question per qubit, and the state is gone after it.
On real hardware the right-hand column will not come back as a clean 1000 and 0. A few dozen shots land in the wrong row, from gate and readout errors that a section below is about. Either way the pattern is unmistakable.
When the odds are not fifty-fifty
Every circuit so far has aimed at an even split or a certainty. Real circuits mostly want neither, and Entangled Body is a good place to see why that matters.
Entangled Body is a 3D human figure whose fourteen regions are fourteen qubits. Touch one and the figure responds around it, strongly nearby and less further away.
Nothing in that description is a coin flip. Each region needs its own probability of lighting up, and the piece has a two-line function that turns a probability into an Ry angle.
def _prob_to_ry(prob):
1 p = max(0.0, min(1.0, prob))
2 return 2.0 * asin(sqrt(p))
- 1Hold the requested probability between 0 and 1, so a rounding error upstream cannot ask for odds that do not exist.
- 2Turn it into an Ry angle. You name the odds you want and this hands back the rotation that produces them, which is the whole bridge between "how likely" and "which gate".
That conversion is exact rather than an approximation. Ask for 0.84 and the odds of reading 1 are 0.84, not 0.839 or 0.841.
Entangled Body uses that to draw its ripple. A hover sets the region you touched to a certainty, its nearest neighbours to just under 0.995, and the furthest region to 0.90.
All three are close to 1 and they are still very different. In a single shot every region reads 1 and the figure tells you nothing at all. Across the 1024 shots the project runs, the nearest region reads 0 about five times and the furthest about a hundred. No single run contains the ripple. It lives in the difference between five and a hundred.
On top of the rotations, the anatomical links between regions get an rzz coupling, and those entangle the state. They also leave no trace in the counts, for the reason the last section demonstrated. An rzz only moves signs around, and the circuit measures in the one question where signs do not show.
So the entanglement is there and the measurement cannot see it. Nothing is broken and nothing is hidden. You asked the one question this coupling does not answer.
Fork it and put a Hadamard on every region just before the measurement, the same move as the right-hand column of the table above. The couplings then reach the counts instead of hiding in the signs.
Measuring one qubit of an entangled group also changes what the rest will do, which is a subject of its own: Understanding Quantum Entanglement is the article about that.
Entangled BodyEntangled Body is an interactive 3D artwork that treats the body as a network of 14 quantum nodes, each mapped to a specific body region.When the instrument is wrong
A second thing can go wrong, and it is a different thing from the first.
The state can be fine and the reading still wrong. A detector that reports 1 when the qubit was 0 has not disturbed any physics; it has mistyped. And because that error happens after the quantum part is over, ordinary arithmetic can undo it.
function qubitMatrix(q){
let p10=state.p10, p01=state.p01;
1 if(state.hotQubit && q===2){p10=Math.min(0.25,p10*4); p01=Math.min(0.25,p01*4);}
2 return [[1-p10,p01],[p10,1-p01]];
}
function Aentry(i,j){let p=1;
3 for(let q=0;q<N;q++){const bi=(i>>q)&1, bj=(j>>q)&1; p*=qubitMatrix(q)[bi][bj];}
return p;}
- 1One qubit can be worse than the others. Real devices are like this: readout quality is per-qubit and it drifts.
- 2The whole error model for one qubit, as four numbers: how often a 0 is read as 0 or 1, and the same for a 1.
- 3Multiply the per-qubit numbers together to get the chance that the true bitstring j was recorded as i. Do that for every pair and you have a matrix describing the whole readout.
Build that matrix, and correcting the results is a linear algebra problem: you have the corrupted counts and the matrix that corrupted them, so you solve for what went in. The project does exactly that and shows three histograms side by side, ideal, raw and corrected.
This repairs the record, not the run. Nothing recovers a state the measurement already destroyed.
Readout mitigationReadout error corrupts the measurement, not the quantum state - so classical math can undo it. Drag the error sliders on a GHZ-5 and watch three histograms (ideal, raw, corrected) update instantly.Hearing the distribution
Musiq turns a circuit's output into sound. Because the output is a distribution, so is the music: run the same circuit again and you get a variation rather than a repeat.

Its mapper offers two ways to do that, and the choice between them is the difference between probabilities and shots, in one function.
if method == "weighted_sum":
for bitstring, prob in probability_dist.items():
1 if prob > 0.01:
amp = self.map_bitstring_to_amplitude(bitstring)
2 waveform += prob * amp
elif method == "stochastic":
# Probabilistic sampling from quantum outcome distribution
bitstrings = list(probability_dist.keys())
probs = np.array(list(probability_dist.values()))
probs = probs / np.sum(probs)
# Sample based on probability at each time point
for i in range(self.samples):
3 selected = np.random.choice(bitstrings, p=probs)
amp = self.map_bitstring_to_amplitude(selected)
waveform[i] = amp[i]
- 1A threshold, and this one is Musiq's own. Any outcome under one per cent never reaches the chord at all.
- 2Every surviving outcome added in, scaled by how likely it is. You hear the whole tally at once, and the same circuit sounds identical every time.
- 3The other route. Draw one outcome, then another, weighted by those same probabilities. That is shots rather than the distribution, and it comes out different on every run.
weighted_sum sounds the entire distribution at once. Every outcome contributes in proportion to its probability, so what you hear is the tally as a chord, and the same circuit gives the same chord every time.
stochastic draws a single outcome per sample instead, which is shots made audible: a sequence of individual answers, different on every run. Tomoya Hatanaka's docstring is careful about the distinction, calling it sampling from "the quantum outcome distribution (not classical random generation)".
Two honest renderings of one measurement. The probabilities are what the state says will happen. The shots are what happened.
Look again at the threshold on the first branch. A rare outcome and a noise blip look identical in a distribution, and no line of code can separate them. Dropping everything under one per cent is a judgement, and every quantum program makes one somewhere.
This listing comes from the project's repository rather than its Qollab page, which still carries the starter circuit.
MusiqMusiq is a browser-based quantum sonification platform that transforms quantum-circuit outputs into generative audio.Measured once, and fixed from then on
Quantum Garden grows each plant from a real quantum measurement, and it shows the one-way part plainly.

The circuit behind a plant is completely fixed. Each plant derives a seed from its own ID, and the same seed always builds the same five-qubit circuit.
seed = 42 # Each plant gets a deterministic seed from its ID hash
1circuit = QuantumCircuit(5, 5)
# Layer 1: Full superposition — all 32 outcomes initially possible
for i in range(5):
2 circuit.h(i)
# ...
# Measure all qubits
3circuit.measure([0, 1, 2, 3, 4], [0, 1, 2, 3, 4])
- 1Five qubits to do the work, and five ordinary bits waiting to receive the answers. Five bits is thirty-two possible results.
- 2A Hadamard on each one, so all thirty-two start out equally likely. The five layers this excerpt skips then bend the odds between them, without ever closing any of them off.
- 3One draw from those odds. Five bits come out, and every trait the plant shows is read off them.
What the seed fixes is the odds, never the answer. Simulate the finished circuit and all thirty-two outcomes still carry some probability, the likeliest of them only 22%. Run that identical circuit twice and about seven times in eight the second run gives you a different plant.
A plant's identity, then, sits not in its circuit but in the one draw that happened, and no amount of re-running gets that particular draw back.
Which is why the garden keeps it rather than recomputing it. None of this runs while you watch. Its circuits went to IonQ ahead of time, and their results sit in a pool of 500. Hovering a plant assigns it one and fixes its traits from then on. Hover again and nothing changes, because there is nothing left to decide.
The randomness happened once, at the moment of measuring. Everything after it is a record.
Quantum GardenQuantum Garden is an interactive generative art installation where digital plants exist in quantum superposition until observed.You cannot print a qubit
Every section above has been about inferring something from a tally. So the obvious question is what was actually in there. There is exactly one way to look, and the thing you have to do first says everything.
QAVE takes a Qiskit circuit and turns it into a deterministic trace: a frame-by-frame record of how the state evolves, which it then renders as an animation. To do that it has to get at the state, and the state is precisely the thing a measurement destroys.

Its solution is the only one available.
# Inspect the pre-measurement statevector
1pre_measurement = circuit.remove_final_measurements(inplace=False)
2psi = Statevector.from_instruction(pre_measurement)
print("Non-zero amplitudes before measurement (bitstring is |q2 q1 q0>):")
for basis, amp in sorted(psi.to_dict().items()): # Keep output order stable.
if abs(amp) < 1e-12:
continue
3 print(f" |{basis}>: {amp.real:+.6f}{amp.imag:+.6f}j")
- 1To look at the state, you first delete the measurement. Not a trick of this project: a circuit that has measured has no state left to inspect.
- 2
Statevector does not read the qubits. It recomputes, from the gates alone, what the state must be. That is simulation, not observation. - 3An amplitude per outcome. Eight are possible for three qubits; a GHZ state puts weight on just
000 and 111 and leaves the other six at zero.
The amplitudes are the full description, and nothing on real hardware will hand them to you. There is no slow API behind which they hide and no flag that turns them on. A device gives you bitstrings.
So this listing is not a way of reading a quantum computer. It is a simulator being asked to predict what the hardware would have had, on a circuit small enough that a laptop can work it out.
The randomness is seeded
The second half of QAVE's measurement handling makes a point the first half sets up. Because the trace is deterministic, the shots are reproducible.
# Require deterministic shot replay for terminal measurements.
1replay = result.require_measurement_shot_replay()
print(f"measurement_shot_replay.shots_total: {replay.shots_total}")
2print(f"measurement_shot_replay.sampling_seed: {replay.sampling_seed}")
# Print outcomes sorted by probability.
print("Top outcomes from measurement_shot_replay.outcomes:")
for outcome in sorted(replay.outcomes, key=lambda item: item.probability, reverse=True):
3 print(f" {outcome.label}: p={outcome.probability:.6f}")
- 1The individual draws, not just the summary. Every shot the trace generated, in order.
- 2A seed. Run the trace again with the same one and you get the same hundred shots back, which no real device would ever give you.
- 3The odds themselves, straight from the maths, to six decimal places. Hardware never prints this line: it only ever gives you draws you have to infer the odds from.
Those two listings carry the distinction. The probabilities are what the state says will happen. The shots are what happened.
A simulator can show you both. A quantum computer shows you only the second, and everything you want to know about the first has to be reconstructed from a pile of them.
Try this when you fork it. The trace is configured with seed=24 and shot_count=100. Change the seed and re-run: the outcome probabilities printed above are identical, because the state has not changed, while the hundred individual shots are different. Then raise the shot count and watch the tally converge on those probabilities it never had access to.
QAVEQuantum Algorithm Visualization Engine turns Qiskit/OpenQASM quantum circuits into deterministic traces and synchronized animations, making quantum algorithms easier to teach and understand.Where the circuit actually runs
Every listing above assumes you can just run the circuit. You can, and the same circuit has more than one place to go.
Entangled Body settles the question in the open, and its answer is a fallback chain.
def run_measurement(ops, shots, seed=None):
"""Run the circuit and return (counts, backend_label)."""
# 1. hosted runtime backend (e.g. IonQ / IBM / Aer provided as `backend`)
bk = globals().get("backend", None)
if HAVE_QISKIT and bk is not None:
try:
1 tqc = transpile(build_circuit(ops, measure=True), backend=bk, optimization_level=1)
2 counts = bk.run(tqc, shots=shots).result().get_counts()
label = "backend: %s" % getattr(bk, "name", getattr(type(bk), "__name__", "provided"))
return dict(counts), label
except Exception as exc:
3 print(" (provided backend failed: %s -- falling back)" % exc)
# 2. qiskit Statevector sampler (no qiskit_aer required)
if HAVE_QISKIT:
4 sv = Statevector(build_circuit(ops, measure=False))
5 counts = sv.sample_counts(shots)
return {k: int(v) for k, v in counts.items()}, "qiskit Statevector"
# 3. pure-Python fallback
6 return _py_run(ops, shots, seed), "pure-Python state vector"
- 1Rewrite the circuit into the gates this particular machine actually has. Hardware does not run
ry and rzz directly, it runs its own small set, and this is the translation. It is also where a circuit can get longer, and longer means noisier. - 2The only line on this page that touches a quantum computer. Everything else here, including every listing above, is arithmetic about one.
- 3And it sits inside a
try, because a hardware run is a network call to a shared machine with a queue in front of it. It can fail, and this project would rather draw something than stop. - 4Fallback one: work out the state from the gates alone. Note
measure=False, the same move QAVE had to make above. A circuit that measures has no state left to compute. - 5Then draw shots from it. You get the same shot-to-shot randomness as hardware and none of the hardware's errors, which is either the point or the problem depending on what you are testing.
- 6Fallback two: the same maths again with no Qiskit at all, so the piece still runs on a machine with nothing installed.
Three ways to get a tally, and only the first is a quantum computer. Both fallbacks work out what the hardware should have produced and draw shots from that.
The simulator wins on nearly everything a developer cares about day to day. Runs are fast, free, exactly repeatable and never queued. At fourteen qubits it is also perfectly honest: it holds the same state the hardware would.
What it cannot do is keep up. Every qubit you add doubles the state a simulator has to track. Fourteen qubits is 16,384 amplitudes and fits in a quarter of a megabyte.
Fifty qubits is about 1.1 quadrillion amplitudes, which is eighteen petabytes and no longer a laptop problem. A fifty-qubit device holds that state anyway, because it stores nothing. It is the thing.
Errors are the other half of the trade. A simulator gives you the distribution the maths predicts; hardware gives you the distribution a physical device produces, which is the one your results will actually have. Those 58 shots in 01 and 10 in the very first histogram are what a real machine looks like, not a flaw in the example.
So the rule of thumb is unglamorous. Develop against the simulator, where a run takes a second and you can change one line and go again. Move to hardware when the question is whether the circuit survives contact with a real device, because that is the one question a simulator is guaranteed not to answer.
Start with the counts
Every project here ends in the same place: a dictionary of bitstrings and how often each one came up. That tally is the whole output of a quantum computer.
Which comes down to four habits. Read a pattern, never a value, because a single shot says nothing about the odds behind it. Choose the question before you run, because the same state answers different questions differently. Keep a corrupted reading separate from a destroyed state, because only one of those can be repaired. And know which of your runs was a machine and which was a prediction of one.
Fork the histogram example first. The listing needs no hardware and no setup, and once you have put two distributions side by side, everything above is about what you are allowed to conclude from them.
Run it, then change the question.
Fork the histograms example and change the counts by hand until you can predict the chart. Then open any project above and find the line where its measurement happens. Everything here is open and yours to build on.
Stay in the loop.
Get the latest tutorials, demos, and project showcases straight to your inbox. No noise, just the good stuff.
- 1About the author
- 2The smallest measurement you can make
- 3All you get is counts
- 4The gates in these circuits
- 5Which question you ask
- 6When the odds are not fifty-fifty
- 7When the instrument is wrong
- 8Hearing the distribution
- 9Measured once, and fixed from then on
- 10You cannot print a qubit
- 11Where the circuit actually runs
- 12Start with the counts
