Skip to content

Commit

Permalink
polish documentation and formatting
Browse files Browse the repository at this point in the history
  • Loading branch information
Fe-r-oz committed Nov 27, 2024
1 parent ca7c53d commit 9464854
Show file tree
Hide file tree
Showing 4 changed files with 115 additions and 102 deletions.
1 change: 1 addition & 0 deletions docs/src/references.bib
Original file line number Diff line number Diff line change
Expand Up @@ -428,6 +428,7 @@ @misc{goodenough2024bipartiteentanglementnoisystabilizer
url={https://arxiv.org/abs/2406.02427},
}


@article{panteleev2021degenerate,
title = {Degenerate {{Quantum LDPC Codes With Good Finite Length Performance}}},
author = {Panteleev, Pavel and Kalachev, Gleb},
Expand Down
33 changes: 20 additions & 13 deletions src/ecc/codes/classical/golay.jl
Original file line number Diff line number Diff line change
@@ -1,17 +1,22 @@
"""
The family of classical binary Golay codes were discovered by Edouard Golay in his 1949 paper [golay1949notes](@cite), where he described the binary `[23, 12, 7]` Golay code.
The family of classical binary Golay codes were discovered by Edouard Golay
in his 1949 paper [golay1949notes](@cite), where he described the binary
`[23, 12, 7]` Golay code.
There are two binary Golay codes:
1. Binary `[23, 12, 7]` Golay code: The perfect code with code length `n` 23 and dimension `k` 12. Minimum distance is 7, implying it can detect or correct up to 3 errors. By puncturing in any of the coordinates of parity check Matrix `H` = `[24, 12, 8]`, we obtain a `[23, 12, 7]` Golay code.
- Binary `[23, 12, 7]` Golay code: The perfect code with code length `n = 23`
and dimension `k = 12`. By puncturing in any of the coordinates of parity check
matrix `H` = `[24, 12, 8]`, we obtain a `[23, 12, 7]` Golay code.
2. Extended Binary `[24, 12, 8]` Golay code: Obtained by adding a parity check bit to `[23, 12, 7]`. The bordered reverse circulant matrix `(A)` of `[24, 12, 8]` Golay code is self-dual, i.e., A₂₄ is same as A₂₄'.
- Extended Binary `[24, 12, 8]` Golay code: Obtained by adding a parity check bit
to `[23, 12, 7]`. The bordered reverse circulant matrix `(A)` of `[24, 12, 8]`
Golay code is self-dual, i.e., `A₂₄` is same as A₂₄'.
Parity Check Matrix `(H)`: `H` is defined as follows: `H₂₄ = [I₁₂ | A']` where `I₁₂` is the 12 x 12 identity matrix and `A` is a bordered reverse circulant matrix.
Construction method for `A` [huffman2010fundamentals](@cite): The columns of `A` are labeled by ∞, 0, 1, 2, ..., 10. The first row contains 0 in column ∞ and 1 elsewhere. To obtain the second row, a 1 is placed in column ∞ and a 1 is placed in columns 0, 1, 3, 4, 5, and 9; these numbers are precisely the squares of the integers modulo 11. That is, 0² = 0, 1² ≡ 10² ≡ 1 (mod 11), 2² ≡ 2² ≡ 4 (mod 11), etc. The third row of `A` is obtained by putting a 1 in column ∞ and then shifting the components in the second row one place to the left and wrapping the entry in column 0 around to column 10. The fourth row is obtained from the third in the same manner, as are the remaining rows.
Puncturing and then extending any column in​ with an overall parity check `H₂₃` reconstructs the original parity check matrix `H₂₄`. Thus, all punctured codes are equivalent.
The parity check matrix is defined as follows: `H₂₄ = [I₁₂ | A']` where `I₁₂` is the
12 x 12 identity matrix and `A` is a bordered reverse circulant matrix. Puncturing
and then extending any column in​ with an overall parity check `H₂₃` reconstructs
the original parity check matrix `H₂₄`. Thus, all punctured codes are equivalent.
The ECC Zoo has an [entry for this family](https://errorcorrectionzoo.org/c/golay).
"""
Expand Down Expand Up @@ -52,33 +57,35 @@ end
function generator(g::Golay)
if g.n == 24
A₂₄ = _create_A₂₄_golay(24)
I₁₂ = Diagonal(ones(Int, g.n ÷ 2))
I₁₂ = LinearAlgebra.Diagonal(ones(Int, g.n ÷ 2))
G₂₄ = hcat(I₁₂, (A₂₄)')
return G₂₄
else
A₂₄ = _create_A₂₄_golay(24)
A₂₃ = A₂₄[:, 1:end - 1]
I₁₂ = Diagonal(ones(Int, g.n ÷ 2))
I₁₂ = LinearAlgebra.Diagonal(ones(Int, g.n ÷ 2))
G₂₃ = hcat(I₁₂, (A₂₃)')
return G₂₃
end
end

function parity_checks(g::Golay)
if g.n == 24
if g.n == 24
A₂₄ = _create_A₂₄_golay(24)
I₁₂ = Diagonal(ones(Int, g.n ÷ 2))
I₁₂ = LinearAlgebra.Diagonal(ones(Int, g.n ÷ 2))
H₂₄ = hcat((A₂₄)', I₁₂)
return H₂₄
else
A₂₄ = _create_A₂₄_golay(24)
A₂₃ = A₂₄[:, 1:end - 1]
I₁₂ = Diagonal(ones(Int, g.n ÷ 2))
I₁₂ = LinearAlgebra.Diagonal(ones(Int, g.n ÷ 2))
H₂₃ = hcat((A₂₃)', I₁₂)
return H₂₃
end
end

code_n(g::Golay) = g.n

code_k(g::Golay) = 12

distance(g::Golay) = code_n(g::Golay) - code_k(g::Golay) - 4
182 changes: 93 additions & 89 deletions test/test_ecc_golay.jl
Original file line number Diff line number Diff line change
@@ -1,99 +1,103 @@
using Test
using LinearAlgebra
using QuantumClifford
using QuantumClifford.ECC
using QuantumClifford.ECC: AbstractECC, Golay, generator
using Nemo: matrix, GF, echelon_form
@testitem "ECC Golay" begin

"""
- Theorem: Let `C` be a binary linear code. If `C` is self-orthogonal and has a generator matrix `G` where each row has weight divisible by four, then every codeword of `C` has weight
divisible by four.
- `H₂₄` is self-dual because its generator matrix has all rows with weight divisible by four. By above theorem, all codewords of `H₂₄` must have weights divisible by four. Refer to pg. 30 to 33
of Ch1 of Fundamentals of Error Correcting Codes by Huffman, Cary and Pless, Vera.
"""
function code_weight_property(matrix)
for row in eachrow(matrix)
count = sum(row)
if count % 4 == 0
return true
using LinearAlgebra
using Combinatorics
using QuantumClifford.ECC
using QuantumClifford.ECC: AbstractECC, Golay, generator
using Nemo: matrix, GF, echelon_form

# Theorem: Let `C` be a binary linear code. If `C` is self-orthogonal and
# has a generator matrix `G` where each row has weight divisible by four,
# then every codeword of `C` has weight divisible by four. `H₂₄` is self-dual
# because its generator matrix has all rows with weight divisible by four.Thus,
# all codewords of `H₂₄` must have weights divisible by four. Refer to pg. 30 to
# 33 of Ch1 of Fundamentals of Error Correcting Codes by Huffman, Cary and Pless, Vera.
function code_weight_property(matrix)
for row in eachrow(matrix)
count = sum(row)
if count % 4 == 0
return true
end
end
return false
end
return false
end

"""
Test the equivalence of punctured and extended code by verifying that puncturing the binary parity check matrix H₂₄ in any coordinate and then extending it by
adding an overall parity check in the same position yields the original matrix H₂₄.
Steps:
1. Puncture the Code: Remove the i-th column from H₂₄ to create a punctured matrix H₂₃. Note: H₂₃ = H[:, [1:i-1; i+1:end]]
2. Extend the Code: Add a column in the same position to ensure each row has even parity. Note: H'₂₄ = [H₂₃[:, 1:i-1] c H₂₃[:, i:end]]. Here, c is a column vector added to ensure
each row in H'₂₄ has even parity.
3. Equivalence Check: Verify that H'₂₄ = H₂₄.
"""
function puncture_code(mat, i)
return mat[:, [1:i-1; i+1:end]]
end

function extend_code(mat, i)
k, _ = size(mat)
extended_mat = hcat(mat[:, 1:i-1], zeros(Bool, k, 1), mat[:, i:end])
# Calculate the parity for each row
for row in 1:k
row_parity = sum(mat[row, :]) % 2 == 1
extended_mat[row, i] = row_parity
# Test the equivalence of punctured and extended code by verifying that puncturing
# the binary parity check matrix H₂₄ in any coordinate and then extending it by adding
# an overall parity check in the same position yields the original matrix H₂₄.
# Steps:
# 1. Puncture the Code: Remove the i-th column from H₂₄ to create a punctured matrix
# H₂₃. Note: H₂₃ = H[:, [1:i-1; i+1:end]]
# 2. Extend the Code: Add a column in the same position to ensure each row has even
# parity. Note: H'₂₄ = [H₂₃[:, 1:i-1] c H₂₃[:, i:end]]. Here, c is a column vector added
# to ensure each row in H'₂₄ has even parity.
# 3. Equivalence Check: Verify that H'₂₄ = H₂₄.
function puncture_code(mat, i)
return mat[:, [1:i-1; i+1:end]]
end
return extended_mat
end

@testset "Testing binary Golay codes properties" begin
test_cases = [(24, 12), (23, 12)]
for (n, k) in test_cases
H = parity_checks(Golay(n))
mat = matrix(GF(2), parity_checks(Golay(n)))
computed_rank = rank(mat)
@test computed_rank == n - k
function extend_code(mat, i)
k, _ = size(mat)
extended_mat = hcat(mat[:, 1:i-1], zeros(Bool, k, 1), mat[:, i:end])
# Calculate the parity for each row
for row in 1:k
row_parity = sum(mat[row, :]) % 2 == 1
extended_mat[row, i] = row_parity
end
return extended_mat
end
# [[24, 12, 8]] binary Golay code is a self-dual code [huffman2010fundamentals](@cite).
H = parity_checks(Golay(24))
@test code_weight_property(H) == true
@test H[:, (12 + 1):end] == H[:, (12 + 1):end]'
# Example taken from [huffman2010fundamentals](@cite).
@test parity_checks(Golay(24)) == [0 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 0 0;
1 1 1 0 1 1 1 0 0 0 1 0 0 1 0 0 0 0 0 0 0 0 0 0;
1 1 0 1 1 1 0 0 0 1 0 1 0 0 1 0 0 0 0 0 0 0 0 0;
1 0 1 1 1 0 0 0 1 0 1 1 0 0 0 1 0 0 0 0 0 0 0 0;
1 1 1 1 0 0 0 1 0 1 1 0 0 0 0 0 1 0 0 0 0 0 0 0;
1 1 1 0 0 0 1 0 1 1 0 1 0 0 0 0 0 1 0 0 0 0 0 0;
1 1 0 0 0 1 0 1 1 0 1 1 0 0 0 0 0 0 1 0 0 0 0 0;
1 0 0 0 1 0 1 1 0 1 1 1 0 0 0 0 0 0 0 1 0 0 0 0;
1 0 0 1 0 1 1 0 1 1 1 0 0 0 0 0 0 0 0 0 1 0 0 0;
1 0 1 0 1 1 0 1 1 1 0 0 0 0 0 0 0 0 0 0 0 1 0 0;
1 1 0 1 1 0 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0;
1 0 1 1 0 1 1 1 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 1]

# cross-verifying the canonical equivalence of bordered reverse circulant matrix (A) from [huffman2010fundamentals](@cite) with matrix A taken from [bhatia2018mceliece](@cite).
A = [1 1 0 1 1 1 0 0 0 1 0 1;
1 0 1 1 1 0 0 0 1 0 1 1;
0 1 1 1 0 0 0 1 0 1 1 1;
1 1 1 0 0 0 1 0 1 1 0 1;
1 1 0 0 0 1 0 1 1 0 1 1;
1 0 0 0 1 0 1 1 0 1 1 1;
0 0 0 1 0 1 1 0 1 1 1 1;
0 0 1 0 1 1 0 1 1 1 0 1;
0 1 0 1 1 0 1 1 1 0 0 1;
1 0 1 1 0 1 1 1 0 0 0 1;
0 1 1 0 1 1 1 0 0 0 1 1;
1 1 1 1 1 1 1 1 1 1 1 0]
@test echelon_form(matrix(GF(2), A)) == echelon_form(matrix(GF(2), H[1:12, 1:12]))
# test self-duality for extended Golay code, G == H
@test echelon_form(matrix(GF(2), generator(Golay(24)))) == echelon_form(matrix(GF(2), parity_checks(Golay(24))))
# All punctured and extended matrices are equivalent to the H₂₄.
# Test each column for puncturing and extending
for i in 1:24
punctured_mat = puncture_code(H, i)
extended_mat = extend_code(punctured_mat, i)
# Test equivalence
@test extended_mat == H
@testset "Testing binary Golay codes properties" begin
test_cases = [(24, 12), (23, 12)]
for (n, k) in test_cases
H = parity_checks(Golay(n))
mat = matrix(GF(2), parity_checks(Golay(n)))
computed_rank = rank(mat)
@test computed_rank == n - k
end

# [24, 12, 8] binary Golay code is a self-dual code [huffman2010fundamentals](@cite).
H = parity_checks(Golay(24))
@test code_weight_property(H) == true
@test H[:, (12 + 1):end] == H[:, (12 + 1):end]'
# Example taken from [huffman2010fundamentals](@cite).
@test parity_checks(Golay(24)) == [0 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 0 0;
1 1 1 0 1 1 1 0 0 0 1 0 0 1 0 0 0 0 0 0 0 0 0 0;
1 1 0 1 1 1 0 0 0 1 0 1 0 0 1 0 0 0 0 0 0 0 0 0;
1 0 1 1 1 0 0 0 1 0 1 1 0 0 0 1 0 0 0 0 0 0 0 0;
1 1 1 1 0 0 0 1 0 1 1 0 0 0 0 0 1 0 0 0 0 0 0 0;
1 1 1 0 0 0 1 0 1 1 0 1 0 0 0 0 0 1 0 0 0 0 0 0;
1 1 0 0 0 1 0 1 1 0 1 1 0 0 0 0 0 0 1 0 0 0 0 0;
1 0 0 0 1 0 1 1 0 1 1 1 0 0 0 0 0 0 0 1 0 0 0 0;
1 0 0 1 0 1 1 0 1 1 1 0 0 0 0 0 0 0 0 0 1 0 0 0;
1 0 1 0 1 1 0 1 1 1 0 0 0 0 0 0 0 0 0 0 0 1 0 0;
1 1 0 1 1 0 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0;
1 0 1 1 0 1 1 1 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 1]

# cross-verifying the canonical equivalence of bordered reverse circulant matrix (A)
# from [huffman2010fundamentals](@cite) with matrix A taken from [bhatia2018mceliece](@cite).
A = [1 1 0 1 1 1 0 0 0 1 0 1;
1 0 1 1 1 0 0 0 1 0 1 1;
0 1 1 1 0 0 0 1 0 1 1 1;
1 1 1 0 0 0 1 0 1 1 0 1;
1 1 0 0 0 1 0 1 1 0 1 1;
1 0 0 0 1 0 1 1 0 1 1 1;
0 0 0 1 0 1 1 0 1 1 1 1;
0 0 1 0 1 1 0 1 1 1 0 1;
0 1 0 1 1 0 1 1 1 0 0 1;
1 0 1 1 0 1 1 1 0 0 0 1;
0 1 1 0 1 1 1 0 0 0 1 1;
1 1 1 1 1 1 1 1 1 1 1 0]

@test echelon_form(matrix(GF(2), A)) == echelon_form(matrix(GF(2), H[1:12, 1:12]))
# test self-duality for extended Golay code, G == H
@test echelon_form(matrix(GF(2), generator(Golay(24)))) == echelon_form(matrix(GF(2), parity_checks(Golay(24))))

# All punctured and extended matrices are equivalent to the H₂₄. Test each column for puncturing and extending.
for i in 1:24
punctured_mat = puncture_code(H, i)
extended_mat = extend_code(punctured_mat, i)
@test extended_mat == H
end
end
end
1 change: 1 addition & 0 deletions test/test_ecc_throws.jl
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
@testitem "ECC throws" begin

using QuantumClifford.ECC: ReedMuller, BCH, RecursiveReedMuller, Golay

@test_throws ArgumentError ReedMuller(-1, 3)
Expand Down

0 comments on commit 9464854

Please sign in to comment.