Error mitigation and fidelity
How Qsolve measures fidelity, how to declare error mitigation with report_mitigation, how mitigated figures are scored and labelled, and what you may claim.
Updated 12 November 2026 View as markdown
On this page
Qsolve measures the fidelity of your quantum run from what crossed the backend, and you declare any error mitigation with ctx.report_mitigation. The raw fidelity is always shown. Your mitigated figures appear beside it, labelled reported, and Qsolve recomputes the fidelity against the same ideal output rather than taking your number.
What fidelity means here
Fidelity compares two probability distributions over bit strings: p, what the device returned, and q, the ideal output of the same circuit. Qsolve uses the classical (Bhattacharyya) fidelity:
F = ( sum over bit strings i of sqrt(p_i * q_i) ) ^ 2
F is 1 for identical distributions and 0 for disjoint ones. With finite shots even a perfect device scores below 1, so every figure comes with a shot-noise floor: the fidelity a noise-free device would get with the same shots.
The ideal output is simulated noise-free and exactly, up to 20 qubits. A circuit with more qubits, or with mid-circuit measurement, resets or classical control, cannot be scored. The share of your quantum method's shots that could be scored is reported as coverage.
What Qsolve measures without you
For the quantum method, Qsolve computes the raw fidelity of the circuits that carry the run's noise:
- A circuit whose ideal output is a single bit string, such as a mirror or calibration circuit, computes nothing the answer depends on and is left out.
- Every other circuit counts, whether or not you reported it. Reporting a flattering subset changes nothing.
- Only circuits with at least half the two-qubit operations of the largest circuit are averaged, so a trivial circuit sent alongside carries no weight.
- The average is weighted by shots. All dispatches of one circuit are pooled before scoring.
With no report, mitigated fidelity equals raw fidelity and the share kept is 1.0. The result's source is ideal_simulator, noise_model or hardware. On an ideal simulator fidelity is only the shot-noise floor, so mitigation is validated on noise-model targets; see Benchmarks.
Declaring mitigation
If you post-process counts to reduce the effect of noise, say so with ctx.report_mitigation. Readout correction, post-selection, zero-noise extrapolation and anything else all count.
ctx.report_mitigation(
circuits=[dispatch], # indices from pub_result.metadata["qsolve"][k]["dispatch"]
distribution={"0101": 0.62, "1010": 0.31, ...}, # the mitigated output, bit string to weight
methods=["readout correction", "post-selection (exactly k ones)"],
kept=0.87, # share of shots kept, between 0 and 1
steps=[{"name": "raw counts", "fidelity": 0.81},
{"name": "readout correction", "fidelity": 0.90},
{"name": "post-selection", "fidelity": 0.96}],
)
| Argument | Required | Meaning |
|---|---|---|
circuits |
Yes | Dispatch indices of the circuits whose output this distribution mitigates, from metadata["qsolve"][k]["dispatch"] of the pub result. |
distribution |
Yes | The mitigated distribution, bit string to weight. Weights must be finite, not negative, and sum to more than zero. Qsolve normalises them. |
methods |
No | Names of the mitigation methods, as plain text. |
kept |
No | The share of shots that survived your checks, 0 to 1. Omit it when nothing was discarded. |
steps |
No | Your own ladder: a list of {"name": ..., "fidelity": ...}. Shown as you give it. |
Bit strings use Qiskit order (classical bit 0 on the right) and must match the measured register's width. This is the real call from the examples:
if run.report and run.dispatch is not None:
ctx.report_mitigation(circuits=[run.dispatch], **run.report)
run.report is a dictionary with distribution, methods, kept and steps, built after readout correction and post-selection in max-cut. molecular-ground-state makes one call per measured circuit, with the dispatch indices of its copies.
A call raises WorkflowError when:
circuitsis empty or cites a circuit that was not sent: "report_mitigation cites circuits [3], but 2 were sent so far (a dispatch id is in pub_result.metadata['qsolve'][k]['dispatch'])";- the distribution is empty, has a negative or non-finite weight, or sums to zero;
keptis outside 0 to 1.
How a report is scored
Qsolve computes the fidelity of your distribution against the ideal output of the circuits it covers. A report is used only when every circuit it cites shares one ideal output, and only for circuits sent by the quantum method. Otherwise it is ignored.
| Number | Source |
|---|---|
| Raw fidelity and its floor | Measured by Qsolve |
| Mitigated fidelity | Recomputed by Qsolve from your distribution; labelled reported |
| Share of shots kept | The mean of your reports' kept values; reported |
| Methods | The union of the names you gave; reported |
| Steps | Your list, as written; reported |
| Coverage | Measured by Qsolve |
Fidelity requirements in benchmark cases
You set the bar yourself in benchmarks/cases.yaml, on a noisy target:
- name: noise-model-ring-6
input_file: examples/ring_6.json
target: fake:fez@1.6
seed: 1
expect: {max_gap: 0.0, min_fidelity: 0.97, max_two_qubit_gates: 40}
expect key |
The case fails when |
|---|---|
min_fidelity |
no mitigation numbers exist; fewer than 90% of the shots could be scored; or the mitigated fidelity is below the bound |
min_postselection |
no mitigation numbers exist, or the share of shots kept is below the bound |
max_two_qubit_gates |
the largest sent circuit, transpiled to cx, rz, sx, x, has more two-qubit gates than the bound |
The gate fidelity_checked fails unless at least one case sets min_fidelity on a fake: or ibm: target. Set bounds to what your circuit measurably reaches, with a margin.
What you may and may not claim
You may report a distribution you computed from the counts that came back through ctx, with post-processing described in methods and steps, and kept as the share of those shots your checks retained.
You may not report a distribution that was not derived from the measured counts: no ideal output from a simulation, no answer known in advance, no classical solution dressed up as a measurement. Qsolve scores a report against the ideal output, so a distribution equal to the ideal output scores a fidelity of 1.
Qsolve can check that the numbers are consistent, not that your mitigation is legitimate. That is why raw figures are shown next to yours and yours are labelled reported. Describe each step in methods and steps so a reader can judge it.
Practical advice
- Readout correction works on the full distribution, so it needs
2^nentries. The examples apply it up to 16 qubits and skip it above. - Post-selection suits problems with a conserved quantity, such as exactly k ones. Report the discarded share honestly in
kept. - Include a
stepsladder when you can; it shows what each stage bought. - Do not rely on mitigation to rescue a deep circuit. Keep circuits shallow first; see Backends and targets.
For how a researcher reads these figures, see Accuracy, fidelity and noise.