This is quite efficient (probably much faster than SVD or QR), but is terrible for other reasons:
- The determinant will rarely be exactly zero because roundoff errors make it difficult to distinguish singular from near-singular matrices.
- In consequence of (1), for a near-singular matrix, you want to check that the determinant is small rather than zero, but small compared to what? (See below.)
- Determinants of large matrices can easily overflow the largest representable floating-point value (though you can use
logabsdet
to avoid this). - Computing A^\dagger A = \overline{A^T} A (also denoted A^* A) squares the condition number of A and exacerbates roundoff errors. SVD and QR methods (below) avoid computing this matrix explicitly.
Right, but be careful — you should check for small singular values compared to the largest singular value. (There is no such thing as “small” in an absolute sense — it’s always important to ask “small compared to what?”)
Of course, comparing the smallest singular value to the largest singular value is the same as computing the condition number of the matrix, which you can do with cond
. If cond(A)
is \gg 1 then the matrix is close to rank-deficient.
(Alternatively, you can call the rank
function, which counts the number of singular values that are not too small compared to the largest one, but if you just want to check that it is full rank I would simply look at the condition number.)
(Both cond
and rank
use the SVD.)
Yes, Julia has pivoted QR, and you can use this to estimate the rank, though in principle the SVD-based methods are more reliable. See How to find the linearly independent columns (rows) of a matrix - #14 by stevengj and rank(::QRPivoted) method? · Issue #53214 · JuliaLang/julia · GitHub.
You could also use QR to compute the condition number, since if A = QR then \mathrm{cond}(A) = \mathrm{cond}(R) in exact arithmetic, and cond(qr(A, ColumnNorm()).R)
should be faster than cond(A)
(via the SVD) for a very “tall” matrix.