Skip to content

codes module fixes (capacity estimation and logical operators) - #577

Merged
perlinm merged 6 commits into
mainfrom
fix/p5-code-core
Aug 27, 2026
Merged

codes module fixes (capacity estimation and logical operators)#577
perlinm merged 6 commits into
mainfrom
fix/p5-code-core

Conversation

@perlinm

@perlinm perlinm commented Aug 27, 2026

Copy link
Copy Markdown
Collaborator

AI-generated summary

Correctness and robustness fixes in codes/common.py, plus extraction of the Monte-Carlo capacity helpers into a new codes/_monte_carlo.py. No public API signatures are added or removed; the behavioral changes are bug fixes and tightened/loosened input validation on existing methods.

Capacity estimation

  • Decode against stabilizer generators (not the gauge matrix), fixing a crash on subsystem codes and letting the decoder be selected correctly for codes over non-binary fields.
  • Extract the Monte-Carlo helpers (ErrorRateFunc, sample allocation, error-weight probabilities, decode-and-erasure) into codes/_monte_carlo.py, re-exported from codes, with dedicated unit tests; rename the per-weight sampler to reflect that it returns failure and discard counts.
  • ErrorRateFunc: at error_rate == 1 place the probability mass at block_length only when it is in range (no out-of-bounds slice or impossible weights), and share one zero-sample divisor guard across the infidelity and discard-rate paths.

Logical operators

  • set_logical_ops: validate the full symplectic Gram matrix, so a basis with anticommuting same-type logicals is rejected rather than silently accepted.
  • set_logical_ops_x / set_logical_ops_z: accept a width-n single-type matrix as a convenience alongside the full width-2n symplectic form, and validate the operator count and shape up front, so a wrong number of operators (or a 1-D array) raises a clear error instead of a cryptic linear-algebra or indexing failure. The check is shared by the QuditCode and CSSCode implementations.
  • Transversal-circuit logical corrections: look up logical operators through the code's own get_logical_ops, so CSS and non-CSS codes read the shared logical-operator cache in a consistent format.

Other

  • from_strings: reject an empty collection of parity checks with a clear error instead of an IndexError, and report the mismatched lengths when checks differ.
  • _get_distance_exact: cover a reachable fallback with a bare-CSSCode distance test.
  • Assorted naming and docstring cleanups.

perlinm and others added 6 commits August 25, 2026 19:36
…tract Monte-Carlo helpers

Decode subsystem codes against their stabilizer generators in the code-capacity logical error rate
estimators:

- CSSCode: compute syndromes from the stabilizer generators (the matrices the decoders are built to
  invert), fixing a crash on subsystem codes, whose number of stabilizer generators differs from the
  number of gauge generators (parity checks).
- QuditCode: build the decoder and syndromes from get_stabilizer_ops() instead of the full gauge
  matrix. For non-subsystem codes this is unchanged; for subsystem codes it decodes against the
  measurable stabilizer generators rather than the non-commuting gauge generators.
- Keep the syndrome matrix as a field array so that get_decoder can select a decoder appropriate to
  the field; code-capacity estimation now works for codes over non-binary fields.

Also:

- get_syndrome_subgraphs: include every check present in the Tanner graph, so a check whose support
  overlaps no other check still appears in a returned subgraph.
- concatenate: operate on a copy of the outer code so that the caller's logical operators are not
  modified.
- CSSCode capacity: decide whether the X-type and Z-type decoders can be shared using the fully
  merged decoder arguments.

Move the Monte-Carlo helpers (ErrorRateFunc, sample allocation, error-weight probabilities, and
decode-and-erasure) into codes/_monte_carlo.py and re-export them, with dedicated unit tests.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
- get_distance_bound (CSSCode): make pauli keyword-only, matching the base signature's
  num_trials-first convention and removing a misleading positional-pauli affordance.
- num_qubits: emit a single-line error message with a real class name (previously a raw
  string left a literal "\n" and an unfriendly class repr).
- from_strings (QuditCode): reject an empty collection of parity checks with a clear error
  instead of an IndexError, and report the mismatched lengths when checks differ.
- Rename the per-weight sampling helpers to reflect that they return failure and discard
  counts (not a variance), and to use consistent names across the code classes.
- _get_distance_exact (CSSCode): drop a "no cover" pragma from a reachable fallback and cover
  it with a bare-CSSCode distance test.
- set_logical_ops_x / set_logical_ops_z (QuditCode): drop an untested branch for
  single-type-support input; the documented input is a full symplectic (k, 2n) matrix.
- get_destabilizer_ops: document that a pauli argument selects the destabilizers dual to the
  stabilizer generators of the opposite type.
- Document that CSSCode's promise_equal_distance_xz is trusted rather than verified.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
set_logical_ops previously checked only that the X-type and Z-type logical operators had the
correct cross-type commutation relations (Lx Ω Lz.T = I).  It now checks the full symplectic Gram
matrix Lx Ω L.T against the block anti-diagonal [[0, I], [-I, 0]], which additionally requires that
the X-type logicals mutually commute and the Z-type logicals mutually commute.  A basis that
satisfies the cross-type relations but has, for example, two anticommuting X-type logicals is now
rejected rather than silently accepted.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…ss instance

QuditCode.get_logical_ops and CSSCode.get_logical_ops cache logical operators in the same
self._logical_ops attribute but in different formats: the base implementation stores the symplectic
(mixed-support) form, while CSSCode stores the block-diagonal single-type form.  Invoking the base
implementation directly on a CSSCode instance (as circuits/transversal.py does) populated the shared
cache with a base-format basis, after which CSSCode.get_logical_ops(Pauli.X, symplectic=True) misread
it and returned X-type logical operators with spurious Z-type support.

Guard the base implementation so that, when it is called on an instance whose type overrides
get_logical_ops, it defers to that override.  The cache is then always read and written in the format
of the most-derived implementation.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
At error_rate == 1, _get_error_probs_by_weight assigns the unit mass to
weight == block_length only when that weight lies within the array, and
otherwise leaves the probabilities at zero (fully truncated), rather than
slicing past the end of the array or marking impossible weights.

The zero-sample divisor guard is factored into ErrorRateFunc._as_divisor
and applied to both the infidelity and discard-rate paths, so a weight
with no (kept) samples yields a zero rate and variance instead of nan or
inf. The optimistic zero-kept-samples behavior and its link to the
deferred Jeffreys error-bar fix are documented in place.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…e set_logical_ops shapes

- Look up logical operators through the code's own get_logical_ops in the transversal-circuit
  corrections, so CSS and non-CSS codes read the shared cache in a consistent format, and drop
  the base-method dispatch guard (and its test) that this made unnecessary.
- Accept a width-n single-type matrix in QuditCode.set_logical_ops_x/z alongside the full
  width-2n symplectic form, and validate the operator count and shape up front via a shared
  _validate_logical_ops_shape used by both QuditCode and CSSCode, so a wrong count or a 1-D
  input raises a clear error rather than a cryptic linear-algebra or indexing failure.
- Restore the positional pauli argument on CSSCode.get_distance_bound.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@perlinm
perlinm merged commit 3ef4d11 into main Aug 27, 2026
3 checks passed
@perlinm
perlinm deleted the fix/p5-code-core branch August 27, 2026 00:41
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