Define lq for sparse matrices as the adjoint of the sparse QR of the adjoint - #833
Merged
Merged
Conversation
…adjoint `lq(A)` returns `qr(A')'`, an `AdjointQRSparse`, with `L`, `Q`, `prow` and `pcol` properties so that `A[F.prow, F.pcol] == F.L * F.Q`, and `F \ b` gives the minimum-norm solution through the adjoint solve. `qr` also accepts adjoint and transpose wrappers directly. The padded Q products keyed the thin width on the number of stored reflectors, which SPQR keeps below the column count for sparse enough matrices; it now comes from the column count. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Codecov Report❌ Patch coverage is
Additional details and impacted files@@ Coverage Diff @@
## main #833 +/- ##
==========================================
+ Coverage 92.56% 92.60% +0.04%
==========================================
Files 12 12
Lines 8699 8723 +24
==========================================
+ Hits 8052 8078 +26
+ Misses 647 645 -2 ☔ View full report in Codecov by Harness. 🚀 New features to boost your workflow:
|
ViralBShah
added this pull request to stack #834
September 17, 2026 21:37
ViralBShah
added a commit
that referenced
this pull request
Sep 17, 2026
#831) Fixes #301. Stacked on #833, which adds the sparse `lq`. `A \ b` for a wide sparse `A` returned a basic solution, while dense `\` returns the minimum-norm one: ```julia julia> A = sparse([1.0 0 1 0; 0 1 0 1]); b = [1.0, 2.0]; julia> A \ b 4-element Vector{Float64}: 1.0 2.0 0.0 0.0 julia> Matrix(A) \ b 4-element Vector{Float64}: 0.5 1.0 0.5 1.0 ``` The wide branch of `\` called `qr(A) \ B`, which SPQR solves by back-substituting with the leading `rank` columns of `R`. It now calls `lq(A) \ B`, the minimum-norm solve through the adjoint of the QR factorization of `A'` from #804, as the `Adjoint`/`Transpose` methods already do for a tall parent. `factorize(A)` returns `lq(A)` for a wide `A`, so `factorize(A) \ b == A \ b`. `qr(A) \ b` still returns the basic solution and its docstring says so. Tests added next to the existing underdetermined check in the SPQR `\` testset; `spqr`, `linalg`, `linalg_solvers`, whitespace and the doctests pass on 1.14-DEV. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-authored-by: Claude Fable 5.1 <noreply@anthropic.com>
ViralBShah
added a commit
that referenced
this pull request
Sep 19, 2026
…841) The solvers page listed the factorizations and their docstrings but had no narrative. This adds a section covering what `A \ b` and `factorize` dispatch to (substitution, `cholesky` with its fallback, `lu`, `qr`, and `lq` for the minimum-norm solution of wide systems), reusing and refactorizing a factorization (`F \ B`, `ldiv!`, `lu!`/`cholesky!`/`ldlt!`), extracting factors with the permuted identities they satisfy, and the symmetric-input and `check = false`/`issuccess` rules. The material comes from reading `\` and `factorize` in `src/linalg.jl`, the Hermitian `\` in `src/solvers/cholmod.jl`, the `lu`/`cholesky`/`qr`/`lq` docstrings, and #830, #831, #833, #835. One thing the text makes explicit: for a Hermitian matrix that is not positive definite, `\` falls back to `lu` while `factorize` falls back to `ldlt`. Every example is a doctest printing only `true`/`false`; the Documenter build and doctests pass on nightly with no new warnings. Docs only; tuning keywords and threading are left to a separate PR. The insertion sits directly above the `@docs` line that #838 edits, so whichever merges second will need a trivial rebase. 🤖 Generated with [Claude Code](https://claude.com/claude-code) --------- Co-authored-by: Viral B. Shah <ViralBShah@users.noreply.github.com> Co-authored-by: Claude Fable 5.1 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Fixes #114.
lq(A)now returnsqr(A')', theAdjointQRSparsefrom #804, computed by SPQR on the sparse transpose, withtolandorderingpassed through. It getsL,Q,prowandpcolproperties so thatA[F.prow, F.pcol] == F.L * F.Q, withF.La lower triangularSparseMatrixCSCandF.Qthe adjoint of the sparseQ;F \ bis the minimum-norm solution for a wideAand throwsDimensionMismatchfor a tall one, as denselqdoes;F'isqr(A'),lq(A')reusesqr(A)without a copy, andrankandshowwork.qralso accepts adjoint and transpose wrappers of aSparseMatrixCSCdirectly, and the\for a tallA'uses that instead of spelling the copy. The identityF.L * F.Qexposed a bug in the padded products with a sparseQ: they took the thin width from the number of stored Householder vectors, which SPQR keeps below the column count when the matrix is sparse enough, soqr(A).Q * qr(A).RthrewDimensionMismatchfor such anA. The width now comes from the column count thatQRSparseQrecords.Tests in
test/spqr.jlcover the factorization identity, properties, solves, tolerance, the tall error, the adjoint and transpose inputs and the thin product regression, for real and complex eltypes and both index types;spqr,linalg, Aqua, whitespace and the doctests pass on 1.14-DEV.docs/src/solvers.mdlistslq. #831 will uselqfor the wide\.🤖 Generated with Claude Code