From 927361d78782a836d5c3d09687c8930012d2c0ab Mon Sep 17 00:00:00 2001 From: Luc Maisonobe Date: Fri, 21 Feb 2014 13:18:35 +0000 Subject: [PATCH] QR decomposition can compute pseudo-inverses for tall matrices. Thanks to Sean Owen for the patch. JIRA: MATH-1053 git-svn-id: https://svn.apache.org/repos/asf/commons/proper/math/trunk@1570566 13f79535-47bb-0310-9956-ffa450edef68 --- src/changes/changes.xml | 3 +++ .../commons/math3/linear/QRDecomposition.java | 2 +- .../commons/math3/linear/QRDecompositionTest.java | 15 +++++++++++++++ 3 files changed, 19 insertions(+), 1 deletion(-) 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(){