Decoder setup

To decode using belief propagation, first load an instance of the ldpc.bp_decoder class.

[30]:
import numpy as np
from ldpc.codes import rep_code
from ldpc import bp_decoder
H=rep_code(3) #parity check matrix for the length-3 repetition code
n=H.shape[1] #the codeword length

bpd=bp_decoder(
    H, #the parity check matrix
    error_rate=0.1, # the error rate on each bit
    max_iter=n, #the maximum iteration depth for BP
    bp_method="product_sum", #BP method. The other option is `minimum_sum'
    channel_probs=[None] #channel probability probabilities. Will overide error rate.
)

Received vector decoding

Given a corrupted codeword, the bp_decoder.decode will provide an estimate of its unerrored form. For example, consider the case where we are encoding via a three-bit repetition code:

[31]:
codeword=np.array([1,1,1])

If the above codeword is subject to an error on its first bit the received vector is given by

[32]:
received_vector=np.array([0,1,1])

The above vector can be corrected using the bp_decoder.decode as follows:

[33]:
decoded_codeword=bpd.decode(received_vector)

print(decoded_codeword)
[1 1 1]

Syndrome decoding

In syndrome decoding, the error syndrome is input to bp_decoder.decode function. This is useful in settings where the codeword cannot be directly measured. eg. in quantum error correction. The output of the syndrome recovery is an estimate of the error.

[34]:
error=np.array([0,1,0])
syndrome=H@error%2
decoding=bpd.decode(syndrome)
print(f"Error: {error}")
print(f"Syndrome: {syndrome}")
print(f"Decoding: {decoding}")
Error: [0 1 0]
Syndrome: [1 1]
Decoding: [0 1 0]

Assymetric error channels

If the code bits are subject to different error rates, a channel probability vector can be provided instead of the error rate.

[35]:
bpd=bp_decoder(
    H,
    max_iter=n,
    bp_method="product_sum",
    channel_probs=[0.1,0,0.1] #channel probability probabilities. Will overide error rate.
)

error=np.array([1,0,1])
syndrome=H@error%2
decoding=bpd.decode(syndrome)
print(f"Error: {error}")
print(f"Syndrome: {syndrome}")
print(f"Decoding: {decoding}")
Error: [1 0 1]
Syndrome: [1 1]
Decoding: [1 0 1]

Example: error correction over the binary symmetric channel

[36]:
import numpy as np
from ldpc.codes import rep_code
from ldpc import bp_decoder

n=13
error_rate=0.3
runs=5
H=rep_code(n)

#BP decoder class. Make sure this is defined outside the loop
bpd=bp_decoder(H,error_rate=error_rate,max_iter=n,bp_method="product_sum")
error=np.zeros(n).astype(int) #error vector

for _ in range(runs):
    for i in range(n):
        if np.random.random()<error_rate:
            error[i]=1
        else: error[i]=0
    syndrome=H@error %2 #calculates the error syndrome
    print(f"Error: {error}")
    print(f"Syndrome: {syndrome}")
    decoding=bpd.decode(syndrome)
    print(f"Decoding: {error}\n")
Error: [1 0 0 0 0 1 0 0 0 0 0 0 1]
Syndrome: [1 0 0 0 1 1 0 0 0 0 0 1]
Decoding: [1 0 0 0 0 1 0 0 0 0 0 0 1]

Error: [1 0 0 0 0 1 0 0 1 0 0 1 0]
Syndrome: [1 0 0 0 1 1 0 1 1 0 1 1]
Decoding: [1 0 0 0 0 1 0 0 1 0 0 1 0]

Error: [0 0 1 0 0 0 1 0 1 0 0 0 1]
Syndrome: [0 1 1 0 0 1 1 1 1 0 0 1]
Decoding: [0 0 1 0 0 0 1 0 1 0 0 0 1]

Error: [0 0 0 0 0 0 1 1 0 0 1 1 0]
Syndrome: [0 0 0 0 0 1 0 1 0 1 0 1]
Decoding: [0 0 0 0 0 0 1 1 0 0 1 1 0]

Error: [0 0 0 1 1 0 0 0 1 0 1 0 0]
Syndrome: [0 0 1 0 1 0 0 1 1 1 1 0]
Decoding: [0 0 0 1 1 0 0 0 1 0 1 0 0]