Add verified matrix factorizations: Cholesky and QR (exact)#2
Add verified matrix factorizations: Cholesky and QR (exact)#2NicolasRouquette wants to merge 3 commits into
Conversation
The exact, finite half of a verified matrix-factorization foundation for classical / scientific-ML
models (Gaussian processes, kernel-ridge regression, PCA, least squares).
Spec (NN/Spec/Core/Tensor/Factorizations.lean): choleskySpec (A = L·Lᵀ, lower-triangular L, via a
column fold with a strict array @[implemented_by]), the triangular and Cholesky linear solves, and
qrSpec (A = Q·R by modified Gram–Schmidt), over the readable Fin n → Fin n → α representation with
toMatFn/ofMatFn tensor bridges.
Proofs over ℝ via Mathlib (NN/Proofs/Tensor/Basic/Factorizations*.lean):
- predicates IsCholesky / IsQR;
- Cholesky is lower-triangular (from the column fold) and reconstructs A = L·Lᵀ under SPD pivots;
- QR reconstructs A = Q·R with Qᵀ·Q = 1 under full column rank, bridged to Mathlib's gramSchmidt.
These are exact finite identities — no iteration, no asymptotic caveat — the bedrock the iterative
eigensolver/SVD build on separately.
Examples (NN/Examples/Factorization/{Cholesky,QR}): #eval witnesses, each a positive reconstruction /
orthonormality check plus a negative control (indefinite A fails Cholesky; rank-deficient A breaks
QR orthonormality), wrapped in `#guard_msgs (drop info)` so a regression still fails the build without
polluting the log.
Blueprint: a focused Ch.4 chapter "Matrix Factorizations: Cholesky and QR".
sorry/admit-free. Builds green: lake build NN.Proofs.Tensor.Basic
NN.Examples.Factorization (and the blueprint).
Robertboy18
left a comment
There was a problem hiding this comment.
Thanks for splitting this down to the exact Cholesky/QR core. I like the direction a lot: the main theorem endpoints look useful, and I did not find any new axioms, sorry, admit, unsafe, or opaque in the added proof files.
I do think this needs another cleanup pass before merge. The biggest issue is not the math direction; it is that the PR still contains residue from the broader CHD/eig/SVD version, plus a couple of proof-engineering/trust-boundary details that should be made explicit. Once those are cleaned up, this will be a much easier PR to review and maintain.
Address review feedback on lean-dojo#2: - Spec header: trim to Cholesky/QR + ridge-solve helpers; drop symEigJacobiSpec/svdSpec, the eigendecompSpec section, dead ltBool/leBool, and CHD solve_variationnal mentions. - Proofs header: rewrite to describe only the IsCholesky/IsQR predicates, the fold-indexing lemmas, and choleskyFn_lower_triangular. - Minimize proof imports: drop the five unused spectral/Hermitian/unitary Mathlib imports (residue from the removed eig/SVD work). - @[implemented_by] trust boundary: add an explicit "Trust boundary" note — the strict-array …Impl substitution is trusted, not verified; examples are evidence, not an equivalence proof. Soften per-def overclaims. - De-duplicate the snoc-fold lemmas (length_foldl_snoc / getD_foldl_snoc_lt / getD_foldl_snoc_read) into one public home in Factorizations.lean; delete the duplicate FoldSnoc section from FactorizationsReconstruction.lean. - Blueprint Ch.4: weaken the pivot wording — isCholesky_of_pos assumes positive executable pivots directly; PosDef -> positive pivots is not formalized here. - Examples/Common: drop the (Cholesky, QR, SymEig, SVD) header and the dead diagFromVec/diagOf/offDiagFrobSq/totalFrobSq/assertApproxEq helpers. sorry/admit/unsafe/opaque-free; builds NN.Proofs.Tensor.Basic, NN.Examples.Factorization, and the blueprint.
Address review feedback on lean-dojo#2: - Spec header: trim to Cholesky/QR + ridge-solve helpers; drop symEigJacobiSpec/svdSpec, the eigendecompSpec section, dead ltBool/leBool, and CHD solve_variationnal mentions. - Proofs header: rewrite to describe only the IsCholesky/IsQR predicates, the fold-indexing lemmas, and choleskyFn_lower_triangular. - Minimize proof imports: drop the five unused spectral/Hermitian/unitary Mathlib imports (residue from the removed eig/SVD work). - @[implemented_by] trust boundary: add an explicit "Trust boundary" note — the strict-array …Impl substitution is trusted, not verified; examples are evidence, not an equivalence proof. Soften per-def overclaims. - De-duplicate the snoc-fold lemmas (length_foldl_snoc / getD_foldl_snoc_lt / getD_foldl_snoc_read) into one public home in Factorizations.lean; delete the duplicate FoldSnoc section from FactorizationsReconstruction.lean. - Blueprint Ch.4: weaken the pivot wording — isCholesky_of_pos assumes positive executable pivots directly; PosDef -> positive pivots is not formalized here. - Examples/Common: drop the (Cholesky, QR, SymEig, SVD) header and the dead diagFromVec/diagOf/offDiagFrobSq/totalFrobSq/assertApproxEq helpers. sorry/admit/unsafe/opaque-free; builds NN.Proofs.Tensor.Basic, NN.Examples.Factorization, and the blueprint. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
|
Thanks for the careful review — all six points addressed in 93f6272. Summary:
I also cleaned the matching residue in Still Co-Authored-By: Claude Opus 4.8 (1M context) noreply@anthropic.com |
|
Thanks for the cleanup in Before we merge, I think there are a few remaining cleanup/policy items:
|
Follow-up to the maintainer's second review on lean-dojo#2: - QR is renamed from "modified" to "classical" Gram-Schmidt across spec, proofs, examples, and the blueprint: the recurrence computes r[k,j] = q_k . a_j against the original column a_j and subtracts all projections in one pass, which is the classical presentation. The implementation is unchanged; only the name/docs now match it. - Replace the "omega-free" claims with "sorry/admit-free" (omega is a normal tactic and is used in some scripts; the old wording was inaccurate). - Disambiguate the R above/below-diagonal naming. With R indexed row-then-column, k < j is strictly above the diagonal (the nonzero upper part) and k > j is strictly below. Renamed rStep_above -> rStep_below_diag_zero (proves the strictly-below entry vanishes) and R_below -> Rmat_above_diag_dot (the strictly-above entry is the Q.a inner product), and corrected the rStep docstring, which had above/below swapped. - Make the solve-helper theorem surface explicit: a "Verification scope" note in the spec header (and the blueprint) states that triSolveLower/Upper, cholSolve, and solveRidge are executable APIs only -- this PR does not yet prove their correctness. The verified contribution is the factorizations. - Drop the stale eig/SVD "companion chapter" forward references from the blueprint (that work is out of scope for this PR). - @[implemented_by]: keep the hooks with the existing explicit trust-boundary note (trusted, not verified); no change needed there. Builds green: lake build NN.Proofs.Tensor.Basic NN.Examples.Factorization and the blueprint chapter. sorry/admit/unsafe/opaque-free.
Address review feedback on lean-dojo#2: - Spec header: trim to Cholesky/QR + ridge-solve helpers; drop symEigJacobiSpec/svdSpec, the eigendecompSpec section, dead ltBool/leBool, and CHD solve_variationnal mentions. - Proofs header: rewrite to describe only the IsCholesky/IsQR predicates, the fold-indexing lemmas, and choleskyFn_lower_triangular. - Minimize proof imports: drop the five unused spectral/Hermitian/unitary Mathlib imports (residue from the removed eig/SVD work). - @[implemented_by] trust boundary: add an explicit "Trust boundary" note — the strict-array …Impl substitution is trusted, not verified; examples are evidence, not an equivalence proof. Soften per-def overclaims. - De-duplicate the snoc-fold lemmas (length_foldl_snoc / getD_foldl_snoc_lt / getD_foldl_snoc_read) into one public home in Factorizations.lean; delete the duplicate FoldSnoc section from FactorizationsReconstruction.lean. - Blueprint Ch.4: weaken the pivot wording — isCholesky_of_pos assumes positive executable pivots directly; PosDef -> positive pivots is not formalized here. - Examples/Common: drop the (Cholesky, QR, SymEig, SVD) header and the dead diagFromVec/diagOf/offDiagFrobSq/totalFrobSq/assertApproxEq helpers. sorry/admit/unsafe/opaque-free; builds NN.Proofs.Tensor.Basic, NN.Examples.Factorization, and the blueprint.
Follow-up to the maintainer's second review on lean-dojo#2: - QR is renamed from "modified" to "classical" Gram-Schmidt across spec, proofs, examples, and the blueprint: the recurrence computes r[k,j] = q_k . a_j against the original column a_j and subtracts all projections in one pass, which is the classical presentation. The implementation is unchanged; only the name/docs now match it. - Replace the "omega-free" claims with "sorry/admit-free" (omega is a normal tactic and is used in some scripts; the old wording was inaccurate). - Disambiguate the R above/below-diagonal naming. With R indexed row-then-column, k < j is strictly above the diagonal (the nonzero upper part) and k > j is strictly below. Renamed rStep_above -> rStep_below_diag_zero (proves the strictly-below entry vanishes) and R_below -> Rmat_above_diag_dot (the strictly-above entry is the Q.a inner product), and corrected the rStep docstring, which had above/below swapped. - Make the solve-helper theorem surface explicit: a "Verification scope" note in the spec header (and the blueprint) states that triSolveLower/Upper, cholSolve, and solveRidge are executable APIs only -- this PR does not yet prove their correctness. The verified contribution is the factorizations. - Drop the stale eig/SVD "companion chapter" forward references from the blueprint (that work is out of scope for this PR). - @[implemented_by]: keep the hooks with the existing explicit trust-boundary note (trusted, not verified); no change needed there. Builds green: lake build NN.Proofs.Tensor.Basic NN.Examples.Factorization and the blueprint chapter. sorry/admit/unsafe/opaque-free.
93f6272 to
3a2fde9
Compare
|
Thanks for the detailed review; I made the requested changes and forced-pushed an update. |
3a2fde9 to
37a220e
Compare
A small, single-purpose contribution: the exact, finite half of a verified
matrix-factorization foundation that classical / scientific-ML models rely on —
Gaussian processes, kernel-ridge regression, PCA, least squares.
Context — this supersedes #1
#1 had grown to mix three separable things:
Following the question of whether this belongs in TorchLean or in a repo of its own, I've split them:
Only the generic, domain-independent factorizations — pure linear algebra, no CHD anywhere.
To keep review small, even this is split into
All CHD- and KernelFlows-specific work, as its own Lean package that takes TorchLean as a library dependency
zero changes to TorchLean's source.
So this PR is intentionally the minimal, self-contained piece.
What's here
NN/Spec/Core/Tensor/Factorizations.lean):choleskySpec(
A = L·Lᵀ, lower-triangularL, via a column fold with a strict-array@[implemented_by]so#evalstays fast), the triangular and Cholesky linearsolves, and
qrSpec(A = Q·Rby modified Gram–Schmidt) — over the readableFin n → Fin n → αrepresentation, withtoMatFn/ofMatFntensor bridges.NN/Proofs/Tensor/Basic/Factorizations*.lean):IsCholesky/IsQR;A = L·Lᵀunder SPD pivots;
A = Q·RwithQᵀ·Q = 1under full column rank, bridged toMathlib's
gramSchmidt.NN/Examples/Factorization/{Cholesky,QR}):#evalwitnesses, each apositive reconstruction / orthonormality check plus a negative control (indefinite
Afails Cholesky; rank-deficientAbreaks QR orthonormality), wrapped in#guard_msgs (drop info)so a regression still fails the build without polluting thelog.
Scope honesty
Everything here is an exact finite identity — no iteration, no sweep count, no
asymptotic limit. The only hypotheses are the genuine success conditions of the
algorithms (SPD pivots for Cholesky, full column rank for QR), and nothing is assumed
away. The iterative factorizations — whose convergence is captured by an a-posteriori
residual certificate, since Mathlib has no Jacobi convergence theory — are deliberately
kept out of this PR and into the follow-up.
sorry/admit/omega-free.Building it
Co-Authored-By: Claude Opus 4.8 (1M context) noreply@anthropic.com