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

add QuantumCliffordOscarExt to provide convenient API for finitely presented groups via specific group presentation #400

Open
wants to merge 2 commits 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
5 changes: 5 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,11 @@ jobs:
arch: ${{ matrix.arch }}
- uses: julia-actions/cache@v2
- uses: julia-actions/julia-buildpkg@v1
- name: "Inject Oscar as test dependency (if not Windows and not threaded)"
if: ${{ matrix.os != 'windows-latest' && matrix.threads == 1 }}
continue-on-error: true
run: |
sed -i -e "s/\[deps\]/[deps]\nOscar = \"f1435218-dba5-11e9-1e4d-f1a5fab5fc13\"/" test/Project.toml
- uses: julia-actions/julia-runtest@v1
env:
JULIA_NUM_THREADS: ${{ matrix.threads }}
Expand Down
3 changes: 3 additions & 0 deletions Project.toml
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ CUDA = "052768ef-5323-5732-b1bb-66c8b64840ba"
Hecke = "3e1990a7-5d81-5526-99ce-9ba3ff248f21"
LDPCDecoders = "3c486d74-64b9-4c60-8b1a-13a564e77efb"
Makie = "ee78f7c6-11fb-53f2-987a-cfe4a2b5a57a"
Oscar = "f1435218-dba5-11e9-1e4d-f1a5fab5fc13"
Plots = "91a5bcdd-55d7-5caf-9e0b-520d859cae80"
PyQDecoders = "17f5de1a-9b79-4409-a58d-4d45812840f7"
Quantikz = "b0d11df0-eea3-4d79-b4a5-421488cbf74b"
Expand All @@ -37,6 +38,7 @@ QuantumCliffordGPUExt = "CUDA"
QuantumCliffordHeckeExt = "Hecke"
QuantumCliffordLDPCDecodersExt = "LDPCDecoders"
QuantumCliffordMakieExt = "Makie"
QuantumCliffordOscarExt = ["Hecke", "Oscar"]
QuantumCliffordPlotsExt = "Plots"
QuantumCliffordPyQDecodersExt = "PyQDecoders"
QuantumCliffordQOpticsExt = "QuantumOpticsBase"
Expand All @@ -57,6 +59,7 @@ 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"
Oscar = "1.1.1"
Plots = "1.38.0"
PrecompileTools = "1.2"
PyQDecoders = "0.2.1"
Expand Down
7 changes: 6 additions & 1 deletion docs/make.jl
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,11 @@ import Hecke

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

ENV["OSCAR_PRINT_BANNER"] = "false"
import Oscar

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

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

ENV["LINES"] = 80 # for forcing `displaysize(io)` to be big enough
Expand All @@ -25,7 +30,7 @@ doctest = false,
clean = true,
sitename = "QuantumClifford.jl",
format = Documenter.HTML(size_threshold_ignore = ["API.md"]),
modules = [QuantumClifford, QuantumClifford.Experimental.NoisyCircuits, QuantumClifford.ECC, QuantumInterface, QuantumCliffordHeckeExt],
modules = [QuantumClifford, QuantumClifford.Experimental.NoisyCircuits, QuantumClifford.ECC, QuantumInterface, QuantumCliffordHeckeExt, QuantumCliffordOscarExt],
warnonly = [:missing_docs],
linkcheck = true,
authors = "Stefan Krastanov",
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 @@ -10,4 +10,11 @@ Private = false
```@autodocs
Modules = [QuantumCliffordHeckeExt]
Private = true
```

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

```@autodocs
Modules = [QuantumCliffordOscarExt]
Private = true
```
20 changes: 20 additions & 0 deletions docs/src/references.bib
Original file line number Diff line number Diff line change
Expand Up @@ -561,3 +561,23 @@ @article{haah2011local
pages={042330},
year={2011},
}

@inproceedings{wang2023abelian,
title={Abelian and non-Abelian quantum two-block codes},
author={Wang, Renyu and Lin, Hsiang-Ku and Pryadko, Leonid P},
booktitle={2023 12th International Symposium on Topics in Coding (ISTC)},
pages={1--5},
year={2023},
organization={IEEE}
}

@article{naghipour2015quantum,
title={Quantum stabilizer codes from Abelian and non-Abelian groups association schemes},
author={Naghipour, Avaz and Jafarizadeh, Mohammad Ali and Shahmorad, Sedaghat},
journal={International Journal of Quantum Information},
volume={13},
number={03},
pages={1550021},
year={2015},
publisher={World Scientific}
}
2 changes: 2 additions & 0 deletions docs/src/references.md
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,8 @@ For quantum code construction routines:
- [lin2024quantum](@cite)
- [bravyi2024high](@cite)
- [haah2011local](@cite)
- [wang2023abelian](@cite)
- [naghipour2015quantum](@cite)

For classical code construction routines:
- [muller1954application](@cite)
Expand Down
19 changes: 19 additions & 0 deletions ext/QuantumCliffordOscarExt/QuantumCliffordOscarExt.jl
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
module QuantumCliffordOscarExt

using DocStringExtensions

import Nemo
import Nemo: FqFieldElem
import Hecke: group_algebra, GF, abelian_group, gens, quo, one, GroupAlgebra,
GroupAlgebraElem, direct_product, sub
import Oscar
import Oscar: free_group, small_group_identification, describe, order, FPGroupElem, FPGroup,
BasicGAPGroupElem, DirectProductGroup, cyclic_group

import QuantumClifford.ECC: two_block_group_algebra_codes

include("types.jl")
include("direct_product.jl")
include("group_presentation.jl")

end # module
110 changes: 110 additions & 0 deletions ext/QuantumCliffordOscarExt/direct_product.jl
Original file line number Diff line number Diff line change
@@ -0,0 +1,110 @@
"""
# Direct Product of Groups

The direct product of groups is instrumental in constructing group algebra of two-block
group algebra code. Lin and Pryadko illustrate this method in Appendix C, Table 2 of
[lin2024quantum](@cite), where they utilize the direct product of two cyclic groups,
expressed as `C₂ₘ = Cₘ × C₂`, with an order of `2m`.

`Hecke.jl` contains only abelian groups and a list of all finite groups of order up to 100.
`Oscar.jl` brings in comprehensive functionality for computational group theory, including
support for **arbitrary finitely presented groups** (groups of the form `⟨X | S⟩`. `Oscar.jl`
supports the **direct product** operation between two or more arbitrary **general** groups,
including non-abelian groups such as `alternating_group`, `dihedral_group`, `symmetric_group`,
and even arbitrary finitely presented groups (e.g., `free_group`). This capability is not
available in `Hecke.jl`. The 2BGA codes discovered in [lin2024quantum](@cite) rely on direct
products of two or more *general* groups, which necessitate the use of `Oscar.direct_product`.

The schematic below illustrates the limitations of `Hecke.direct_product` compared to
`Oscar.direct_product`:

```@raw html
<div class="mermaid">
graph TB
root[Direct Product of Groups]

root --> A[Hecke.direct_product]
root --> B[Oscar.direct_product]

%% Hecke Branch
A --> A1[Supports mostly abelian groups and list of finite groups]
A1--> A2[abelian_group symmetric_group small_group]
A2 --> A3[C × C, C × S]

%% Oscar Branch
B --> B1[Supports finite general groups, including non-abelian groups]
B1--> B2[alternating_group <br> dihedral_group <br> free_group <br> cyclic_group <br> permutation_group <br> quaternion_group <br> symmetric_group <br> abelian_group<br> small_group]
B2--> B3[A × C, A × D <br> D × C, D × D <br> F × F, F × A, F × D <br> F × S, F × C <br> C × C, C × S]
</div>
```

# Example

The [[56, 28, 2]] abelian 2BGA code from Appendix C, Table II in [lin2024quantum](@cite)
can be constructed using the direct product of two cyclic groups. Specifically, the group
`C₂₈` of order `l = 28` can be represented as `C₁₄ × C₂`, where the first group has order
`m = 14` and the second group has order `n = 2`.

```jldoctest directprod
julia> import Oscar: cyclic_group, small_group_identification, describe, order; # hide

julia> import Hecke: gens, quo, group_algebra, GF, one, direct_product, sub; # hide

julia> m = 14; n = 2;

julia> C₁₄ = cyclic_group(m);

julia> C₂ = cyclic_group(n);

julia> G = direct_product(C₁₄, C₂);

julia> GA = group_algebra(GF(2), G);

julia> x, s = gens(GA)[1], gens(GA)[3];

julia> a = [one(GA), x^7];

julia> b = [one(GA), x^7, s, x^8, s * x^7, x];

julia> c = twobga_from_direct_product(a, b, GA);

julia> order(G)
28

julia> code_n(c), code_k(c)
(56, 28)

julia> describe(G), small_group_identification(G)
("C14 x C2", (28, 4))
```

!!! note When using the direct product of two cyclic groups, it is essential to verify
the group presentation `Cₘ = ⟨x, s | xᵐ = s² = xsx⁻¹s⁻¹ = 1⟩` is satisfied, where the
order is `2m`. Ensure that the selected generators have the correct orders of `m = 14`
and `n = 2`, respectively. If the group presentation is not satisfied, the resulting
group algebra over `GF(2)` will not represent the intended group, `C₂₈ = C₁₄ × C₂`. In
addition, `Oscar.sub` can be used to determine if `H` is a subgroup of `G` and to
confirm that both `C₁₄` and `C₂` are subgroups of `C₂₈`.

```jldoctest directprod
julia> order(gens(G)[1])
14

julia> order(gens(G)[3])
2

julia> x^14 == s^2 == x * s * x^-1 * s^-1
true

julia> H, _ = sub(G, [gens(G)[1], gens(G)[3]]);

julia> H == G
true
```
"""
function twobga_from_direct_product(a_elts::VectorDirectProductGroupElem, b_elts::VectorDirectProductGroupElem, F2G::DirectProductGroupAlgebra)
a = sum(F2G(x) for x in a_elts)
b = sum(F2G(x) for x in b_elts)
c = two_block_group_algebra_codes(a,b)
return c
end
151 changes: 151 additions & 0 deletions ext/QuantumCliffordOscarExt/group_presentation.jl
Original file line number Diff line number Diff line change
@@ -0,0 +1,151 @@
"""
# Specific Group Presentations

For quantum error-correcting codes like the two-block group algebra (2BGA) code, designing specific
group presentations for both abelian and non-abelian groups is crucial. These presentations are essential
for constructing the group algebra of the 2BGA code for a given finite general group, `G`.

Lin and Pryadko, in their seminal paper titled "Quantum Two-Block Group Algebra Codes" [lin2024quantum](@cite),
employ specific presentations that necessitate the use of `Oscar.free_group`. The diagram below distinguishes
between small groups (`Hecke/Oscar.small_group`) and finitely presented groups (`Oscar.free_group`) by highlighting
the existence of extra relations in their presentations.

```@raw html
<div class="mermaid">
graph TD
A[Group Presentation ⟨S ∣ R⟩] --> B{Are there <br> extra relations?}
B -- No --> C[Small groups <br> Hecke/Oscar.small_group]
C --> D[Independent generators]
C --> E["Example: <br> ⟨r, s ∣ s⁴, r⁹⟩"]
B -- Yes --> F[Finitely presented groups <br> Oscar.free_group]
F --> G[Defined by interactions]
F --> H["Example: <br> ⟨r, s ∣ s⁴, r⁹, s⁻¹rsr⟩"]
</div>
```

# Example

The [[96, 12, 10]] 2BGA code from Table I in [lin2024quantum](@cite) has the group presentation
`⟨r, s | s⁶ = r⁸ = r⁻¹srs = 1⟩` and a group structure of `C₂ × (C₃ ⋉ C₈)`.

```jldoctest finitegrp
julia> import Oscar: free_group, small_group_identification, describe, order; # hide

julia> import Hecke: gens, quo, group_algebra, GF, one; # hide

julia> F = free_group(["r", "s"]);

julia> r, s = gens(F); # generators

julia> G, = quo(F, [s^6, r^8, r^(-1) * s * r * s]); # relations

julia> GA = group_algebra(GF(2), G);

julia> r, s = gens(G);

julia> a = [one(G), r, s^3 * r^2, s^2 * r^3];

julia> b = [one(G), r, s^4 * r^6, s^5 * r^3];

julia> c = twobga_from_fp_group(a, b, GA);

julia> order(G)
48

julia> code_n(c), code_k(c)
(96, 12)

julia> describe(G), small_group_identification(G)
("C2 x (C3 : C8)", (48, 9))
```

# Cyclic Groups

Cyclic groups with specific group presentations, given by `Cₘ = ⟨x, s | xᵐ = s² = xsx⁻¹s⁻¹ = 1⟩`,
where the order is `2m`, are supported.

To construct the group algebra for a cyclic group, specify the group presentation `⟨S | R⟩`, using
its generators `S` and defining relations `R`.

# Example

The [[56, 28, 2]] abelian 2BGA code from Appendix C, Table II in [lin2024quantum](@cite) is constructed using
the cyclic group `C₂₈ = C₁₄ × C₂`.

```jldoctest finitegrp
julia> m = 14;

julia> F = free_group(["x", "s"]);

julia> x, s = gens(F); # generators

julia> G, = quo(F, [x^m, s^2, x * s * x^-1 * s^-1]); # relations

julia> GA = group_algebra(GF(2), G);

julia> x, s = gens(G);

julia> a = [one(G), x^7];

julia> b = [one(G), x^7, s, x^8, s * x^7, x];

julia> c = twobga_from_fp_group(a, b, GA);

julia> order(G)
28

julia> code_n(c), code_k(c)
(56, 28)

julia> describe(G), small_group_identification(G)
("C14 x C2", (28, 4))
```

# Dihedral Groups

Dihedral groups with specific group presentations, given by `Dₘ = ⟨r, s | rᵐ = s² = (rs)² = 1⟩`,
where the order is `2m`, are supported.

To construct the group algebra for a dihedral group, specify the group presentation `⟨S | R⟩`
using its generators `S` and defining relations `R`.

# Example

The [[24, 8, 3]] 2BGA code from Appendix C, Table III in [lin2024quantum](@cite) is constructed
using the dihedral group `D₆ = C₆ ⋉ C₂`.

```jldoctest finitegrp
julia> m = 6;

julia> F = free_group(["r", "s"]);

julia> r, s = gens(F); # generators

julia> G, = quo(F, [r^m, s^2, (r*s)^2]); # relations

julia> GA = group_algebra(GF(2), G);

julia> r, s = gens(G);

julia> a = [one(G), r^4];

julia> b = [one(G), s*r^4, r^3, r^4, s*r^2, r];

julia> c = twobga_from_fp_group(a, b, GA);

julia> order(G)
12

julia> code_n(c), code_k(c)
(24, 8)

julia> describe(G), small_group_identification(G)
("D12", (12, 4))
```
"""
function twobga_from_fp_group(a_elts::VectorFPGroupElem, b_elts::VectorFPGroupElem, F2G::FqFieldFPGroupAlgebra)
a = sum(F2G(x) for x in a_elts)
b = sum(F2G(x) for x in b_elts)
c = two_block_group_algebra_codes(a,b)
return c
end
7 changes: 7 additions & 0 deletions ext/QuantumCliffordOscarExt/types.jl
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
const VectorFPGroupElem = Vector{FPGroupElem}

const VectorDirectProductGroupElem = Vector{GroupAlgebraElem{FqFieldElem, GroupAlgebra{FqFieldElem, DirectProductGroup, BasicGAPGroupElem{DirectProductGroup}}}}

const FqFieldFPGroupAlgebra = GroupAlgebra{FqFieldElem, FPGroup, FPGroupElem}

const DirectProductGroupAlgebra = GroupAlgebra{FqFieldElem, DirectProductGroup, BasicGAPGroupElem{DirectProductGroup}}
Loading
Loading