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

Circulant GF(2) permutation matrix-based construction of Bivariate Bicycle quantum LDPC code #352

Draft
wants to merge 10 commits into
base: master
Choose a base branch
from
4 changes: 2 additions & 2 deletions Project.toml
Original file line number Diff line number Diff line change
Expand Up @@ -48,15 +48,15 @@ Combinatorics = "1.0"
DataStructures = "0.18"
DocStringExtensions = "0.9"
Graphs = "1.9"
Hecke = "0.28, 0.29, 0.30, 0.31, 0.32, 0.33, 0.34"
Hecke = "0.28, 0.29, 0.30, 0.31, 0.32, 0.33, 0.34, 0.34.3"
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

why is this needed?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is not needed now thanks to Tommy CI Oscar Injection!

This PR was done earlier, why I was trying to add Oscar to test runner, so that's why the weird additions

HostCPUFeatures = "0.1.6"
ILog2 = "0.2.3"
InteractiveUtils = "1.9"
LDPCDecoders = "0.3.1"
LinearAlgebra = "1.9"
MacroTools = "0.5.9"
Makie = "0.20, 0.21"
Nemo = "0.42.1, 0.43, 0.44, 0.45, 0.46, 0.47"
Nemo = "0.42.1, 0.43, 0.44, 0.45, 0.46, 0.47, 0.47.1"
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

why is this needed?

Plots = "1.38.0"
PrecompileTools = "1.2"
PyQDecoders = "0.2.1"
Expand Down
25 changes: 25 additions & 0 deletions docs/src/references.bib
Original file line number Diff line number Diff line change
Expand Up @@ -487,3 +487,28 @@
year={2014},
publisher={APS}
}

@article{bravyi2024high,
title={High-threshold and low-overhead fault-tolerant quantum memory},
author={Bravyi, Sergey and Cross, Andrew W and Gambetta, Jay M and Maslov, Dmitri and Rall, Patrick and Yoder, Theodore J},
journal={Nature},
volume={627},
number={8005},
pages={778--782},
year={2024},
publisher={Nature Publishing Group UK London}
}

@article{berthusen2024toward,
title={Toward a 2D local implementation of quantum LDPC codes},
author={Berthusen, Noah and Devulapalli, Dhruv and Schoute, Eddie and Childs, Andrew M and Gullans, Michael J and Gorshkov, Alexey V and Gottesman, Daniel},

Check warning on line 504 in docs/src/references.bib

View workflow job for this annotation

GitHub Actions / Spell Check with Typos

"Childs" should be "Children".
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

"Childs" needs to be added to the spellchecker (the .typos file)

journal={arXiv preprint arXiv:2404.17676},
year={2024}
}

@article{wang2024coprime,
title={Coprime Bivariate Bicycle Codes and their Properties},
author={Wang, Ming and Mueller, Frank},
journal={arXiv preprint arXiv:2408.10001},
year={2024}
}
3 changes: 3 additions & 0 deletions docs/src/references.md
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,9 @@ For quantum code construction routines:
- [steane1999quantum](@cite)
- [campbell2012magic](@cite)
- [anderson2014fault](@cite)
- [bravyi2024high](@cite)
- [berthusen2024toward](@cite)
- [wang2024coprime](@cite)

For classical code construction routines:
- [muller1954application](@cite)
Expand Down
2 changes: 2 additions & 0 deletions src/ecc/ECC.jl
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ export parity_checks, parity_checks_x, parity_checks_z, iscss,
Toric, Gottesman, Surface, Concat, CircuitCode, QuantumReedMuller,
LPCode, two_block_group_algebra_codes, generalized_bicycle_codes, bicycle_codes,
random_brickwork_circuit_code, random_all_to_all_circuit_code,
circulant_bivariate_bicycle,
evaluate_decoder,
CommutationCheckECCSetup, NaiveSyndromeECCSetup, ShorSyndromeECCSetup,
TableDecoder,
Expand Down Expand Up @@ -384,5 +385,6 @@ include("codes/quantumreedmuller.jl")
# qLDPC
include("codes/classical/lifted.jl")
include("codes/lifted_product.jl")
include("codes/circulant_bivariate_bicycle.jl")

end #module
49 changes: 49 additions & 0 deletions src/ecc/codes/circulant_bivariate_bicycle.jl
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
"""
A bivariate bicycle (BB) quantum LDPC code was introduced by Bravyi et al. in their 2024 paper [bravyi2024high](@cite). This code uses identity and cyclic shift matrices. Define `Iₗ` as the `l × l` identity matrix and `Sₗ` as the cyclic shift matrix of the same size, where each row of `Sₗ` has a single '1' at the column `(i + 1) mod l`.

The matrices `x = Sₗ ⊗ Iₘ` and `y = Iₗ ⊗ Sₘ` are used. The BB code is represented by matrices `A` and `B`, defined as: `A = A₁ + A₂ + A₃` and `B = B₁ + B₂ + B₃`. The addition and multiplication operations on binary matrices are performed modulo 2. The check matrices are: `Hx = [A|B]` and `Hz = [B'|A']`. Both `Hx` and `Hz` are `(n/2)×n` matrices.

The ECC Zoo has an [entry for this family](https://errorcorrectionzoo.org/c/qcga).
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This also needs:

  • explanation of what the l,m,A,B entries are
  • doctest example
  • comparison to using directly the other ways in which this code can already be created in this library
  • "see also" for other codes and constructions
  • a remark in the "see also" that mentions alternative way to construct these same codes

"""
struct circulant_bivariate_bicycle <: AbstractECC
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this should be named like a struct, not like a function (e.g. CirculantBivariateBicycle)

l::Int
m::Int
A::Vector{Int}
B::Vector{Int}
function circulant_bivariate_bicycle(l,m,A,B)
(l >= 0 && m >= 0) || error("l and m must be non-negative")
(length(A) == 3 && length(B) == 3) || error("A and B must each have exactly 3 entries")
(all(x -> x >= 0, A) && all(x -> x >= 0, B)) || error("A and B must contain only non-negative integers")
(all(x -> x in 0:max(l, m), A) && all(x -> x in 0:max(l, m), B)) || error("Each element in A and B must be in the range [0, $(max(l, m))].")
Comment on lines +14 to +17
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

could you use an explicit throw of an argument error or domain error instead of a generic error

new(l,m,A,B)
end
end

function iscss(::Type{circulant_bivariate_bicycle})
return true
end

function parity_checks(c::circulant_bivariate_bicycle)
a₁,a₂,a₃ = c.A[1],c.A[2],c.A[3]
b₁,b₂,b₃ = c.B[1],c.B[2],c.B[3]
Iₗ = Matrix{Bool}(LinearAlgebra.I,c.l,c.l)
Iₘ = Matrix{Bool}(LinearAlgebra.I,c.m,c.m)
x = Dict{Bool, Matrix{Bool}}()
y = Dict{Bool, Matrix{Bool}}()
x = Dict(i => kron(circshift(Iₗ,(0,i)),Iₘ) for i in 0:(c.l))
y = Dict(i => kron(Iₗ,circshift(Iₘ,(0,i))) for i in 0:(c.m))
A = mod.(x[a₁]+y[a₂]+y[a₃],2)
B = mod.(y[b₁]+x[b₂]+x[b₃],2)
Hx = hcat(A,B)
Hz = hcat(B',A')
H = CSS(Hx,Hz)
Stabilizer(H)
end

code_n(c::circulant_bivariate_bicycle) = 2*c.l*c.m

code_k(c::circulant_bivariate_bicycle) = code_n(c) - LinearAlgebra.rank(matrix(GF(2), parity_checks_x(c))) - LinearAlgebra.rank(matrix(GF(2), parity_checks_z(c)))

parity_checks_x(c::circulant_bivariate_bicycle) = stab_to_gf2(parity_checks(circulant_bivariate_bicycle(c.l, c.m, c.A, c.B)))[1:end÷2,:]

parity_checks_z(c::circulant_bivariate_bicycle) = stab_to_gf2(parity_checks(circulant_bivariate_bicycle(c.l, c.m, c.A, c.B)))[end÷2+1:end,:]
4 changes: 4 additions & 0 deletions test/Project.toml
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ ArrayInterface = "4fba245c-0d91-5ea0-9b3e-6abc04ee57a9"
CUDA = "052768ef-5323-5732-b1bb-66c8b64840ba"
Combinatorics = "861a8166-3701-5b0c-9a16-15d98fcdc6aa"
DocStringExtensions = "ffbed154-4ef7-542d-bbb7-c09d3a79fcae"
GAP = "c863536a-3901-11e9-33e7-d5cd0df7b904"
Documenter = "e30172f5-a6a5-5a46-863b-614d45cd2de4"
Graphs = "86223c79-3864-5bf0-83f7-82e725a168b6"
Hecke = "3e1990a7-5d81-5526-99ce-9ba3ff248f21"
Expand All @@ -16,12 +17,15 @@ 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"
Polymake = "d720cf60-89b5-51f5-aff5-213f193123e7"
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

why is polymake needed?

PyQDecoders = "17f5de1a-9b79-4409-a58d-4d45812840f7"
Quantikz = "b0d11df0-eea3-4d79-b4a5-421488cbf74b"
QuantumInterface = "5717a53b-5d69-4fa3-b976-0bf2f97ca1e5"
QuantumOpticsBase = "4f57444f-1401-5e15-980d-4471b28d5678"
Random = "9a3f8284-a2c9-5f02-9a11-845980a1fd5c"
RecipesBase = "3cdcf5f2-1ef4-517c-9805-6587b60abb01"
Singular = "bcd08a7b-43d2-5ff7-b6d4-c458787f915c"
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

why is Singular needed?

SIMD = "fdea26ae-647d-5447-a871-4b548cad5224"
StableRNGs = "860ef19b-820b-49d6-a774-d7a799459cd3"
Static = "aedffcd0-7271-4cad-89d0-dc628f76c6d3"
Expand Down
3 changes: 2 additions & 1 deletion test/test_ecc_base.jl
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,8 @@ const code_instance_args = Dict(
:Concat => [(Perfect5(), Perfect5()), (Perfect5(), Steane7()), (Steane7(), Cleve8()), (Toric(2, 2), Shor9())],
:CircuitCode => random_circuit_code_args,
:LPCode => (c -> (c.A, c.B)).(vcat(LP04, LP118, test_gb_codes, other_lifted_product_codes)),
:QuantumReedMuller => [3, 4, 5]
:QuantumReedMuller => [3, 4, 5],
:circulant_bivariate_bicycle => [(9,6,[3,1,2],[3,1,2]),(15,3,[9,1,2],[0,2,7]),(6,6,[3,1,2],[3,1,2]),(14,7,[6,5,6],[0,4,13]),(15,5,[5,2,3],[2,7,6])]
)

function all_testablable_code_instances(;maxn=nothing)
Expand Down
53 changes: 53 additions & 0 deletions test/test_ecc_circulantbivariatebicycle.jl
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
@testitem "ECC circulant_bivariate_bicycle" begin
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

these tests probable also need a subset of tests that verify correctness against the other construction method you have already contributed

using Test
using QuantumClifford: stab_to_gf2
using QuantumClifford.ECC
using Nemo: nullspace, GF, matrix
using Oscar: hom, free_module, kernel, domain, map, gens

Check warning on line 6 in test/test_ecc_circulantbivariatebicycle.jl

View workflow job for this annotation

GitHub Actions / Spell Check with Typos

"hom" should be "home".
using QuantumClifford.ECC: AbstractECC, circulant_bivariate_bicycle, parity_checks_x, parity_checks_z

# According to Lemma 1 from [bravyi2024high](@cite), k = 2·dim(ker(A)∩ker(B)).
function _formula_k(stab)
Hx = parity_checks_x(stab)
n = size(Hx,2)÷2
A = matrix(GF(2), Hx[:,1:n])
B = matrix(GF(2), Hx[:,n+1:end])
k = GF(2)
hA = hom(free_module(k, size(A, 1)), free_module(k, size(A, 2)), A)

Check warning on line 16 in test/test_ecc_circulantbivariatebicycle.jl

View workflow job for this annotation

GitHub Actions / Spell Check with Typos

"hom" should be "home".
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

hom needs to be added to the spellchecker (the .typos file)

hB = hom(free_module(k, size(B, 1)), free_module(k, size(B, 2)), B)

Check warning on line 17 in test/test_ecc_circulantbivariatebicycle.jl

View workflow job for this annotation

GitHub Actions / Spell Check with Typos

"hom" should be "home".
ans = kernel(hA)[1] ∩ kernel(hB)[1]
k = 2*size(map(domain(hA), gens(ans[1])), 1)
return k
end

@testset "Verify number of logical qubits `k` from Table 3: bravyi2024high" begin
# Refer to [bravyi2024high](@cite) for code constructions
@test code_k(circulant_bivariate_bicycle(9 , 6 , [3 , 1 , 2] , [3 , 1 , 2])) == 8 == _formula_k(circulant_bivariate_bicycle(9 , 6 , [3 , 1 , 2] , [3 , 1 , 2]))
@test code_k(circulant_bivariate_bicycle(15, 3 , [9 , 1 , 2] , [0 , 2 , 7])) == 8 == _formula_k(circulant_bivariate_bicycle(15, 3 , [9 , 1 , 2] , [0 , 2 , 7]))
@test code_k(circulant_bivariate_bicycle(12, 12, [3 , 2 , 7] , [3 , 1 , 2])) == 12 == _formula_k(circulant_bivariate_bicycle(12, 12, [3 , 2 , 7] , [3 , 1 , 2]))
@test code_k(circulant_bivariate_bicycle(12, 6 , [3 , 1 , 2] , [3 , 1 , 2])) == 12 == _formula_k(circulant_bivariate_bicycle(12, 6 , [3 , 1 , 2] , [3 , 1 , 2]))
@test code_k(circulant_bivariate_bicycle(6 , 6 , [3 , 1 , 2] , [3 , 1 , 2])) == 12 == _formula_k(circulant_bivariate_bicycle(6 , 6 , [3 , 1 , 2] , [3 , 1 , 2]))
@test code_k(circulant_bivariate_bicycle(30, 6 , [9 , 1 , 2] , [3 , 25, 26])) == 12 == _formula_k(circulant_bivariate_bicycle(30, 6 , [9 , 1 , 2] , [3 , 25, 26]))
@test code_k(circulant_bivariate_bicycle(21, 18, [3 , 10, 17], [5 , 3 , 19])) == 16 == _formula_k(circulant_bivariate_bicycle(21, 18, [3 , 10, 17], [5 , 3 , 19]))
@test code_k(circulant_bivariate_bicycle(28, 14, [26, 6 , 8] , [7 , 9 , 20])) == 24 == _formula_k(circulant_bivariate_bicycle(28, 14, [26, 6 , 8] , [7 , 9 , 20]))
end

@testset "Verify number of logical qubits `k` from Table 1: berthusen2024toward" begin
# Refer to [berthusen2024toward](@cite) for code constructions
@test code_k(circulant_bivariate_bicycle(12, 3 , [9 , 1 , 2] , [0 , 1 , 11])) == 8 == _formula_k(circulant_bivariate_bicycle(12, 3 , [9 , 1 , 2] , [0 , 1 ,11]))
@test code_k(circulant_bivariate_bicycle(9 , 5 , [8 , 4 , 1] , [5 , 8 , 7])) == 8 == _formula_k(circulant_bivariate_bicycle(9 , 5 , [8 , 4 , 1], [5 , 8 , 7]))
@test code_k(circulant_bivariate_bicycle(12, 5 , [10, 4 , 1] , [0 , 1 , 2])) == 8 == _formula_k(circulant_bivariate_bicycle(12, 5 , [10, 4 , 1] , [0 , 1 , 2]))
@test code_k(circulant_bivariate_bicycle(15, 5 , [5 , 2 , 3] , [2 , 7 , 6])) == 8 == _formula_k(circulant_bivariate_bicycle(15, 5 , [5 , 2 , 3] , [2 , 7 , 6]))
@test code_k(circulant_bivariate_bicycle(14, 7 , [6 , 5 , 6] , [0 , 4, 13])) == 12 == _formula_k(circulant_bivariate_bicycle(14, 7 , [6 , 5 , 6] , [0 , 4, 13]))
end

@testset "Verify number of logical qubits `k` from Table 1: wang2024coprime" begin
# # Refer to [wang2024coprime](@cite) for code constructions
@test code_k(circulant_bivariate_bicycle(3, 9 , [0 , 2 , 4] , [3 , 1 , 2])) == 8 == _formula_k(circulant_bivariate_bicycle(3, 9 , [0 , 2 , 4] , [3 , 1 , 2]))
@test code_k(circulant_bivariate_bicycle(7, 7 , [3 , 5 , 6] , [2 , 3 , 5])) == 6 == _formula_k(circulant_bivariate_bicycle(7, 7 , [3 , 5 , 6] , [2 , 3 , 5]))
@test code_k(circulant_bivariate_bicycle(3, 21 , [0 , 2 ,10] , [3 , 1 , 2])) == 8 == _formula_k(circulant_bivariate_bicycle(3, 21 , [0 , 2 ,10] , [3 , 1 , 2]))
@test code_k(circulant_bivariate_bicycle(5, 15 , [0 , 6 , 8] , [5 , 1 , 4])) == 16 == _formula_k(circulant_bivariate_bicycle(5, 15 , [0 , 6 , 8] , [5 , 1 , 4]))
@test code_k(circulant_bivariate_bicycle(3, 27 , [0 , 10,14] , [12, 1 , 2])) == 8 == _formula_k(circulant_bivariate_bicycle(3, 27 , [0 , 10,14] , [12, 1 , 2]))
@test code_k(circulant_bivariate_bicycle(6, 15 , [3 , 1 , 2] , [6 , 4 , 5])) == 8 == _formula_k(circulant_bivariate_bicycle(6, 15 , [3 , 1 , 2] , [6 , 4 , 5]))
end
end
Loading