Kernel-basis extraction and completeness #
Lean-QEC's kernel basis (a basis of the null space of a parity-check matrix) is produced by
an external Python script, and the correctness of that script is not part of the
trusted base: the companion paper states that only the rank and the orthogonality are
checked after the fact. This module supplies a proof inside the kernel: a set of
generators is read directly off the pivot structure of row reduction, and
ker(H) = span(kernel generators)
is closed in both directions inside the Lean kernel. With it, the step "the kernel basis is produced by an external script" drops out of the trusted base.
Mechanism #
Row reduction outputs a mutually reduced set of pivot rows D (see IsReduced). The pivot
columns are the occupied columns and the remaining columns are the free columns. For
each free column j the kernel vector is taken to be
kerVec D j := e_j + ∑_{r ∈ D} (r_j) · e_{pivot(r)}
that is, e_j corrected along the pivot directions by the entry of each row in column j.
Orthogonality comes from (R2): every row takes the value 1 at its own pivot column and 0 at
the pivot columns of the other rows, so the two kinds of contribution cancel exactly.
Main results #
kerVec_mem_kerL: a kernel vector really does lie in the kernel (the soundness direction).kerL_le_spanL_kerBasis: every vector in the kernel is a linear combination of the kernel generators (the completeness direction).kerL_rowReduce:ker H = span (kerBasis (rowReduce H)), bringing the two sides together.hammingNorm_kerVec_le/kerVec_ne_zero/exists_light_mem_kerL: the Singleton-type count; when the kernel is nontrivial it contains a nonzero element of weight at most the rank plus one. The frontier argument in the companion paper uses exactly this step.
Single-term summation helpers (collapsing a column-selection sum to one term) #
The kernel #
The kernel of a list of rows: all vectors orthogonal to every row (zero GF(2) dot product).
This is the algebraic description of the error space of a quantum error-correcting
code, namely the Pauli operators commuting with every parity-check row. It is tied to
LeanQEC's LinearMap.ker M.toLin' through mem_ker_iff_dotProd_rows_eq_zero.
Equations
Instances For
Pivot columns and free columns #
The set of pivot columns.
Equations
- QECCertificates.pivCols D = (List.map (fun (x : QECCertificates.PivRow n) => x.2) D).toFinset
Instances For
A free column: a column that is not the pivot column of any row.
Equations
- QECCertificates.IsFreeCol D j = ∀ ri ∈ D, ri.2 ≠ j
Instances For
Kernel vectors #
The kernel vector attached to the free column j: e_j plus the pivot corrections
determined by the entries of the rows in column j.
Equations
Instances For
Soundness direction: a kernel vector really does lie in the kernel of these rows.
The proof cancels two sums: the dot product of rk with the kernel vector is expanded into
a double sum, the order of summation is exchanged, and the Kronecker form of (R1)/(R2)
collapses the inner sum to a single term.
The Singleton-type count: how light a kernel vector is #
The Singleton-type count: the support of a kernel vector lies in $\{j\}\cup$ the pivot columns, so its weight is at most $1+\#D$.
This holds for every column j, free or not: kerVec D j can be nonzero only at j
and at the pivot columns, and every other column is free and hence vanishes by
kerVec_apply_free. There are exactly #D pivot columns, and #D is the rank. Together
with kerVec_ne_zero this makes "a nontrivial kernel $\Rightarrow$ there is a nonzero
kernel vector of weight $\le\rho+1$" a theorem rather than an informal remark.
Kernel generators #
The kernel generators: each free column yields one kernel vector. (There are exactly
n − #D free columns, so the number of generators is the dimension of the kernel; see the
completeness half of kerL_rowReduce.)
Equations
- QECCertificates.kerBasis D = List.map (QECCertificates.kerVec D) (List.filter (fun (j : Fin n) => decide (j ∉ QECCertificates.pivCols D)) (List.finRange n))
Instances For
Completeness #
The entries at the pivot columns determine everything: a vector supported on the pivot columns that also lies in the kernel must be zero.
Agreement with the original code #
Main theorem: the kernel equals the space spanned by the kernel generators. The list of rows is first put through the trusted row reduction, and the kernel generators are read directly off the pivot structure that it outputs; the whole chain closes inside the kernel.
The row-list form of the frontier-argument step: as long as rowReduce L still
has a free column, that is, as long as the kernel is nontrivial, the kernel of L contains
a nonzero element of weight $\le 1+\#(rowReduce L)$.
Now $\#(rowReduce L)$ is the rank of L, so this is the full statement that a matrix of
rank $\rho$ has a nonzero kernel vector of weight $\le\rho+1$: existence comes from the
completeness direction of kerL_rowReduce, while nonzeroness and the weight bound come
from the two results above.
The indexed form: the kernel vector given by the free column j lies in the
kernel, has weight at most the rank plus one, and takes the value $1$ at j.
The clause "takes the value 1 at j" is needed for the frontier argument: the witness
construction for the hypergraph product requires the seed kernel vector to be nonzero at
some index (s a₀ = 1 in xwLeft).
Agreement with the LeanQEC matrix interface #
The kernel of a parity-check matrix (LeanQEC's LinearMap.ker M.toLin') agrees
with the kernel of its list of rows. This bridge lets the row-space theorems already
available in LeanQEC act directly on kerL of this module.
Main theorem for external use (LeanQEC interface version): the kernel of a
parity-check matrix M equals the space spanned by the kernel generators. The generators
are read directly off the list of rows of M by the trusted row reduction, and the whole
procedure closes inside the kernel.