Noise Sandbox and Mitigation
Pick a circuit and an observable, dial in a noise model, and watch the ideal value, the noisy value and two mitigated estimates — with the error bar mitigation costs you.
Results
⟨Z0Z1⟩ · Bell pair
—Hollow rose: what the device reports at each fold scale. Amber: the same counts after readout inversion, ± one bootstrap standard error. Violet: the fit through the amber points, run back to λ = 0. The dashed line is the exact statevector answer, which a real device never shows you.
Learned extrapolator
0 / 600 steps · loss —A 3 → 16 → 16 → 1 network, trained here in your tab with Adam on batches of 64 synthetic curves: E(λ) = c + (E₀ − c)·e^(−aλ) at λ = 1, 3, 5 with shot noise added, target E₀. It never sees your circuit. It is bounded at 600 steps, runs in animation-frame slices, and the Stop button is honoured between slices. Once trained, switch the extrapolation to “Learned” and the three amber points go through it instead of a formula.
Fidelity vs depth · Bell pair
not runFidelity is the trajectory average of |⟨ψ_ideal|ψ⟩|², the overlap with the exact state — readout error is not part of it. The dotted reference assumes every one of the 2 gates per block fails independently and no error ever cancels. Budget: 400 trajectories per depth, 9 depths, stoppable.
What to try, in this order
Turn everything off. Zero every slider and switch T1/T2 off. All four numbers agree with the dashed line to the last digit, and the error bars collapse: with no noise the trajectory engine is the ordinary statevector engine, bit for bit.
Readout only. Leave the gate noise at zero and raise the two readout sliders. The raw number sinks; the readout-mitigated number comes back to the ideal — but its bar is wider than the raw bar. That widening is 1/(1 − P(1|0) − P(0|1)) per qubit.
Add gate noise, then fold. Now raise the two-qubit depolarising. Readout mitigation stops being enough: the amber point at λ = 1 sits below the line, and the amber points at 3 and 5 sit lower still. The fit through them, run back to zero, is the ZNE estimate. Try the four fits: the exponential is exact for pure depolarising, the line undershoots on a curve, the parabola chases the noise, and the learned one — once trained — is a compromise the network found on its own.
Change the seed. Same circuit, same noise, different dice. Watch the ZNE estimate wander by roughly its own error bar. If it wanders more than that, the bar is lying; here it should not.
Scan depth. Repeat the block and watch fidelity fall. The Bell pair at depth 2 is the identity — H·CX·CX·H — and the state should be |00⟩ again, which it nearly is; the gap between the measured curve and the dotted product is the errors that cancelled or that the observable never noticed.
What just happened
Each shot is one trajectory: the circuit runs on the ordinary statevector simulator, and after every gate a coin is flipped — with the depolarising probability, a random Pauli is applied to that gate’s qubits. A qubit that has no gate in a layer idles, and per idle step it may relax (|1⟩ → |0⟩, probability 1 − e^(−1/T1)) or pick up a phase flip (from T2). Then every qubit is read out and each classical bit flips with the readout probabilities. Averaged over shots this reproduces the noise channels exactly; per shot it produces the scatter a device produces.
Readout mitigation measures |0…0⟩ and |1…1⟩ on the same noisy device, builds one 2×2 confusion matrix per qubit, and applies the inverse to your counts. The result is a quasi-probability — entries can go slightly negative — and the expectation value over it is unbiased. Zero-noise extrapolation replaces every gate G by G·G†·G and G·G†·G·G†·G, which changes nothing about the ideal unitary and triples or quintuples the noise, measures the observable at each, and fits a curve back to the noise level you cannot reach. Both are post-processing: the device is not better, your estimate of what it would have said is.
What this tool does not do
It does not scale. Readout inversion needs a calibration of 2ⁿ states in general — the two circuits here identify only the uncorrelated model — and a 2ⁿ × 2ⁿ matrix to invert. ZNE needs the circuit at three to five times its depth to still return a signal; past a certain depth the folded points are pure noise and the extrapolation is a line through static. Neither technique turns a 100-qubit, 1,000-gate circuit into a reliable one. That is what error correction is for, and it is a different page.
It amplifies variance. Every mitigated number on this page has a wider bar than the raw number it came from. Inverting readout multiplies shot noise by 1/(1 − P(1|0) − P(0|1)) per qubit; extrapolating from λ ∈ {1, 3, 5} to 0 multiplies it by about 1.5× for a line and far more for a parabola. Mitigation trades bias for variance, and the trade is paid in shots — often 10× to 100× more for the same bar.
It only sees what folding scales. Gate folding multiplies gate errors. It does not stretch idle time, so T1 and T2 decay on idle qubits are not extrapolated away — the “Idle |1⟩” preset shows three identical points. It also assumes the noise is the same at every scale, which real crosstalk and drift violate.
The learned extrapolator is not a physics model. It was trained on the exponential family with shot noise, because that is what depolarising noise produces. On a circuit whose noise curve is not in that family it will be confidently wrong, exactly like a formula fitted to the wrong shape. Its advantage is only that it has seen the noise at training time and learned not to chase it.
The noise model is a model. Uniform depolarising, one T1 and T2 for every qubit, uncorrelated readout, no crosstalk, no coherent over-rotation, no leakage. It is the model most mitigation papers benchmark against; it is not a device.
Take the circuit with you
The circuit being measured, as OpenQASM 3. Paste it into the simulator, or fold it yourself — the scale-3 version is every gate followed by its inverse and itself.
OPENQASM 3.0; include "stdgates.inc"; qubit[2] q; bit[2] c; h q[0]; cx q[0], q[1]; c = measure q;
Checked in lib/quantum/noise.test.ts (zero noise is bit-identical to the ideal engine; a depolarised X gives 1 − 2p/3; an idle |1⟩ decays as e^(−t/T1)) and lib/workbench/mitigation.test.ts (readout inversion recovers a known distribution; ZNE recovers a line’s intercept; the network’s gradients match finite differences).