Note
Go to the end to download the full example code or to run this example in your browser via JupyterLite.
Reed-Solomon codes: recovering lost and corrupted symbols (1960)#
Reed and Solomon treated k symbols of data as a polynomial of degree
below k over a finite field, and sent its values at n points.
Two such polynomials agree on at most k - 1 points, so any k of the
n values determine all the others. The code survives the loss of up to
n - k symbols, and up to (n - k) / 2 symbols that arrive wrong:
The same code protects CDs and QR codes, and, on blockchains, lets a block be rebuilt from any half of its extended shares.
Correcting errors with Berlekamp and Welch#
With no erasures, n - k = 6 spare symbols correct 3 wrong ones. For each number of errors, corrupt random positions and try to decode.
trials, rates = 40, []
error_counts = range(0, 7)
for errors in error_counts:
decoded = 0
for _ in range(trials):
received = list(codeword)
for i in rng.sample(range(n), errors):
received[i] = (received[i] + rng.randrange(1, 65_537)) % 65_537
with suppress(ValueError): # Too many errors to correct.
decoded += bk.channels.rs_decode(received, k) == tuple(message)
rates.append(decoded / trials)
print("decoding success by number of errors:", rates)
assert rates[:4] == [1.0] * 4 and max(rates[4:]) < 1
fig, (left, right) = plt.subplots(1, 2, figsize=(11, 4))
plot_shares(bk.channels.commit_shares(k, codeword), withheld=set(range(n)) - set(kept), ax=left)
left.set_title("Any 5 of the 11 shares rebuild the rest")
right.bar(error_counts, rates, color=["#16a34a" if e <= 3 else "#dc2626" for e in error_counts])
right.axvline(3.5, color="black", linestyle="--", label="(n - k) / 2")
right.set(xlabel="symbols corrupted", ylabel="fraction decoded correctly")
right.set_title("Errors are corrected up to half the redundancy")
right.legend()
fig.tight_layout()
plt.show()

decoding success by number of errors: [1.0, 1.0, 1.0, 1.0, 0.0, 0.0, 0.0]
Exercise#
Combine erasures and errors: with n = 11 and k = 5, erase two
symbols (pass None) and corrupt some others. How many corruptions can
rs_decode() still
correct, and does it match the bound above?
A worked solution is in Exercises: channels.
Total running time of the script: (0 minutes 0.153 seconds)