You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Fix bit pack of mwpf and fusion blossom decoders under multiple logical observable (#873)
This PR fixed two bugs in MWPF decoder
## 1. Supporting decomposed detector error model
While MWPF expects a decoding hypergraph, the input detector error model
from sinter is by default decomposed. The decomposed DEM may contain the
same detector or logical observable multiple times, which is not
considered by the previous implementation.
The previous implementation assumes that each detector and logical
observable only appears once, thus, I used
```python
frames: List[int] = []
...
frames.append(t.val)
```
However, this no longer works if the same frame appears in multiple
decomposed parts. In this case, the DEM actually means that "the
hyperedge contributes to the logical observable iff count(frame) % 2 ==
1". This is fixed by
```python
frames: set[int] = set()
...
frames ^= { t.val }
```
## 2. Supporting multiple logical observables
Although a previous [PR
#864](#864) has fixed the panic
issue when multiple logical observables are encountered, the returned
value is actually problematic and causes significantly higher logical
error rate.
The previous implementation converts a `int` typed bitmask to a
bitpacked value using `np.packbits(prediction, bitorder="little")`.
However, this doesn't work for more than one logical observables.
For example, if I define an observable using `OBSERVABLE_INCLUDE(2)
...`, supposedly the bitpacked value should be `[4]` because $1<<2 = 4$.
However, `np.packbits(4, bitorder="little") = [1]`, which is incorrect.
The correct procedure is first generate the binary representation with
`self.num_obs` bits using `np.binary_repr(prediction,
width=self.num_obs)`, in this case, `'100'`, and then revert the order
of the bits to `['0', '0', '1']`, and then run the packbits which gives
us the correct value `[4]`.
The full code is below:
```python
predictions[shot] = np.packbits(
np.array(list(np.binary_repr(prediction, width=self.num_obs))[::-1],dtype=np.uint8),
bitorder="little",
)
```
0 commit comments