Skip to content

Commit

Permalink
Merge branch 'master' into BBQLDPC
Browse files Browse the repository at this point in the history
  • Loading branch information
Fe-r-oz authored Sep 26, 2024
2 parents 8c4d158 + 01cc0f0 commit e77e1ca
Show file tree
Hide file tree
Showing 23 changed files with 564 additions and 28 deletions.
5 changes: 4 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,12 +5,15 @@

# News

## dev
## v0.9.10 - 2024-09-26

- The lifted product class of quantum LDPC codes is implemented in the ECC submodule.
- **(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`.
- Implementing many more named single-qubit gates following naming convention similar to the stim package in python.
- **(fix)** Bug fix to the `parity_checks(ReedMuller(r, m))` of classical Reed-Muller code (it was returning generator matrix).
- `RecursiveReedMuller` code implementation as an alternative implementation of `ReedMuller`.


## v0.9.9 - 2024-08-05

- `inv` is implemented for all Clifford operator types (symbolic, dense, sparse).
Expand Down
7 changes: 5 additions & 2 deletions Project.toml
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
name = "QuantumClifford"
uuid = "0525e862-1e90-11e9-3e4d-1b39d7109de1"
authors = ["Stefan Krastanov <[email protected]> and QuantumSavory community members"]
version = "0.9.9"
version = "0.9.10"

[deps]
Combinatorics = "861a8166-3701-5b0c-9a16-15d98fcdc6aa"
Expand All @@ -24,6 +24,7 @@ SumTypes = "8e1ec7a9-0e02-4297-b0fe-6433085c89f2"

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

[extensions]
QuantumCliffordGPUExt = "CUDA"
QuantumCliffordHeckeExt = "Hecke"
QuantumCliffordLDPCDecodersExt = "LDPCDecoders"
QuantumCliffordMakieExt = "Makie"
QuantumCliffordPlotsExt = "Plots"
Expand All @@ -46,14 +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"
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, 0.43, 0.44, 0.45, 0.46"
Nemo = "^0.42.1, 0.43, 0.44, 0.45, 0.46"
Plots = "1.38.0"
PrecompileTools = "1.2"
PyQDecoders = "0.2.1"
Expand Down
1 change: 1 addition & 0 deletions docs/Project.toml
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ Documenter = "e30172f5-a6a5-5a46-863b-614d45cd2de4"
DocumenterCitations = "daee34ce-89f3-4625-b898-19384cb65244"
GraphMakie = "1ecd5474-83a3-4783-bb4f-06765db800d2"
Graphs = "86223c79-3864-5bf0-83f7-82e725a168b6"
Hecke = "3e1990a7-5d81-5526-99ce-9ba3ff248f21"
LDPCDecoders = "3c486d74-64b9-4c60-8b1a-13a564e77efb"
Nemo = "2edaba10-b0f1-5616-af89-8c11ac63239a"
Plots = "91a5bcdd-55d7-5caf-9e0b-520d859cae80"
Expand Down
8 changes: 7 additions & 1 deletion docs/make.jl
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,11 @@ using QuantumClifford
using QuantumClifford.Experimental.NoisyCircuits
using QuantumInterface

ENV["HECKE_PRINT_BANNER"] = "false"
import Hecke

const QuantumCliffordHeckeExt = Base.get_extension(QuantumClifford, :QuantumCliffordHeckeExt)

#DocMeta.setdocmeta!(QuantumClifford, :DocTestSetup, :(using QuantumClifford); recursive=true)

ENV["LINES"] = 80 # for forcing `displaysize(io)` to be big enough
Expand All @@ -20,8 +25,9 @@ doctest = false,
clean = true,
sitename = "QuantumClifford.jl",
format = Documenter.HTML(size_threshold_ignore = ["API.md"]),
modules = [QuantumClifford, QuantumClifford.Experimental.NoisyCircuits, QuantumClifford.ECC, QuantumInterface],
modules = [QuantumClifford, QuantumClifford.Experimental.NoisyCircuits, QuantumClifford.ECC, QuantumInterface, QuantumCliffordHeckeExt],
warnonly = [:missing_docs],
linkcheck = true,
authors = "Stefan Krastanov",
pages = [
"QuantumClifford.jl" => "index.md",
Expand Down
7 changes: 7 additions & 0 deletions docs/src/ECC_API.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,3 +4,10 @@
Modules = [QuantumClifford.ECC]
Private = false
```

## Implemented in an extension requiring `Hecke.jl`

```@autodocs
Modules = [QuantumCliffordHeckeExt]
Private = true
```
51 changes: 51 additions & 0 deletions docs/src/references.bib
Original file line number Diff line number Diff line change
Expand Up @@ -403,6 +403,57 @@ @inproceedings{brown2013short
doi = {10.1109/ISIT.2013.6620245}
}

@article{panteleev2021degenerate,
title = {Degenerate {{Quantum LDPC Codes With Good Finite Length Performance}}},
author = {Panteleev, Pavel and Kalachev, Gleb},
year = {2021},
month = nov,
journal = {Quantum},
volume = {5},
eprint = {1904.02703},
primaryclass = {quant-ph},
pages = {585},
issn = {2521-327X},
doi = {10.22331/q-2021-11-22-585},
archiveprefix = {arXiv}
}

@inproceedings{panteleev2022asymptotically,
title = {Asymptotically Good {{Quantum}} and Locally Testable Classical {{LDPC}} Codes},
booktitle = {Proceedings of the 54th {{Annual ACM SIGACT Symposium}} on {{Theory}} of {{Computing}}},
author = {Panteleev, Pavel and Kalachev, Gleb},
year = {2022},
month = jun,
pages = {375--388},
publisher = {ACM},
address = {Rome Italy},
doi = {10.1145/3519935.3520017},
isbn = {978-1-4503-9264-8}
}

@article{roffe2023bias,
title = {Bias-Tailored Quantum {{LDPC}} Codes},
author = {Roffe, Joschka and Cohen, Lawrence Z. and Quintavalle, Armanda O. and Chandra, Daryus and Campbell, Earl T.},
year = {2023},
month = may,
journal = {Quantum},
volume = {7},
pages = {1005},
doi = {10.22331/q-2023-05-15-1005}
}

@article{raveendran2022finite,
title = {Finite {{Rate QLDPC-GKP Coding Scheme}} That {{Surpasses}} the {{CSS Hamming Bound}}},
author = {Raveendran, Nithin and Rengaswamy, Narayanan and Rozp{\k e}dek, Filip and Raina, Ankur and Jiang, Liang and Vasi{\'c}, Bane},
year = {2022},
month = jul,
journal = {Quantum},
volume = {6},
pages = {767},
issn = {2521-327X},
doi = {10.22331/q-2022-07-20-767},
}

@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},
Expand Down
19 changes: 19 additions & 0 deletions ext/QuantumCliffordHeckeExt/QuantumCliffordHeckeExt.jl
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
module QuantumCliffordHeckeExt

using DocStringExtensions

import QuantumClifford, LinearAlgebra
import Hecke: Group, GroupElem, AdditiveGroup, AdditiveGroupElem,
GroupAlgebra, GroupAlgebraElem, FqFieldElem, representation_matrix, dim, base_ring,
multiplication_table, coefficients, abelian_group, group_algebra
import Nemo: characteristic, matrix_repr, GF, ZZ

import QuantumClifford.ECC: AbstractECC, CSS, ClassicalCode,
hgp, code_k, code_n, code_s, iscss, parity_checks, parity_checks_x, parity_checks_z, parity_checks_xz,
two_block_group_algebra_codes, generalized_bicycle_codes, bicycle_codes

include("types.jl")
include("lifted.jl")
include("lifted_product.jl")

end # module
101 changes: 101 additions & 0 deletions ext/QuantumCliffordHeckeExt/lifted.jl
Original file line number Diff line number Diff line change
@@ -0,0 +1,101 @@
"""
$TYPEDEF
Classical codes lifted over a group algebra, used for lifted product code construction ([panteleev2021degenerate](@cite), [panteleev2022asymptotically](@cite))
The parity-check matrix is constructed by applying `repr` to each element of `A`,
which is mathematically a linear map from a group algebra element to a binary matrix.
The size of the parity check matrix will enlarged with each element of `A` being inflated into a matrix.
The procedure is called a lift [panteleev2022asymptotically](@cite).
## Constructors
A lifted code can be constructed via the following approaches:
1. A matrix of group algebra elements.
2. A matrix of group elements, where a group element will be considered as a group algebra element by assigning a unit coefficient.
3. A matrix of integers, where each integer represent the shift of a cyclic permutation. The order of the cyclic permutation should be specified.
The default `GA` is the group algebra of `A[1, 1]`, the default representation `repr` is the permutation representation.
## The representation function `repr`
In this struct, we use the default representation function `default_repr` to convert a `GF(2)`-group algebra element to a binary matrix.
The default representation, provided by `Hecke`, is the permutation representation.
We also accept a custom representation function.
Such a customization would be useful to reduce the number of bits required by the code construction.
For example, if we use a D4 group for lifting, our default representation will be `8×8` permutation matrices,
where 8 is the group's order.
However, we can find a `4×4` matrix representation for the group,
e.g. by using the typical [`2×2` representation](https://en.wikipedia.org/wiki/Dihedral_group)
and converting it into binary representation by replacing "1" with the Pauli I, and "-1" with the Pauli X matrix.
See also: [`LPCode`](@ref).
$TYPEDFIELDS
"""
struct LiftedCode <: ClassicalCode
"""the base matrix of the code, whose elements are in a group algebra."""
A::GroupAlgebraElemMatrix
"""the group algebra for which elements in `A` are from."""
GA::GroupAlgebra
"""
a function that converts a group algebra element to a binary matrix;
default to be the permutation representation for GF(2)-algebra."""
repr::Function

function LiftedCode(A::GroupAlgebraElemMatrix; GA::GroupAlgebra=parent(A[1, 1]), repr::Function)
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")
new(A, GA, repr)
end
end

default_repr(y::GroupAlgebraElem{FqFieldElem, <: GroupAlgebra}) = Matrix((x -> Bool(Int(lift(ZZ, x)))).(representation_matrix(y)))

"""
`LiftedCode` constructor using the default `GF(2)` representation (coefficients converted to a permutation matrix by `representation_matrix` provided by Hecke).
""" # TODO doctest example
function LiftedCode(A::Matrix{GroupAlgebraElem{FqFieldElem, <: GroupAlgebra}}; GA::GroupAlgebra=parent(A[1,1]))
!(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")
LiftedCode(A; GA=GA, repr=default_repr)
end

# TODO document and doctest example
function LiftedCode(group_elem_array::Matrix{<: GroupOrAdditiveGroupElem}; GA::GroupAlgebra=group_algebra(GF(2), parent(group_elem_array[1,1])), repr::Union{Function, Nothing}=nothing)
A = zeros(GA, size(group_elem_array)...)
for i in axes(group_elem_array, 1), j in axes(group_elem_array, 2)
A[i, j] = GA[A[i, j]]
end
if repr === nothing
return LiftedCode(A; GA=GA, repr=default_repr)
else
return LiftedCode(A; GA=GA, repr=repr)
end
end

# TODO document and doctest example
function LiftedCode(shift_array::Matrix{Int}, l::Int; GA::GroupAlgebra=group_algebra(GF(2), abelian_group(l)))
A = zeros(GA, size(shift_array)...)
for i in 1:size(shift_array, 1)
for j in 1:size(shift_array, 2)
A[i, j] = GA[shift_array[i, j]%l+1]
end
end
return LiftedCode(A; GA=GA, repr=default_repr)
end

function lift(repr::Function, mat::GroupAlgebraElemMatrix)
vcat([hcat([repr(mat[i, j]) for j in axes(mat, 2)]...) for i in axes(mat, 1)]...)
end

function parity_checks(c::LiftedCode)
return lift(c.repr, c.A)
end

code_n(c::LiftedCode) = size(c.A, 2) * size(zero(c.GA), 2)

code_s(c::LiftedCode) = size(c.A, 1) * size(zero(c.GA), 1)
Loading

0 comments on commit e77e1ca

Please sign in to comment.