Skip to content

Improve STN/MAST simulators: locality-ordered projection, prefix-tree sampling, qec-grade defaults, full Python exposure and docs - #521

Closed
ciaranra wants to merge 15 commits into
devfrom
stn-pepsy-lessons
Closed

Improve STN/MAST simulators: locality-ordered projection, prefix-tree sampling, qec-grade defaults, full Python exposure and docs#521
ciaranra wants to merge 15 commits into
devfrom
stn-pepsy-lessons

Conversation

@ciaranra

Copy link
Copy Markdown
Member

Improves the experimental STN/MAST simulators (exp/pecos-stab-tn) with techniques
validated against sibling implementations of the same representation, flips the general
defaults to the qec-grade posture, and closes the Python exposure gaps. Design notes,
cross-review record, and benchmarks live in the design vault; cross-implementation
correctness was verified against an independent oracle (all backends agree to 1e-16 on
identical small circuits).

Simulator improvements

  • MinSpan deferred projection order for Mast (now the default; Input preserves the
    legacy order bit-for-bit including RNG consumption). Ancillas are projected by dynamic
    frame locality, recomputed after every collapse. At the T=2N saturation regime
    (32 data / 64 T), peak projection bond drops 64 -> <=2 and wall time 12.8 s -> 7 ms.
    Verified by 5-sigma sampled-distribution tests against exact STN probabilities at
    n=3..5, T=3..6. Per-projection diagnostics (projection_records) included.
  • Numerical |0> flag re-detection (opt-in numerical_flag_redetection): when the
    symbolic disentangling-flag search misses, product sites are tested numerically at a
    fixed 1e-12 tolerance and the existing verified fast path takes over. Detection only —
    no new absorption algebra. Adversarial-regime fast-path rate improves 1.8% -> 6.2%
    (deep 2q) and 16.4% -> 24.0% with mean bond 1.43 -> 1.23 (T-heavy 3q); research-target
    regimes are unchanged (already optimal). Guarded off while lazy deferred ops are
    pending (stored tensors differ from the effective state by the deferred Clifford).
  • Prefix-sharing perfect sampling (sample_bitstrings): depth-first prefix tree over
    the existing forced-projection sequence; each distinct measurement prefix is projected
    once and shared across all shots taking that branch. At n=20 / 10k shots: 24 s -> 9 ms
    vs the per-shot-clone sampler. Distribution equivalence verified at 5 sigma against
    exact probabilities; original simulator state preserved; the existing sample_bitstring
    is unchanged.
  • Typed execution advice (StabMpsCompile::advise): injection-mode recommendation
    (direct / immediate / deferred) with ancilla-budget feasibility (one fresh ancilla per
    non-Clifford RZ under deferral), exact Angle64 injectable classification (a gate's
    correction is Clifford iff its doubled angle is Clifford, matching the MAST
    correction), and warnings as data. SimulatorKind gains Mast; recommend() is
    unchanged for existing callers.

Defaults

StabMps now defaults to the qec-grade posture: max bond 128, adaptive truncation-error
bound 1e-8, merged same-qubit RZ. MpsConfig::default() is aligned so StabMps, Mast,
direct Mps use, and the sim_neo lane share one default posture. Every legacy behavior is
one explicit call away (max_bond_dim(64), max_truncation_error(0.0) — the documented
disable, verified by a dedicated test — merge_rz(false), ProjectionOrder::Input).
Tests that exercised legacy paths now pin those paths explicitly; no assertion was
weakened.

Python bindings (pecos-rslib-exp)

  • Boolean constructor kwargs are tri-state (None = default, explicit True/False
    actually applies — previously False was silently ignored).
  • New constructor kwargs: svd_cutoff, numerical_flag_redetection; Mast gains
    projection_order ("min_span" | "input") and numerical_flag_redetection.
  • New surfaces: sample_bitstrings, amplitude, amplitude_iterative,
    overlap_with_stabilizer, renyi_s2 / s2_pce / s2_pcmps, disentangle,
    stats(), OFD telemetry (ofd_nullity, theoretical_min_bond_dim, ...),
    bond_cap_hits, apply_bit_flip / apply_phase_flip, Mast projection diagnostics,
    and a new StabMpsCompile class with recommend() / advise().
  • Python smoke tests in python/pecos-rslib-exp/tests/test_exposure.py (require a built
    wheel; exercised in the comparison-harness environment).

API consistency and usability

From an audited ergonomics review of both API surfaces:

  • One bitstring convention everywhere: bits[q] == qubit q for prob_bitstring,
    amplitude, amplitude_iterative, and both samplers (previously the probability and
    amplitude APIs interpreted their argument reversed, so sampled rows fed back into
    prob_bitstring silently produced wrong values). Breaking change to those two APIs,
    documented at crate level and pinned by a sampler-to-probability round-trip
    regression test.
  • Python reads materialize pending state: read methods flush merged RZs and lazy
    deferred operations first, so results are never stale; status reads
    (is_state_exact, pragmatic_drift_count) deliberately do not flush. Rust flush()
    now materializes lazy deferred operations as well as pending RZs.
  • Uniform Python validation: qubit bounds raise IndexError, malformed
    bitstrings / Pauli strings / probabilities raise ValueError across all three
    classes; no Rust panic is reachable from bad Python arguments.
  • Mast capacity visibility: remaining_injections() (Rust and Python) plus
    constructor docs for the capacity workflow; advise() computes the requirement.
  • Docstrings across both surfaces carry conventions, costs, and performance steering
    (per-shot vs prefix-tree sampling, dense vs iterative amplitude), with Python
    quickstart documentation under docs/ wired into the doc-test framework.

Verification

  • Full crate suite (unit + verification + doc tests) and clippy (--all-targets -D warnings) green on every commit; caches forced cold on changed code.
  • Cross-implementation validation: 1,470 comparisons on identical circuits against an
    independent dense oracle — statevector, Pauli expectation, and bitstring probability
    agreement at ~1e-16 for both PECOS configurations.
  • Benchmarks recorded with environment/commit provenance in the comparison harness;
    headline numbers above reproduce on rerun.

@ciaranra

Copy link
Copy Markdown
Member Author

API-naming question for the owner: the sampler pair is now sample_bitstring (legacy, per-shot clone — kept for per-shot RNG-order reproducibility) and sample_bitstrings (prefix-tree, up to ~2700x faster, the documented primary). The ergonomics audit recommended renaming to sample_bitstrings_independent / sample_bitstrings_prefix_tree with deprecated aliases. Current state keeps both names with docstrings steering to the plural. Rename or keep as is?

@ciaranra
ciaranra marked this pull request as draft August 15, 2026 14:45
@ciaranra

Copy link
Copy Markdown
Member Author

Superseded by #523 (same commits, branch renamed). All review findings carry over; fix program in progress.

@ciaranra ciaranra closed this Aug 15, 2026
@ciaranra
ciaranra deleted the stn-pepsy-lessons branch August 15, 2026 15:08
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant