diff --git a/ext/QuantumCliffordGPUExt/fastmemlayout.jl b/ext/QuantumCliffordGPUExt/fastmemlayout.jl index f5706b641..490903ef9 100644 --- a/ext/QuantumCliffordGPUExt/fastmemlayout.jl +++ b/ext/QuantumCliffordGPUExt/fastmemlayout.jl @@ -8,7 +8,7 @@ TableauAdj is the type of Tableau with its data stored in an adjoint of a CUDA a rest of the fastrow, fastcolumn functions are implemented in QuantumClifford.jl """ -# todo when we use to_gpu, to_cpu the efffect of fastrow, fastcolumn disappears +# todo when we use to_gpu, to_cpu the effect of fastrow, fastcolumn disappears fastrow(t::TableauCUDA) = t fastrow(t::TableauAdj) = Tableau(t.phases, t.nqubits, CuArray(t.xzs)) fastcolumn(t::TableauCUDA) = Tableau(t.phases, t.nqubits, CuArray(t.xzs')') diff --git a/ext/QuantumCliffordOscarExt/QuantumCliffordOscarExt.jl b/ext/QuantumCliffordOscarExt/QuantumCliffordOscarExt.jl index b65df2b75..70aae076e 100644 --- a/ext/QuantumCliffordOscarExt/QuantumCliffordOscarExt.jl +++ b/ext/QuantumCliffordOscarExt/QuantumCliffordOscarExt.jl @@ -17,7 +17,8 @@ import Oscar: free_group, small_group_identification, describe, order, FPGroupEl base_ring, ComplexOfMorphisms, coefficients, zero_matrix, hcat, circshift, size, zeros, enumerate, kronecker_product, FqMatrix, identity_matrix, iszero, FqPolyRingElem, laurent_polynomial_ring, hnf_with_transform, ideal, intersect, ==, is_coprime, quo, groebner_basis, length, FqMPolyRingElem, - first, length, MPolyQuoRingElem, FqMPolyRingElem, modulus, ideal, monomials, terms, coeff, degree, mod + first, MPolyQuoRingElem, FqMPolyRingElem, modulus, ideal, monomials, terms, coeff, degree, mod, + monomial, exponent_vector, nvars import Oscar.Generic.MatSpaceElem import Oscar.Generic.DirectSumModule import Oscar.Generic.LaurentMPolyWrap @@ -37,6 +38,7 @@ export twobga_from_direct_product, twobga_from_fp_group, DDimensionalSurfaceCode include("types.jl") include("direct_product.jl") +include("bivariate_bicycle.jl") include("generalized_toric.jl") include("group_presentation.jl") include("d_dimensional_codes.jl") diff --git a/ext/QuantumCliffordOscarExt/bivariate_bicycle.jl b/ext/QuantumCliffordOscarExt/bivariate_bicycle.jl new file mode 100644 index 000000000..bab634353 --- /dev/null +++ b/ext/QuantumCliffordOscarExt/bivariate_bicycle.jl @@ -0,0 +1,182 @@ +""" + $TYPEDEF + +Bivariate Bicycle codes are CSS codes constructed using the *quotient ring* +``R = \\mathbb{F}_2[x, y] / \\langle x^\\ell - 1, y^m - 1 \\rangle``. + +There is an injective ring homomorphism from ``R`` to ``\\mathbb{F}_2^{\\ell m \\times \\ell m}`` +given by ``x \\mapsto S_\\ell \\otimes I_m`` and ``y \\mapsto I_k \\otimes S_m``, +where ``S_k`` is the cyclic shift matrix of size ``k \\times k`` [eberhardt2024logical](@cite). + +This homomorphism allows us to work with either the polynomial quotient ring +or explicit circulant matrix formulation. We implement the polynomial quotient ring formalism. + +#### Examples + +Here is the `[[54, 8, 6]]` from Table 1 [wang2024coprime](@cite) + +```jldoctest +julia> using Oscar; using QuantumClifford.ECC; + +julia> l=3; m=9; + +julia> R, (x, y) = polynomial_ring(GF(2), [:x, :y]); + +julia> I = ideal(R, [x^l-1, y^m-1]); + +julia> S, _ = quo(R, I); + +julia> A = S(1 + y^2 + y^4); + +julia> B = S(y^3 + x + x^2); + +julia> c = BivariateBicycleCode(l, m, A, B); + +julia> code_n(c), code_k(c) +(54, 8) +``` + +Here is the `[[72, 12, 6]]` from Table 3 of [bravyi2024high](@cite) + +```jldoctest +julia> using Oscar; using QuantumClifford.ECC; + +julia> l=6; m=6; + +julia> R, (x, y) = polynomial_ring(GF(2), [:x, :y]); + +julia> I = ideal(R, [x^l-1, y^m-1]); + +julia> S, _ = quo(R, I); + +julia> A = S(x^3 + y + y^2); + +julia> B = S(y^3 + x + x^2); + +julia> c = BivariateBicycleCode(l, m, A, B); + +julia> code_n(c), code_k(c) +(72, 12) +``` + +Here is the `[[756, 16, ≤ 34]]` from Table 3 of [bravyi2024high](@cite) + +```jldoctest +julia> using Oscar; using QuantumClifford.ECC; + +julia> l=21; m=18; + +julia> R, (x, y) = polynomial_ring(GF(2), [:x, :y]); + +julia> I = ideal(R, [x^l-1, y^m-1]); + +julia> S, _ = quo(R, I); + +julia> A = S(x^3 + y^10 + y^17); + +julia> B = S(y^5 + x^3 + x^19); + +julia> c = BivariateBicycleCode(l, m, A, B); + +julia> code_n(c), code_k(c) +(756, 16) +``` + +Here is the `[[128, 14, 12]]` from Table 1 [eberhardt2024logical](@cite) + +```jldoctest +julia> using Oscar; using QuantumClifford.ECC; + +julia> l=8; m=8; + +julia> R, (x, y) = polynomial_ring(GF(2), [:x, :y]); + +julia> I = ideal(R, [x^l-1, y^m-1]); + +julia> S, _ = quo(R, I); + +julia> A = S(x^2 + y + y^3 + y^4); + +julia> B = S(y^2 + x + x^3 + x^4); + +julia> c = BivariateBicycleCode(l, m, A, B); + +julia> code_n(c), code_k(c) +(128, 14) +``` + +See also: [`GeneralizedCirculantBivariateBicycle`](@ref) + +### Fields + $TYPEDFIELDS +""" +struct BivariateBicycleCode <: AbstractCSSCode + """Order of the first abelian group in ``\\mathbb{F}_2[\\mathbb{Z}_\\ell \\times \\mathbb{Z}_m]``""" + ℓ::Int + """Order of the second abelian group in ``\\mathbb{F}_2[\\mathbb{Z}_\\ell \\times \\mathbb{Z}_m]``""" + m::Int + """First bivariate polynomial in quotient ring ``\\frac{\\mathbb{F}_2[x, y]}{\\langle x^\\ell-1, y^m-1 \\rangle}``""" + c::MPolyQuoRingElem + """Second bivariate polynomial in quotient ring ``\\frac{\\mathbb{F}_2[x, y]}{\\langle x^\\ell-1, y^m-1 \\rangle}``""" + d::MPolyQuoRingElem + + function BivariateBicycleCode(ℓ::Int, m::Int, c::MPolyQuoRingElem, d::MPolyQuoRingElem) + ℓ > 0 || throw(ArgumentError("ℓ must be positive")) + m > 0 || throw(ArgumentError("m must be positive")) + parent(c) == parent(d) || throw(ArgumentError("Polynomials must be in the same quotient ring")) + Q = parent(c) + R = base_ring(Q) + base_ring(R) == GF(2) || throw(ArgumentError("Base ring must be GF(2)")) + nvars(R) == 2 || throw(ArgumentError("Must be bivariate polynomials")) + new(ℓ, m, c, d) + end +end + +function _poly_to_coeff_mat(poly::MPolyQuoRingElem, ℓ::Int, m::Int) + mat = zeros(Int, ℓ, m) + for term in terms(lift(poly)) + coeffᵥₐₗ = coeff(term, 1) + coeffᵢₙₜ = iszero(coeffᵥₐₗ) ? 0 : 1 + monom = monomial(term, 1) + exps = exponent_vector(monom, 1) + i = length(exps) >= 1 ? exps[1] : 0 + j = length(exps) >= 2 ? exps[2] : 0 + i = mod(i, ℓ) + j = mod(j, m) + if i < ℓ && j < m + mat[i+1, j+1] = coeffᵢₙₜ + end + end + return mat +end + +function _bivariate_circulant(coeff_mat::Matrix{Int}) + ℓ, m = size(coeff_mat) + n = ℓ*m + circ_mat = zeros(Int, n, n) + for i₁ in 0:ℓ-1, j₁ in 0:m-1 + row_idx = i₁*m+j₁+1 + for i₂ in 0:ℓ-1, j₂ in 0:m-1 + i_mod = mod(i₁+i₂, ℓ) + j_mod = mod(j₁+j₂, m) + col_idx = i_mod*m+j_mod+1 + circ_mat[row_idx, col_idx] += coeff_mat[i₂+1, j₂+1] + end + end + return circ_mat +end + +function parity_matrix_xz(c::BivariateBicycleCode) + A_coeff = _poly_to_coeff_mat(c.c, c.ℓ, c.m) + B_coeff = _poly_to_coeff_mat(c.d, c.ℓ, c.m) + A = _bivariate_circulant(A_coeff) + B = _bivariate_circulant(B_coeff) + hx, hz = hcat(A, B), hcat(transpose(B), transpose(A)) + return hx, hz +end + +parity_matrix_x(c::BivariateBicycleCode) = parity_matrix_xz(c)[1] + +parity_matrix_z(c::BivariateBicycleCode) = parity_matrix_xz(c)[2] + +code_n(c::BivariateBicycleCode) = 2*c.ℓ*c.m diff --git a/src/ecc/ECC.jl b/src/ecc/ECC.jl index fc60c46ed..d1119db41 100644 --- a/src/ecc/ECC.jl +++ b/src/ecc/ECC.jl @@ -41,7 +41,7 @@ export parity_checks, parity_matrix_x, parity_matrix_z, iscss, GeneralizedCirculantBivariateBicycle, GeneralizedHyperGraphProductCode, GeneralizedBicycleCode, ExtendedGeneralizedBicycleCode, HomologicalProductCode, DoubleHomologicalProductCode, - GeneralizedToricCode, TrivariateTricycleCode, + GeneralizedToricCode, TrivariateTricycleCode, BivariateBicycleCode, evaluate_decoder, CommutationCheckECCSetup, NaiveSyndromeECCSetup, ShorSyndromeECCSetup, TableDecoder, diff --git a/src/ecc/codes/concat.jl b/src/ecc/codes/concat.jl index 0bd8f627b..1304f36ea 100644 --- a/src/ecc/codes/concat.jl +++ b/src/ecc/codes/concat.jl @@ -25,7 +25,7 @@ function parity_checks(c::Concat) phases_logx₁ = phases(logx_ops(c₁)) h_logz₁ = stab_to_gf2(logz_ops(c₁)) phases_logz₁ = phases(logz_ops(c₁)) - # parity checks of c₂ with qubits repalced with logical qubits of c₁ + # parity checks of c₂ with qubits replaced with logical qubits of c₁ outer_check_h = transpose(hcat([vcat( kron(h₂[i, 1:end÷2], h_logx₁[j, 1:end÷2]) .⊻ kron(h₂[i, end÷2+1:end], h_logz₁[j, 1:end÷2]), # X part kron(h₂[i, 1:end÷2], h_logx₁[j, end÷2+1:end]) .⊻ kron(h₂[i, end÷2+1:end], h_logz₁[j, end÷2+1:end]) # Z part diff --git a/src/ecc/codes/qeccs_using_oscar.jl b/src/ecc/codes/qeccs_using_oscar.jl index 71db55148..c6a33d70e 100644 --- a/src/ecc/codes/qeccs_using_oscar.jl +++ b/src/ecc/codes/qeccs_using_oscar.jl @@ -74,3 +74,13 @@ function TrivariateTricycleCode(args...; kwargs...) end return ext.TrivariateTricycleCode(args...; kwargs...) end + +"""Bivariate Bicycle codes ([jacob2025singleshotdecodingfaulttolerantgates](@cite)) +Implemented as a package extension with `Oscar`. Check the [QuantumClifford documentation](http://qc.quantumsavory.org/stable/ECC_API/) for more details on that extension.""" +function BivariateBicycleCode(args...; kwargs...) + ext = Base.get_extension(QuantumClifford, :QuantumCliffordOscarExt) + if isnothing(ext) + throw("The `BivariateBicycleCode` depends on the package `Oscar` but you have not installed or imported it yet. Immediately after you import `Oscar`, the `BivariateBicycleCode` will be available.") + end + return ext.BivariateBicycleCode(args...; kwargs...) +end diff --git a/src/randoms.jl b/src/randoms.jl index b1150a0a4..b45c28018 100644 --- a/src/randoms.jl +++ b/src/randoms.jl @@ -287,7 +287,7 @@ function _reset!(memory::RandDestabMemory) end end -# Allocation free inverse of upper trinagular int matrix with 1 on diagonal. +# Allocation free inverse of upper triangular int matrix with 1 on diagonal. function _inv!(inverse, A) for i in 2:size(A, 2) for j in 1:i-1 diff --git a/src/sumtypes.jl b/src/sumtypes.jl index f496532b0..d06ac4a3f 100644 --- a/src/sumtypes.jl +++ b/src/sumtypes.jl @@ -209,7 +209,7 @@ end ## -# `concrete_typeparams` annotations for the parameteric types we care about +# `concrete_typeparams` annotations for the parametric types we care about ## function concrete_typeparams(t::Type{ClassicalXOR}) diff --git a/test/test_ecc_base.jl b/test/test_ecc_base.jl index 89460e987..8b34000b3 100644 --- a/test/test_ecc_base.jl +++ b/test/test_ecc_base.jl @@ -523,13 +523,55 @@ const code_instance_args = Dict( α1₆ = (0, 3) α2₆ = (19, 1) + # Bivariate Bicycle codes using polynomial quotient ring + # [[72, 12, 6]] + l_bb₁=6; m_bb₁=6 + R_bb₁, (x, y) = polynomial_ring(GF(2), [:x, :y]) + I_bb₁ = ideal(R_bb₁, [x^l-1, y^m-1]) + S_bb₁, _ = quo(R_bb₁, I_bb₁) + A_bb₁ = S_bb₁(x^3 + y + y^2) + B_bb₁ = S_bb₁(y^3 + x + x^2) + + # [[90, 8, 10]] + l_bb₂=15; m_bb₂=3 + R_bb₂, (x, y) = polynomial_ring(GF(2), [:x, :y]) + I_bb₂ = ideal(R_bb₂, [x^l-1, y^m-1]) + S_bb₂, _ = quo(R_bb₂, I_bb₂) + A_bb₂ = S_bb₂(x^9 + y + y^2) + B_bb₂ = S_bb₂(1 + x^2 + x^7) + + # [[108, 8, 10]] + l_bb₃=9; m_bb₃=6 + R_bb₃, (x, y) = polynomial_ring(GF(2), [:x, :y]) + I_bb₃ = ideal(R_bb₃, [x^l-1, y^m-1]) + S_bb₃, _ = quo(R_bb₃, I_bb₃) + A_bb₃ = S_bb₃(x^3 + y + y^2) + B_bb₃ = S_bb₃(y^3 + x + x^2) + + # [[54, 8, 6]] + l_bb₄=3; m_bb₄=9 + R_bb₄, (x, y) = polynomial_ring(GF(2), [:x, :y]) + I_bb₄ = ideal(R_bb₄, [x^l-1, y^m-1]) + S_bb₄, _ = quo(R_bb₄, I_bb₄) + A_bb₄ = S_bb₄(1 + y^2 + y^4) + B_bb₄ = S_bb₄(y^3 + x + x^2) + + # [[98, 6, 12]] + l_bb₅=7; m_bb₅=7 + R_bb₅, (x, y) = polynomial_ring(GF(2), [:x, :y]) + I_bb₅ = ideal(R_bb₅, [x^l-1, y^m-1]) + S_bb₅, _ = quo(R_bb₅, I_bb₅) + A_bb₅ = S_bb₅(x^3 + y^5 + y^6) + B_bb₅ = S_bb₅(y^2 + x^3 + x^5) + oscar_code_instance_args = Dict( :DDimensionalSurfaceCode => [(2, 3), (3, 2), (3, 3), (4, 2)], :DDimensionalToricCode => [(2, 3), (3, 2), (3, 3), (4, 2)], :GeneralizedToricCode => [(f₁, g₁, α1₁, α2₁), (f₂, g₂, α1₂, α2₂), (f₃, g₃, α1₃, α2₃), (f₄, g₄, α1₄, α2₄), (f₅, g₅, α1₅, α2₅), (f₆, g₆, α1₆, α2₆)], :HomologicalProductCode => [([H₁, transpose(H₁)], l₁), ([H₂, transpose(H₂)], l₂), ([H₃, transpose(H₃)],), ([δ₄, δ₄, δ₄],)], :DoubleHomologicalProductCode => [(δ₁,), (δ₂,)], - :TrivariateTricycleCode => [(ℓ₁, m₁, p₁, A₁, B₁, C₁), (ℓ₂, m₂, p₂, A₂, B₂, C₂), (ℓ₃, m₃, p₃, A₃, B₃, C₃), (ℓ₄, m₄, p₄, A₄, B₄, C₄)] + :TrivariateTricycleCode => [(ℓ₁, m₁, p₁, A₁, B₁, C₁), (ℓ₂, m₂, p₂, A₂, B₂, C₂), (ℓ₃, m₃, p₃, A₃, B₃, C₃), (ℓ₄, m₄, p₄, A₄, B₄, C₄)], + :BivariateBicycleCode => [(l_bb₁, m_bb₁, A_bb₁, B_bb₁), (l_bb₂, m_bb₂, A_bb₂, B_bb₂), (l_bb₃, m_bb₃, A_bb₃, B_bb₃), (l_bb₄, m_bb₄, A_bb₄, B_bb₄), (l_bb₅, m_bb₅, A_bb₅, B_bb₅)] ) merge!(code_instance_args, oscar_code_instance_args) end diff --git a/test/test_ecc_bivaraite_bicycle_via_quotient_ring.jl b/test/test_ecc_bivaraite_bicycle_via_quotient_ring.jl new file mode 100644 index 000000000..29c4697df --- /dev/null +++ b/test/test_ecc_bivaraite_bicycle_via_quotient_ring.jl @@ -0,0 +1,536 @@ +@testitem "ECC Bivaraite Bicycle" tags=[:ecc] begin + using Hecke + using HiGHS + using JuMP + using Hecke: group_algebra, GF, abelian_group, gens, one + using QuantumClifford.ECC: two_block_group_algebra_codes, code_k, code_n, distance, DistanceMIPAlgorithm + + @testset "Reproduce Table 3 bravyi2024high" begin + # [[72, 12, 6]] + l=6; m=6 + R, (x, y) = polynomial_ring(GF(2), [:x, :y]) + I = ideal(R, [x^l-1, y^m-1]) + S, _ = quo(R, I) + A = S(x^3 + y + y^2) + B = S(y^3 + x + x^2) + c = BivariateBicycleCode(l, m, A, B) + @test code_n(c) == 72 && code_k(c) == 12 + Hx = parity_matrix_x(c) + n = size(Hx,2)÷2 + A = Hx[:,1:n] + B = Hx[:,n+1:end] + @test all(sum(A, dims=2) .== 3) + @test all(sum(B, dims=2) .== 3) + @test all(sum(A, dims=1) .== 3) + @test all(sum(B, dims=1) .== 3) + @test A*B == B*A + @test iszero(A*B+B*A) == iszero(2*A*B) + + # [[90, 8, 10]] + l=15; m=3 + R, (x, y) = polynomial_ring(GF(2), [:x, :y]) + I = ideal(R, [x^l-1, y^m-1]) + S, _ = quo(R, I) + A = S(x^9 + y + y^2) + B = S(1 + x^2 + x^7) + c = BivariateBicycleCode(l, m, A, B) + @test code_n(c) == 90 && code_k(c) == 8 + Hx = parity_matrix_x(c) + n = size(Hx,2)÷2 + A = Hx[:,1:n] + B = Hx[:,n+1:end] + @test all(sum(A, dims=2) .== 3) + @test all(sum(B, dims=2) .== 3) + @test all(sum(A, dims=1) .== 3) + @test all(sum(B, dims=1) .== 3) + @test A*B == B*A + @test iszero(A*B+B*A) == iszero(2*A*B) + + # [[108, 8, 10]] + l=9; m=6 + R, (x, y) = polynomial_ring(GF(2), [:x, :y]) + I = ideal(R, [x^l-1, y^m-1]) + S, _ = quo(R, I) + A = S(x^3 + y + y^2) + B = S(y^3 + x + x^2) + c = BivariateBicycleCode(l, m, A, B) + @test code_n(c) == 108 && code_k(c) == 8 + Hx = parity_matrix_x(c) + n = size(Hx,2)÷2 + A = Hx[:,1:n] + B = Hx[:,n+1:end] + @test all(sum(A, dims=2) .== 3) + @test all(sum(B, dims=2) .== 3) + @test all(sum(A, dims=1) .== 3) + @test all(sum(B, dims=1) .== 3) + @test A*B == B*A + @test iszero(A*B+B*A) == iszero(2*A*B) + + # [[144, 12, 12]] + l=12; m=6 + R, (x, y) = polynomial_ring(GF(2), [:x, :y]) + I = ideal(R, [x^l-1, y^m-1]) + S, _ = quo(R, I) + A = S(x^3 + y + y^2) + B = S(y^3 + x + x^2) + c = BivariateBicycleCode(l, m, A, B) + @test code_n(c) == 144 && code_k(c) == 12 + Hx = parity_matrix_x(c) + n = size(Hx,2)÷2 + A = Hx[:,1:n] + B = Hx[:,n+1:end] + @test all(sum(A, dims=2) .== 3) + @test all(sum(B, dims=2) .== 3) + @test all(sum(A, dims=1) .== 3) + @test all(sum(B, dims=1) .== 3) + @test A*B == B*A + @test iszero(A*B+B*A) == iszero(2*A*B) + + # [[288, 12, 12]] + l=12; m=12 + R, (x, y) = polynomial_ring(GF(2), [:x, :y]) + I = ideal(R, [x^l-1, y^m-1]) + S, _ = quo(R, I) + A = S(x^3 + y^2 + y^7) + B = S(y^3 + x + x^2) + c = BivariateBicycleCode(l, m, A, B) + @test code_n(c) == 288 && code_k(c) == 12 + + Hx = parity_matrix_x(c) + n = size(Hx,2)÷2 + A = Hx[:,1:n] + B = Hx[:,n+1:end] + @test all(sum(A, dims=2) .== 3) + @test all(sum(B, dims=2) .== 3) + @test all(sum(A, dims=1) .== 3) + @test all(sum(B, dims=1) .== 3) + @test A*B == B*A + @test iszero(A*B+B*A) == iszero(2*A*B) + + # [[360, 12, ≤ 24]] + l=30; m=6 + R, (x, y) = polynomial_ring(GF(2), [:x, :y]) + I = ideal(R, [x^l-1, y^m-1]) + S, _ = quo(R, I) + A = S(x^9 + y + y^2) + B = S(y^3 + x^25 + x^26) + c = BivariateBicycleCode(l, m, A, B) + @test code_n(c) == 360 && code_k(c) == 12 + Hx = parity_matrix_x(c) + n = size(Hx,2)÷2 + A = Hx[:,1:n] + B = Hx[:,n+1:end] + @test all(sum(A, dims=2) .== 3) + @test all(sum(B, dims=2) .== 3) + @test all(sum(A, dims=1) .== 3) + @test all(sum(B, dims=1) .== 3) + @test A*B == B*A + @test iszero(A*B+B*A) == iszero(2*A*B) + + # [[756, 16, ≤ 34]] + l=21; m=18 + R, (x, y) = polynomial_ring(GF(2), [:x, :y]) + I = ideal(R, [x^l-1, y^m-1]) + S, _ = quo(R, I) + A = S(x^3 + y^10 + y^17) + B = S(y^5 + x^3 + x^19) + c = BivariateBicycleCode(l, m, A, B) + @test code_n(c) == 756 && code_k(c) == 16 + Hx = parity_matrix_x(c) + n = size(Hx,2)÷2 + A = Hx[:,1:n] + B = Hx[:,n+1:end] + @test all(sum(A, dims=2) .== 3) + @test all(sum(B, dims=2) .== 3) + @test all(sum(A, dims=1) .== 3) + @test all(sum(B, dims=1) .== 3) + @test A*B == B*A + @test iszero(A*B+B*A) == iszero(2*A*B) + end + + @testset "Reproduce Table 1 berthusen2024toward" begin + # [[72, 8, 6]] + l=12; m=3 + R, (x, y) = polynomial_ring(GF(2), [:x, :y]) + I = ideal(R, [x^l-1, y^m-1]) + S, _ = quo(R, I) + A = S(x^9 + y + y^2) + B = S(1 + x + x^11) + c = BivariateBicycleCode(l, m, A, B) + @test code_n(c) == 72 && code_k(c) == 8 + Hx = parity_matrix_x(c) + n = size(Hx,2)÷2 + A = Hx[:,1:n] + B = Hx[:,n+1:end] + @test all(sum(A, dims=2) .== 3) + @test all(sum(B, dims=2) .== 3) + @test all(sum(A, dims=1) .== 3) + @test all(sum(B, dims=1) .== 3) + @test A*B == B*A + @test iszero(A*B+B*A) == iszero(2*A*B) + + # [[90, 8, 6]] + l=9; m=5 + R, (x, y) = polynomial_ring(GF(2), [:x, :y]) + I = ideal(R, [x^l-1, y^m-1]) + S, _ = quo(R, I) + A = S(x^8 + y^4 + y) + B = S(y^5 + x^8 + x^7) + c = BivariateBicycleCode(l, m, A, B) + @test code_n(c) == 90 && code_k(c) == 8 + Hx = parity_matrix_x(c) + n = size(Hx,2)÷2 + A = Hx[:,1:n] + B = Hx[:,n+1:end] + @test all(sum(A, dims=2) .== 3) + @test all(sum(B, dims=2) .== 3) + @test all(sum(A, dims=1) .== 3) + @test all(sum(B, dims=1) .== 3) + @test A*B == B*A + @test iszero(A*B+B*A) == iszero(2*A*B) + + # [[120, 8, 8]] + l=12; m=5 + R, (x, y) = polynomial_ring(GF(2), [:x, :y]) + I = ideal(R, [x^l-1, y^m-1]) + S, _ = quo(R, I) + A = S(x^10 + y^4 + y) + B = S(1 + x + x^2) + c = BivariateBicycleCode(l, m, A, B) + @test code_n(c) == 120 && code_k(c) == 8 + Hx = parity_matrix_x(c) + n = size(Hx,2)÷2 + A = Hx[:,1:n] + B = Hx[:,n+1:end] + @test all(sum(A, dims=2) .== 3) + @test all(sum(B, dims=2) .== 3) + @test all(sum(A, dims=1) .== 3) + @test all(sum(B, dims=1) .== 3) + @test A*B == B*A + @test iszero(A*B+B*A) == iszero(2*A*B) + + # [[150, 8, 8]] + l=15; m=5 + R, (x, y) = polynomial_ring(GF(2), [:x, :y]) + I = ideal(R, [x^l-1, y^m-1]) + S, _ = quo(R, I) + A = S(x^5 + y^2 + y^3) + B = S(y^2 + x^7 + x^6) + c = BivariateBicycleCode(l, m, A, B) + @test code_n(c) == 150 && code_k(c) == 8 + Hx = parity_matrix_x(c) + n = size(Hx,2)÷2 + A = Hx[:,1:n] + B = Hx[:,n+1:end] + @test all(sum(A, dims=2) .== 3) + @test all(sum(B, dims=2) .== 3) + @test all(sum(A, dims=1) .== 3) + @test all(sum(B, dims=1) .== 3) + @test A*B == B*A + @test iszero(A*B+B*A) == iszero(2*A*B) + + # [[196, 12, 8]] + l=14; m=7 + R, (x, y) = polynomial_ring(GF(2), [:x, :y]) + I = ideal(R, [x^l-1, y^m-1]) + S, _ = quo(R, I) + A = S(x^6 + y^5 + y^6) + B = S(1 + x^4 + x^13) + c = BivariateBicycleCode(l, m, A, B) + @test code_n(c) == 196 && code_k(c) == 12 + Hx = parity_matrix_x(c) + n = size(Hx,2)÷2 + A = Hx[:,1:n] + B = Hx[:,n+1:end] + @test all(sum(A, dims=2) .== 3) + @test all(sum(B, dims=2) .== 3) + @test all(sum(A, dims=1) .== 3) + @test all(sum(B, dims=1) .== 3) + @test A*B == B*A + @test iszero(A*B+B*A) == iszero(2*A*B) + end + + @testset "Reproduce Table 1 wang2024coprime" begin + # [[54, 8, 6]] + l=3; m=9 + R, (x, y) = polynomial_ring(GF(2), [:x, :y]) + I = ideal(R, [x^l-1, y^m-1]) + S, _ = quo(R, I) + A = S(1 + y^2 + y^4) + B = S(y^3 + x + x^2) + c = BivariateBicycleCode(l, m, A, B) + @test code_n(c) == 54 && code_k(c) == 8 + Hx = parity_matrix_x(c) + n = size(Hx,2)÷2 + A = Hx[:,1:n] + B = Hx[:,n+1:end] + @test all(sum(A, dims=2) .== 3) + @test all(sum(B, dims=2) .== 3) + @test all(sum(A, dims=1) .== 3) + @test all(sum(B, dims=1) .== 3) + @test A*B == B*A + @test iszero(A*B+B*A) == iszero(2*A*B) + + # [[98, 6, 12]] + l=7; m=7 + R, (x, y) = polynomial_ring(GF(2), [:x, :y]) + I = ideal(R, [x^l-1, y^m-1]) + S, _ = quo(R, I) + A = S(x^3 + y^5 + y^6) + B = S(y^2 + x^3 + x^5) + c = BivariateBicycleCode(l, m, A, B) + @test code_n(c) == 98 && code_k(c) == 6 + Hx = parity_matrix_x(c) + n = size(Hx,2)÷2 + A = Hx[:,1:n] + B = Hx[:,n+1:end] + @test all(sum(A, dims=2) .== 3) + @test all(sum(B, dims=2) .== 3) + @test all(sum(A, dims=1) .== 3) + @test all(sum(B, dims=1) .== 3) + @test A*B == B*A + @test iszero(A*B+B*A) == iszero(2*A*B) + + # [[126, 8, 10]] + l=3; m=21 + R, (x, y) = polynomial_ring(GF(2), [:x, :y]) + I = ideal(R, [x^l-1, y^m-1]) + S, _ = quo(R, I) + A = S(1 + y^2 + y^10) + B = S(y^3 + x + x^2) + c = BivariateBicycleCode(l, m, A, B) + @test code_n(c) == 126 && code_k(c) == 8 + Hx = parity_matrix_x(c) + n = size(Hx,2)÷2 + A = Hx[:,1:n] + B = Hx[:,n+1:end] + @test all(sum(A, dims=2) .== 3) + @test all(sum(B, dims=2) .== 3) + @test all(sum(A, dims=1) .== 3) + @test all(sum(B, dims=1) .== 3) + @test A*B == B*A + @test iszero(A*B+B*A) == iszero(2*A*B) + + # [[150, 16, 8]] + l=5; m=15 + R, (x, y) = polynomial_ring(GF(2), [:x, :y]) + I = ideal(R, [x^l-1, y^m-1]) + S, _ = quo(R, I) + A = S(1 + y^6 + y^8) + B = S(y^5 + x + x^4) + c = BivariateBicycleCode(l, m, A, B) + @test code_n(c) == 150 && code_k(c) == 16 + Hx = parity_matrix_x(c) + n = size(Hx,2)÷2 + A = Hx[:,1:n] + B = Hx[:,n+1:end] + @test all(sum(A, dims=2) .== 3) + @test all(sum(B, dims=2) .== 3) + @test all(sum(A, dims=1) .== 3) + @test all(sum(B, dims=1) .== 3) + @test A*B == B*A + @test iszero(A*B+B*A) == iszero(2*A*B) + + # [[162, 8, 14]] + l=3; m=27 + R, (x, y) = polynomial_ring(GF(2), [:x, :y]) + I = ideal(R, [x^l-1, y^m-1]) + S, _ = quo(R, I) + A = S(1 + y^10 + y^14) + B = S(y^12 + x + x^2) + c = BivariateBicycleCode(l, m, A, B) + @test code_n(c) == 162 && code_k(c) == 8 + Hx = parity_matrix_x(c) + n = size(Hx,2)÷2 + A = Hx[:,1:n] + B = Hx[:,n+1:end] + @test all(sum(A, dims=2) .== 3) + @test all(sum(B, dims=2) .== 3) + @test all(sum(A, dims=1) .== 3) + @test all(sum(B, dims=1) .== 3) + @test A*B == B*A + @test iszero(A*B+B*A) == iszero(2*A*B) + + # [[180, 8, 16]] + l=6; m=15 + R, (x, y) = polynomial_ring(GF(2), [:x, :y]) + I = ideal(R, [x^l-1, y^m-1]) + S, _ = quo(R, I) + A = S(x^3 + y + y^2) + B = S(y^6 + x^4 + x^5) + c = BivariateBicycleCode(l, m, A, B) + @test code_n(c) == 180 && code_k(c) == 8 + Hx = parity_matrix_x(c) + n = size(Hx,2)÷2 + A = Hx[:,1:n] + B = Hx[:,n+1:end] + @test all(sum(A, dims=2) .== 3) + @test all(sum(B, dims=2) .== 3) + @test all(sum(A, dims=1) .== 3) + @test all(sum(B, dims=1) .== 3) + @test A*B == B*A + @test iszero(A*B+B*A) == iszero(2*A*B) + end + + @testset "Reproduce Table 1 eberhardt2024logical" begin + # [[108, 16, 6]] + l=6; m=9 + R, (x, y) = polynomial_ring(GF(2), [:x, :y]) + I = ideal(R, [x^l-1, y^m-1]) + S, _ = quo(R, I) + A = S(1 + y + y^2) + B = S(y^3 + x^2 + x^4) + c = BivariateBicycleCode(l, m, A, B) + @test code_n(c) == 108 && code_k(c) == 16 + Hx = parity_matrix_x(c) + n = size(Hx,2)÷2 + A = Hx[:,1:n] + B = Hx[:,n+1:end] + @test all(sum(A, dims=2) .== 3) + @test all(sum(B, dims=2) .== 3) + @test all(sum(A, dims=1) .== 3) + @test all(sum(B, dims=1) .== 3) + @test A*B == B*A + @test iszero(A*B+B*A) == iszero(2*A*B) + + # [[128, 14, 12]] + l=8; m=8 + R, (x, y) = polynomial_ring(GF(2), [:x, :y]) + I = ideal(R, [x^l-1, y^m-1]) + S, _ = quo(R, I) + A = S(x^2 + y + y^3 + y^4) + B = S(y^2 + x + x^3 + x^4) + c = BivariateBicycleCode(l, m, A, B) + @test code_n(c) == 128 && code_k(c) == 14 + Hx = parity_matrix_x(c) + n = size(Hx,2)÷2 + A = Hx[:,1:n] + B = Hx[:,n+1:end] + @test all(sum(A, dims=2) .== 4) + @test all(sum(B, dims=2) .== 4) + @test all(sum(A, dims=1) .== 4) + @test all(sum(B, dims=1) .== 4) + @test A*B == B*A + @test iszero(A*B+B*A) == iszero(2*A*B) + + # [[162, 4, 16]] + l=9; m=9 + R, (x, y) = polynomial_ring(GF(2), [:x, :y]) + I = ideal(R, [x^l-1, y^m-1]) + S, _ = quo(R, I) + A = S(1 + x + y) + B = S(x^3 + y + y^2) + c = BivariateBicycleCode(l, m, A, B) + @test code_n(c) == 162 && code_k(c) == 4 + Hx = parity_matrix_x(c) + n = size(Hx,2)÷2 + A = Hx[:,1:n] + B = Hx[:,n+1:end] + @test all(sum(A, dims=2) .== 3) + @test all(sum(B, dims=2) .== 3) + @test all(sum(A, dims=1) .== 3) + @test all(sum(B, dims=1) .== 3) + @test A*B == B*A + @test iszero(A*B+B*A) == iszero(2*A*B) + + # [[162, 12, 8]] + l=9; m=9 + R, (x, y) = polynomial_ring(GF(2), [:x, :y]) + I = ideal(R, [x^l-1, y^m-1]) + S, _ = quo(R, I) + A = S(1 + x + y^6) + B = S(y^3 + x^2 + x^3) + c = BivariateBicycleCode(l, m, A, B) + @test code_n(c) == 162 && code_k(c) == 12 + Hx = parity_matrix_x(c) + n = size(Hx,2)÷2 + A = Hx[:,1:n] + B = Hx[:,n+1:end] + @test all(sum(A, dims=2) .== 3) + @test all(sum(B, dims=2) .== 3) + @test all(sum(A, dims=1) .== 3) + @test all(sum(B, dims=1) .== 3) + @test A*B == B*A + @test iszero(A*B+B*A) == iszero(2*A*B) + + # [[162, 24, 6]] + l=9; m=9 + R, (x, y) = polynomial_ring(GF(2), [:x, :y]) + I = ideal(R, [x^l-1, y^m-1]) + S, _ = quo(R, I) + A = S(1 + y + y^2) + B = S(y^3 + x^3 + x^6) + c = BivariateBicycleCode(l, m, A, B) + @test code_n(c) == 162 && code_k(c) == 24 + Hx = parity_matrix_x(c) + n = size(Hx,2)÷2 + A = Hx[:,1:n] + B = Hx[:,n+1:end] + @test all(sum(A, dims=2) .== 3) + @test all(sum(B, dims=2) .== 3) + @test all(sum(A, dims=1) .== 3) + @test all(sum(B, dims=1) .== 3) + @test A*B == B*A + @test iszero(A*B+B*A) == iszero(2*A*B) + + # [[270, 8, 18]] + l=9; m=15 + R, (x, y) = polynomial_ring(GF(2), [:x, :y]) + I = ideal(R, [x^l-1, y^m-1]) + S, _ = quo(R, I) + A = S(x^3 + y + y^2) + B = S(y^3 + x + x^2) + c = BivariateBicycleCode(l, m, A, B) + @test code_n(c) == 270 && code_k(c) == 8 + Hx = parity_matrix_x(c) + n = size(Hx,2)÷2 + A = Hx[:,1:n] + B = Hx[:,n+1:end] + @test all(sum(A, dims=2) .== 3) + @test all(sum(B, dims=2) .== 3) + @test all(sum(A, dims=1) .== 3) + @test all(sum(B, dims=1) .== 3) + @test A*B == B*A + @test iszero(A*B+B*A) == iszero(2*A*B) + + # [[98, 6, 12]] + l=7; m=7 + R, (x, y) = polynomial_ring(GF(2), [:x, :y]) + I = ideal(R, [x^l-1, y^m-1]) + S, _ = quo(R, I) + A = S(x + y^3 + y^4) + B = S(y + x^3 + x^4) + c = BivariateBicycleCode(l, m, A, B) + @test code_n(c) == 98 && code_k(c) == 6 + Hx = parity_matrix_x(c) + n = size(Hx,2)÷2 + A = Hx[:,1:n] + B = Hx[:,n+1:end] + @test all(sum(A, dims=2) .== 3) + @test all(sum(B, dims=2) .== 3) + @test all(sum(A, dims=1) .== 3) + @test all(sum(B, dims=1) .== 3) + @test A*B == B*A + @test iszero(A*B+B*A) == iszero(2*A*B) + + # [[162, 8, 12]] + l=9; m=9 + R, (x, y) = polynomial_ring(GF(2), [:x, :y]) + I = ideal(R, [x^l-1, y^m-1]) + S, _ = quo(R, I) + A = S(x^3 + y + y^2) + B = S(y^3 + x + x^2) + c = BivariateBicycleCode(l, m, A, B) + @test code_n(c) == 162 && code_k(c) == 8 + Hx = parity_matrix_x(c) + n = size(Hx,2)÷2 + A = Hx[:,1:n] + B = Hx[:,n+1:end] + @test all(sum(A, dims=2) .== 3) + @test all(sum(B, dims=2) .== 3) + @test all(sum(A, dims=1) .== 3) + @test all(sum(B, dims=1) .== 3) + @test A*B == B*A + @test iszero(A*B+B*A) == iszero(2*A*B) + end +end diff --git a/test/test_noisycircuits.jl b/test/test_noisycircuits.jl index b1eb33c3f..83e31dc8f 100644 --- a/test/test_noisycircuits.jl +++ b/test/test_noisycircuits.jl @@ -272,7 +272,7 @@ @test pet_y[true_success_stat] == 1 @test pet_y[failure_stat] == 0 - #checks probabilstic case to see if the phase of measurement anticommuting stabilizer is the same in both branches + #checks probabilistic case to see if the phase of measurement anticommuting stabilizer is the same in both branches ghz_state = S"XXX ZZI IZZ" reg = Register(ghz_state, [0]) branches = applybranches(reg, sMRZ(1,1))