From c64492bebd974389976616a55347f5e6a1f71ecb Mon Sep 17 00:00:00 2001 From: Rabqubit Date: Fri, 14 Jun 2024 21:51:30 +0800 Subject: [PATCH] Concatenated quantum code (#289) --------- Co-authored-by: Stefan Krastanov --- CHANGELOG.md | 4 ++- docs/src/references.bib | 9 ++++++- docs/src/references.md | 1 + src/ecc/ECC.jl | 10 +++++-- src/ecc/codes/concat.jl | 47 +++++++++++++++++++++++++++++++++ test/test_ecc_base.jl | 3 ++- test/test_ecc_codeproperties.jl | 2 +- 7 files changed, 70 insertions(+), 6 deletions(-) create mode 100644 src/ecc/codes/concat.jl diff --git a/CHANGELOG.md b/CHANGELOG.md index 0232077d8..c6d5cc47c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,8 +5,10 @@ # News -## v0.9.4 - dev +## v0.9.4 - 2024-06-14 +- Addition of a constructor for concatenated quantum codes -- `Concat`. +- Addition of multiple unexported classical code constructors. - Gate errors are now conveniently supported by the various ECC benchmark setups in the `ECC` module. - Remove printing of spurious debug info from the PyBP decoder. - Significant improvements to the low-level circuit compiler (the sumtype compactifier), leading to faster Pauli frame simulation of noisy circuits. diff --git a/docs/src/references.bib b/docs/src/references.bib index f67523219..c492d0ea7 100644 --- a/docs/src/references.bib +++ b/docs/src/references.bib @@ -378,4 +378,11 @@ @book{error2024lin author={Lin, Shu and Costello, Daniel}, year={2024}, publisher={Pearson} -} \ No newline at end of file +} + +@article{knill1996concatenated, + title={Concatenated quantum codes}, + author={Knill, Emanuel and Laflamme, Raymond}, + journal={arXiv preprint quant-ph/9608012}, + year={1996} +} diff --git a/docs/src/references.md b/docs/src/references.md index f4d3fc0b2..b37e94d4e 100644 --- a/docs/src/references.md +++ b/docs/src/references.md @@ -36,6 +36,7 @@ For quantum code construction routines: - [chao2018quantum](@cite) - [kitaev2003fault](@cite) - [fowler2012surface](@cite) +- [knill1996concatenated](@cite) For classical code construction routines: - [muller1954application](@cite) diff --git a/src/ecc/ECC.jl b/src/ecc/ECC.jl index 0e6216eb7..bae3df389 100644 --- a/src/ecc/ECC.jl +++ b/src/ecc/ECC.jl @@ -8,7 +8,7 @@ using DocStringExtensions using Combinatorics: combinations using SparseArrays: sparse using Statistics: std -using Nemo: ZZ, residue_ring, matrix, finite_field, GF, minpoly, coeff, lcm, FqPolyRingElem, FqFieldElem, is_zero, degree, defining_polynomial, is_irreducible +using Nemo: ZZ, residue_ring, matrix, finite_field, GF, minpoly, coeff, lcm, FqPolyRingElem, FqFieldElem, is_zero, degree, defining_polynomial, is_irreducible abstract type AbstractECC end @@ -19,7 +19,7 @@ export parity_checks, parity_checks_x, parity_checks_z, iscss, RepCode, CSS, Shor9, Steane7, Cleve8, Perfect5, Bitflip3, - Toric, Gottesman, Surface, + Toric, Gottesman, Surface, Concat, evaluate_decoder, CommutationCheckECCSetup, NaiveSyndromeECCSetup, ShorSyndromeECCSetup, TableDecoder, @@ -49,6 +49,11 @@ function parity_checks_z(code::AbstractECC) throw(lazy"Codes of type $(typeof(code)) do not have separate X and Z parity checks, either because they are not a CSS code and thus inherently do not have separate checks, or because its separate checks are not yet implemented in this library.") end + +"""Check if the code is CSS. + +Return `nothing` if unknown from the type. +""" function iscss(::Type{T}) where T<:AbstractECC return false end @@ -353,6 +358,7 @@ include("codes/clevecode.jl") include("codes/toric.jl") include("codes/gottesman.jl") include("codes/surface.jl") +include("codes/concat.jl") include("codes/classical/reedmuller.jl") include("codes/classical/bch.jl") end #module diff --git a/src/ecc/codes/concat.jl b/src/ecc/codes/concat.jl new file mode 100644 index 000000000..e0e02f5c8 --- /dev/null +++ b/src/ecc/codes/concat.jl @@ -0,0 +1,47 @@ +""" +`Concat(c₁, c₂)` is a code concatenation of two quantum codes [knill1996concatenated](@cite). + +The inner code c₁ and the outer code c₂. +The construction is the following: replace each qubit in code c₂ with logical qubits encoded by code c₁. +The resulting code will have `n = n₁ × n₂` qubits and `k = k₁ × k₂` logical qubits. +""" +struct Concat <: AbstractECC + c₁::AbstractECC + c₂::AbstractECC +end + +function parity_checks(c::Concat) + c₁ = c.c₁ + c₂ = c.c₂ + k₁ = code_k(c₁) + n₁ = code_n(c₁) + n₂ = code_n(c₂) + s₁ = code_s(c₁) + s₂ = code_s(c₂) + inner_checks = Stabilizer(vcat([embed(n₁ * n₂, 1+(i-1)*n₁:i*n₁, parity_checks(c₁)[j]) for i in 1:n₂ for j in 1:s₁])) # parity checks of c₁ on each qubit of c₂ + h₂ = parity_matrix(c₂) + phases₂ = phases(parity_checks(c₂)) + h_logx₁ = stab_to_gf2(logx_ops(c₁)) + phases_logx₁ = phases(logx_ops(c₁)) + h_logz₁ = stab_to_gf2(logz_ops(c₁)) + phases_logz₁ = phases(logz_ops(c₁)) + # parity checks of c₂ with qubits repalced with logical qubits of c₁ + outer_check_h = transpose(hcat([vcat( + kron(h₂[i, 1:end÷2], h_logx₁[j, 1:end÷2]) .⊻ kron(h₂[i, end÷2+1:end], h_logz₁[j, 1:end÷2]), # X part + kron(h₂[i, 1:end÷2], h_logx₁[j, end÷2+1:end]) .⊻ kron(h₂[i, end÷2+1:end], h_logz₁[j, end÷2+1:end]) # Z part + ) for i in 1:s₂ for j in 1:k₁]...)) + outer_check_phase = [UInt8(sum(h₂[i, 1:end÷2] * phases_logx₁[j]) + sum(h₂[i, end÷2+1:end] * phases_logz₁[j]) + phases₂[i]) & 0x3 for i in 1:s₂ for j in 1:k₁] + outer_checks = Stabilizer(outer_check_phase, outer_check_h) + vcat(inner_checks, outer_checks) +end + +code_n(c::Concat) = code_n(c.c₁) * code_n(c.c₂) + +code_k(c::Concat) = code_k(c.c₁) * code_k(c.c₂) + +function iscss(c::Concat) + if iscss(c.c₁) && iscss(c.c₂) + true + end + return nothing # if c.c₁ or c.c₂ are non-CSS; in this case, `Concat(c₁, c₂)` can still be CSS +end diff --git a/test/test_ecc_base.jl b/test/test_ecc_base.jl index 89b8f5204..ecf9a2999 100644 --- a/test/test_ecc_base.jl +++ b/test/test_ecc_base.jl @@ -9,7 +9,8 @@ const code_instance_args = Dict( Toric => [(3,3), (4,4), (3,6), (4,3), (5,5)], Surface => [(3,3), (4,4), (3,6), (4,3), (5,5)], Gottesman => [3, 4, 5], - CSS => (c -> (parity_checks_x(c), parity_checks_z(c))).([Shor9(), Steane7(), Toric(4,4)]) + 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())], ) function all_testablable_code_instances(;maxn=nothing) diff --git a/test/test_ecc_codeproperties.jl b/test/test_ecc_codeproperties.jl index 90ab54c87..c464ea545 100644 --- a/test/test_ecc_codeproperties.jl +++ b/test/test_ecc_codeproperties.jl @@ -22,7 +22,7 @@ end @testset "is CSS" begin for code in all_testablable_code_instances() H = parity_checks(code) - @test iscss(code) == is_css_matrix(H) + @test iscss(code) in (is_css_matrix(H), nothing) end end