Skip to content

Commit 4801b11

Browse files
royessKrastanovhanakl
authored
Lifted and lifted product codes via Hecke's GroupAlgebra (#356)
--------- Co-authored-by: Stefan Krastanov <[email protected]> Co-authored-by: hanakl <[email protected]>
1 parent 05491d9 commit 4801b11

23 files changed

+564
-25
lines changed

CHANGELOG.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,10 @@
1111
- **(fix)** Bug fix to the `parity_checks(ReedMuller(r, m))` of classical Reed-Muller code (it was returning generator matrix).
1212
- `RecursiveReedMuller` code implementation as an alternative implementation of `ReedMuller`.
1313

14+
## v0.9.10 - 2024-09-26
15+
16+
- **(fix)** `ECC.code_s` now gives the number of parity checks with redundancy. If you want the number of linearly independent parity checks, you can use `LinearAlgebra.rank`.
17+
1418
## v0.9.9 - 2024-08-05
1519

1620
- `inv` is implemented for all Clifford operator types (symbolic, dense, sparse).

Project.toml

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ SumTypes = "8e1ec7a9-0e02-4297-b0fe-6433085c89f2"
2424

2525
[weakdeps]
2626
CUDA = "052768ef-5323-5732-b1bb-66c8b64840ba"
27+
Hecke = "3e1990a7-5d81-5526-99ce-9ba3ff248f21"
2728
LDPCDecoders = "3c486d74-64b9-4c60-8b1a-13a564e77efb"
2829
Makie = "ee78f7c6-11fb-53f2-987a-cfe4a2b5a57a"
2930
Plots = "91a5bcdd-55d7-5caf-9e0b-520d859cae80"
@@ -33,6 +34,7 @@ QuantumOpticsBase = "4f57444f-1401-5e15-980d-4471b28d5678"
3334

3435
[extensions]
3536
QuantumCliffordGPUExt = "CUDA"
37+
QuantumCliffordHeckeExt = "Hecke"
3638
QuantumCliffordLDPCDecodersExt = "LDPCDecoders"
3739
QuantumCliffordMakieExt = "Makie"
3840
QuantumCliffordPlotsExt = "Plots"
@@ -46,14 +48,15 @@ Combinatorics = "1.0"
4648
DataStructures = "0.18"
4749
DocStringExtensions = "0.9"
4850
Graphs = "1.9"
51+
Hecke = "0.28, 0.29, 0.30, 0.31, 0.32, 0.33"
4952
HostCPUFeatures = "0.1.6"
5053
ILog2 = "0.2.3"
5154
InteractiveUtils = "1.9"
5255
LDPCDecoders = "0.3.1"
5356
LinearAlgebra = "1.9"
5457
MacroTools = "0.5.9"
5558
Makie = "0.20, 0.21"
56-
Nemo = "0.42, 0.43, 0.44, 0.45, 0.46"
59+
Nemo = "^0.42.1, 0.43, 0.44, 0.45, 0.46"
5760
Plots = "1.38.0"
5861
PrecompileTools = "1.2"
5962
PyQDecoders = "0.2.1"

docs/Project.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ Documenter = "e30172f5-a6a5-5a46-863b-614d45cd2de4"
55
DocumenterCitations = "daee34ce-89f3-4625-b898-19384cb65244"
66
GraphMakie = "1ecd5474-83a3-4783-bb4f-06765db800d2"
77
Graphs = "86223c79-3864-5bf0-83f7-82e725a168b6"
8+
Hecke = "3e1990a7-5d81-5526-99ce-9ba3ff248f21"
89
LDPCDecoders = "3c486d74-64b9-4c60-8b1a-13a564e77efb"
910
Nemo = "2edaba10-b0f1-5616-af89-8c11ac63239a"
1011
Plots = "91a5bcdd-55d7-5caf-9e0b-520d859cae80"

docs/make.jl

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,11 @@ using QuantumClifford
77
using QuantumClifford.Experimental.NoisyCircuits
88
using QuantumInterface
99

10+
ENV["HECKE_PRINT_BANNER"] = "false"
11+
import Hecke
12+
13+
const QuantumCliffordHeckeExt = Base.get_extension(QuantumClifford, :QuantumCliffordHeckeExt)
14+
1015
#DocMeta.setdocmeta!(QuantumClifford, :DocTestSetup, :(using QuantumClifford); recursive=true)
1116

1217
ENV["LINES"] = 80 # for forcing `displaysize(io)` to be big enough
@@ -20,8 +25,9 @@ doctest = false,
2025
clean = true,
2126
sitename = "QuantumClifford.jl",
2227
format = Documenter.HTML(size_threshold_ignore = ["API.md"]),
23-
modules = [QuantumClifford, QuantumClifford.Experimental.NoisyCircuits, QuantumClifford.ECC, QuantumInterface],
28+
modules = [QuantumClifford, QuantumClifford.Experimental.NoisyCircuits, QuantumClifford.ECC, QuantumInterface, QuantumCliffordHeckeExt],
2429
warnonly = [:missing_docs],
30+
linkcheck = true,
2531
authors = "Stefan Krastanov",
2632
pages = [
2733
"QuantumClifford.jl" => "index.md",

docs/src/ECC_API.md

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,3 +4,10 @@
44
Modules = [QuantumClifford.ECC]
55
Private = false
66
```
7+
8+
## Implemented in an extension requiring `Hecke.jl`
9+
10+
```@autodocs
11+
Modules = [QuantumCliffordHeckeExt]
12+
Private = true
13+
```

docs/src/references.bib

Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -402,3 +402,55 @@ @inproceedings{brown2013short
402402
pages = {346--350},
403403
doi = {10.1109/ISIT.2013.6620245}
404404
}
405+
406+
@article{panteleev2021degenerate,
407+
title = {Degenerate {{Quantum LDPC Codes With Good Finite Length Performance}}},
408+
author = {Panteleev, Pavel and Kalachev, Gleb},
409+
year = {2021},
410+
month = nov,
411+
journal = {Quantum},
412+
volume = {5},
413+
eprint = {1904.02703},
414+
primaryclass = {quant-ph},
415+
pages = {585},
416+
issn = {2521-327X},
417+
doi = {10.22331/q-2021-11-22-585},
418+
archiveprefix = {arXiv}
419+
}
420+
421+
422+
@inproceedings{panteleev2022asymptotically,
423+
title = {Asymptotically Good {{Quantum}} and Locally Testable Classical {{LDPC}} Codes},
424+
booktitle = {Proceedings of the 54th {{Annual ACM SIGACT Symposium}} on {{Theory}} of {{Computing}}},
425+
author = {Panteleev, Pavel and Kalachev, Gleb},
426+
year = {2022},
427+
month = jun,
428+
pages = {375--388},
429+
publisher = {ACM},
430+
address = {Rome Italy},
431+
doi = {10.1145/3519935.3520017},
432+
isbn = {978-1-4503-9264-8}
433+
}
434+
435+
@article{roffe2023bias,
436+
title = {Bias-Tailored Quantum {{LDPC}} Codes},
437+
author = {Roffe, Joschka and Cohen, Lawrence Z. and Quintavalle, Armanda O. and Chandra, Daryus and Campbell, Earl T.},
438+
year = {2023},
439+
month = may,
440+
journal = {Quantum},
441+
volume = {7},
442+
pages = {1005},
443+
doi = {10.22331/q-2023-05-15-1005}
444+
}
445+
446+
@article{raveendran2022finite,
447+
title = {Finite {{Rate QLDPC-GKP Coding Scheme}} That {{Surpasses}} the {{CSS Hamming Bound}}},
448+
author = {Raveendran, Nithin and Rengaswamy, Narayanan and Rozp{\k e}dek, Filip and Raina, Ankur and Jiang, Liang and Vasi{\'c}, Bane},
449+
year = {2022},
450+
month = jul,
451+
journal = {Quantum},
452+
volume = {6},
453+
pages = {767},
454+
issn = {2521-327X},
455+
doi = {10.22331/q-2022-07-20-767},
456+
}
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
module QuantumCliffordHeckeExt
2+
3+
using DocStringExtensions
4+
5+
import QuantumClifford, LinearAlgebra
6+
import Hecke: Group, GroupElem, AdditiveGroup, AdditiveGroupElem,
7+
GroupAlgebra, GroupAlgebraElem, FqFieldElem, representation_matrix, dim, base_ring,
8+
multiplication_table, coefficients, abelian_group, group_algebra
9+
import Nemo: characteristic, matrix_repr, GF, ZZ
10+
11+
import QuantumClifford.ECC: AbstractECC, CSS, ClassicalCode,
12+
hgp, code_k, code_n, code_s, iscss, parity_checks, parity_checks_x, parity_checks_z, parity_checks_xz,
13+
two_block_group_algebra_codes, generalized_bicycle_codes, bicycle_codes
14+
15+
include("types.jl")
16+
include("lifted.jl")
17+
include("lifted_product.jl")
18+
19+
end # module

ext/QuantumCliffordHeckeExt/lifted.jl

Lines changed: 101 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,101 @@
1+
"""
2+
$TYPEDEF
3+
4+
Classical codes lifted over a group algebra, used for lifted product code construction ([panteleev2021degenerate](@cite), [panteleev2022asymptotically](@cite))
5+
6+
The parity-check matrix is constructed by applying `repr` to each element of `A`,
7+
which is mathematically a linear map from a group algebra element to a binary matrix.
8+
The size of the parity check matrix will enlarged with each element of `A` being inflated into a matrix.
9+
The procedure is called a lift [panteleev2022asymptotically](@cite).
10+
11+
## Constructors
12+
13+
A lifted code can be constructed via the following approaches:
14+
15+
1. A matrix of group algebra elements.
16+
17+
2. A matrix of group elements, where a group element will be considered as a group algebra element by assigning a unit coefficient.
18+
19+
3. A matrix of integers, where each integer represent the shift of a cyclic permutation. The order of the cyclic permutation should be specified.
20+
21+
The default `GA` is the group algebra of `A[1, 1]`, the default representation `repr` is the permutation representation.
22+
23+
## The representation function `repr`
24+
25+
In this struct, we use the default representation function `default_repr` to convert a `GF(2)`-group algebra element to a binary matrix.
26+
The default representation, provided by `Hecke`, is the permutation representation.
27+
28+
We also accept a custom representation function.
29+
Such a customization would be useful to reduce the number of bits required by the code construction.
30+
31+
For example, if we use a D4 group for lifting, our default representation will be `8×8` permutation matrices,
32+
where 8 is the group's order.
33+
However, we can find a `4×4` matrix representation for the group,
34+
e.g. by using the typical [`2×2` representation](https://en.wikipedia.org/wiki/Dihedral_group)
35+
and converting it into binary representation by replacing "1" with the Pauli I, and "-1" with the Pauli X matrix.
36+
37+
See also: [`LPCode`](@ref).
38+
39+
$TYPEDFIELDS
40+
"""
41+
struct LiftedCode <: ClassicalCode
42+
"""the base matrix of the code, whose elements are in a group algebra."""
43+
A::GroupAlgebraElemMatrix
44+
"""the group algebra for which elements in `A` are from."""
45+
GA::GroupAlgebra
46+
"""
47+
a function that converts a group algebra element to a binary matrix;
48+
default to be the permutation representation for GF(2)-algebra."""
49+
repr::Function
50+
51+
function LiftedCode(A::GroupAlgebraElemMatrix; GA::GroupAlgebra=parent(A[1, 1]), repr::Function)
52+
all(elem.parent == GA for elem in A) || error("The base ring of all elements in the code must be the same as the group algebra")
53+
new(A, GA, repr)
54+
end
55+
end
56+
57+
default_repr(y::GroupAlgebraElem{FqFieldElem, <: GroupAlgebra}) = Matrix((x -> Bool(Int(lift(ZZ, x)))).(representation_matrix(y)))
58+
59+
"""
60+
`LiftedCode` constructor using the default `GF(2)` representation (coefficients converted to a permutation matrix by `representation_matrix` provided by Hecke).
61+
""" # TODO doctest example
62+
function LiftedCode(A::Matrix{GroupAlgebraElem{FqFieldElem, <: GroupAlgebra}}; GA::GroupAlgebra=parent(A[1,1]))
63+
!(characteristic(base_ring(A[1, 1])) == 2) && error("The default permutation representation applies only to GF(2) group algebra; otherwise, a custom representation function should be provided")
64+
LiftedCode(A; GA=GA, repr=default_repr)
65+
end
66+
67+
# TODO document and doctest example
68+
function LiftedCode(group_elem_array::Matrix{<: GroupOrAdditiveGroupElem}; GA::GroupAlgebra=group_algebra(GF(2), parent(group_elem_array[1,1])), repr::Union{Function, Nothing}=nothing)
69+
A = zeros(GA, size(group_elem_array)...)
70+
for i in axes(group_elem_array, 1), j in axes(group_elem_array, 2)
71+
A[i, j] = GA[A[i, j]]
72+
end
73+
if repr === nothing
74+
return LiftedCode(A; GA=GA, repr=default_repr)
75+
else
76+
return LiftedCode(A; GA=GA, repr=repr)
77+
end
78+
end
79+
80+
# TODO document and doctest example
81+
function LiftedCode(shift_array::Matrix{Int}, l::Int; GA::GroupAlgebra=group_algebra(GF(2), abelian_group(l)))
82+
A = zeros(GA, size(shift_array)...)
83+
for i in 1:size(shift_array, 1)
84+
for j in 1:size(shift_array, 2)
85+
A[i, j] = GA[shift_array[i, j]%l+1]
86+
end
87+
end
88+
return LiftedCode(A; GA=GA, repr=default_repr)
89+
end
90+
91+
function lift(repr::Function, mat::GroupAlgebraElemMatrix)
92+
vcat([hcat([repr(mat[i, j]) for j in axes(mat, 2)]...) for i in axes(mat, 1)]...)
93+
end
94+
95+
function parity_checks(c::LiftedCode)
96+
return lift(c.repr, c.A)
97+
end
98+
99+
code_n(c::LiftedCode) = size(c.A, 2) * size(zero(c.GA), 2)
100+
101+
code_s(c::LiftedCode) = size(c.A, 1) * size(zero(c.GA), 1)

0 commit comments

Comments
 (0)