From 279a175a8bb4a948fc16182501fc81214fb2c684 Mon Sep 17 00:00:00 2001 From: Fe-r-oz Date: Fri, 18 Oct 2024 21:45:05 +0500 Subject: [PATCH] Group Presentation via Oscar Free Group --- .../QuantumCliffordHeckeExt.jl | 2 +- ext/QuantumCliffordHeckeExt/lifted_product.jl | 42 --- test/Project.toml | 1 + test/test_ecc_2bga_group_presentation.jl | 254 ++++++++++++++++++ 4 files changed, 256 insertions(+), 43 deletions(-) create mode 100644 test/test_ecc_2bga_group_presentation.jl diff --git a/ext/QuantumCliffordHeckeExt/QuantumCliffordHeckeExt.jl b/ext/QuantumCliffordHeckeExt/QuantumCliffordHeckeExt.jl index 83c3dc036..29e9de8ce 100644 --- a/ext/QuantumCliffordHeckeExt/QuantumCliffordHeckeExt.jl +++ b/ext/QuantumCliffordHeckeExt/QuantumCliffordHeckeExt.jl @@ -5,7 +5,7 @@ using DocStringExtensions import QuantumClifford, LinearAlgebra import Hecke: Group, GroupElem, AdditiveGroup, AdditiveGroupElem, GroupAlgebra, GroupAlgebraElem, FqFieldElem, representation_matrix, dim, base_ring, - multiplication_table, coefficients, abelian_group, group_algebra, small_group, direct_product + multiplication_table, coefficients, abelian_group, group_algebra import Nemo import Nemo: characteristic, matrix_repr, GF, ZZ, lift diff --git a/ext/QuantumCliffordHeckeExt/lifted_product.jl b/ext/QuantumCliffordHeckeExt/lifted_product.jl index d9fa7c280..ef09eddbb 100644 --- a/ext/QuantumCliffordHeckeExt/lifted_product.jl +++ b/ext/QuantumCliffordHeckeExt/lifted_product.jl @@ -161,48 +161,6 @@ function two_block_group_algebra_codes(a::GroupAlgebraElem, b::GroupAlgebraElem) LPCode(A, B) end -""" -[[72, 8, 9]] 2BGA code from Table 1 of [lin2024quantum](@cite) with direct product -of `C₉ x C₄`. - -```jldoctest -julia> c = two_block_group_algebra_codes([0, 28], [0, 9, 18, 12, 29, 14], (36, 2)); - -julia> code_n(c), code_k(c) -(72, 8) -``` -""" -function two_block_group_algebra_codes(a_shifts::Array{Int}, b_shifts::Array{Int}, sg::Tuple{Int,Int}) - m, i = sg - g1 = small_group(m, i) - GA = group_algebra(GF(2), g1) - a = sum(GA[n%dim(GA)+1] for n in a_shifts) - b = sum(GA[n%dim(GA)+1] for n in b_shifts) - two_block_group_algebra_codes(a, b) -end - -""" -[[48, 8, 6]] 2BGA code from Table 3 of [lin2024quantum](@cite) with dihedral group of -order `l = 12`. - -```jldoctest -julia> c = two_block_group_algebra_codes([0, 10], [0, 8, 9, 4, 2, 5], (12, 4), (2, 1)); - -julia> code_n(c), code_k(c) -(48, 8) -``` -""" -function two_block_group_algebra_codes(a_shifts::Array{Int}, b_shifts::Array{Int}, sg1::Tuple{Int,Int}, sg2::Tuple{Int,Int}) - m, i = sg1 - l, i = sg2 - g1 = small_group(m, i) - g2 = small_group(l, i) - GA = group_algebra(GF(2), direct_product(g1, g2)) - a = sum(GA[n%dim(GA)+1] for n in a_shifts) - b = sum(GA[n%dim(GA)+1] for n in b_shifts) - two_block_group_algebra_codes(a, b) -end - """ Generalized bicycle codes, which are a special case of 2GBA codes (and therefore of lifted product codes). Here the group is chosen as the cyclic group of order `l`, diff --git a/test/Project.toml b/test/Project.toml index cd15ae310..c69088264 100644 --- a/test/Project.toml +++ b/test/Project.toml @@ -16,6 +16,7 @@ LDPCDecoders = "3c486d74-64b9-4c60-8b1a-13a564e77efb" LinearAlgebra = "37e2e46d-f89d-539d-b4ee-838fcccc9c8e" MacroTools = "1914dd2f-81c6-5fcd-8719-6d5c9610ff09" Nemo = "2edaba10-b0f1-5616-af89-8c11ac63239a" +Oscar = "f1435218-dba5-11e9-1e4d-f1a5fab5fc13" PyQDecoders = "17f5de1a-9b79-4409-a58d-4d45812840f7" Quantikz = "b0d11df0-eea3-4d79-b4a5-421488cbf74b" QuantumInterface = "5717a53b-5d69-4fa3-b976-0bf2f97ca1e5" diff --git a/test/test_ecc_2bga_group_presentation.jl b/test/test_ecc_2bga_group_presentation.jl new file mode 100644 index 000000000..6b8dca652 --- /dev/null +++ b/test/test_ecc_2bga_group_presentation.jl @@ -0,0 +1,254 @@ +@testitem "ECC 2BGA abelian and non-abelian groups via group presentation" begin + using Nemo: FqFieldElem + using Hecke: group_algebra, GF, abelian_group, gens, quo, one, GroupAlgebra + using QuantumClifford.ECC + using QuantumClifford.ECC: code_k, code_n, two_block_group_algebra_codes + using Oscar: free_group, small_group_identification, describe, order, FPGroupElem, FPGroup, FPGroupElem + + function get_code(a_elts::Vector{FPGroupElem}, b_elts::Vector{FPGroupElem}, F2G::GroupAlgebra{FqFieldElem, FPGroup, FPGroupElem}) + a = sum(F2G(x) for x in a_elts) + b = sum(F2G(x) for x in b_elts) + c = two_block_group_algebra_codes(a,b) + return c + end + + @testset "Reproduce Table 1 Block 1" begin + # [[72, 8, 9]] + l = 36 + F = free_group(["r"]) + r = gens(F)[1] + G, = quo(F, [r^l]) + F2G = group_algebra(GF(2), G) + r = gens(G)[1] + a_elts = [one(G), r^28] + b_elts = [one(G), r, r^18, r^12, r^29, r^14] + c = get_code(a_elts, b_elts, F2G) + @test order(G) == l + @test describe(G) == "C$l" + @test code_n(c) == 72 && code_k(c) == 8 + # Oscar.describe(Oscar.small_group(l, 2)) is C₃₆, cross-check it with G + @test small_group_identification(G) == (order(G), 2) + end + + @testset "Reproduce Table 1 Block 2" begin + # [[72, 8, 9]] + l = 9 + m = 4 + F = free_group(["r", "s"]) + r, s = gens(F) + G, = quo(F, [s^m, r^l, s^(-1)*r*s*r]) + F2G = group_algebra(GF(2), G) + r, s = gens(G) + a_elts = [one(G), r] + b_elts = [one(G), s, r^6, s^3 * r, s * r^7, s^3 * r^5] + c = get_code(a_elts, b_elts, F2G) + @test order(G) == l*m + @test describe(G) == "C$l : C$m" + @test code_n(c) == 72 && code_k(c) == 8 + # Oscar.describe(Oscar.small_group(l*m, 1)) is C₉ x C₄, cross-check it with G + @test small_group_identification(G) == (order(G), 1) + + # [[80, 8, 10]] + l = 5 + m = 8 + F = free_group(["r", "s"]) + r, s = gens(F) + G, = quo(F, [s^l, r^m, r^(-1)*s*r*s]) + F2G = group_algebra(GF(2), G) + r, s = gens(G) + a_elts = [one(G), s*r^4] + b_elts = [one(G), r, r^2, s, s^3 * r, s^2 * r^6] + c = get_code(a_elts, b_elts, F2G) + @test order(G) == l*m + @test describe(G) == "C$l : C$m" + @test code_n(c) == 80 && code_k(c) == 8 + # Oscar.describe(Oscar.small_group(l*m, 1)) is C₅ x C₈, cross-check it with G + @test small_group_identification(G) == (order(G), 1) + end + + @testset "Reproduce Table 1 Block 3" begin + # [[54, 6, 9]] + l = 27 + F = free_group(["r"]) + r = gens(F)[1] + G, = quo(F, [r^l]) + F2G = group_algebra(GF(2), G) + r = gens(G)[1] + a_elts = [one(G), r, r^3, r^7] + b_elts = [one(G), r, r^12, r^19] + c = get_code(a_elts, b_elts, F2G) + @test order(G) == l + @test describe(G) == "C$l" + @test code_n(c) == 54 && code_k(c) == 6 + # Oscar.describe(Oscar.small_group(l, 1)) is C₂₇, cross-check it with G + @test small_group_identification(G) == (order(G), 1) + + # [[60, 6, 10]] + l = 30 + F = free_group(["r"]) + r = gens(F)[1] + G, = quo(F, [r^l]) + F2G = group_algebra(GF(2), G) + r = gens(G)[1] + a_elts = [one(G), r^10, r^6, r^13] + b_elts = [one(G), r^25, r^16, r^12] + c = get_code(a_elts, b_elts, F2G) + @test order(G) == l + @test describe(G) == "C$l" + @test code_n(c) == 60 && code_k(c) == 6 + # Oscar.describe(Oscar.small_group(l, 4)) is C₃₀, cross-check it with G + @test small_group_identification(G) == (order(G), 4) + + # [[70, 8, 10]] + l = 35 + F = free_group(["r"]) + r = gens(F)[1] + G, = quo(F, [r^l]) + F2G = group_algebra(GF(2), G) + r = gens(G)[1] + a_elts = [one(G), r^15, r^16, r^18] + b_elts = [one(G), r, r^24, r^27] + c = get_code(a_elts, b_elts, F2G) + @test order(G) == l + @test describe(G) == "C$l" + @test code_n(c) == 70 && code_k(c) == 8 + # Oscar.describe(Oscar.small_group(l, 1)) is C₃₅, cross-check it with G + @test small_group_identification(G) == (order(G), 1) + + # [[72, 8, 10]] + l = 36 + F = free_group(["r"]) + r = gens(F)[1] + G, = quo(F, [r^l]) + F2G = group_algebra(GF(2), G) + r = gens(G)[1] + a_elts = [one(G), r^9, r^28, r^31] + b_elts = [one(G), r, r^21, r^34] + c = get_code(a_elts, b_elts, F2G) + @test order(G) == l + @test describe(G) == "C$l" + @test code_n(c) == 72 && code_k(c) == 8 + # Oscar.describe(Oscar.small_group(l, 2)) is C₃₆, cross-check it with G + @test small_group_identification(G) == (order(G), 2) + + # [[72, 10, 9]] + F = free_group(["r"]) + r = gens(F)[1] + G, = quo(F, [r^l]) + F2G = group_algebra(GF(2), G) + r = gens(G)[1] + a_elts = [one(G), r^9, r^28, r^13] + b_elts = [one(G), r, r^3, r^22] + c = get_code(a_elts, b_elts, F2G) + @test order(G) == l + @test describe(G) == "C$l" + @test code_n(c) == 72 && code_k(c) == 10 + # Oscar.describe(Oscar.small_group(l, 2)) is C₃₆, cross-check it with G + @test small_group_identification(G) == (order(G), 2) + end + + @testset "Reproduce Table 1 Block 4" begin + # [[72, 8, 9]] + l = 9 + m = 4 + F = free_group(["r", "s"]) + r, s = gens(F) + G, = quo(F, [s^m, r^l, s^(-1)*r*s*r]) + F2G = group_algebra(GF(2), G) + r, s = gens(G) + a_elts = [one(G), s, r, s*r^6] + b_elts = [one(G), s^2*r, s^2*r^6, r^2] + c = get_code(a_elts, b_elts, F2G) + @test order(G) == l*m + @test describe(G) == "C$l : C$m" + @test code_n(c) == 72 && code_k(c) == 8 + # Oscar.describe(Oscar.small_group(l*m, 1)) is C₉ x C₄, cross-check it with G + @test small_group_identification(G) == (order(G), 1) + + # [[80, 8, 10]] + l = 5 + m = 8 + F = free_group(["r", "s"]) + r, s = gens(F) + G, = quo(F, [s^l, r^m, r^(-1)*s*r*s]) + F2G = group_algebra(GF(2), G) + r, s = gens(G) + a_elts = [one(G), r, s, s^3*r^5] + b_elts = [one(G), r^2, s*r^4, s^3*r^2] + c = get_code(a_elts, b_elts, F2G) + @test order(G) == l*m + @test describe(G) == "C$l : C$m" + @test code_n(c) == 80 && code_k(c) == 8 + # Oscar.describe(Oscar.small_group(l*m, 1)) is C₅ x C₈, cross-check it with G + @test small_group_identification(G) == (order(G), 1) + + # [[96, 8, 12]] + l = 3 + m = 16 + F = free_group(["r", "s"]) + r, s = gens(F) + G, = quo(F, [s^l, r^m, r^(-1)*s*r*s]) + F2G = group_algebra(GF(2), G) + r, s = gens(G) + a_elts = [one(G), r, s, r^14] + b_elts = [one(G), r^2, s*r^4, r^11] + c = get_code(a_elts, b_elts, F2G) + @test order(G) == l*m + @test describe(G) == "C$l : C$m" + @test code_n(c) == 96 && code_k(c) == 6 + # Oscar.describe(Oscar.small_group(l*m, 1)) is C₃ x C₁₆, cross-check it with G + @test small_group_identification(G) == (order(G), 1) + + # [[84, 10, 9]] + l = 7 + m = 3 + F = free_group(["r", "s"]) + r, s = gens(F) + G, = quo(F, [s^m, r^14, r^(-1)*s*r*s]) + F2G = group_algebra(GF(2), G) + r, s = gens(G) + a_elts = [one(G), r^7, r^8, s*r^10] + b_elts = [one(G), s, r^5, s^2*r^13] + c = get_code(a_elts, b_elts, F2G) + @test order(G) == 2*l*m + @test describe(G) == "C$l x S$m" + @test code_n(c) == 84 && code_k(c) == 10 + # Oscar.describe(Oscar.small_group(2*l*m, 3)) is C₇ x S₃, cross-check it with G + @test small_group_identification(G) == (order(G), 3) + + # [[96, 6, 12]] + l = 12 + m = 4 + F = free_group(["r", "s"]) + r, s = gens(F) + G, = quo(F, [s^m, r^l, s^(-1)*r*s*r]) + F2G = group_algebra(GF(2), G) + r, s = gens(G) + a_elts = [one(G), s, r^9, s * r] + b_elts = [one(G), s^2 * s^9, r^7, r^2] + c = get_code(a_elts, b_elts, F2G) + @test order(G) == l*m + @test describe(G) == "C$l : C$m" + @test code_n(c) == 96 && code_k(c) == 6 + # Oscar.describe(Oscar.small_group(l*m, 13)) is C₁₂ x C₄, cross-check it with G + @test small_group_identification(G) == (order(G), 13) + + # [[96, 12, 10]] + l = 2 + m = 3 + n = 8 + F = free_group(["r", "s"]) + r, s = gens(F) + G, = quo(F, [s^(l*m), r^n, r^(-1)*s*r*s]) + F2G = group_algebra(GF(2), G) + r, s = gens(G) + a_elts = [one(G), r, s^3 * r^2, s^2 * r^3] + b_elts = [one(G), r, s^4 * r^6, s^5 * r^3] + c = get_code(a_elts, b_elts, F2G) + @test order(G) == l*m*n + @test describe(G) == "C$l x (C$m : C$n)" + @test code_n(c) == 96 && code_k(c) == 12 + # Oscar.describe(Oscar.small_group(l*m*n, 9)) is C₂ x (C₃ : C₈), cross-check it with G + @test small_group_identification(G) == (order(G), 9) + end +end