|
| 1 | +""" |
| 2 | +Bivariate Bicycle code using *polynomial quotient ring formalism*: The set of |
| 3 | +monomials ``\\{x^i y^j \\mid 0 \\leq i < \\ell, 0 \\leq j < m}`` forms a basis |
| 4 | +for the matrix algebra generated by ``x`` and ``y``, establishing a [bijection](https://en.wikipedia.org/wiki/Bijection) |
| 5 | +between these monomials and the resulting ``(\\ell m) \\times (\\ell m)`` matrices. |
| 6 | +This correspondence allows us to work equivalently with either the polynomial or |
| 7 | +matrix formulation [wang2024coprime](@cite). |
| 8 | +""" |
| 9 | +struct BivariateBicycleCode <: AbstractCSSCode |
| 10 | + """Order of the first abelian group in ``\\mathbb{F}_2[\\mathbb{Z}_\\ell \\times \\mathbb{Z}_m]``""" |
| 11 | + ℓ::Int |
| 12 | + """Order of the second abelian group in ``\\mathbb{F}_2[\\mathbb{Z}_\\ell \\times \\mathbb{Z}_m]``""" |
| 13 | + m::Int |
| 14 | + """First bivariate polynomial in quotient ring ``\\frac{\\mathbb{F}_2[x, y]}{\\langle x^\\ell-1, y^m-1 \\rangle}``""" |
| 15 | + c::MPolyQuoRingElem |
| 16 | + """Second bivariate polynomial in quotient ring ``\\frac{\\mathbb{F}_2[x, y]}{\\langle x^\\ell-1, y^m-1 \\rangle}``""" |
| 17 | + d::MPolyQuoRingElem |
| 18 | + |
| 19 | + function BivariateBicycleCode(ℓ::Int, m::Int, c::MPolyQuoRingElem, d::MPolyQuoRingElem) |
| 20 | + ℓ > 0 || throw(ArgumentError("ℓ must be positive")) |
| 21 | + m > 0 || throw(ArgumentError("m must be positive")) |
| 22 | + parent(c) == parent(d) || throw(ArgumentError("Polynomials must be in the same quotient ring")) |
| 23 | + Q = parent(c) |
| 24 | + R = base_ring(Q) |
| 25 | + base_ring(R) == GF(2) || throw(ArgumentError("Base ring must be GF(2)")) |
| 26 | + nvars(R) == 2 || throw(ArgumentError("Must be bivariate polynomials")) |
| 27 | + new(ℓ, m, c, d) |
| 28 | + end |
| 29 | +end |
| 30 | + |
| 31 | +function poly_to_coeff_mat(poly::MPolyQuoRingElem, ℓ::Int, m::Int) |
| 32 | + mat = zeros(Int, ℓ, m) |
| 33 | + poly_lift = lift(poly) |
| 34 | + for term in terms(poly_lift) |
| 35 | + coeffᵥₐₗ = coeff(term, 1) |
| 36 | + coeffᵢₙₜ = iszero(coeffᵥₐₗ) ? 0 : 1 |
| 37 | + monom = monomial(term, 1) |
| 38 | + exps = exponent_vector(monom, 1) |
| 39 | + i = length(exps) >= 1 ? exps[1] : 0 |
| 40 | + j = length(exps) >= 2 ? exps[2] : 0 |
| 41 | + i = mod(i, ℓ) |
| 42 | + j = mod(j, m) |
| 43 | + if i < ℓ && j < m |
| 44 | + mat[i+1, j+1] = coeffᵢₙₜ |
| 45 | + end |
| 46 | + end |
| 47 | + return mat |
| 48 | +end |
| 49 | + |
| 50 | +function build_bivariate_circulant(coeff_mat::Matrix{Int}) |
| 51 | + ℓ, m = size(coeff_mat) |
| 52 | + n = ℓ*m |
| 53 | + circ_mat = zeros(Int, n, n) |
| 54 | + for i₁ in 0:ℓ-1, j₁ in 0:m-1 |
| 55 | + row_idx = i₁*m+j₁+1 |
| 56 | + for i₂ in 0:ℓ-1, j₂ in 0:m-1 |
| 57 | + i_res = mod(i₁ + i₂, ℓ) |
| 58 | + j_res = mod(j₁ + j₂, m) |
| 59 | + col_idx = i_res*m + j_res + 1 |
| 60 | + circ_mat[row_idx, col_idx] += coeff_mat[i₂+1, j₂+1] |
| 61 | + end |
| 62 | + end |
| 63 | + return circ_mat |
| 64 | +end |
| 65 | + |
| 66 | +function parity_matrix_xz(c::BivariateBicycleCode) |
| 67 | + A_coeff = poly_to_coeff_mat(c.c, c.ℓ, c.m) |
| 68 | + B_coeff = poly_to_coeff_mat(c.d, c.ℓ, c.m) |
| 69 | + A = build_bivariate_circulant(A_coeff) |
| 70 | + B = build_bivariate_circulant(B_coeff) |
| 71 | + hx, hz = hcat(A, B), hcat(transpose(B), transpose(A)) |
| 72 | + return hx, hz |
| 73 | +end |
| 74 | + |
| 75 | +parity_matrix_x(c::BivariateBicycleCode) = parity_matrix_xz(c)[1] |
| 76 | + |
| 77 | +parity_matrix_z(c::BivariateBicycleCode) = parity_matrix_xz(c)[2] |
| 78 | + |
| 79 | +code_n(c::BivariateBicycleCode) = 2*c.ℓ*c.m |
0 commit comments