A side-scroller where a quantum measurement decides where the gap goes.
Built for Leveraging AI Workflows on qBraid · Chicago Quantum Exchange Q-Ready · Aug 2026
Play it · The presets · Real QPU data · Multi-agent prompt
One idea, made concrete: a quantum circuit doesn't give you an answer, it gives you a probability distribution. Here that distribution is the level you're flying through.
No prior quantum experience needed. Nothing to install.
1. Launch it. Find Q-Ready Quantum Runner on the qBraid Explore page and click launch. That drops the whole project into your Lab — nothing to clone, nothing to install.
2. Open a terminal in Lab and run:
cd quantum-runner
python3 build-canvas.py
qbraid-canvas game/quantum-runner.html --title "Quantum Runner"3. The Canvas panel opens on the right. Press Space to fly.
↑ ↓ or W S to move · P to pause
That's it. The quantum simulator runs right there in the panel — real statevector maths, about 80 lines of JavaScript, no backend.
What the two commands do.
build-canvas.pyembeds the measured data into the HTML;qbraid-canvasrenders it into the Lab panel. The embed matters because Canvas runs artifacts in a sandboxed frame where a relative file fetch can't resolve — without it the Simulator and Real QPU buttons would silently fail. Re-run both any time you change a data file.
Prefer to run it outside qBraid?
git clone https://github.com/avanbussum/quantum-runner && cd quantum-runner
python3 -m http.server 8000Then open http://localhost:8000/game/quantum-runner.html. Everything works the same — the data is embedded, so it runs offline.
measure 3 qubits → 011 → read as binary → 3 → the gap goes in row 3
Every wall has exactly one gap. A measurement picks where. So the histogram under the game is the measurement distribution — each wall is one sample, and the bars converge on the circuit's true probabilities.
Hit Sample ×100 a few times and watch it happen. That's the law of large numbers, and it's why quantum jobs always run hundreds of "shots."
| Preset | Circuit | What you see | Idea |
|---|---|---|---|
| 1 · Uniform | H on all 3 |
flat histogram, gap anywhere | superposition |
| 2 · Biased | H + RY(θ) |
histogram tilts, gaps favour the bottom | amplitude → probability |
| 3 · Entangled | H + 2×CNOT (GHZ) |
only top or bottom; 6 of 8 impossible | entanglement |
| 4 · Interference | H + RY(−90°) |
one position; 7 of 8 impossible | amplitudes cancel |
Preset 4 is the interesting one. The state panel shows why:
a(1) = (+0.707 −0.707) / √2 = 0.000
Two contributions arrive with opposite signs and cancel to exactly zero. Classical probabilities can only add — they're never negative, so they can never cancel. That's the one thing here with no classical counterpart, and it's how every quantum algorithm that beats a classical one works.
|ψ⟩ = a|0⟩ + b|1⟩ probability = amplitude² a² + b² = 1
Why squared? |ψ⟩ is an arrow of length 1, and a, b are its coordinates. Pythagoras gives
a² + b² = 1 for free — and anything that sums to 1 can be read as probabilities.
Check it with H: amplitudes are 0.707 and 0.707. Raw, they sum to 1.414 — impossible.
Squared: 0.5 + 0.5 = 1. ✓
RY(θ) tilts the arrow. Up = definitely 0, down = definitely 1, horizontal = 50/50:
| θ | arrow | P(1) |
|---|---|---|
| −90° | straight up | 0.00 |
| 0° | horizontal | 0.50 |
| +45° | tilted down | 0.85 |
| +90° | straight down | 1.00 |
RY(−90°) rotates the arrow back up — it undoes the H. That's preset 4.
Bloch arrow length = entanglement. Full arrow means not entangled. A dot at the centre means maximally entangled — that qubit has no state of its own left, because the information moved into the correlations between qubits, which a Bloch sphere can't draw.
The game has three data sources you can switch between — and the middle one is what makes the argument airtight:
| Source | Shots | What it adds |
|---|---|---|
| Theory | none | the circuit's exact probabilities, computed live |
| Simulator | 512 | + sampling noise (qBraid qir-sv) |
| Real QPU | 1000 | + hardware noise (IQM Garnet) |
On the entangled preset, only 000 and 111 should ever appear:
| Source | Result | Impossible outcomes |
|---|---|---|
| Theory | exactly 50/50 | 0 |
| Simulator | [237,0,0,0,0,0,0,275] |
0 |
| Real QPU | [497,12,2,7,8,98,7,369] |
134 |
The simulator is also off from a perfect 256/256 — that's randomness from only taking 512 samples. But it produces zero impossible outcomes. So randomness alone can never do that. Only the hardware can.
Full QPU result for the entangled preset:
000: 497 001: 12 010: 2 011: 7
100: 8 101: 98 110: 7 111: 369
In the game, gaps start appearing in rows where the theory line is flat zero. That's decoherence, and you can watch it happen.
A second lesson, from comparing two circuits:
| Circuit | Two-qubit gates | Forbidden outcomes | Error |
|---|---|---|---|
| Interference | none | 19 / 1000 | 1.9% |
| Entangled | 2 CNOTs | 134 / 1000 | 13.4% |
Same device, same shot count. Two CNOTs made it seven times worse. Two-qubit gates are where the errors live — which is why error mitigation is an entire research field.
In a Lab notebook — this is the circuit behind the Entangled preset:
from qiskit import QuantumCircuit
from qbraid.runtime import QbraidProvider
device = QbraidProvider().get_device("qbraid:qbraid:sim:qir-sv") # free
qc = QuantumCircuit(3)
qc.h(0); qc.cx(0, 1); qc.cx(1, 2) # GHZ — the entangled preset
qc.measure_all()
job = device.run(qc, shots=1000)
job.wait_for_final_state()
print(job.result().data.get_counts())Swap the device for aws:iqm:qpu:garnet to run on real hardware.
Devices bill in two different ways, and it changes which one is cheapest:
| Device | Billing | 1000 shots, small circuit |
|---|---|---|
qbraid:qbraid:sim:qir-sv |
— | free |
ionq:ionq:sim:simulator |
— | free |
rigetti:rigetti:qpu:cepheus-1-108q |
per second of execution | ~45 |
aws:iqm:qpu:garnet |
30/task + 0.145/shot | 175 |
aws:iqm:qpu:emerald |
30/task + 0.160/shot | 190 |
aws:quera:qpu:aquila |
30/task + 1.00/shot | 1,030 |
aws:ionq:qpu:forte-enterprise-1 |
30/task + 8.00/shot | 8,030 |
Per-second billing looks alarming and usually isn't. Rigetti's headline rate is 12,000 credits/minute, but a shallow 3-qubit circuit executes in a fraction of a second. A real 1,500-shot run on it cost 67 credits — about a third of a second of machine time, and 3.7× cheaper than the same job on IQM.
1500 shots, small circuit
Rigetti 67 credits (0.34 s of execution)
IQM 247 credits (30 + 0.145 × 1500)
The break-even is around 1.2 seconds of execution. Below that Rigetti wins; above it the per-minute rate compounds and per-shot pricing becomes safer.
Rule of thumb: shallow circuits → per-second device is cheapest. Deep circuits, long runs, or anything unattended → per-shot pricing, because you can compute the bill before you submit.
openquantum:* devices appear free but need a linked OpenQuantum account and fail without one.
Free signup credits go a long way on the simulator, which is free and unlimited. Prototype there, then spend on hardware.
1 — Find the blind spot. Set the entangle knob above 0 and leave θ at 0. Nothing happens. Why?
(After H every qubit is perfectly balanced, and a CNOT on perfectly balanced qubits produces no
entanglement. Nudge θ and watch the Bloch arrows shrink.)
2 — Predict before you look. At θ = 45° each qubit is 85% likely to read 1. What's P(111)? (Cube it. Then check the histogram.)
3 — Break it on hardware. Run the GHZ circuit on aws:iqm:qpu:garnet and count your own
forbidden outcomes. Then try 4 qubits — does it get worse? (It will. More CNOTs.)
4 — Extend it with an agent. This is the whole point of the workshop. From a Lab terminal:
qbraid agents launch --tool claude --cwd ~/quantum-runner --name game-builder
qbraid agents send game-builder --text "Add a score counter to game/quantum-runner.html that gives bonus points when the gap lands on an outcome with under 5% probability."
qbraid agents send game-builder --text $'\r'The second
sendis the Enter key —sendtypes the text but doesn't submit it.
Watch it work with qbraid agents watch game-builder, then re-render:
python3 build-canvas.py && qbraid-canvas game/quantum-runner.html --title "Quantum Runner"prompts/multi-agent-error-mitigation.md
The same platform runs AI agents on cloud compute. That file is a single prompt that spins up a lead agent plus three workers, has them investigate quantum error mitigation — GPU simulations, real QPU jobs, cross-validation — and produces a self-updating HTML report. It runs 30–45 minutes unattended.
errmit-lead (leader)
|
+-------------------+-------------------+
| | |
errmit-zne errmit-pec errmit-rem
(worker) (worker) (worker)
→ See the report it actually produced
The headline finding is a negative result, which is the interesting part:
"The real Garnet device is far cleaner than our noise model, so there is almost nothing to mitigate. ZNE's on-device gain falls inside the error bar, and REM actually overshoots — worse than raw. Mitigation only pays when there is genuinely enough noise to mitigate."
The team fixed its pass/fail criteria before running anything, benchmarked against a circuit with a known ideal answer, ran null controls, propagated error bars, and re-derived every number from raw job counts — then reported that the thing it was asked to evaluate didn't help.
It's also a decent case study in why multi-agent prompts fail. Four constraints in there exist
because the obvious version breaks — agent messaging is local-host only, compute up steals your
subscription server, agents calling qbraid-canvas hijack your screen, and "ask me anything you
need" guarantees it stalls waiting for you. The file explains each one.
The Agent Canvas is a panel in Lab that renders HTML next to your terminal. From a Lab terminal:
qbraid-canvas prompts/multi-agent-error-mitigation.report.html --title "Error Mitigation Study"The panel auto-opens on the right within ~2 seconds. The report is self-contained — no external resources, no relative links — so it renders correctly inside Canvas's sandboxed frame.
If you're running the prompt yourself, the agents serve a live, multi-page site instead, and you point Canvas at the port rather than a file:
qbraid-canvas --port 8080 --title "Error Mitigation — live"| Use | Command |
|---|---|
| One self-contained HTML file | qbraid-canvas <file>.html --title "…" |
| A live site with linked sub-pages | qbraid-canvas --port 8080 --title "…" |
| Full docs | qbraid-canvas guide |
A single HTML file can't link to sibling pages inside Canvas, which is why the live version serves a directory on a port. There is also only one Canvas — each render replaces the last.
game/quantum-runner.html the game — self-contained, no build step
data/sim_results.json qBraid simulator runs, 512 shots
data/qpu_results.json IQM Garnet runs, 1000 shots
build-canvas.py re-embeds the data after you change it
prompts/multi-agent-error-mitigation.md the four-agent orchestration prompt
prompts/multi-agent-error-mitigation.report.html what it produced — open in a browser
If you edit a data file, run
python3 build-canvas.py. The measurements are embedded directly in the HTML so the game works offline and inside the qBraid Agent Canvas sandbox, where a relativefetchcan't resolve.
This is not quantum advantage. numpy.random.choice makes this game perfectly well. The quantum
part is real, but the value is that the concepts become visible — not that it's faster.
This doesn't prove entanglement. Measuring in a single basis, you can't distinguish quantum correlation from classical correlation; that needs a Bell test. What it shows is how circuit structure shapes a distribution.
The interference result is the strong claim, and it holds. Amplitude cancellation to exactly zero is genuinely non-classical.
Built on qBraid · one login, 34 devices, ten hardware providers.
