| Documentation |
|
| Continuous integration |
|
| Code coverage |
|
QuantumExpanders is a
Julia Language
package for constructing quantum Tanner codes. To install QuantumExpanders,
please open
Julia's interactive session (known as REPL) and press the ] key in the REPL to use the package mode, and then type:
pkg> add https://github.com/QuantumSavory/QuantumExpanders.jl.gitTo update, just type up in the package mode.
random_quantum_Tanner_codeconstructs a quantum CSS code by instantiating two classical Tanner codes, 𝒞ᶻ and 𝒞ˣ, on the graphs 𝒢₀□ and 𝒢₁□ of a left-right Cayley complex leverrier2022quantum. This complex is generated from a group G, and two generating sets A and B of sizes Δ_A and Δ_B, which, need not satisfy the Total No-Conjugacy condition because of quadripartite construction of LRCC. The code's qubits bijectively correspond to the squares Q of the complex, with theedge_*_idxoutput providing the essential mappings between qubit indices, graph edges in 𝒢₀□ and 𝒢₁□, and the local coordinate sets A×B at each vertex. The Z-parity checks of the quantum code are defined as the generators of 𝒞ᶻ = T(𝒢₀□, (C_A⊗C_B)⊥), enforcing local constraints from the dual tensor code at each vertex of V₀. Similarly, the X-parity checks are generators of 𝒞ˣ = T(𝒢₁□, (C_A⊥⊗C_B⊥)⊥), enforced at vertices of V₁. When the Cayley graphs Cay(G,A) and Cay(G,B) are Ramanujan and the component codes C_A and C_B are randomly chosen with robust dual tensor properties, this construction produces an asymptotically good quantum LDPC code with parameters [[n, Θ(n), Θ(n)]]. The QT code implementation provides a simplified variant of the Panteleev-Kalachev quantum LDPC codes panteleev2022asymptoticallygoodquantumlocally and is related to the locally testable code of dinur2022locally.
Here is the [[360, 10, 4]] quantum Tanner code constructed from Morgenstern Ramanujan graphs
for even prime power q.
julia> l = 1; i = 2;
julia> q = 2^l
2
julia> Δ = q+1
3
julia> SL₂, B = morgenstern_generators(l, i)
[ Info: |SL₂(𝔽(4))| = 60
(SL(2,4), MatrixGroupElem{FqFieldElem, FqMatrix}[[o+1 o+1; 1 o+1], [o+1 1; o+1 o+1], [o+1 o; o o+1]])
julia> A = alternative_morgenstern_generators(B, FirstOnly())
4-element Vector{MatrixGroupElem{FqFieldElem, FqMatrix}}:
[0 1; 1 o+1]
[o+1 1; 1 0]
[o+1 o+1; o 0]
[0 o+1; o o+1]
julia> rng = MersenneTwister(10);
julia> hx, hz = random_quantum_Tanner_code(0.4, SL₂, A, B, rng=deepcopy(rng));
julia> c = CSS(hx, hz);
julia> import JuMP; import HiGHS;
julia> code_n(c), code_k(c), distance(c, DistanceMIPAlgorithm(solver=HiGHS, time_limit=120))
(360, 10, 4)
Expanding upon the work of radebold2025explicit, which was confined to dihedral groups, we have constructed new explicit quantum Tanner codes based on a broader class of Frobenius groups.
Here is the [[150, 48, 4]] using symmetric group of order 3.
julia> rng = MersenneTwister(43);
julia> G = symmetric_group(3);
julia> S = normal_cayley_subset(G);
julia> hx, hz = random_quantum_Tanner_code(0.65, G, S, S, bipartite=false, use_same_local_code=true, rng=deepcopy(rng));
(length(group), length(A), length(B)) = (6, 5, 5)
length(group) * length(A) * length(B) = 150
[ Info: |Q| = |G||A||B| = 150
Hᴬ = [1 1 0 1 1]
Hᴮ = [1 1 0 1 0; 0 0 0 1 0; 1 1 0 1 1]
Cᴬ = [1 1 0 0 0; 0 0 1 0 0; 1 0 0 1 0; 1 0 0 0 1]
Cᴮ = [1 1 0 0 0; 0 0 1 0 0; 1 0 0 1 0; 1 0 0 0 1]
size(Cˣ) = (16, 25)
size(Cᶻ) = (1, 25)
r1 = rank(𝒞ˣ) = 96
r2 = rank(𝒞ᶻ) = 6
julia> c = CSS(hx, hz);
julia> import JuMP; import HiGHS;
julia> code_n(c), code_k(c), distance(c, DistanceMIPAlgorithm(solver=HiGHS, time_limit=120))
(150, 48, 4)
Here is the [[36, 16, 3]] code based on permutation group
of order 4 that improves upon the [[36, 8, 3]] parameters presented in Table 5 of radebold2025explicit,
achieving twice the number of logical qubits while maintaining the same distance.
julia> rng = MersenneTwister(52);
julia> x = cperm([1,2,3,4]);
julia> G = permutation_group(4, [x]);
julia> S = normal_cayley_subset(G)
3-element Vector{PermGroupElem}:
(1,2,3,4)
(1,3)(2,4)
(1,4,3,2)
julia> hx, hz = random_quantum_Tanner_code(0.65, G, S, S, bipartite=false, use_same_local_code=true, rng=deepcopy(rng));
(length(group), length(A), length(B)) = (4, 3, 3)
length(group) * length(A) * length(B) = 36
[ Info: |Q| = |G||A||B| = 36
Hᴬ = [1 1 1]
Hᴮ = [1 0 1]
Cᴬ = [1 1 0; 1 0 1]
Cᴮ = [1 1 0; 1 0 1]
size(Cˣ) = (4, 9)
size(Cᶻ) = (1, 9)
r1 = rank(𝒞ˣ) = 16
r2 = rank(𝒞ᶻ) = 4
julia> c = CSS(hx, hz);
julia> import JuMP; import HiGHS;
julia> code_n(c), code_k(c), distance(c, DistanceMIPAlgorithm(solver=HiGHS, time_limit=120))
(36, 16, 3)
Here is the [[252, 70, 6]] using cyclic group of order 7.
julia> rng = MersenneTwister(54);
julia> G = cyclic_group(7);
julia> S = normal_cayley_subset(G);
julia> hx, hz = random_quantum_Tanner_code(0.7, G, S, S, bipartite=false, use_same_local_code=true, rng=deepcopy(rng));
(length(group), length(A), length(B)) = (7, 6, 6)
length(group) * length(A) * length(B) = 252
[ Info: |Q| = |G||A||B| = 252
Hᴬ = [1 1 1 1 1 1]
Hᴮ = [1 0 0 1 1 0; 1 1 0 1 1 0; 0 1 1 0 1 0; 1 0 1 1 1 0]
Cᴬ = [1 1 0 0 0 0; 1 0 1 0 0 0; 1 0 0 1 0 0; 1 0 0 0 1 0; 1 0 0 0 0 1]
Cᴮ = [1 1 0 0 0 0; 1 0 1 0 0 0; 1 0 0 1 0 0; 1 0 0 0 1 0; 1 0 0 0 0 1]
size(Cˣ) = (25, 36)
size(Cᶻ) = (1, 36)
r1 = rank(𝒞ˣ) = 175
r2 = rank(𝒞ᶻ) = 7
julia> c = CSS(hx, hz);
julia> import JuMP; import HiGHS;
julia> code_n(c), code_k(c), distance(c, DistanceMIPAlgorithm(solver=HiGHS, time_limit=120))
(252, 70, 6)
Here is a [[392, 96, 5]] code using quaternion group of order 8.
julia> rng = MersenneTwister(42);
julia> G = small_group(8, 4);
julia> describe(G), small_group_identification(G)
("Q8", (8, 4))
julia> S = normal_cayley_subset(G);
julia> hx, hz = random_quantum_Tanner_code(0.72, G, S, S, bipartite=false, use_same_local_code=true, rng=deepcopy(rng));
(length(group), length(A), length(B)) = (8, 7, 7)
length(group) * length(A) * length(B) = 392
[ Info: |Q| = |G||A||B| = 392
Hᴬ = [0 1 0 1 1 1 1]
Hᴮ = [1 0 0 1 0 1 0; 0 0 1 0 0 0 1; 0 0 1 0 1 0 1; 0 0 0 1 0 0 1; 1 1 1 1 0 1 0]
Cᴬ = [1 0 0 0 0 0 0; 0 0 1 0 0 0 0; 0 1 0 1 0 0 0; 0 1 0 0 1 0 0; 0 1 0 0 0 1 0; 0 1 0 0 0 0 1]
Cᴮ = [1 0 0 0 0 0 0; 0 0 1 0 0 0 0; 0 1 0 1 0 0 0; 0 1 0 0 1 0 0; 0 1 0 0 0 1 0; 0 1 0 0 0 0 1]
size(Cˣ) = (36, 49)
size(Cᶻ) = (1, 49)
r1 = rank(𝒞ˣ) = 288
r2 = rank(𝒞ᶻ) = 8
julia> c = CSS(hx, hz);
julia> import JuMP; import HiGHS;
julia> c = CSS(hx, hz);
julia> code_n(c), code_k(c), distance(c, DistanceMIPAlgorithm(solver=HiGHS, time_limit=120))
(392, 96, 5)
Here is a [[576, 126, 7]] code using the direct product of two cyclic groups (C₃ × C₃).
julia> rng = MersenneTwister(20);
julia> G = small_group(9, 2);
julia> describe(G), small_group_identification(G)
("C3 x C3", (9, 2))
julia> S = normal_cayley_subset(G);
julia> hx, hz = random_quantum_Tanner_code(0.8, G, S, S, bipartite=false, use_same_local_code=true, rng=deepcopy(rng));
(length(group), length(A), length(B)) = (9, 8, 8)
length(group) * length(A) * length(B) = 576
[ Info: |Q| = |G||A||B| = 576
Hᴬ = [1 1 1 0 1 1 1 1]
Hᴮ = [0 0 0 1 0 1 1 1; 1 1 0 1 1 1 0 0; 1 0 1 0 1 1 1 1; 1 0 1 0 0 0 1 0; 1 1 1 0 1 1 1 1; 1 0 1 1 1 0 1 0]
Cᴬ = [1 1 0 0 0 0 0 0; 1 0 1 0 0 0 0 0; 0 0 0 1 0 0 0 0; 1 0 0 0 1 0 0 0; 1 0 0 0 0 1 0 0; 1 0 0 0 0 0 1 0; 1 0 0 0 0 0 0 1]
Cᴮ = [1 1 0 0 0 0 0 0; 1 0 1 0 0 0 0 0; 0 0 0 1 0 0 0 0; 1 0 0 0 1 0 0 0; 1 0 0 0 0 1 0 0; 1 0 0 0 0 0 1 0; 1 0 0 0 0 0 0 1]
size(Cˣ) = (49, 64)
size(Cᶻ) = (1, 64)
r1 = rank(𝒞ˣ) = 441
r2 = rank(𝒞ᶻ) = 9
julia> c = CSS(hx, hz);
julia> import JuMP; import HiGHS;
julia> c = CSS(hx, hz);
julia> code_n(c), code_k(c), distance(c, DistanceMIPAlgorithm(solver=HiGHS, time_limit=120))
(576, 126, 7)