Skip to content

Commit

Permalink
updating union find syntax
Browse files Browse the repository at this point in the history
  • Loading branch information
quantumgizmos committed Nov 17, 2023
1 parent c47dc76 commit f87ce77
Show file tree
Hide file tree
Showing 9 changed files with 79 additions and 37 deletions.
41 changes: 30 additions & 11 deletions docs/source/quantum_decoder.ipynb
Original file line number Diff line number Diff line change
Expand Up @@ -58,18 +58,30 @@
"\n",
"The belief propagation + union-find decoder (belief-find) is an alternative to BP+OSD for decoding quantum LDPC codes. Belief-find first attempts to solve the decoding using belief propagation. If this fails, a union-find decoder is run as a post-processor using the output of BP to guide cluster growth. The `LDPC` package implements two versions of belief-find:\n",
"\n",
"1) **Peeling belief-find**. This approach uses a peeling decoder to solve the local decoding problem on each code. Peeling uinon-find is limited to decoding codes that have point like syndromes. e.g, the surface and toric codes. The peeling version of union-find decoder was first proposed by Delfosse & Nickerson in (https://arxiv.org/abs/1709.06218). Peeling belief-find was first proposed and implemented by Oscar Higgott (https://arxiv.org/abs/2203.04948).\n",
"1) **Peeling belief-find**. This approach uses a peeling decoder to solve the local decoding problem in each cluster. Peeling uinon-find is limited to decoding codes that have point like syndromes. e.g, the surface and toric codes. The peeling version of union-find decoder was first proposed by Delfosse & Nickerson in (https://arxiv.org/abs/1709.06218). Peeling belief-find was first proposed and implemented by Oscar Higgott (https://arxiv.org/abs/2203.04948).\n",
"\n",
"2) **Cluster-inversion belief-find**. This approach solves the local decoding problem on each cluster using matrix inverison. Cluster-inversion union find can be applied to any quantum LDPC code. Matrix inversion find was first proposed by Delfosse et al. (https://arxiv.org/abs/2103.08049), and later improved by Berent et al. (https://arxiv.org/abs/2209.01180). As far as I am aware, the `LDPCv2` has the first implementation of cluster-inversion belief-find.\n",
"\n",
"The `LDPC` implementation of belief-find inherits from the `ldpc.BpDecoder` class. Examples of belief-find in use are given below:"
"The `LDPC` implementation of belief-find inherits from the `ldpc.BpDecoder` class.\n",
"\n",
"An example of the cluster-inversion belief-find decoder is below:"
]
},
{
"cell_type": "code",
"execution_count": null,
"execution_count": 3,
"metadata": {},
"outputs": [],
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"Syndrome: [1 0 0 1 0]\n",
"Decoding: [0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0]\n",
"Decoding syndrome: [1 0 0 1 0]\n"
]
}
],
"source": [
"import numpy as np\n",
"import ldpc.codes\n",
Expand All @@ -84,7 +96,7 @@
" bp_method = 'product_sum',\n",
" max_iter = 7,\n",
" schedule = 'serial',\n",
" matrix_solve = True, # If set to True, union-find clusters are solved by matrix inversion\n",
" uf_method = \"inversion\", # Union-find clusters are solved by matrix inversion\n",
" bits_per_step = 1 ## this is the number of bits by which clusters are expanded in each growth step \n",
" )\n",
"\n",
Expand All @@ -101,12 +113,12 @@
"cell_type": "markdown",
"metadata": {},
"source": [
"The peeling version of belief-find can be activated by setting `matrix_solve=False`. This method only works for parity check matrix that yield point-like syndromes. An example of using peeling belief-find on the repetition code is show below:"
"The peeling version of belief-find can be activated by setting `uf_method=\"peeling\"`. This method only works for parity check matrix that yield point-like syndromes. An example of using peeling belief-find on the repetition code is show below:"
]
},
{
"cell_type": "code",
"execution_count": 10,
"execution_count": 4,
"metadata": {},
"outputs": [],
"source": [
Expand All @@ -123,23 +135,23 @@
" bp_method = 'product_sum',\n",
" max_iter = 7,\n",
" schedule = 'serial',\n",
" matrix_solve = False, # If matrix_solve is set to False, union-find clusters are solved using a peeling decoder\n",
" uf_method = \"peeling\", # If uf_method is set to False, union-find clusters are solved using a peeling decoder\n",
" bits_per_step = 1 ## this is the number of bits by which clusters are expanded in each growth step \n",
" )\n",
"\n"
]
},
{
"cell_type": "code",
"execution_count": 13,
"execution_count": 7,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"Decoding: [1 1 1 1 1 1 0 0 0 0 0 0 1 0 0]\n",
"Decoding syndrome: [0 0 0 0 0 1 0 0 0 0 0 1 1 0 1]\n"
"Decoding: [0 0 0 1 0 1 0 1 0 1 0 0 0 0 1]\n",
"Decoding syndrome: [0 0 1 1 1 1 1 1 1 1 0 0 0 1 1]\n"
]
}
],
Expand All @@ -152,6 +164,13 @@
"decoding_syndrome = H@decoding % 2\n",
"print(f\"Decoding syndrome: {decoding_syndrome}\")"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": []
}
],
"metadata": {
Expand Down
4 changes: 2 additions & 2 deletions python_test/test_qcodes.py
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,7 @@ def test_400_16_6_hgp():
decoder = BpOsdDecoder(hx, error_rate=error_rate, max_iter=5, bp_method="ps", schedule="parallel", osd_method = "osd0")
ler, min_logical, speed = quantum_mc_sim(hx, lx, error_rate, run_count, seed, decoder,"Prod-sum osd-0 parallel schedule")

decoder = BeliefFindDecoder(hx, error_rate=error_rate, max_iter=5, bp_method="ms", ms_scaling_factor=0.625, schedule="parallel", matrix_solve=True, bits_per_step=1)
decoder = BeliefFindDecoder(hx, error_rate=error_rate, max_iter=5, bp_method="ms", ms_scaling_factor=0.625, schedule="parallel", uf_method="inversion", bits_per_step=1)
ler, min_logical, speed = quantum_mc_sim(hx, lx, error_rate, run_count, seed, decoder,"Belief-find parallel schedule")


Expand Down Expand Up @@ -102,5 +102,5 @@ def test_toric_20():
decoder = BpOsdDecoder(hx, error_rate=error_rate, max_iter=5, bp_method="ps", schedule="parallel", osd_method = "osd0")
ler, min_logical, speed = quantum_mc_sim(hx, lx, error_rate, run_count, seed, decoder,"Prod-sum osd-0 parallel schedule")

decoder = BeliefFindDecoder(hx, error_rate=error_rate, max_iter=5, bp_method="ms", ms_scaling_factor=0.625, schedule="parallel", matrix_solve=False, bits_per_step=1)
decoder = BeliefFindDecoder(hx, error_rate=error_rate, max_iter=5, bp_method="ms", ms_scaling_factor=0.625, schedule="parallel", uf_method="peeling", bits_per_step=1)
ler, min_logical, speed = quantum_mc_sim(hx, lx, error_rate, run_count, seed, decoder,"Belief-find parallel schedule")
2 changes: 1 addition & 1 deletion python_test/test_scratch.py
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@
bp_method = 'product_sum',
max_iter = 1,
schedule = 'serial',
matrix_solve = True, # If matrix_solve is set to False, union-find clusters are solved using a peeling decoder
uf_method = True, # If uf_method is set to False, union-find clusters are solved using a peeling decoder
bits_per_step = 1 ## this is the number of bits by which clusters are expanded in each growth step
)

Expand Down
16 changes: 11 additions & 5 deletions src_python/ldpc/belief_find_decoder/__init__.pyi
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ class BeliefFindDecoder(BpDecoderBase):
The BeliefFindDecoder is designed to decode binary linear codes by initially attempting BP decoding, and if that fails,
it falls back to the Union Find Decoder algorithm. The UFD algorithm is based on the principles outlined in
https://arxiv.org/abs/1709.06218, with an option to utilise a more general version as described in
https://arxiv.org/abs/2103.08049 for LDPC codes by setting `matrix_solve=True`.
https://arxiv.org/abs/2103.08049 for LDPC codes by setting `uf_method=True`.
Parameters
----------
Expand All @@ -33,17 +33,18 @@ class BeliefFindDecoder(BpDecoderBase):
serial_schedule_order : Optional[List[int]], optional
A list of integers specifying the serial schedule order. Must be of length equal to the block length of the code,
by default None.
matrix_solve : bool, optional
If set to True, implements the more general version of union find as described in
https://arxiv.org/abs/2103.08049 for LDPC codes, by default True.
uf_method : str, optional
The method used to solve the local decoding problem in each cluster. Choose from: 1) 'inversion' or 2) 'peeling'.
By default set to 'inversion'. The 'peeling' method is only suitable for LDPC codes with point like syndromes.
The inversion method can be applied to any parity check matrix.
bits_per_step : int, optional
Specifies the number of bits added to the cluster in each step of the UFD algorithm. If no value is provided, this is set the block length of the code.
Notes
-----
The `BeliefFindDecoder` class leverages soft information outputted by the BP decoder to guide the cluster growth
in the UFD algorithm. The number of bits added to the cluster in each step is controlled by the `bits_per_step` parameter.
The `matrix_solve` parameter activates a more general version of the UFD algorithm suitable for LDPC codes when set to True.
The `uf_method` parameter activates a more general version of the UFD algorithm suitable for LDPC codes when set to True.
"""


Expand All @@ -70,3 +71,8 @@ class BeliefFindDecoder(BpDecoderBase):
If the length of the input syndrome is not equal to the length of the code.
"""


@property
def uf_method(self):
@uf_method.setter
def uf_method(self, uf_method: str):
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ cdef class BeliefFindDecoder(BpDecoderBase):
cdef uf_decoder_cpp* ufd
cdef vector[uint8_t] bf_decoding
cdef vector[uint8_t] residual_syndrome
cdef bool matrix_solve
cdef str uf_method
cdef int bits_per_step


Expand Down
35 changes: 26 additions & 9 deletions src_python/ldpc/belief_find_decoder/_belief_find_decoder.pyx
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ cdef class BeliefFindDecoder(BpDecoderBase):
The BeliefFindDecoder is designed to decode binary linear codes by initially attempting BP decoding, and if that fails,
it falls back to the Union Find Decoder algorithm. The UFD algorithm is based on the principles outlined in
https://arxiv.org/abs/1709.06218, with an option to utilise a more general version as described in
https://arxiv.org/abs/2103.08049 for LDPC codes by setting `matrix_solve=True`.
https://arxiv.org/abs/2103.08049 for LDPC codes by setting `uf_method=True`.
Parameters
----------
Expand All @@ -37,28 +37,29 @@ cdef class BeliefFindDecoder(BpDecoderBase):
serial_schedule_order : Optional[List[int]], optional
A list of integers specifying the serial schedule order. Must be of length equal to the block length of the code,
by default None.
matrix_solve : bool, optional
If set to True, implements the more general version of union find as described in
https://arxiv.org/abs/2103.08049 for LDPC codes, by default True.
uf_method : str, optional
The method used to solve the local decoding problem in each cluster. Choose from: 1) 'inversion' or 2) 'peeling'.
By default set to 'inversion'. The 'peeling' method is only suitable for LDPC codes with point like syndromes.
The inversion method can be applied to any parity check matrix.
bits_per_step : int, optional
Specifies the number of bits added to the cluster in each step of the UFD algorithm. If no value is provided, this is set the block length of the code.
Notes
-----
The `BeliefFindDecoder` class leverages soft information outputted by the BP decoder to guide the cluster growth
in the UFD algorithm. The number of bits added to the cluster in each step is controlled by the `bits_per_step` parameter.
The `matrix_solve` parameter activates a more general version of the UFD algorithm suitable for LDPC codes when set to True.
The `uf_method` parameter activates a more general version of the UFD algorithm suitable for LDPC codes when set to True.
"""

def __cinit__(self, pcm: Union[np.ndarray, scipy.sparse.spmatrix], error_rate: Optional[float] = None,
error_channel: Optional[List[float]] = None, max_iter: Optional[int] = 0, bp_method: Optional[str] = 'minimum_sum',
ms_scaling_factor: Optional[float] = 1.0, schedule: Optional[str] = 'parallel', omp_thread_count: Optional[int] = 1,
random_schedule_seed: Optional[int] = 0, serial_schedule_order: Optional[List[int]] = None, matrix_solve: bool = True, bits_per_step:int = 0, input_vector_type: str = "syndrome"):
random_schedule_seed: Optional[int] = 0, serial_schedule_order: Optional[List[int]] = None, uf_method: str = True, bits_per_step:int = 0, input_vector_type: str = "syndrome"):
self.MEMORY_ALLOCATED=False
self.ufd = new uf_decoder_cpp(self.pcm[0])
self.bf_decoding.resize(self.n) #C vector for the bf decoding
self.residual_syndrome.resize(self.m) #C vector for the bf decoding
self.matrix_solve = matrix_solve
self.uf_method = uf_method
if bits_per_step == 0:
self.bits_per_step = pcm.shape[1]
else:
Expand Down Expand Up @@ -114,15 +115,31 @@ cdef class BeliefFindDecoder(BpDecoderBase):
for i in range(self.n): out[i] = self.bpd.decoding[i]

if not self.bpd.converge:
if self.matrix_solve:
if self.uf_method == "inversion":
self.ufd.decoding = self.ufd.matrix_decode(self._syndrome, self.bpd.log_prob_ratios,self.bits_per_step)
else:
elif self.uf_method == "peeling":
self.ufd.decoding = self.ufd.peel_decode(self._syndrome, self.bpd.log_prob_ratios,self.bits_per_step)
for i in range(self.n):
# self.bf_decoding[i] = self.ufd.decoding[i]^self.bpd.decoding[i]
out[i] = self.ufd.decoding[i]

return out


@property
def uf_method(self):
return self.uf_method

@uf_method.setter
def uf_method(self, uf_method: str):
if uf_method.lower() in ["inversion", "invert", "matrix"]:
self.uf_method = "inversion"
elif uf_method.lower() in ["peeling", "peel"]:
self.uf_method = "peeling"
else:
raise ValueError(f"Invalid UF method: {uf_method}. Must be one of 'inversion' or 'peeling'.")



# def maximum_cluster_size(self):
# return self.ufd.maximum_cluster_size[0], self.ufd.maximum_cluster_size[1]
4 changes: 2 additions & 2 deletions src_python/ldpc/union_find_decoder/__init__.pyi
Original file line number Diff line number Diff line change
Expand Up @@ -5,14 +5,14 @@ class UnionFindDecoder:
A decoder class that implements the Union Find Decoder (UFD) algorithm to decode binary linear codes.
The decoder operates on a provided parity-check matrix (PCM) and can function with or without soft information
from a channel. The UFD algorithm can be run in two modes: matrix solve and peeling, controlled by the
`matrix_solve` flag.
`uf_method` flag.
Parameters
----------
pcm : Union[np.ndarray, spmatrix]
The parity-check matrix (PCM) of the code. This should be either a dense matrix (numpy ndarray)
or a sparse matrix (scipy sparse matrix).
matrix_solve : bool, optional
uf_method : bool, optional
If True, the decoder operates in matrix solve mode. If False, it operates in peeling mode.
Default is False.
"""
Expand Down
2 changes: 1 addition & 1 deletion src_python/ldpc/union_find_decoder/_union_find_decoder.pxd
Original file line number Diff line number Diff line change
Expand Up @@ -25,5 +25,5 @@ cdef class UnionFindDecoder():
cdef BpSparse* pcm
cdef vector[uint8_t] _syndrome
cdef vector[double] uf_llrs
cdef bool matrix_solve
cdef bool uf_method
cdef int bits_per_step
10 changes: 5 additions & 5 deletions src_python/ldpc/union_find_decoder/_union_find_decoder.pyx
Original file line number Diff line number Diff line change
Expand Up @@ -48,19 +48,19 @@ cdef class UnionFindDecoder:
A decoder class that implements the Union Find Decoder (UFD) algorithm to decode binary linear codes.
The decoder operates on a provided parity-check matrix (PCM) and can function with or without soft information
from a channel. The UFD algorithm can be run in two modes: matrix solve and peeling, controlled by the
`matrix_solve` flag.
`uf_method` flag.
Parameters
----------
pcm : Union[np.ndarray, spmatrix]
The parity-check matrix (PCM) of the code. This should be either a dense matrix (numpy ndarray)
or a sparse matrix (scipy sparse matrix).
matrix_solve : bool, optional
uf_method : bool, optional
If True, the decoder operates in matrix solve mode. If False, it operates in peeling mode.
Default is False.
"""

def __cinit__(self, pcm: Union[np.ndarray, spmatrix], matrix_solve: bool = False):
def __cinit__(self, pcm: Union[np.ndarray, spmatrix], uf_method: str = False):

self.MEMORY_ALLOCATED=False

Expand All @@ -78,7 +78,7 @@ cdef class UnionFindDecoder:
self.ufd = new uf_decoder_cpp(self.pcm[0])
self._syndrome.resize(self.m) #C vector for the syndrome
self.uf_llrs.resize(self.n) #C vector for the log-likehood ratios
self.matrix_solve = matrix_solve
self.uf_method = uf_method
self.MEMORY_ALLOCATED=True

def __del__(self):
Expand Down Expand Up @@ -142,7 +142,7 @@ cdef class UnionFindDecoder:
else:
self.bits_per_step = bits_per_step

if self.matrix_solve:
if self.uf_method:
if llrs is not None:
self.ufd.decoding = self.ufd.matrix_decode(self._syndrome, self.uf_llrs,self.bits_per_step)
else:
Expand Down

0 comments on commit f87ce77

Please sign in to comment.