diff --git a/src/changes/changes.xml b/src/changes/changes.xml index 3b6593e01..5f4f53cb1 100644 --- a/src/changes/changes.xml +++ b/src/changes/changes.xml @@ -51,6 +51,9 @@ If the output is not quite correct, check for invisible trailing spaces! + + Improved documentation of QR decomposition handling of singular matrices. + QR decomposition can compute pseudo-inverses for tall matrices. diff --git a/src/main/java/org/apache/commons/math3/linear/QRDecomposition.java b/src/main/java/org/apache/commons/math3/linear/QRDecomposition.java index 9c3480afc..112a43fe2 100644 --- a/src/main/java/org/apache/commons/math3/linear/QRDecomposition.java +++ b/src/main/java/org/apache/commons/math3/linear/QRDecomposition.java @@ -291,6 +291,14 @@ public class QRDecomposition { /** * Get a solver for finding the A × X = B solution in least square sense. + *

+ * Least Square sense means a solver can be computed for an overdetermined system, + * (i.e. a system with more equations than unknowns, which corresponds to a tall A + * matrix with more rows than columns). In any case, if the matrix is singular + * within the tolerance set at {@link QRDecomposition#QRDecomposition(RealMatrix, + * double) construction}, an error will be triggered when + * the {@link DecompositionSolver#solve(RealVector) solve} method will be called. + *

* @return a solver */ public DecompositionSolver getSolver() { diff --git a/src/main/java/org/apache/commons/math3/linear/RRQRDecomposition.java b/src/main/java/org/apache/commons/math3/linear/RRQRDecomposition.java index ecff6cb29..acd5b0443 100644 --- a/src/main/java/org/apache/commons/math3/linear/RRQRDecomposition.java +++ b/src/main/java/org/apache/commons/math3/linear/RRQRDecomposition.java @@ -184,6 +184,14 @@ public class RRQRDecomposition extends QRDecomposition { /** * Get a solver for finding the A × X = B solution in least square sense. + *

+ * Least Square sense means a solver can be computed for an overdetermined system, + * (i.e. a system with more equations than unknowns, which corresponds to a tall A + * matrix with more rows than columns). In any case, if the matrix is singular + * within the tolerance set at {@link RRQRDecomposition#RRQRDecomposition(RealMatrix, + * double) construction}, an error will be triggered when + * the {@link DecompositionSolver#solve(RealVector) solve} method will be called. + *

* @return a solver */ @Override diff --git a/src/site/xdoc/userguide/linear.xml b/src/site/xdoc/userguide/linear.xml index d219173ca..fc767d061 100644 --- a/src/site/xdoc/userguide/linear.xml +++ b/src/site/xdoc/userguide/linear.xml @@ -144,10 +144,16 @@ RealVector solution = solver.solve(constants); Each type of decomposition has its specific semantics and constraints on the coefficient matrix as shown in the following table. For algorithms that solve AX=B in least squares sense the value returned for X is such that the - residual AX-B has minimal norm. If an exact solution exist (i.e. if for some - X the residual AX-B is exactly 0), then this exact solution is also the solution - in least square sense. This implies that algorithms suited for least squares - problems can also be used to solve exact problems, but the reverse is not true. + residual AX-B has minimal norm. Least Square sense means a solver can be computed + for an overdetermined system, (i.e. a system with more equations than unknowns, + which corresponds to a tall A matrix with more rows than columns). If an exact + solution exist (i.e. if for some X the residual AX-B is exactly 0), then this + exact solution is also the solution in least square sense. This implies that + algorithms suited for least squares problems can also be used to solve exact + problems, but the reverse is not true. In any case, if the matrix is singular + within the tolerance set at construction, an error will be triggered when + the solve method will be called, both for algorithms that compute exact solutions + and for algorithms that compute least square solutions.

diff --git a/src/test/java/org/apache/commons/math3/linear/QRDecompositionTest.java b/src/test/java/org/apache/commons/math3/linear/QRDecompositionTest.java index 1b780cc20..a2d93f7bb 100644 --- a/src/test/java/org/apache/commons/math3/linear/QRDecompositionTest.java +++ b/src/test/java/org/apache/commons/math3/linear/QRDecompositionTest.java @@ -273,5 +273,14 @@ public class QRDecompositionTest { }); return m; } + + @Test(expected=SingularMatrixException.class) + public void testQRSingular() { + final RealMatrix a = MatrixUtils.createRealMatrix(new double[][] { + { 1, 6, 4 }, { 2, 4, -1 }, { -1, 2, 5 } + }); + final RealVector b = new ArrayRealVector(new double[]{ 5, 6, 1 }); + new QRDecomposition(a, 1.0e-15).getSolver().solve(b); + } }