diff --git a/CHANGELOG.md b/CHANGELOG.md index 3d3d071bb..4ee772527 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -8,6 +8,7 @@ ## v0.9.11-dev - `hcat` of Tableaux objects +- `QuantumReedMuller` codes added to the ECC module ## v0.9.10 - 2024-09-26 diff --git a/docs/src/references.bib b/docs/src/references.bib index 1cbde2910..29500a034 100644 --- a/docs/src/references.bib +++ b/docs/src/references.bib @@ -454,3 +454,36 @@ @article{raveendran2022finite issn = {2521-327X}, doi = {10.22331/q-2022-07-20-767}, } + +@article{steane1999quantum, + title={Quantum reed-muller codes}, + author={Steane, Andrew M}, + journal={IEEE Transactions on Information Theory}, + volume={45}, + number={5}, + pages={1701--1703}, + year={1999}, + publisher={IEEE} +} + +@article{campbell2012magic, + title={Magic-state distillation in all prime dimensions using quantum reed-muller codes}, + author={Campbell, Earl T and Anwar, Hussain and Browne, Dan E}, + journal={Physical Review X}, + volume={2}, + number={4}, + pages={041021}, + year={2012}, + publisher={APS} +} + +@article{anderson2014fault, + title={Fault-tolerant conversion between the steane and reed-muller quantum codes}, + author={Anderson, Jonas T and Duclos-Cianci, Guillaume and Poulin, David}, + journal={Physical review letters}, + volume={113}, + number={8}, + pages={080501}, + year={2014}, + publisher={APS} +} diff --git a/docs/src/references.md b/docs/src/references.md index b37e94d4e..35e944a21 100644 --- a/docs/src/references.md +++ b/docs/src/references.md @@ -37,6 +37,9 @@ For quantum code construction routines: - [kitaev2003fault](@cite) - [fowler2012surface](@cite) - [knill1996concatenated](@cite) +- [steane1999quantum](@cite) +- [campbell2012magic](@cite) +- [anderson2014fault](@cite) For classical code construction routines: - [muller1954application](@cite) diff --git a/src/ecc/ECC.jl b/src/ecc/ECC.jl index d8e863136..cdda7742e 100644 --- a/src/ecc/ECC.jl +++ b/src/ecc/ECC.jl @@ -20,7 +20,7 @@ export parity_checks, parity_checks_x, parity_checks_z, iscss, RepCode, LiftedCode, CSS, Shor9, Steane7, Cleve8, Perfect5, Bitflip3, - Toric, Gottesman, Surface, Concat, CircuitCode, + 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, evaluate_decoder, @@ -376,10 +376,10 @@ include("codes/gottesman.jl") include("codes/surface.jl") include("codes/concat.jl") include("codes/random_circuit.jl") - include("codes/classical/reedmuller.jl") include("codes/classical/recursivereedmuller.jl") include("codes/classical/bch.jl") +include("codes/quantumreedmuller.jl") # qLDPC include("codes/classical/lifted.jl") diff --git a/src/ecc/codes/quantumreedmuller.jl b/src/ecc/codes/quantumreedmuller.jl new file mode 100644 index 000000000..6813d6646 --- /dev/null +++ b/src/ecc/codes/quantumreedmuller.jl @@ -0,0 +1,41 @@ +""" +The family of `[[2ᵐ - 1, 1, 3]]` CSS Quantum-Reed-Muller codes, as discovered by Steane in his 1999 paper [steane1999quantum](@cite). + +Quantum codes are constructed from shortened Reed-Muller codes `RM(1, m)`, by removing the first row and column of the generator matrix `Gₘ`. Similarly, we can define truncated dual codes `RM(m - 2, m)` using the generator matrix `Hₘ` [anderson2014fault](@cite). The quantum Reed-Muller codes `QRM(m)` derived from `RM(1, m)` are CSS codes. + +Given that the stabilizers of the quantum code are defined through the generator matrix of the classical code, the minimum distance of the quantum code corresponds to the minimum distance of the dual classical code, which is `d = 3`, thus it can correct any single qubit error. Since one stabilizer from the original and one from the dual code are removed in the truncation process, the code parameters are `[[2ᵐ - 1, 1, 3]]`. + +You might be interested in consulting [anderson2014fault](@cite) and [campbell2012magic](@cite) as well. + +The ECC Zoo has an [entry for this family](https://errorcorrectionzoo.org/c/quantum_reed_muller). +""" +struct QuantumReedMuller <: AbstractECC + m::Int + function QuantumReedMuller(m) + if m < 3 + throw(DomainError("Invalid parameters: m must be bigger than 2 in order to have a valid code.")) + end + new(m) + end +end + +function iscss(::Type{QuantumReedMuller}) + return true +end + +function parity_checks(c::QuantumReedMuller) + RM₁₋ₘ = generator(RecursiveReedMuller(1, c.m)) + RM₍ₘ₋₂₎₋ₘ₎ = generator(RecursiveReedMuller(c.m-2, c.m)) + QRM = CSS(RM₁₋ₘ[2:end, 2:end], RM₍ₘ₋₂₎₋ₘ₎[2:end, 2:end]) + Stabilizer(QRM) +end + +code_n(c::QuantumReedMuller) = 2^c.m - 1 + +code_k(c::QuantumReedMuller) = 1 + +distance(c::QuantumReedMuller) = 3 + +parity_checks_x(c::QuantumReedMuller) = stab_to_gf2(parity_checks(QuantumReedMuller(c.m)))[1:c.m, 1:end÷2] + +parity_checks_z(c::QuantumReedMuller) = stab_to_gf2(parity_checks(QuantumReedMuller(c.m)))[end-(code_n(c::QuantumReedMuller)-2-c.m):end, end÷2+1:end] diff --git a/test/test_ecc_base.jl b/test/test_ecc_base.jl index d9afc09bb..6dd7e5162 100644 --- a/test/test_ecc_base.jl +++ b/test/test_ecc_base.jl @@ -63,7 +63,8 @@ const code_instance_args = Dict( CSS => (c -> (parity_checks_x(c), parity_checks_z(c))).([Shor9(), Steane7(), Toric(4, 4)]), 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)) + LPCode => (c -> (c.A, c.B)).(vcat(LP04, LP118, test_gb_codes, other_lifted_product_codes)), + QuantumReedMuller => [3, 4, 5] ) function all_testablable_code_instances(;maxn=nothing) diff --git a/test/test_ecc_decoder_all_setups.jl b/test/test_ecc_decoder_all_setups.jl index 4a8382c17..bf479cd0b 100644 --- a/test/test_ecc_decoder_all_setups.jl +++ b/test/test_ecc_decoder_all_setups.jl @@ -60,6 +60,33 @@ end end + @testset "BitFlipDecoder decoder, good for sparse codes" begin + codes = [ + QuantumReedMuller(3), + QuantumReedMuller(4) + ] + + noise = 0.001 + + setups = [ + CommutationCheckECCSetup(noise), + NaiveSyndromeECCSetup(noise, 0), + ShorSyndromeECCSetup(noise, 0), + ] + + for c in codes + for s in setups + for d in [c->BitFlipDecoder(c, maxiter=10)] + e = evaluate_decoder(d(c), s, 100000) + #@show c + #@show s + #@show e + @assert max(e...) < noise/4 + end + end + end + end + ## using Test diff --git a/test/test_ecc_quantumreedmuller.jl b/test/test_ecc_quantumreedmuller.jl new file mode 100644 index 000000000..efb76918f --- /dev/null +++ b/test/test_ecc_quantumreedmuller.jl @@ -0,0 +1,50 @@ +@testitem "Quantum Reed-Muller" begin + using Test + using Nemo: echelon_form, matrix, GF + using LinearAlgebra + using QuantumClifford + using QuantumClifford: canonicalize!, Stabilizer, stab_to_gf2 + using QuantumClifford.ECC + using QuantumClifford.ECC: AbstractECC, QuantumReedMuller, Steane7, CSS + + function designed_distance(mat) + dist = 3 + for row in eachrow(mat) + count = sum(row) + if count < dist + return false + end + end + return true + end + + @testset "Test QuantumReedMuller(r,m) properties" begin + for m in 3:10 + stab = parity_checks(QuantumReedMuller(m)) + H = stab_to_gf2(stab) + @test designed_distance(H) == true + # QuantumReedMuller(3) is the Steane7 code. + @test canonicalize!(parity_checks(Steane7())) == parity_checks(QuantumReedMuller(3)) + @test code_n(QuantumReedMuller(m)) == 2^m - 1 + @test code_k(QuantumReedMuller(m)) == 1 + @test distance(QuantumReedMuller(m)) == 3 + @test H == stab_to_gf2(parity_checks(CSS(parity_checks_x(QuantumReedMuller(m)), parity_checks_z(QuantumReedMuller(m))))) + # [[15,1,3]] qrm code from table 1 of https://arxiv.org/pdf/1705.0010 + qrm₁₅₁₃ = S"ZIZIZIZIZIZIZIZ + IZZIIZZIIZZIIZZ + IIIZZZZIIIIZZZZ + IIIIIIIZZZZZZZZ + IIZIIIZIIIZIIIZ + IIIIZIZIIIIIZIZ + IIIIIZZIIIIIIZZ + IIIIIIIIIZZIIZZ + IIIIIIIIIIIZZZZ + IIIIIIIIZIZIZIZ + XIXIXIXIXIXIXIX + IXXIIXXIIXXIIXX + IIIXXXXIIIIXXXX + IIIIIIIXXXXXXXX" + @test canonicalize!(parity_checks(qrm₁₅₁₃)) == canonicalize!(parity_checks(QuantumReedMuller(4))) + end + end +end