Skip to content

Commit 3fe8b69

Browse files
committed
correctness tests for classical ECCs
1 parent 5b44b1c commit 3fe8b69

File tree

3 files changed

+108
-0
lines changed

3 files changed

+108
-0
lines changed

test/runtests.jl

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,12 @@ testfilter = ti -> begin
5555
push!(exclude, :ecc)
5656
end
5757

58+
if get(ENV, "CECC_TEST", "") == "true"
59+
return :cecc in ti.tags
60+
else
61+
push!(exclude, :cecc)
62+
end
63+
5864
if CUDA_flag
5965
return :cuda in ti.tags
6066
else

test/test_cecc.jl

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
@testitem "CECC" tags=[:cecc] begin
2+
using Nemo
3+
using QuantumClifford.ECC
4+
using QuantumClifford.ECC: AbstractCECC, QECCore
5+
6+
include("test_cecc_base.jl")
7+
8+
codes = all_testable_classical_code_instances()
9+
10+
@testset "correctness checks for classical ECCs" begin
11+
for code in codes
12+
H = parity_matrix(code)
13+
n, k, s = code_n(code), code_k(code), size(H, 1)
14+
@test all(col -> any(H[:, col] .!= 0), 1:n)
15+
@test size(H, 1) <= size(H, 2) && size(H, 2) == n
16+
H = matrix(GF(2), H)
17+
computed_rank = rank(H)
18+
@test n - k == computed_rank
19+
@test computed_rank <= s && computed_rank <= n
20+
@test n > 0 && k > 0 && k <= n
21+
@test 0 < k/n <= 1.0
22+
end
23+
end
24+
end

test/test_cecc_base.jl

Lines changed: 78 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,78 @@
1+
using Test
2+
using QuantumClifford.ECC.QECCore
3+
using QuantumClifford
4+
using QuantumClifford.ECC
5+
using QuantumClifford.ECC: BCH
6+
using InteractiveUtils
7+
using SparseArrays
8+
9+
import Nemo: GF, matrix, rank, finite_field, polynomial_ring
10+
import LinearAlgebra
11+
12+
# generate instances of all implemented codes to make sure nothing skips being checked
13+
14+
# Goppa Codes
15+
m₁ = 4
16+
t₁ = 2
17+
F, α = finite_field(2, m₁, )
18+
R, x = polynomial_ring(F, :x)
19+
g₁ = x^2 + x + α^3
20+
L₁ =^i for i in 2:13]
21+
22+
m₂ = 6
23+
F, α = finite_field(2, m₂, )
24+
R, x = polynomial_ring(F, :x)
25+
t₂ = 9
26+
g₂ = x^t₂ + 1
27+
28+
m₃ = 3
29+
F, α = finite_field(2, m₃, )
30+
R, x = polynomial_ring(F, :x)
31+
t₃ = 2
32+
g₃ = x^t₃ + x + 1
33+
34+
m₄ = 4
35+
t₄ = 2
36+
F, α = finite_field(2, m₄, )
37+
R, z = polynomial_ring(F, :z)
38+
g₄ = z^2 + α^7*z + 1
39+
L₄ =^i for i in 2:13]
40+
41+
const classical_code_instance_args = Dict(
42+
:RepCode => [3, 4, 5, 6, 7, 8, 9, 10],
43+
:BCH => [(3, 1), (3, 2), (4, 1), (4, 1), (5, 1), (5, 2), (6, 1), (6, 2)],
44+
:ReedMuller => [(1, 3), (1, 4), (2, 3), (1, 5), (2, 4), (2, 5), (3, 5)],
45+
:RecursiveReedMuller => [(1, 3), (1, 4), (2, 3), (1, 5), (2, 4), (2, 5), (3, 5)],
46+
:Golay => [(23), (24)],
47+
:Hamming => [2, 3, 4, 5, 6, 7, 8],
48+
:GallagerLDPC => [(3, 3, 4), (3, 4, 5), (4, 5, 7), (4, 6, 7)],
49+
:GoppaCode => [(m₁, t₁, g₁, L₁), (m₂, t₂, g₂), (m₃, t₃, g₃), (m₄, t₄, g₄, L₄)]
50+
)
51+
52+
function all_testable_classical_code_instances(;maxn=nothing)
53+
types_to_check = subtypes(AbstractCECC)
54+
all_concrete_types = Type[]
55+
56+
while !isempty(types_to_check)
57+
current = popfirst!(types_to_check)
58+
if isabstracttype(current)
59+
append!(types_to_check, subtypes(current))
60+
else
61+
push!(all_concrete_types, current)
62+
end
63+
end
64+
codeinstances = []
65+
for t in all_concrete_types
66+
t_name = Symbol(split(string(t), ".")[end])
67+
for args in get(classical_code_instance_args, t_name, [])
68+
try
69+
codeinstance = t(args...)
70+
!isnothing(maxn) && code_n(codeinstance) > maxn && continue
71+
push!(codeinstances, codeinstance)
72+
catch e
73+
@warn "Failed to create $t with args $args: $e"
74+
end
75+
end
76+
end
77+
return codeinstances
78+
end

0 commit comments

Comments
 (0)