Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

2D Local implementation of Bivariate Bicycle qLDPC codes: Toric Layouts #387

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 4 additions & 2 deletions src/ecc/ECC.jl
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ using QuantumClifford: AbstractOperation, AbstractStabilizer, Stabilizer
import QuantumClifford: Stabilizer, MixedDestabilizer, nqubits
using DocStringExtensions
using Combinatorics: combinations
using SparseArrays: sparse
using SparseArrays: SparseMatrixCSC, sparse, spzeros
using Statistics: std
using Nemo: ZZ, residue_ring, matrix, finite_field, GF, minpoly, coeff, lcm, FqPolyRingElem, FqFieldElem, is_zero, degree, defining_polynomial, is_irreducible, echelon_form

Expand All @@ -27,7 +27,8 @@ export parity_checks, parity_checks_x, parity_checks_z, iscss,
CommutationCheckECCSetup, NaiveSyndromeECCSetup, ShorSyndromeECCSetup,
TableDecoder,
BeliefPropDecoder, BitFlipDecoder,
PyBeliefPropDecoder, PyBeliefPropOSDecoder, PyMatchingDecoder
PyBeliefPropDecoder, PyBeliefPropOSDecoder, PyMatchingDecoder,
bivariate_toric_layout

"""Parity check tableau of a code.

Expand Down Expand Up @@ -361,6 +362,7 @@ end

include("circuits.jl")
include("decoder_pipeline.jl")
include("bivariate_toric_layout.jl")

include("codes/util.jl")

Expand Down
78 changes: 78 additions & 0 deletions src/ecc/bivariate_toric_layout.jl
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
using LinearAlgebra
using SparseArrays: SparseMatrixCSC, sparse, spzeros

function cyclic_shift_matrix(l::Int)
arr = spzeros(Int,l,l)
for i in 1:l
arr[i, mod(i,l)+1] = 1
end
return arr
end

pow²(mat::SparseMatrixCSC{Int, Int},exp::Int) = (mat^exp).%2

function order(mat::SparseMatrixCSC{Int}, m::Int, l::Int)
n = size(mat,1)
I = sparse(LinearAlgebra.I(n))
p = mat
for i in 1:m*l
if p == I return i end
p *= mat
end
return -1

Check warning on line 22 in src/ecc/bivariate_toric_layout.jl

View check run for this annotation

Codecov / codecov/patch

src/ecc/bivariate_toric_layout.jl#L22

Added line #L22 was not covered by tests
end

function _toric_layout₁(As::Vector{SparseMatrixCSC{Int64, Int64}}, Bs::Vector{SparseMatrixCSC{Int64, Int64}}, m::Int, l::Int)
A_ord = [order(AA,m,l) for AA in As]
B_ord = [order(BB,m,l) for BB in Bs]
valid_orders = []
for (i, Ao) in enumerate(A_ord)
for (j, Bo) in enumerate(B_ord)
Ao * Bo == m*l && push!(valid_orders, (Ao,Bo,i,j))
end
end
return valid_orders
end

function _toric_layout₂(As::Vector{SparseMatrixCSC{Int64, Int64}}, Bs::Vector{SparseMatrixCSC{Int64, Int64}}, m::Int, l::Int, codes::NTuple{4,Int64})
mₑ, lₑ, A_idx, B_idx = codes
(A_idx < 1 || A_idx > length(As)) && throw(DimensionMismatch("Invalid index A_idx: $A_idx"))
(B_idx < 1 || B_idx > length(Bs)) && throw(DimensionMismatch("Invalid index B_idx: $B_idx"))
visited = Set{Int}()
v = sparse(As[A_idx])
h = sparse(Bs[B_idx])
zero = zeros(Int, m*l)
zero[1] = 1
for i in 0:mₑ-1
tmp = (v^i)*zero
for j in 0:lₑ-1
visited = union(visited, Set(findall(j == 0 ? tmp .>0 : h^j*tmp .> 0)))
end
end
return length(visited) == l*m
end

"""Determines if a bivariate bicycle code has a toric layout on a `2ℓ × 2m` grid."""
function bivariate_toric_layout(code::Vector{Int})
l = code[1]
m = code[2]
x = kron(cyclic_shift_matrix(l), LinearAlgebra.I(m))
y = kron(LinearAlgebra.I(l), cyclic_shift_matrix(m))
A₁ = pow²(x, code[3])
A₂ = pow²(y, code[4])
A₃ = pow²(y, code[5])
A = (A₁+A₂+A₃).%2
B₁ = pow²(y, code[6])
B₂ = pow²(x, code[7])
B₃ = pow²(x, code[8])
B = (B₁+B₂+B₃).%2
As = [A₁*A₂', A₂'*A₁, A₂*A₃', A₃'*A₂, A₁*A₃', A₃'*A₁]
Bs = [B₁*B₂', B₂'*B₁, B₂*B₃', B₃'*B₂, B₁*B₃', B₃'*B₁]
selected_codes = []
valid_codes = _toric_layout₁(As, Bs, m, l)
for valid_code in valid_codes
_toric_layout₂(As, Bs, m, l, valid_code) && push!(selected_codes, valid_code)
end
orig_layout = [(params[1], params[2], params[3]-1, params[4]-1) for params in selected_codes]
return orig_layout
end
20 changes: 20 additions & 0 deletions test/test_ecc_bivariate_toric_layout.jl
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
@testitem "ECC Bivaraite Toric Layout" begin
using QuantumClifford.ECC
using QuantumClifford.ECC: AbstractECC, bivariate_toric_layout

codes = [[6 ,6 ,3 ,1 ,2 ,3 ,1 ,2 ],
[15,3 ,9 ,1 ,2 ,0 ,2 ,7 ],
[6 ,9 ,3 ,1 ,2 ,3 ,1 ,2 ],
[12,6 ,3 ,1 ,2 ,3 ,1 ,2 ],
[12,12,3 ,2 ,7 ,3 ,1 ,2 ],
[30,6 ,9 ,1 ,2 ,3 ,25,26],
[21,18,3 ,10,17,5 ,3 ,19]]
# cross checks taken from https://arxiv.org/pdf/2404.17676.
@test bivariate_toric_layout(codes[1]) == [(6, 6, 0, 2), (6, 6, 0, 3), (6, 6, 0, 4), (6, 6, 0, 5), (6, 6, 1, 2), (6, 6, 1, 3), (6, 6, 1, 4), (6, 6, 1, 5), (6, 6, 2, 0), (6, 6, 2, 1), (6, 6, 2, 2), (6, 6, 2, 3), (6, 6, 3, 0), (6, 6, 3, 1), (6, 6, 3, 2), (6, 6, 3, 3), (6, 6, 4, 0), (6, 6, 4, 1), (6, 6, 4, 4), (6, 6, 4, 5), (6, 6, 5, 0), (6, 6, 5, 1), (6, 6, 5, 4), (6, 6, 5, 5)]
@test bivariate_toric_layout(codes[2]) == [(15, 3, 0, 2), (15, 3, 0, 3), (15, 3, 1, 2), (15, 3, 1, 3), (3, 15, 2, 0), (3, 15, 2, 1), (3, 15, 2, 4), (3, 15, 2, 5), (3, 15, 3, 0), (3, 15, 3, 1), (3, 15, 3, 4), (3, 15, 3, 5), (15, 3, 4, 2), (15, 3, 4, 3), (15, 3, 5, 2), (15, 3, 5, 3)]
@test bivariate_toric_layout(codes[3]) == [(18, 3, 0, 4), (18, 3, 0, 5), (18, 3, 1, 4), (18, 3, 1, 5), (9, 6, 2, 0), (9, 6, 2, 1), (9, 6, 2, 2), (9, 6, 2, 3), (9, 6, 3, 0), (9, 6, 3, 1), (9, 6, 3, 2), (9, 6, 3, 3), (18, 3, 4, 4), (18, 3, 4, 5), (18, 3, 5, 4), (18, 3, 5, 5)]
@test bivariate_toric_layout(codes[4]) == [(12, 6, 0, 4), (12, 6, 0, 5), (12, 6, 1, 4), (12, 6, 1, 5), (6, 12, 2, 0), (6, 12, 2, 1), (6, 12, 2, 2), (6, 12, 2, 3), (6, 12, 3, 0), (6, 12, 3, 1), (6, 12, 3, 2), (6, 12, 3, 3), (12, 6, 4, 4), (12, 6, 4, 5), (12, 6, 5, 4), (12, 6, 5, 5)]
@test bivariate_toric_layout(codes[5]) == [(12, 12, 0, 0), (12, 12, 0, 1), (12, 12, 0, 4), (12, 12, 0, 5), (12, 12, 1, 0), (12, 12, 1, 1), (12, 12, 1, 4), (12, 12, 1, 5), (12, 12, 2, 0), (12, 12, 2, 1), (12, 12, 2, 2), (12, 12, 2, 3), (12, 12, 3, 0), (12, 12, 3, 1), (12, 12, 3, 2), (12, 12, 3, 3), (12, 12, 4, 2), (12, 12, 4, 3), (12, 12, 4, 4), (12, 12, 4, 5), (12, 12, 5, 2), (12, 12, 5, 3), (12, 12, 5, 4), (12, 12, 5, 5)]
@test bivariate_toric_layout(codes[6]) == [(6, 30, 2, 2), (6, 30, 2, 3), (6, 30, 3, 2), (6, 30, 3, 3), (30, 6, 4, 0), (30, 6, 4, 1), (30, 6, 5, 0), (30, 6, 5, 1)]
@test bivariate_toric_layout(codes[7]) == [(18, 21, 2, 2), (18, 21, 2, 3), (18, 21, 3, 2), (18, 21, 3, 3)]
end
Loading