diff --git a/docs/src/references.bib b/docs/src/references.bib index c93eeae..2fc8b9b 100644 --- a/docs/src/references.bib +++ b/docs/src/references.bib @@ -560,3 +560,26 @@ @misc{panteleev2022asymptoticallygoodquantumlocally primaryClass={cs.IT}, url={https://arxiv.org/abs/2111.03654}, } + +@misc{liu2020shortenedlinearcodesfinite, + title={Shortened Linear Codes over Finite Fields}, + author={Yang Liu and Cunsheng Ding and Chunming Tang}, + year={2020}, + eprint={2007.05901}, + archivePrefix={arXiv}, + primaryClass={cs.IT}, + url={https://arxiv.org/abs/2007.05901}, +} + +@article{Gundersen_2025, + title={Puncturing Quantum Stabilizer Codes}, + volume={6}, + ISSN={2641-8770}, + url={http://dx.doi.org/10.1109/JSAIT.2025.3562287}, + DOI={10.1109/jsait.2025.3562287}, + journal={IEEE Journal on Selected Areas in Information Theory}, + publisher={Institute of Electrical and Electronics Engineers (IEEE)}, + author={Gundersen, Jaron Skovsted and Christensen, René Bødker and Grassl, Markus and Popovski, Petar and Wisniewski, Rafał}, + year={2025}, + pages={74–84} } + diff --git a/src/QuantumExpanders.jl b/src/QuantumExpanders.jl index 70e4313..4586dc7 100644 --- a/src/QuantumExpanders.jl +++ b/src/QuantumExpanders.jl @@ -25,6 +25,7 @@ using Multigraphs using ProgressMeter using DocStringExtensions +include("utils.jl") include("cayley_graphs.jl") include("tensor_codes.jl") include("morgenstern.jl") @@ -51,6 +52,8 @@ export parity_matrix, parity_matrix_x, parity_matrix_z, parity_matrix_xz, code_n, code_k, # tensor codes uniformly_random_code_checkmatrix, dual_code, good_css, - normal_cayley_subset, GeneralizedQuantumTannerCode, find_random_generating_sets + normal_cayley_subset, GeneralizedQuantumTannerCode, find_random_generating_sets, + # puncturing + puncture end #module diff --git a/src/utils.jl b/src/utils.jl new file mode 100644 index 0000000..5b72d97 --- /dev/null +++ b/src/utils.jl @@ -0,0 +1,40 @@ +""" +Puncturing is a standard technique for constructing new linear codes from existing ones ([liu2020shortenedlinearcodesfinite](@cite), [Gundersen_2025](@cite)). + +Let C be an [n, k, d] linear code over Galois field with characteristic 2 with parity-check matrix +``H_B``, and let t be a set of coordinates given by `cols`. The punctured code ``C_t`` is obtained +by deleting the coordinates in t from every codeword of C. The resulting code is linear and has length +n − |t|. + +Returns a parity-check matrix for the punctured code ``C_t``. The construction proceeds by +computing a generator matrix G of C from ``H_B``, deleting the columns indexed by t, and then +computing a parity-check matrix for the resulting punctured code. + +Here is an example of puncturing the classical [6,3,3] code: + +```jldoctest +julia> using QuantumExpanders; using Nemo + +julia> H = [1 0 0 0 1 1; + 0 1 0 1 0 1; + 0 0 1 1 1 0]; + +julia> H_new = puncture(H, [6]) +2×5 Matrix{Int64}: + 1 1 1 0 0 + 1 1 0 1 1 + +julia> rank(matrix(GF(2), H_new)) +2 +``` + +Now, it is a [5,2,2] code. This distance is verified from [dist-m4ri](https://github.com/QEC-pages/dist-m4ri) program. + +""" +function puncture(H::AbstractMatrix, cols::AbstractVector{<:Integer}) + G = Matrix{Int}(lift.(dual_code(matrix(ZZ, H)))) + keep = setdiff(1:size(G,2), cols) + G_p = G[:, keep] + H = Matrix{Int}(lift.(dual_code(matrix(ZZ, G_p)))) + return H +end diff --git a/test/test_quantum_tanner_codes.jl b/test/test_quantum_tanner_codes.jl index 3f77b47..903dbf2 100644 --- a/test/test_quantum_tanner_codes.jl +++ b/test/test_quantum_tanner_codes.jl @@ -715,4 +715,35 @@ end end end + + @testset "Test Puncture" begin + for seed in 1:50 + G = small_group(12,1) + rng = MersenneTwister(seed) + A, B = find_random_generating_sets(G, 6, 5; rng=rng) + H_A = [1 0 0 0 1 1; + 0 1 0 1 0 1; + 0 0 1 1 1 0]; + G_A = Matrix{Int}(lift.(dual_code(matrix(ZZ, H_A)))) + H_B = puncture(H_A, [6]) + G_B = Matrix{Int}(lift.(dual_code(matrix(ZZ, H_B)))) + classical_code_pair = ((Matrix{Int}(H_A), G_A), (H_B, G_B)) + c = QuantumTannerCode(G, A, B, classical_code_pair) + @test stab_looks_good(parity_checks(c), remove_redundant_rows=true) + end + + # Here is an example of novel [[180, 2, 8]] code + G = small_group(12,1) + rng = MersenneTwister(1) + A, B = find_random_generating_sets(G, 6, 5; rng=rng) + H_A = [1 0 0 0 1 1; + 0 1 0 1 0 1; + 0 0 1 1 1 0]; + G_A = Matrix{Int}(lift.(dual_code(matrix(ZZ, H_A)))) + H_B = puncture(H_A, [6]) + G_B = Matrix{Int}(lift.(dual_code(matrix(ZZ, H_B)))) + classical_code_pair = ((Matrix{Int}(H_A), G_A), (H_B, G_B)) + c = QuantumTannerCode(G, A, B, classical_code_pair) + @test stab_looks_good(parity_checks(c), remove_redundant_rows=true) + end end