diff --git a/src/changes/changes.xml b/src/changes/changes.xml index 47e68ec73..3b6593e01 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! + + QR decomposition can compute pseudo-inverses for tall matrices. + Field vectors now implement the visitor pattern just like real vectors. 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 a3f3c6e12..9c3480afc 100644 --- a/src/main/java/org/apache/commons/math3/linear/QRDecomposition.java +++ b/src/main/java/org/apache/commons/math3/linear/QRDecomposition.java @@ -463,7 +463,7 @@ public class QRDecomposition { * @throws SingularMatrixException if the decomposed matrix is singular. */ public RealMatrix getInverse() { - return solve(MatrixUtils.createRealIdentityMatrix(rDiag.length)); + return solve(MatrixUtils.createRealIdentityMatrix(qrt[0].length)); } } } 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 a458e5274..1b780cc20 100644 --- a/src/test/java/org/apache/commons/math3/linear/QRDecompositionTest.java +++ b/src/test/java/org/apache/commons/math3/linear/QRDecompositionTest.java @@ -248,6 +248,21 @@ public class QRDecompositionTest { qr.getSolver().getInverse(); } + @Test + public void testInvertTallSkinny() { + RealMatrix a = MatrixUtils.createRealMatrix(testData4x3); + RealMatrix pinv = new QRDecomposition(a).getSolver().getInverse(); + Assert.assertEquals(0, pinv.multiply(a).subtract(MatrixUtils.createRealIdentityMatrix(3)).getNorm(), 1.0e-6); + } + + @Test + public void testInvertShortWide() { + RealMatrix a = MatrixUtils.createRealMatrix(testData3x4); + RealMatrix pinv = new QRDecomposition(a).getSolver().getInverse(); + Assert.assertEquals(0, a.multiply(pinv).subtract(MatrixUtils.createRealIdentityMatrix(3)).getNorm(), 1.0e-6); + Assert.assertEquals(0, pinv.multiply(a).getSubMatrix(0, 2, 0, 2).subtract(MatrixUtils.createRealIdentityMatrix(3)).getNorm(), 1.0e-6); + } + private RealMatrix createTestMatrix(final Random r, final int rows, final int columns) { RealMatrix m = MatrixUtils.createRealMatrix(rows, columns); m.walkInOptimizedOrder(new DefaultRealMatrixChangingVisitor(){