Repository navigation
qLDPC v0.4.1
This release adds the Tesseract and Frontier decoders, introduces a settings-based way to build decoders, and improves code retrieval and distance tracking.
Important
This release contains small breaking changes to decoder imports and options.
See Migrating from qLDPC 0.4.0 before upgrading.
Highlights
- Settings-based decoder construction (#636). Every decoder is now configured with a settings helper and then built:
decoders.bp_osd(...).build(pcm_or_dem)ordecoders.mwpm(...).build_observable_decoder(dem).
Settings helpers for ldpc, PyMatching, and Relay-BP accept other backend options through abackend_optionsmapping. - Tesseract decoder (#635):
decoders.tesseract(...),decoders.tesseract_preset(...), anddecoders.TesseractDecoder.
Install it withpip install 'qldpc[tesseract]'(Python ≥ 3.12, platforms with published wheels). - Frontier observable decoder (#634):
decoders.frontier(...)anddecoders.FrontierObservableDecoder, which integrate the separately installed Frontier pruned maximum-likelihood decoder for binary detector error models. - Lookup decoder upgrades (#633): a
probability_cutoffoption that skips unlikely errors when building the table, and support for correlated error channels given as a callable over full errors.
Other improvements
- qLDPC Challenge codes (#629):
QuditCode.from_qldpc_challenge_id(...)andCSSCode.from_qldpc_challenge_id(...)load verified submissions, including non-CSS stabilizer codes, together with their certified distance bounds. - QECDB retrieval fixed (#629) to use QECDB's current JSON API.
- Best known distance bounds (#630): codes remember the best distance upper bound they have found or been given, with separate X and Z bounds for CSS codes.
get_distance_bound()now defaults tonum_trials=None, which returns the exact distance or best known bound if available, and otherwise computes a single bound.
A call with explicit trials never returns a worse bound than the best known one. - Cache refresh (#631): functions decorated with
qldpc.cache.use_disk_cachehave a.refresh(...)method, with the same signature, that recomputes the result and overwrites its cache entry.
This release also fixes two caching bugs: callingget_generatorswithout its optional keyword crashed, and calling the group-intersection function with keyword arguments failed. - Python 3.14 development installs (#628). The in-process GAP binding (
libgap) requires Python 3.13; other versions use an executable GAP. - New
qldpc[decoders]extra that installs the optional decoder backends available for your platform.
Breaking changes
qldpc.decoders.construction,qldpc.decoders.custom,qldpc.decoders.external, andqldpc.decoders.construction.specsno longer re-export decoder builders, settings helpers, or resolution functions.
Import these fromqldpc.decodersinstead.- Builders that were never exported from
qldpc.decodershave been removed, for exampleget_error_decoder_mwpm,get_observable_decoder_mwpm,get_relay_bp_decoder,get_min_sum_bp_decoder, andget_observable_decoder_lookup.
Use settings helpers and theirbuild/build_observable_decodermethods. - Passing
error_channelorerror_ratetogether with a detector error model now raises aValueError, because the model supplies its own probabilities.
Previously, the ldpc decoders (BP+OSD, BP+LSD, BF) ignorederror_ratehere and leterror_channeloverride the model's probabilities.
To override them, decode the model's detector-flip matrix, which serves as a parity-check matrix, and map predicted errors to observables yourself:
arrays = decoders.DetectorErrorModelArrays(dem),
decoder = decoders.bp_osd(error_channel=p).build(arrays.detector_flip_matrix), and
observables = arrays.observable_flip_matrix @ decoder.decode(syndrome) % 2. get_decoder_mwpmandget_decoder(..., with_MWPM=True)now reject options that PyMatching would silently ignore, and reservefaults_matrixfordecoders.mwpm(...).build_observable_decoder(dem).
Deprecations
Each of the following still works, but emits a DeprecationWarning that names its replacement:
| Deprecated | Replacement |
|---|---|
error_rate=p |
error_channel=p |
decoders.get_decoder_<NAME>(pcm_or_dem, ...) |
decoders.<NAME>(...).build(pcm_or_dem) |
decoders.get_decoder_rbp(...) |
decoders.relay_bp(...) or decoders.min_sum_bp(...), then .build(...) |
decoders.get_error_decoder(pcm_or_dem, decoder=settings) |
settings.build(pcm_or_dem) |
decoders.get_observable_decoder(dem, decoder=settings) |
settings.build_observable_decoder(dem) |
decoders.get_observable_decoder(dem, decoder=error_decoder) |
decoders.ErrorsToObservablesDecoder(error_decoder, dem) |
decoders.decode_observables(dem, syndrome, decoder=settings) |
settings.build_observable_decoder(dem).decode_observables(syndrome) |
decoders.lookup_table(...) |
decoders.lookup(...) |
penalty_func= (lookup decoders) |
a callable error_channel |
Internal
- One-sentence-per-line formatting for documentation sources (#632).
- Reorganized decoder modules into sections, moving code without changing it (#637).
Full changelog: v0.4.0...v0.4.1