Guides · 4 of 5 · 12 min read

Rare-event estimation

Reach 10⁻⁷ logical error rates without 10⁹ shots, using the decoder-agnostic glean.dss and glean.splitting estimators.

The deepest published logical error rates (around 10⁻⁷) are infeasible by direct Monte-Carlo — you would need on the order of 10⁹ shots to see a handful of failures. Glean ships two decoder-agnostic importance-sampling estimators that reach those depths, both reusing the same DEM (H / observables / priors) and batched decode.

The 10⁹-shot wall

To resolve a failure rate of p_L you need roughly 1/p_L shots just to see one failure, and many multiples of that for a tight estimate. At p_L ≈ 10⁻⁷ that is hundreds of millions of decodes — out of reach. Both estimators sidestep this by importance sampling: spend shots where the failures actually live, then correct the bias analytically.

The decode_fn contract

Both estimators are decoder-agnostic: you hand them a decode_fn(syndromes) that takes a list[list[int]] and returns an array-like of shape (len(syndromes), num_observables). Any of the three decoders works — wrap relay-BP to drop its iteration counts. That single contract is why one estimator harness serves BP+OSD, relay-BP, and BP+OTF alike.

glean.dss — Dynamical Subset Sampling

DSS (Heußen 2024) stratifies the independent faults by their weight w and writes p_L(p) = Σ_w A_w(p) · p_fail^(w). The weight probabilities A_w are exact and decoder-independent (a Poisson–binomial of the priors), so only the few contributing low-w classes (w ≳ d/2) need sampling — and the dominant w=0 class is never sampled at all.

dss.py
import glean, numpy as np

g = glean.load_dem(dem_text, n_det, n_obs)
decode_fn = lambda s: np.asarray(g.decode_batch(s, osd_order=10, parallel=True))

# Stratify on fault weight; only the contributing low-w classes are sampled.
est = glean.dss.estimate(g, decode_fn, weights=range(1, 13), shots=50_000)
print(est.p_L, "+/-", est.err, "bracket", (est.p_L_lo, est.p_L_hi))

DssEstimate carries p_L, err, a rigorous truncation bracket (p_L_lo, p_L_hi), and the per-class breakdown. Even a class with zero observed failures gets a positive Wilson upper bound, which is what keeps the bracket honest.

B8 — unbiased on Glean's pipeline, 0.0σ vs direct MC at p=3×10⁻³.

One campaign, a whole curve

Because p_fail^(w) does not depend on the physical error rate, you decode once and recombine with A_w(p) at every target rate to trace the whole p_L(p) curve — no re-decoding.

dss_curve.py
# Decode ONCE — p_fail^(w) is independent of the physical error rate p.
table = glean.dss.sample_pfail(g, decode_fn, weights=range(1, 13), shots=50_000)

# Recombine with the (decoder-independent, exact) weight probabilities A_w(p)
# at each target rate — no re-decoding.
for p in (1e-3, 2e-3, 3e-3):
    g_p = glean.load_dem(build_dem_at(p), n_det, n_obs)   # your DEM rebuilt at rate p
    A = glean.dss.weight_probs(g_p, w_max=12)
    print(p, glean.dss.combine(table, A).p_L)

glean.splitting — the deep-number pin

DSS hits a resolution wall when a single mode dominates the deepest classes. Splitting (Bravyi–Vargo 2013; Mayer 2025) has no such wall: it writes P_L(p_target) = P_L(p_1) · ∏_j R_j as a telescoping product of ratios, each estimated by Bennett's acceptance-ratio method over a Metropolis-in-F chain.

splitting.py
import glean, numpy as np

g = glean.load_dem(dem_text, n_det, n_obs)

# Telescope from a tractable rate down to the deep target. The decoder is fixed at
# the target rate, so the estimate is the standard matched logical error rate.
p_seq = [3e-3, 2.4e-3, 1.8e-3, 1.4e-3, 1e-3]
priors_per_rate = [build_priors(p) for p in p_seq]        # DEM priors rebuilt per rate

est = glean.splitting.estimate(
    g, p_seq, priors_per_rate,
    seed_log_pL=np.log(2.4e-3), seed_log_pL_err=0.1,
    n_chains=8, burn_in=50_000, n_samples=4000, thin=2000, seed=0)

print(est.pL, "band", (est.pL_lo, est.pL_hi), "rhat", est.rhat)

SplittingEstimate reports pL, a band (pL_lo, pL_hi), the per-rate ratios, and rhat — the Gelman–Rubin mixing diagnostic. Trust the estimate when rhat < 1.1. See benchmarks/splitting_gross.py for the full deep-point harness, including building the per-rate priors.

B9/B10 — unbiased vs direct MC at p=3×10⁻³ (0.07σ) and p=2×10⁻³ (0.30σ); pins the Bravyi Nature deep point within convention+extrapolation uncertainty.

Which to use

  • DSS — fast, gives the whole curve from one campaign, and is exact where a few low-weight classes dominate. Reach for it first.
  • splitting — the deep-number pin. Use it when DSS's bracket is wide because one mode dominates, or to telescope two-plus decades into the rare regime.

Honesty. These estimators reach depths direct MC cannot, but the very deepest numbers (the full XYZ ~2-OOM, the FPGA relay point) remain compute-walled even so — each write-up states what is pinned and what is deferred.