diff --git a/ext/QuantumCliffordHeckeExt/QuantumCliffordHeckeExt.jl b/ext/QuantumCliffordHeckeExt/QuantumCliffordHeckeExt.jl index 0b9932472..ec0be7fd1 100644 --- a/ext/QuantumCliffordHeckeExt/QuantumCliffordHeckeExt.jl +++ b/ext/QuantumCliffordHeckeExt/QuantumCliffordHeckeExt.jl @@ -4,25 +4,24 @@ using QECCore import QECCore: code_n, code_s, code_k, rate, distance using DocStringExtensions -import QuantumClifford -import QuantumClifford: gf2_row_echelon_with_pivots! -import LinearAlgebra +import QuantumClifford, LinearAlgebra + import Hecke: Group, GroupElem, AdditiveGroupElem, GroupAlgebra, GroupAlgebraElem, FqFieldElem, representation_matrix, dim, base_ring, multiplication_table, coefficients, abelian_group, group_algebra, rand, gens, order, is_commutative, FqPolyRingElem, residue_ring, coeff, zero_matrix, mod1, lift, ZZ, gen, - matrix, ncols, nrows, degree, EuclideanRingResidueRingElem, quo, parent, zero, gcd, - polynomial_ring, characteristic, isone, mod, factor, zeros + polynomial_ring, characteristic, isone, mod, factor, zeros, group, EuclideanRingResidueRingElem, + degree, gcd, nrows, ncols import Hecke.Generic.MatSpaceElem import Nemo -import Nemo: characteristic, matrix_repr, GF, ZZ, lift, rank +import Nemo: characteristic, matrix_repr, GF, ZZ, lift, matrix, rank -import QuantumClifford.ECC: iscss, parity_checks, +import QuantumClifford.ECC: iscss, parity_checks, parity_matrix, two_block_group_algebra_codes, generalized_bicycle_codes, bicycle_codes, check_repr_commutation_relation, haah_cubic_codes, honeycomb_color_codes, check_repr_regular_linear, random_qc_ghp_code_matrix_A import QECCore: AbstractQECC, CSS, AbstractCSSCode, - hgp, code_k, code_n, code_s, parity_matrix_x, parity_matrix_z, parity_matrix_xz + hgp, code_k, code_n, code_s, parity_matrix_x, parity_matrix_z, parity_matrix_xz, parity_matrix import Random import Random: AbstractRNG, default_rng, randperm diff --git a/ext/QuantumCliffordHeckeExt/lifted.jl b/ext/QuantumCliffordHeckeExt/lifted.jl index 0cfa986c2..094e1d62f 100644 --- a/ext/QuantumCliffordHeckeExt/lifted.jl +++ b/ext/QuantumCliffordHeckeExt/lifted.jl @@ -70,7 +70,44 @@ function LiftedCode(A::Matrix{GroupAlgebraElem{FqFieldElem, <: GroupAlgebra}}; G LiftedCode(A; GA=GA, repr=representation_matrix) end -# TODO document and doctest example +""" +Constructs a group algebra code by embedding a matrix of group elements into the +specified group algebra `GA`, with optional custom representation `repr`. + +# Example + +```jldoctest +julia> import Hecke: group_algebra, GF, abelian_group, gens, representation_matrix + +julia> import QuantumClifford.ECC: LiftedCode, code_n, code_k, code_s + +julia> import QuantumClifford.ECC.QECCore: parity_matrix + +julia> l = 12; GA = group_algebra(GF(2), abelian_group(l)); x = gens(GA)[]; + +julia> B = reshape([1 + x + x^3 + x^6], (1, 1)); + +julia> c = LiftedCode(B, repr = representation_matrix); + +julia> code = parity_matrix(c) +12×12 Matrix{Bool}: + 1 0 0 0 0 0 1 0 0 1 0 1 + 1 1 0 0 0 0 0 1 0 0 1 0 + 0 1 1 0 0 0 0 0 1 0 0 1 + 1 0 1 1 0 0 0 0 0 1 0 0 + 0 1 0 1 1 0 0 0 0 0 1 0 + 0 0 1 0 1 1 0 0 0 0 0 1 + 1 0 0 1 0 1 1 0 0 0 0 0 + 0 1 0 0 1 0 1 1 0 0 0 0 + 0 0 1 0 0 1 0 1 1 0 0 0 + 0 0 0 1 0 0 1 0 1 1 0 0 + 0 0 0 0 1 0 0 1 0 1 1 0 + 0 0 0 0 0 1 0 0 1 0 1 1 + +julia> code_n(c), code_k(c), code_s(c) +(12, 3, 12) +``` +""" function LiftedCode(group_elem_array::Matrix{<: GroupOrAdditiveGroupElem}; GA::GroupAlgebra=group_algebra(GF(2), parent(group_elem_array[1,1])), repr::Union{Function, Nothing}=nothing) A = zeros(GA, size(group_elem_array)...) for i in axes(group_elem_array, 1), j in axes(group_elem_array, 2) @@ -83,7 +120,37 @@ function LiftedCode(group_elem_array::Matrix{<: GroupOrAdditiveGroupElem}; GA::G end end -# TODO document and doctest example +""" +Constructs a group algebra code over `GF(2)` by lifting a matrix of cyclic shifts +(entries modulo `l`) to the group algebra of the abelian group `ℤ/lℤ` of order `l`. + +# Example + +```jldoctest +julia> import Hecke; import QuantumClifford.ECC: LiftedCode, code_n, code_k, code_s + +julia> import QuantumClifford.ECC.QECCore: parity_matrix + +julia> base_matrix = [0 0 0 0; 0 1 2 5; 0 6 3 1]; l = 3; + +julia> c = LiftedCode(base_matrix, l); + +julia> code = parity_matrix(c) +9×12 Matrix{Bool}: + 1 0 0 1 0 0 1 0 0 1 0 0 + 0 1 0 0 1 0 0 1 0 0 1 0 + 0 0 1 0 0 1 0 0 1 0 0 1 + 1 0 0 0 0 1 0 1 0 0 1 0 + 0 1 0 1 0 0 0 0 1 0 0 1 + 0 0 1 0 1 0 1 0 0 1 0 0 + 1 0 0 1 0 0 1 0 0 0 0 1 + 0 1 0 0 1 0 0 1 0 1 0 0 + 0 0 1 0 0 1 0 0 1 0 1 0 + +julia> code_n(c), code_k(c), code_s(c) +(12, 5, 9) +``` +""" function LiftedCode(shift_array::Matrix{Int}, l::Int; GA::GroupAlgebra=group_algebra(GF(2), abelian_group(l)), repr=representation_matrix) A = zeros(GA, size(shift_array)...) for i in 1:size(shift_array, 1) @@ -103,10 +170,10 @@ function concat_lift_repr(repr, mat) return z end -function parity_checks(c::LiftedCode) - return lift(c.repr, c.A) +function parity_matrix(c::LiftedCode) + return concat_lift_repr(c.repr, c.A) end -code_n(c::LiftedCode) = size(c.A, 2) * size(zero(c.GA), 2) +code_n(c::LiftedCode) = size(c.A, 2) * order(group(c.GA)) -code_s(c::LiftedCode) = size(c.A, 1) * size(zero(c.GA), 1) +code_s(c::LiftedCode) = size(c.A, 1) * order(group(c.GA)) diff --git a/ext/QuantumCliffordOscarExt/bivariate_bicycle.jl b/ext/QuantumCliffordOscarExt/bivariate_bicycle.jl index 438966673..ae9fef342 100644 --- a/ext/QuantumCliffordOscarExt/bivariate_bicycle.jl +++ b/ext/QuantumCliffordOscarExt/bivariate_bicycle.jl @@ -25,7 +25,7 @@ We consider the specific ideal generated by two polynomials enforcing periodic b ```math \\begin{aligned} -J = \\langle x^\\ell - 1, y^m - 1 \\rangle = { p(x,y)(x^\ell - 1) + q(x,y)(y^m - 1) \\mid p, q \\in \\mathbb{F}_2[x,y]} +J = \\langle x^\\ell - 1, y^m - 1 \\rangle = { p(x,y)(x^\\ell - 1) + q(x,y)(y^m - 1) \\mid p, q \\in \\mathbb{F}_2[x,y]} \\end{aligned} ``` @@ -37,7 +37,7 @@ conditions in the y-direction. Formally, to verify that ``J`` satisfies the *ideal* requirements, the properties of J are as follows: -- ``(J, +) \\leq mathbb{F}_2[x, y], +)`` +- ``(J, +) \\leq \\mathbb{F}_2[x, y], +)`` For any ``f(x,y) \\in \\mathbb{F}_2[x, y]`` and any ``j(x,y) \\in J``: - ``f(x,y) \\cdot j(x,y) \\in J`` diff --git a/test/test_cecc.jl b/test/test_cecc.jl index cb7ce692f..8e7964c33 100644 --- a/test/test_cecc.jl +++ b/test/test_cecc.jl @@ -1,5 +1,6 @@ @testitem "ECC" tags=[:ecc, :ecc_base] begin using Nemo + using Hecke using QuantumClifford.ECC using QuantumClifford.ECC: AbstractCECC, QECCore diff --git a/test/test_cecc_base.jl b/test/test_cecc_base.jl index e4210c358..a00e7a2b7 100644 --- a/test/test_cecc_base.jl +++ b/test/test_cecc_base.jl @@ -7,6 +7,7 @@ using InteractiveUtils using SparseArrays import Nemo: GF, matrix, rank, finite_field, polynomial_ring +import Hecke: group_algebra, abelian_group, gens, representation_matrix import LinearAlgebra include("test_ecc_base.jl") @@ -40,6 +41,13 @@ R, z = polynomial_ring(F, :z) g₄ = z^2 + α^7*z + 1 L₄ = [α^i for i in 2:13] +# Lifted Codes +l₁ = 12; GA₁ = group_algebra(GF(2), abelian_group(l)); x = gens(GA)[] +B₁ = reshape([1 + x + x^3 + x^6], (1, 1)) +c = LiftedCode(B, repr = representation_matrix) + +base_matrix₂ = [0 0 0 0; 0 1 2 5; 0 6 3 1]; l₂ = 3; + const classical_code_instance_args = Dict( :RepCode => [3, 4, 5, 6, 7, 8, 9, 10], :BCH => [(3, 1), (3, 2), (4, 1), (4, 1), (5, 1), (5, 2), (6, 1), (6, 2)], @@ -48,7 +56,8 @@ const classical_code_instance_args = Dict( :Golay => [(23), (24)], :Hamming => [2, 3, 4, 5, 6, 7, 8], :GallagerLDPC => [(3, 3, 4), (3, 4, 5), (4, 5, 7), (4, 6, 7)], - :GoppaCode => [(m₁, t₁, g₁, L₁), (m₂, t₂, g₂), (m₃, t₃, g₃), (m₄, t₄, g₄, L₄)] + :GoppaCode => [(m₁, t₁, g₁, L₁), (m₂, t₂, g₂), (m₃, t₃, g₃), (m₄, t₄, g₄, L₄)], + :LiftedCode => [(B₁, repr = representation_matrix), (base_matrix₂, l₂), (base_matrix₂, 5), (base_matrix₂, 7)] ) function all_testable_classical_code_instances(; maxn=nothing) diff --git a/test/test_ecc_throws.jl b/test/test_ecc_throws.jl index e55ead749..7913499e0 100644 --- a/test/test_ecc_throws.jl +++ b/test/test_ecc_throws.jl @@ -1,6 +1,8 @@ @testitem "ECC throws" tags=[:ecc, :ecc_base] begin - using QuantumClifford.ECC: ReedMuller, BCH, RecursiveReedMuller, Golay, Triangular488, Triangular666, Hamming + using Hecke + using Hecke: group_algebra, GF, abelian_group, gens, one, representation_matrix + using QuantumClifford.ECC: ReedMuller, BCH, RecursiveReedMuller, Golay, Triangular488, Triangular666, Hamming, LiftedCode, code_k, code_n, code_s, parity_matrix @test_throws ArgumentError ReedMuller(-1, 3) @test_throws ArgumentError ReedMuller(1, 0) @@ -26,4 +28,18 @@ @test_throws ArgumentError Triangular488(1) @test_throws ArgumentError Triangular666(8) @test_throws ArgumentError Triangular666(1) + + l = 12; GA = group_algebra(GF(2), abelian_group(l)); x = gens(GA)[] + B = reshape([1 + x + x^3 + x^6], (1, 1)) + c = LiftedCode(B, repr = representation_matrix) + @test_nowarn parity_matrix(c) + @test_nowarn code_n(c) + @test_nowarn code_k(c) + @test_nowarn code_s(c) + base_matrix = [0 0 0 0; 0 1 2 5; 0 6 3 1]; l = 3; + c = LiftedCode(base_matrix, l); + @test_nowarn parity_matrix(c) + @test_nowarn code_n(c) + @test_nowarn code_k(c) + @test_nowarn code_s(c) end