title | author | date | bibliography |
---|---|---|---|
Notes on `vecdec` |
Leonid P. Pryadko |
2023/07/11 |
refs.bib |
Given a sufficient number of decoding steps (different column permutations hits
for every error vector, we can estimate the probability of
missing the "correct" vector of weight smaller than
In practice, we want to implement hashing storage to keep
For a given column permutation
For a given (transformed) syndrome vector
With level-$t$ random-window decoding (RW-$t$), up to
Unfortunately, especially with LDPC codes, the probabilities of encountering
different information sets (the numbers of permutations
Belief propagation (BP) is notoriously difficult for highly-degenerate quantum
codes, as it gets stuck often at degenerate configurations. On the other hand,
it tends to clear small-weight errors efficiently, after
Currently, there is a function do_local_search()
which for some
reason is extremely slow. It attempts to construct all error vectors
at once. Specifically, for each non-pivot point jj
it
- makes a copy of current error vectors,
- calculates the list
rlis
of pivot positions to update, - after which goes over each syndrome vector:
- calculates the current energy
(may be slow?)
- flips the bit at
jj
- updates the energy by flipping each position in
rlis
- compares with the stored energy values
- calculates the current energy
To speed up this version:
- copy the energy values between recursion levels
- do not copy current error vectors for last recursion level
- introduce the maximum number of columns to do OSD with
- perhaps introduce a cut-off by weight?
- use
mzd_find_pivot()
???
Instead, implement a recursive function do_local_search_one()
which
deals with one syndrome vector and one error vector at a time. Use it
for both mode=0
(information set decoder) and as OSD with BP
(mode=1
).
With a given detector error model (specified by detector-fault incidence matrix
In the case of graph errors, summation over paths can be done approximately with
the help of weighted Hashimoto matrix, defined in terms of directed edges
(arcs), $$ M_{a=i\to j,b=i'\to j'}= W_a \delta_{j,i'}(1-\delta_{i,j'}),\quad
W_a\equiv 2[p_a(1-p_a)]^{1/2}, $$ where
In practice, when
The issue with the expansion over fault-lines (codewords) is non-locality.
Indeed,
The function
- It is increasing, meaning that if
$A\subset B$ ,$P_A(e)\le P_B(e)$ - When sets
$A$ and$B$ have partial overlaps,$A\neq A\cap B\neq\emptyset$ and$B\neq A \cap B$ , as long as$P_{A\cap B}(e)=0$ ,$P_{A\cup B}(e)=P_{A}(e)+P_{B}(e)$ (???)
Furthermore, consider a set of non-trivial irreducible binary codewords
- Implement recursive enumeration of vectors from the information set.
- Implement reading of externally generated simulation data (e.g., from
Stim) using separate files with detection events and the corresponding
observables. Here is a sample command-line to produce binary vectors in
01
format:
stim sample_dem \
--shots 5 \
--in example.dem \
--out dets.01 \
--out_format 01 \
--obs_out obs_flips.01 \
--obs_out_format 01
-
Implement a mode for finding the list of most likely zero-syndrome error vectors.
-
Implement hashing storage for small-weight errors (say, up to weight 2) and the corresponding syndromes for fast lookup decoding. Subsequently, use decoding results to add most likely vectors to this list.
-
Implement hashing storage for near-ML decoding using lists of small-weight errors. Perhaps use
vecdec
in scalar mode for this, working with just one (or a few) syndrome vectors at a time, and keeping the corresponding hashing storage separate, so that only the error vectors (in sparse form?) and the corresponding probabilities need to be store. E.g., try using theuthash
library. -
Implement BP decoding with OSD
- Actual BP steps
- Add
BoxPlus()
fromit++
library - serial BP (c-based): given the order of check nodes, select
c
,- update messages to
c
, - update messages from
c
.
- update messages to
- serial BP (v-based)
- Add error estimation
- BP with randomization of probabilities
- BP with Freezing / Stabilizer inactivation (Savin et al)
- BP version by Kung, Kuo, Lai (http://arXiv.org/abs/2305.03321) and/or Kuo, Lai (http://arXiv.org/abs/2104.13659)
- Add OSD
- Stopping sets analysis?
- Initial BP acceleration ?
- Other tricks from papers by Narayanan; Kuo+Lai; Roffe; Valentin Savin
-
Come up with alternative simulation mechanisms, e.g., in the regime of small error probabilities
$p$ . -
Hashimoto matrix implementation steps
- Given a DEM in a graph form, construct the sparse weighted Hashimoto
matrix (of size
$2n\times 2n$ ). - Construct an in-vector
$x$ and a weighted out-vector$y$ - Calculate the corresponding logical fault-rates
- Estimate the fudge-factor
$\alpha$ , given the statistics of error probabilities - Estimate the effect of correlations between the trajectories.
- Given a DEM in a graph form, construct the sparse weighted Hashimoto
matrix (of size
-
Code transformations reducing the degeneracy for
mode=3
- Check for
w=1
andw=2
degeneracies (submodew
: remove degeneracies up tow
if non-zero, otherwise do no transformations) - Remove
w=3
degeneracies (rows of weight 3 inG
) (see the unfinished functionint star_triangle()
instar_poly.c
) - make a structure for "column", with
[col_number, K, colG, colL]
, wherecolG
andcolL
give sparse representation of the corresponding matrix column; sortable bycol_number
, and a routine to restore the sparseH
,L
matrices and the error vector. - Start with
Ht
,Lt
, and theG
matrix (e.g., read from a file) or even a list of codewords (not necessarily complete) read from a file. - A weight-one row of
G
-- the corresponding column is dropped. - A weight-two row of
G
-- the corresponding columns are combined, two bits of the error vector combined, andK=K1 [+] K2
(operationboxplus
). - A weight-three row of
G
corresponding to columns[b1,b2,b3]
inH
which sum to zero give columns[0,b2,b3]
, and an extra row[1,1,1]
(this extra row carries zero syndrome). Columns[a1,a2,a3]
inL
(which sum to1
) are replaced with[0,a2,a3]
. The new LLR coefficients[B1,B2,B3]
are$$B_3={1\over4}\ln\left[{\cosh(A_1+A_2+A_3)\cosh(A_1+A_2-A_3)\over\cosh(A_1-A_2+A_3)\cosh(A_1-A_2-A_3)}\right]$$ which can also be written asB3=0.5*(A1+A2 [+] A3) + 0.5*(A1-A2 [+] A3)
. - For now, we do not want to give a translation of the error
vectors, just the new
K
andL
matrices and the corresponding LLR coefficients. - Go over
non-overlapping
weight-3 rows inG
and create new matrices; the rest of the columns just writeas is
. - If wanted, the procedure can be repeated again, creating the
codewords list, the corresponding
G
matrix, and writing out the new error model(H, L, probabilities)
. - Make sure that shorter syndrome vectors can be read and used (add zeros)
with the new matrices, along with the transformation matrix
T
- Come up with "header" syntax to specify existing H, L, G, P, etc. matrices [e.g.,
fin=tmp
] - Remove
w=4
degeneracies (rows of weight 4 inG
) - Code for arbitrary row weight (exponentially large matrices may result)
- Check for
-
Write a list of codewords to a file; read it from a file. Format: given
$L$ , each CW$c$ (column) has associated syndrome vector$L c$ (a binary vector) and a list of non-zero positions. We just store non-zero positions. Format:%% NZLIST % end-of-line comments followed by rows formed by of column indices (ordered), % starting with weight `w`, `1`-based and separated by spaces. % w i1 i2 ... iw 4 1 3 7 17 5 2 4 8 23 61
-
Better
G
andK
matrices (use list of codewords read to generate those) -
ML decoding implementation variants
- Given the found error vector (syndrome OK), try to add the codewords one-by-one.
- Given a valid error vector
e
found, use a list of vectors orthogonal to H (e.g., read from file) to make MC moves, compare the time spent in each syndrome. May need to heat up sometimes to get out of local minima. - Similar, but use Bennett acceptance ratios to estimate free energy differences
- List decoding first (e.g., for small-weight vectors, or for vectors where minE decoding may fail)
- During BP decoding OSD, store generated vectors in a hash to estimate FE for each sector (or just make non-vector-based decoding in this case).
- List look-up decoder (use precomputed list of syndromes for small-weight vectors to decode quickly).
- Special mode to generate list of syndromes (generate random
vectors; store the corresponding syndromes in hash, along
with corresponding observables). May want to keep the list
of syndromes for "close" pairs (where ML is actually
needed). Actual structure (can also use NN to store):
- When generating error vectors, use
two_vec_err_t
withdet
,obs
, anderr
vectors, store bydet
first, byerr
second while generating. At the end, will only keep the syndromes encountered several times (???) -- need to optimize for a given wanted size of the hash list, e.g., by running some 100 times larger sample). - Or, can just generate vectors up to some
wmax
weight (these are most likely to be encountered, ifp
is small); ifwmax
is smaller than half of the distance, can ignore possible degeneracy (???) - For any
det
with severalobs
values, calculate the corresponding probabilities carefully (or just sum the probabilities for vectors encountered). - May introduce lower cut-off by vector probability (say,
10^-8
if we expect to run samples of size up to a million). - With
$x=np$ , the probability of any error of weight$w$ is$x^w/w!\exp(-x)$ ; there are some$n^w$ error vectors to store. The amount of speed-up with givenwmax
can be estimated from here. - Come up with a nice storage format for (
det
,obs
) pairs.
- When generating error vectors, use
- Decoding mode (use
finU
to read the look-U
p list).- Read list of likely syndrome vectors into hash
- After reading the detector events,
- Create permutation vector of size
nvec
- Go over syndrome vectors, if small enough weight, seek in hash, if success, record the result
- Indices of the remaining syndrome vectors write into the permutation vector from the end.
- Create a small matrix with syndrome vectors that need decoding
- Output the results in the correct order by going over the list from two ends (different logic depending whether we need to output the observables vectors)
- Create permutation vector of size
- Special mode to generate list of syndromes (generate random
vectors; store the corresponding syndromes in hash, along
with corresponding observables). May want to keep the list
of syndromes for "close" pairs (where ML is actually
needed). Actual structure (can also use NN to store):
- Detailed hash-ML decoding protocol
- using matrix dual to
H
, run an MC chain; store in hash only the vectors within the range dW and dE (if specified); accumulate the total probability.
- using matrix dual to
-
verification and convenience
- add help specific for each
mode
(usevecdec mode=2 help
). To this end, first scan formode
(complain if it is set more than once), then scan fordebug
(set it), then scan forhelp
. - Add the ability to read MTX complex matrices (non-CSS codes).
See
GAP
packageQDistRnd
. - Also, ensure that
QDistRnd
MTX
format is fully compatible withvecdec
. - rename current
bpalpha
tobpgamma
. - Introduce the parameters
beta
andalpha
(see Kuo+Lai papers on modified BP). - make sure
debug=1
prints the values relevant for each mode, and also give parameters of the matrices (dimensions, ranks, etc) - make
debug=2
show command line arguments - make
debug=4
show additional information (e.g.,QLLR
) - make sure program complaints if a value not relevant to the current mode is set on the command line
- verify matrix orthogonality and ranks
- more usage examples in the documentation
- testing facility
- add help specific for each
-
syndrome transformations / detector events creation
- syndrome transformation matrix
T
(e.g., for subcode decoding). Possibly, also for transforming measurement results to detection events.
- syndrome transformation matrix
-
convenience feature: with negative seed, combine
time(null)
with the number provided -
convenience feature: ability to combine several files with codewords (several
finC
arguments). (**do we need this -- given that the codewords are now read uniquely? **) -
a special mode to process ( test / give the stats / select irreducible codewords ) in codewords files.
- write Gaussian prefactor calculation routine for codeword
contribution to fail probability (in addition to current upper
bound and
exact
.) Perhaps only use it for codewords of sufficiently large weights. - Speed-up the
exact
routine - Enable probability
matrices
with several probability vectors inmode=2
for faster operation. Come up with a "label" (e.g., "p=0.001", or just "0.001 0.01") string to distinguish between different probability vectors (prepend the row with regular output). - Enable creation of such matrices (or come up with a shell script to do it).
- See if
Stim
has a guarantee on the structure ofDEM
matrices as the probabilities change (but remain non-zero). - make a routine to keep only irreducible codewords.
- make this routine optional to speedup the calculation (???)
- calculate actual
min_dW
for thedo_hash_remove_reduc()
- Try to write more accurate estimates on BER beyond simple union bound. See Bonferroni inequalities, e.g., here (https://www.probabilitycourse.com/chapter6/6_2_1_union_bound_and_exten.php)
- In particular, account for pair correlations and construct an accurate lower bound on fail probability.
- when reading a codewords file, ensure coordinates are not too big (also orthogonality)
- OSD1 with
mode=2
can degrade the performance when number ofsteps
is large. (???) - verify OSD with
mode=0andmode=1
-
betterfaster prefactor calculation inmode=2
- use
istty()
to detect screen vs.\ redirected output inERROR()
macro; make it color where appropriate.
debug
mode
seed
qllr1
qllr2
qllr3
ntot // mode 0,1
nvec // mode 0.1
pads // mode 0,1 reading syndrome vectors only (fdet)
nfail // mode 0,1 early termination condition
steps // mode 0,1,2
swait // mode 0 and mode 2 early termination condition
lerr // mode 1 max OSD level (-1 for no OSD)
// mode 0 (-1 is same as 0)
useP DEM parameter
dmin // early termination with mode=2
maxosd // only for BP
maxC // error if too long nz file, limit the number of CWs in do_LLR_dist (RIS)
bpalpha
bpretry
epsilon // not used
dE // only mode=2
dW // mode=2 and mode=3 when constructing G and L matrix
maxW // upper bound for creating / reading CWs / mode=2 and mode=3
debug 1 possibly relevant information
debug 2 output matrix ranks
debug 4 parsing input variables
debug 8 file i/o messages
## operation modes
1. ferr specified (usual operation)
2. both fdet and fobs specified (usual operation)
3. fobs specified; generate (pobs and pdet) or (perr) (new)
4. none is specified, generate gerr (and/or others), do no decoding. (new)
make it "mode=0" ???
-
wish1
disablefinL
,fobs
,useP
requirement ifsteps=0
or (fdet
andperr
) are specified -
wish2
for some reasongobs
returns nothing -
wish3
withmode=0
withsteps=0
,fobs
,finL
,ferr
count decoding success (do not requireuseP
andfinH
) -
use
paste
to paste columns from two or more files together -
use
cut
to cut columns from a file (specify a pattern). -
write a (shell ???) script to cut a sub block out of an
mtx
matrix (?)
awk '{print substr($0,1,5) gensub(/./,"*","g",substr($0,6))}' tmpA.01
## SED to achieve the same :
sed -e 's/./*/g6' tmpA.01
overall the script:
input: intervals [(0 r1), (q2 r2), (q3 r3) ...] and [(0,c1), (b2,c2),,, ]; DEM
1. generate initial DET and OBS files
2. write H, L, P from DEM (vecdec mode=3)
3. for each interval
- cut the DET rows (cut)
- cut the matrix: rowblock [A B 0] into A and B
- use A and existing errors `e` to construct modified DET (A e+s)
- use B to decode (vecdec); output error vector using `perr`
- use (cut) and (paste) to update errors `e`
4. At the end use `e` as the predicted error to verify the observables
-
Come up with aUse thenz
file format to keep syndrome / vector pairs. - Add
finU
/outU
parameters to read / write syndrome / vector pairs files -
Add hash value for DEM matrices to insure only matching files are read (???) -- or just verify each entry? - Add parameter
maxU
for maximum number of syndrome vectors to store. - Add parameters
uE
anduW
for max energy / max weight of a codeword to store. -
UsedE
and/ordW
parameters to decide which vectors should be stored (from zero)(should we also use some sort of minimum probability limit?) - Add the ability to store syndrome -> correct vector pairs in a
hash (decoding modes). Implementation:
three_vec_t
structure inutils.h
. - Specific implementation (all decoding modes):
- Routine to read binary 01 vectors into sparse format
- Special vector of size
nvec
if it has been decoded (0
: not, integer: decoder level). Used to track what to output and where. - When syndrome matrices are read, rows are verified against those stored in a hash (including all-zero syndrome row).
- Only rows which are not found are copied to a separate matrix for processing.
- Permutation vector of size
nvec
is used to match the decoded vectors / observables. Entries found are written from the back, not found from the front. - With
mode=0
, if ML decoding is enabled, hash can be updated.
- Add a special mode to generate error / syndrome pairs to ensure near-ML decoding for these syndrome vectors
- Start with each non-zero check node, join all neighboring variable nodes into a cluster. Merge.
- Try look-up decoding in each cluster. Remove clusters where this is successful (add the corresponding error vectors to the output list).
- Check if decoding in a cluster is possible. If yes, do RIS (?) decoding in remaining clusters; remove.
- Try to grow the remaining clusters until some join. Check whether decoding is possible. If yes, do RIS (?) decoding. Otherwise, back to 4 until only one cluster remains.
- This requires the following:
-
prepare_v_v_graph (sparse form of vv connectivity graph).
-
given the error vector, init two_vec_t structure
-
check and optionally insert vector in hash (by error vector).
-
Sort by syndrome vectors and (if multiple
e
pers
) pick the most likelye
; -
Check and insert vector in hash (by syndrome).
-
clean up the hash
-
cluster algorithm implementation:
- variables:
num_clus
; max_clus;int in_cluster[nvar]
;int label[nvar]
. - when two clusters are merging, keep the smaller label.
- data structure for cluster lists (one for
v
, another forc
???)
- Start with
r=1
(n.n.), and for every non-zero check node mark surrounding variable nodes, and an empty setE
. - Connect these into clusters.
- For each cluster
X
, calculateH[X]
, and see if the syndrome rows are redundant, and whether a local error can be found locally. (We can likely use look-up table for this step). Generally, small parameter for this decoder is expected to bep*z
, wherez
is the degree of the variable node connectivity graph, andp
is the typical error probability. Much better thann*p
for the full-matrix look-up decoding. - If yes, move the coordinates of the corresponding (min-weight)
vector to
E
, and erase from the field. - If syndrome is non-zero, increase
r
by one, and go back to 2. - Otherwise, sort coordinates in
E
to get the error vector.
- variables:
Suppose H=A*B is an exact product. Try two-stage decoding. Would this be true for concatenated codes?
List decoding for multi-step decoders, where we have several vectors and corresponding probabilities on the input of next-step decoder.
Generally, given the matrix of syndrome rows HeT
, maintain the list
of rows already decoded (with the reference to corresponding
observable or soft-out row), and rows not-yet decoded.
- Implement
pre
-decoder formode=0
.- fix adjacency graph construction
- add ML features (compare partial FE by L sector)
- pre-compute list of errors ???
- Make sure it works for classical codes
- Debug
pre
-decoder and update documentation. - Replace global errors with cluster generation algorithm based on a connectivity graph (use v-v graph or its powers).
- Generate statistics on rejected clusters (c- and v-node weights)
- Add ML properties for global errors list (
u
-hash). To this end, addobs
and an extra hash handle totwo_vec_t
structure. - Enable min-W operation with no
P
defined (useP=none
with a DEM,null
pointer forP
internally) - Come up with a protocol to check whether a cluster can be decoded
- Add BP / RIS decoders for individual clusters (hope that BP would converge better with many cycles cut); also, as an alternative to block-wise just-in-time decoding.
- Try to figure out why BP is so slow (excessive memory allocation?)
- Rewrite debug statements (reasonable debug bits)
- All debugging output ->
stderr
- make sure steps=0 and uW=0 generates no fail stats when writing
det
andobs
files - Come up with
cli
file to generate nice html documentation fromadoc
(with properly included files) - Come up with a script to verify the results statistics from the
ex_**.sh
files - Make more examples with internal error generation for classical and quantum codes
- here
lerr=1
seems to be detrimental:
./src/vecdec seed=7 steps=5000 lerr=0 finH= ./examples/96.3.963.alist useP=0.05 ntot=10 nvec=10 uW=-1
./src/vecdec seed=7 steps=5000 lerr=1 finH= ./examples/96.3.963.alist useP=0.05 ntot=10 nvec=10 uW=-1
the first line gives 0 fails, the second 1 fail
s=124;
./src/vecdec debug=1 seed=$s steps=5000 lerr=0 finH= ./examples/96.3.963.alist useP=0.05 ntot=1 nvec=1 uW=-1;
echo;
echo ;
./src/vecdec debug=1 seed=$s steps=5000 lerr=1 finH= ./examples/96.3.963.alist useP=0.05 ntot=1 nvec=1 uW=-1
verified this is not a bug but genuine equal-weight vectors (code distance is 6)
- Rewrite the cluster routine in
vecdec
for the special caseuW=2 uR=1
, starting with a single check node and double-cycling over neighboring variable nodes. This would create all $N_cd_c(d_c-1)/2$ weight-two combinations for such neighboring errors (Would it be sufficient to cover all weight-two clusters? Why not?) - generalization for tree-like connected clusters of higher weight.
- For
dist_m4ri
, add a mode for computing the confinement. Namely, store all errors/syndrome combinations by syndrome and the corresponding minimum weight error. - Come up with a notion of a distance suitable for SS two-step and SS one-step decoding. At what minimum error/syndrome weight would a non-trivial error show up? (That would cause the decoding to fail).
- Can we come up with a some sort of a locality distance? That is, error weight to guarantee decoding cluster locality.
- Write a separate program for PRE+BP+OSD decoding, to save on matrix rewriting. Try partial cluster matching (with the partially matched vectors correctly participating in the weight calculation)
- For cluster matching, come up with the notion of locality distance.
- Try to use
sparse6
format to store error vectors and/or binary matrices. Seenauty
source code.