|
| 1 | +""" |
| 2 | +Represents a *bipartite* Tanner graph used in classical coding theory. It connects *variable |
| 3 | +nodes* (codeword bits or qubits) to *check nodes* (parity constraints) and serves as the |
| 4 | +foundation for constructing Tanner graphs in quantum CSS codes. |
| 5 | +""" |
| 6 | +struct BipartiteGraph |
| 7 | + """The underlying undirected graph (from `Graphs.jl`).""" |
| 8 | + g::Graph |
| 9 | + """Indices of variable nodes.""" |
| 10 | + var_nodes::Vector{Int} |
| 11 | + """Indices of check nodes.""" |
| 12 | + check_nodes::Vector{Int} |
| 13 | +end |
| 14 | + |
| 15 | +""" |
| 16 | +Constructs a *Tanner graph* from a given parity-check matrix `H`, where rows correspond to *check nodes* |
| 17 | +and columns to *variable nodes*. The resulting *bipartite* graph indexes variable nodes as `1:n` and check |
| 18 | +nodes as `n+1:n+m` for an `m Γ n` matrix `H`.""" |
| 19 | +function tanner_graph_from_parity_matrix(H::AbstractMatrix) |
| 20 | + m, n = size(H) |
| 21 | + g = SimpleGraph(n + m) |
| 22 | + var_nodes = collect(1:n) |
| 23 | + check_nodes = collect(n+1:n+m) |
| 24 | + for row in 1:m, col in 1:n |
| 25 | + H[row, col] && add_edge!(g, col, n + row) |
| 26 | + end |
| 27 | + return BipartiteGraph(g, var_nodes, check_nodes) |
| 28 | +end |
| 29 | + |
| 30 | +"""Reconstructs the parity-check matrix from a Tanner graph `g`. |
| 31 | +
|
| 32 | +!!! note |
| 33 | + The first block of vertices corresponds to variable nodes and the remaining to check nodes. It |
| 34 | + returns a parity check matrix `H` of size `(number of check nodes) Γ (number of variable nodes).` |
| 35 | +""" |
| 36 | +function parity_matrix_from_tanner_graph(bg::BipartiteGraph) |
| 37 | + n_vars = length(bg.var_nodes) |
| 38 | + n_checks = length(bg.check_nodes) |
| 39 | + H = spzeros(Bool, n_checks, n_vars) |
| 40 | + for (check_idx, check_node) in enumerate(bg.check_nodes) |
| 41 | + for neighbor in neighbors(bg.g, check_node) |
| 42 | + neighbor in bg.var_nodes && (H[check_idx, neighbor] = true) |
| 43 | + end |
| 44 | + end |
| 45 | + return H |
| 46 | +end |
| 47 | + |
| 48 | +""" |
| 49 | +Constructs a bipartite Tanner graph representing the cycle code of length `n`. The graph |
| 50 | +consists of `n` variable nodes and `n` check nodes, totaling `2n` nodes. Each check node `i` |
| 51 | +(for `i` in `1...n`) connects to variable nodes `i` and (``i+1 \\mod n``). This results in a |
| 52 | +parity-check matrix `H`, where each row contains exactly two `1`s, encoding the edges of a |
| 53 | +length-`n` cycle. |
| 54 | +""" |
| 55 | +function cycle_tanner_graph(n::Int) |
| 56 | + g = SimpleGraph(2n) |
| 57 | + var_nodes = collect(1:n) |
| 58 | + check_nodes = collect(n+1:2n) |
| 59 | + for i in 1:n |
| 60 | + check_node = n + i |
| 61 | + add_edge!(g, i, check_node) |
| 62 | + add_edge!(g, mod1(i+1, n), check_node) |
| 63 | + end |
| 64 | + return BipartiteGraph(g, var_nodes, check_nodes) |
| 65 | +end |
| 66 | + |
| 67 | +""" |
| 68 | + $TYPEDEF |
| 69 | +
|
| 70 | +Represents the CSS quantum code `Q(Gβ Γ Gβ)` constructed from two binary codes with |
| 71 | +parity-check matrices `Hβ` and `Hβ`, using the hypergraph product formulation introduced |
| 72 | +by [tillich2013quantum](@cite). |
| 73 | +
|
| 74 | +This construction corresponds to a specific product of Tanner graphs: |
| 75 | +- Let `Gβ = T(Vβ, Cβ, Eβ)` and `Gβ = T(Vβ, Cβ, Eβ)` be the Tanner graphs of `Hβ` and `Hβ`. |
| 76 | +- The product graph `Gβ Γ Gβ` has vertex set `(Vβ Γ Vβ) βͺ (Cβ Γ Cβ)` and check set `(Cβ Γ Vβ) βͺ (Vβ Γ Cβ)`. |
| 77 | +- The Tanner subgraphs `Gβ Γβ Gβ` and `Gβ Γπ Gβ` define classical codes `Cβ` and `Cπ` used in the CSS construction. |
| 78 | +
|
| 79 | +The `hgp(Hβ, Hβ)` function algebraically realizes this graph-theoretic product using Kronecker operations, |
| 80 | +yielding the `X`- and `Z`-type parity-check matrices: |
| 81 | +
|
| 82 | +- `H_X = [Hβ β I | I β Hβα΅]` corresponds to `Gβ Γβ Gβ` |
| 83 | +- `H_Z = [I β Hβ | Hβα΅ β I]` corresponds to `Gβ Γπ Gβ` |
| 84 | +
|
| 85 | +These matrices ensure `H_X * H_Zα΅ = 0`, satisfying the CSS condition. |
| 86 | +
|
| 87 | +See: [tillich2013quantum](@cite), Section 4.3 β βThe hypergraph connection, product codesβ |
| 88 | +
|
| 89 | +# π(πΊβ Γ πΊβ) |
| 90 | +
|
| 91 | +The `π(πΊβ Γ πΊβ)` quantum LDPC codes represent a broader generalization of **quantum expander codes** |
| 92 | +which are derived from the Leverrier-Tillich-ZΓ©mor construction [tillich2013quantum](@cite). |
| 93 | +
|
| 94 | +```jldoctest examples |
| 95 | +julia> using QuantumClifford; using QuantumClifford.ECC; using QECCore |
| 96 | +
|
| 97 | +julia> H1 = [1 0 1 0; 0 1 0 1; 1 1 0 0]; |
| 98 | +
|
| 99 | +julia> H2 = [1 1 0; 0 1 1]; |
| 100 | +
|
| 101 | +julia> c = parity_checks(QuantumTannerGraphProduct(H1, H2)) |
| 102 | ++ X_____X_____X_____ |
| 103 | ++ _X_____X____XX____ |
| 104 | ++ __X_____X____X____ |
| 105 | ++ ___X_____X____X___ |
| 106 | ++ ____X_____X___XX__ |
| 107 | ++ _____X_____X___X__ |
| 108 | ++ X__X____________X_ |
| 109 | ++ _X__X___________XX |
| 110 | ++ __X__X___________X |
| 111 | ++ ZZ__________Z___Z_ |
| 112 | ++ _ZZ__________Z___Z |
| 113 | ++ ___ZZ_________Z_Z_ |
| 114 | ++ ____ZZ_________Z_Z |
| 115 | ++ ______ZZ____Z_____ |
| 116 | ++ _______ZZ____Z____ |
| 117 | ++ _________ZZ___Z___ |
| 118 | ++ __________ZZ___Z__ |
| 119 | +
|
| 120 | +julia> code_n(c), code_k(c) |
| 121 | +(18, 1) |
| 122 | +``` |
| 123 | +
|
| 124 | +# Quantum Expander code |
| 125 | +
|
| 126 | +The `π(πΊβ Γ πΊβ)` code is more general than the **standard quantum expander code** |
| 127 | +[leverrier2015quantum](@cite) construction. The quantum expander code construction |
| 128 | +corresponds to the specific case where `G = G1 = G2`β. |
| 129 | +
|
| 130 | +```jldoctest examples |
| 131 | +julia> H = parity_matrix(RepCode(3)); |
| 132 | +
|
| 133 | +julia> c = parity_checks(QuantumTannerGraphProduct(H, H)) |
| 134 | ++ X__X_____X_X______ |
| 135 | ++ _X__X____XX_______ |
| 136 | ++ __X__X____XX______ |
| 137 | ++ ___X__X_____X_X___ |
| 138 | ++ ____X__X____XX____ |
| 139 | ++ _____X__X____XX___ |
| 140 | ++ X_____X________X_X |
| 141 | ++ _X_____X_______XX_ |
| 142 | ++ __X_____X_______XX |
| 143 | ++ ZZ_______Z_____Z__ |
| 144 | ++ _ZZ_______Z_____Z_ |
| 145 | ++ Z_Z________Z_____Z |
| 146 | ++ ___ZZ____Z__Z_____ |
| 147 | ++ ____ZZ____Z__Z____ |
| 148 | ++ ___Z_Z_____Z__Z___ |
| 149 | ++ ______ZZ____Z__Z__ |
| 150 | ++ _______ZZ____Z__Z_ |
| 151 | ++ ______Z_Z_____Z__Z |
| 152 | +
|
| 153 | +julia> code_n(c), code_k(c) |
| 154 | +(18, 2) |
| 155 | +``` |
| 156 | +
|
| 157 | +### Fields |
| 158 | + $TYPEDFIELDS |
| 159 | +""" |
| 160 | +struct QuantumTannerGraphProduct <: AbstractCSSCode |
| 161 | + """The first classical seed code for the the quantum tanner graph code.""" |
| 162 | + H1::AbstractMatrix |
| 163 | + """The second classical seed code for the the quantum tanner graph code.""" |
| 164 | + H2::AbstractMatrix |
| 165 | +end |
| 166 | + |
| 167 | +parity_matrix_xz(c::QuantumTannerGraphProduct) = hgp(c.H1, c.H2) |
| 168 | + |
| 169 | +""" |
| 170 | + $TYPEDEF |
| 171 | +
|
| 172 | +Constructs a `π(πΊβ Γ πΊβ)` quantum Tanner graph product code using cyclic Tanner graphs of length `2m`. |
| 173 | +
|
| 174 | +```jldoctest |
| 175 | +julia> using QuantumClifford; using QuantumClifford.ECC; |
| 176 | +
|
| 177 | +julia> m = 1; |
| 178 | +
|
| 179 | +julia> c = parity_checks(CyclicQuantumTannerGraphProduct(m)) |
| 180 | ++ X_X_XX__ |
| 181 | ++ _X_XXX__ |
| 182 | ++ X_X___XX |
| 183 | ++ _X_X__XX |
| 184 | ++ ZZ__Z_Z_ |
| 185 | ++ ZZ___Z_Z |
| 186 | ++ __ZZZ_Z_ |
| 187 | ++ __ZZ_Z_Z |
| 188 | +
|
| 189 | +julia> code_n(c), code_k(c) |
| 190 | +(8, 2) |
| 191 | +
|
| 192 | +julia> m = 10; |
| 193 | +
|
| 194 | +julia> c = parity_checks(CyclicQuantumTannerGraphProduct(m)); |
| 195 | +
|
| 196 | +julia> code_n(c), code_k(c) |
| 197 | +(800, 2) |
| 198 | +``` |
| 199 | +
|
| 200 | +### Fields |
| 201 | + $TYPEDFIELDS |
| 202 | +""" |
| 203 | +struct CyclicQuantumTannerGraphProduct <: AbstractCSSCode |
| 204 | + m::Int |
| 205 | + function CyclicQuantumTannerGraphProduct(m::Int) |
| 206 | + m > 0 || throw(ArgumentError("m must be positive.")) |
| 207 | + new(m) |
| 208 | + end |
| 209 | +end |
| 210 | + |
| 211 | +function parity_matrix_xz(Q::CyclicQuantumTannerGraphProduct) |
| 212 | + n = 2*Q.m |
| 213 | + G1 = cycle_tanner_graph(n) |
| 214 | + G2 = cycle_tanner_graph(n) |
| 215 | + H1 = parity_matrix_from_tanner_graph(G1) |
| 216 | + H2 = parity_matrix_from_tanner_graph(G2) |
| 217 | + return hgp(H1, H2) |
| 218 | +end |
| 219 | + |
| 220 | +parity_matrix_x(c::Union{QuantumTannerGraphProduct,CyclicQuantumTannerGraphProduct}) = parity_matrix_xz(c)[1] |
| 221 | + |
| 222 | +parity_matrix_z(c::Union{QuantumTannerGraphProduct,CyclicQuantumTannerGraphProduct}) = parity_matrix_xz(c)[2] |
0 commit comments