Problem
The Python decoder objects that all consume a DEM expose three different call
and result shapes, so user code cannot iterate over decoders uniformly:
| Decoder |
Methods |
Per-shot result |
PyMatchingDecoder |
decode, decode_batch |
.correction (per-observable vector) |
TesseractDecoder |
decode, decode_batch, decode_syndrome |
.observables_mask (bitmask) |
DemAwareDecoder |
decode_syndrome |
.observables_mask (bitmask) |
Writing an explicit comparison therefore needs a different expression per
decoder:
pymatching_errors += pymatching.decode(syndrome).correction[0] != actual
tesseract_errors += (tesseract.decode_syndrome(syndrome).observables_mask & 1) != actual
bp_osd_errors += (bp_osd.decode_syndrome(syndrome).observables_mask & 1) != actual
(from docs/workflows/guppy-dem-decoding.md, which shows this honestly rather
than hiding it behind the stringly-typed SampleBatch.decode_count(text, name)
shortcut).
Proposal
Give the DEM-consuming decoders one shared Python protocol: a single per-shot
method name and a single result shape (mask and per-observable vector both
available on the result, rather than one or the other depending on the class),
plus a batch variant with the same contract. Keep the existing methods as
deprecated aliases during a ramp, as in #424.
The Rust side already has this notion: ObservableDecoder::decode_obs is the
wide primitive the registry dispatches through
(python/pecos-rslib/src/fault_tolerance_bindings.rs,
create_observable_decoder). The Python surface should expose the same
uniformity instead of the stringly-typed registry being the only uniform path.
Related
Consistency series: #422, #423, #424, #425, #428. The stringly-typed
decode_count(text, "name") registry is fine as a fast-path convenience, but it
should not be the only way to treat decoders uniformly.
Problem
The Python decoder objects that all consume a DEM expose three different call
and result shapes, so user code cannot iterate over decoders uniformly:
PyMatchingDecoderdecode,decode_batch.correction(per-observable vector)TesseractDecoderdecode,decode_batch,decode_syndrome.observables_mask(bitmask)DemAwareDecoderdecode_syndrome.observables_mask(bitmask)Writing an explicit comparison therefore needs a different expression per
decoder:
(from
docs/workflows/guppy-dem-decoding.md, which shows this honestly ratherthan hiding it behind the stringly-typed
SampleBatch.decode_count(text, name)shortcut).
Proposal
Give the DEM-consuming decoders one shared Python protocol: a single per-shot
method name and a single result shape (mask and per-observable vector both
available on the result, rather than one or the other depending on the class),
plus a batch variant with the same contract. Keep the existing methods as
deprecated aliases during a ramp, as in #424.
The Rust side already has this notion:
ObservableDecoder::decode_obsis thewide primitive the registry dispatches through
(
python/pecos-rslib/src/fault_tolerance_bindings.rs,create_observable_decoder). The Python surface should expose the sameuniformity instead of the stringly-typed registry being the only uniform path.
Related
Consistency series: #422, #423, #424, #425, #428. The stringly-typed
decode_count(text, "name")registry is fine as a fast-path convenience, but itshould not be the only way to treat decoders uniformly.