Author: tn
Date: Fri Oct 18 21:19:18 2013
New Revision: 1533638

URL: http://svn.apache.org/r1533638
Log:
[MATH-1004] Added new methods to compute the inverse of a matrix to 
DiagonalMatrix and MatrixUtils.

Modified:
    commons/proper/math/trunk/src/changes/changes.xml
    
commons/proper/math/trunk/src/main/java/org/apache/commons/math3/linear/DiagonalMatrix.java
    
commons/proper/math/trunk/src/main/java/org/apache/commons/math3/linear/MatrixUtils.java
    
commons/proper/math/trunk/src/test/java/org/apache/commons/math3/linear/DiagonalMatrixTest.java
    
commons/proper/math/trunk/src/test/java/org/apache/commons/math3/linear/MatrixUtilsTest.java

Modified: commons/proper/math/trunk/src/changes/changes.xml
URL: 
http://svn.apache.org/viewvc/commons/proper/math/trunk/src/changes/changes.xml?rev=1533638&r1=1533637&r2=1533638&view=diff
==============================================================================
--- commons/proper/math/trunk/src/changes/changes.xml (original)
+++ commons/proper/math/trunk/src/changes/changes.xml Fri Oct 18 21:19:18 2013
@@ -51,6 +51,10 @@ If the output is not quite correct, chec
   </properties>
   <body>
     <release version="x.y" date="TBD" description="TBD">
+      <action dev="tn" type="add" issue="MATH-1004" due-to="Ajo Fod">
+        Added new methods to compute the inverse of a matrix to 
"DiagonalMatrix"
+        and "MatrixUtils".
+      </action>
       <action dev="tn" type="fix" issue="MATH-1029">
         The "BigFraction" constructor will throw a 
"FractionConversionException"
         also in case negative values are provided which exceed the allowed 
range

Modified: 
commons/proper/math/trunk/src/main/java/org/apache/commons/math3/linear/DiagonalMatrix.java
URL: 
http://svn.apache.org/viewvc/commons/proper/math/trunk/src/main/java/org/apache/commons/math3/linear/DiagonalMatrix.java?rev=1533638&r1=1533637&r2=1533638&view=diff
==============================================================================
--- 
commons/proper/math/trunk/src/main/java/org/apache/commons/math3/linear/DiagonalMatrix.java
 (original)
+++ 
commons/proper/math/trunk/src/main/java/org/apache/commons/math3/linear/DiagonalMatrix.java
 Fri Oct 18 21:19:18 2013
@@ -319,4 +319,53 @@ public class DiagonalMatrix extends Abst
         }
     }
 
+    /**
+     * Computes the inverse of this diagonal matrix.
+     * <p>
+     * Note: this method will use a singularity threshold of 0,
+     * use {@link #inverse(double)} if a different threshold is needed.
+     *
+     * @return the inverse of {@code m}
+     * @throws SingularMatrixException if the matrix is singular
+     * @since 3.3
+     */
+    public DiagonalMatrix inverse() throws SingularMatrixException {
+        return inverse(0);
+    }
+
+    /**
+     * Computes the inverse of this diagonal matrix.
+     *
+     * @param threshold Singularity threshold.
+     * @return the inverse of {@code m}
+     * @throws SingularMatrixException if the matrix is singular
+     * @since 3.3
+     */
+    public DiagonalMatrix inverse(double threshold) throws 
SingularMatrixException {
+        if (isSingular(threshold)) {
+            throw new SingularMatrixException();
+        }
+
+        final double[] result = new double[data.length];
+        for (int i = 0; i < data.length; i++) {
+            result[i] = 1.0 / data[i];
+        }
+        return new DiagonalMatrix(result, false);
+    }
+
+    /** Returns whether this diagonal matrix is singular, i.e. any diagonal 
entry
+     * is equal to {@code 0} within the given threshold.
+     *
+     * @param threshold Singularity threshold.
+     * @return {@code true} if the matrix is singular, {@code false} otherwise
+     * @since 3.3
+     */
+    public boolean isSingular(double threshold) {
+        for (int i = 0; i < data.length; i++) {
+            if (Precision.equals(data[i], 0.0, threshold)) {
+                return true;
+            }
+        }
+        return false;
+    }
 }

Modified: 
commons/proper/math/trunk/src/main/java/org/apache/commons/math3/linear/MatrixUtils.java
URL: 
http://svn.apache.org/viewvc/commons/proper/math/trunk/src/main/java/org/apache/commons/math3/linear/MatrixUtils.java?rev=1533638&r1=1533637&r2=1533638&view=diff
==============================================================================
--- 
commons/proper/math/trunk/src/main/java/org/apache/commons/math3/linear/MatrixUtils.java
 (original)
+++ 
commons/proper/math/trunk/src/main/java/org/apache/commons/math3/linear/MatrixUtils.java
 Fri Oct 18 21:19:18 2013
@@ -36,6 +36,7 @@ import org.apache.commons.math3.fraction
 import org.apache.commons.math3.fraction.Fraction;
 import org.apache.commons.math3.util.FastMath;
 import org.apache.commons.math3.util.MathArrays;
+import org.apache.commons.math3.util.MathUtils;
 import org.apache.commons.math3.util.Precision;
 
 /**
@@ -1063,4 +1064,57 @@ public class MatrixUtils {
 
         return result;
     }
+
+    /**
+     * Computes the inverse of the given matrix.
+     * <p>
+     * By default, the inverse of the matrix is computed using the 
QR-decomposition,
+     * unless a more efficient method can be determined for the input matrix.
+     * <p>
+     * Note: this method will use a singularity threshold of 0,
+     * use {@link #inverse(RealMatrix, double)} if a different threshold is 
needed.
+     *
+     * @param matrix Matrix whose inverse shall be computed
+     * @return the inverse of {@code matrix}
+     * @throws NullArgumentException if {@code matrix} is {@code null}
+     * @throws SingularMatrixException if m is singular
+     * @throws NonSquareMatrixException if matrix is not square
+     * @since 3.3
+     */
+    public static RealMatrix inverse(RealMatrix matrix)
+            throws NullArgumentException, SingularMatrixException, 
NonSquareMatrixException {
+        return inverse(matrix, 0);
+    }
+
+    /**
+     * Computes the inverse of the given matrix.
+     * <p>
+     * By default, the inverse of the matrix is computed using the 
QR-decomposition,
+     * unless a more efficient method can be determined for the input matrix.
+     *
+     * @param matrix Matrix whose inverse shall be computed
+     * @param threshold Singularity threshold
+     * @return the inverse of {@code m}
+     * @throws NullArgumentException if {@code matrix} is {@code null}
+     * @throws SingularMatrixException if matrix is singular
+     * @throws NonSquareMatrixException if matrix is not square
+     * @since 3.3
+     */
+    public static RealMatrix inverse(RealMatrix matrix, double threshold)
+            throws NullArgumentException, SingularMatrixException, 
NonSquareMatrixException {
+
+        MathUtils.checkNotNull(matrix);
+
+        if (!matrix.isSquare()) {
+            throw new NonSquareMatrixException(matrix.getRowDimension(),
+                                               matrix.getColumnDimension());
+        }
+
+        if (matrix instanceof DiagonalMatrix) {
+            return ((DiagonalMatrix) matrix).inverse(threshold);
+        } else {
+            QRDecomposition decomposition = new QRDecomposition(matrix, 
threshold);
+            return decomposition.getSolver().getInverse();
+        }
+    }
 }

Modified: 
commons/proper/math/trunk/src/test/java/org/apache/commons/math3/linear/DiagonalMatrixTest.java
URL: 
http://svn.apache.org/viewvc/commons/proper/math/trunk/src/test/java/org/apache/commons/math3/linear/DiagonalMatrixTest.java?rev=1533638&r1=1533637&r2=1533638&view=diff
==============================================================================
--- 
commons/proper/math/trunk/src/test/java/org/apache/commons/math3/linear/DiagonalMatrixTest.java
 (original)
+++ 
commons/proper/math/trunk/src/test/java/org/apache/commons/math3/linear/DiagonalMatrixTest.java
 Fri Oct 18 21:19:18 2013
@@ -340,4 +340,29 @@ public class DiagonalMatrixTest {
         Assert.assertEquals( 6.0, diag.getEntry(2, 2), 1.0e-20);
     }
 
+    @Test(expected=SingularMatrixException.class)
+    public void testInverseError() {
+        final double[] data = { 1, 2, 0 };
+        final DiagonalMatrix diag = new DiagonalMatrix(data);
+        diag.inverse();
+    }
+
+    @Test(expected=SingularMatrixException.class)
+    public void testInverseError2() {
+        final double[] data = { 1, 2, 1e-6 };
+        final DiagonalMatrix diag = new DiagonalMatrix(data);
+        diag.inverse(1e-5);
+    }
+
+    @Test
+    public void testInverse() {
+        final double[] data = { 1, 2, 3 };
+        final DiagonalMatrix m = new DiagonalMatrix(data);
+        final DiagonalMatrix inverse = m.inverse();
+
+        final DiagonalMatrix result = m.multiply(inverse);
+        TestUtils.assertEquals("DiagonalMatrix.inverse() returns wrong result",
+                MatrixUtils.createRealIdentityMatrix(data.length), result, 
Math.ulp(1d));
+    }
+
 }

Modified: 
commons/proper/math/trunk/src/test/java/org/apache/commons/math3/linear/MatrixUtilsTest.java
URL: 
http://svn.apache.org/viewvc/commons/proper/math/trunk/src/test/java/org/apache/commons/math3/linear/MatrixUtilsTest.java?rev=1533638&r1=1533637&r2=1533638&view=diff
==============================================================================
--- 
commons/proper/math/trunk/src/test/java/org/apache/commons/math3/linear/MatrixUtilsTest.java
 (original)
+++ 
commons/proper/math/trunk/src/test/java/org/apache/commons/math3/linear/MatrixUtilsTest.java
 Fri Oct 18 21:19:18 2013
@@ -17,6 +17,7 @@
 package org.apache.commons.math3.linear;
 
 import java.math.BigDecimal;
+
 import org.apache.commons.math3.TestUtils;
 import org.apache.commons.math3.fraction.BigFraction;
 import org.apache.commons.math3.fraction.Fraction;
@@ -37,6 +38,8 @@ import org.junit.Test;
 public final class MatrixUtilsTest {
 
     protected double[][] testData = { {1d,2d,3d}, {2d,5d,3d}, {1d,0d,8d} };
+    protected double[][] testData3x3Singular = { { 1, 4, 7, }, { 2, 5, 8, }, { 
3, 6, 9, } };
+    protected double[][] testData3x4 = { { 12, -51, 4, 1 }, { 6, 167, -68, 2 
}, { -4, 24, -41, 3 } };
     protected double[][] nullMatrix = null;
     protected double[] row = {1,2,3};
     protected BigDecimal[] bigRow =
@@ -445,4 +448,38 @@ public final class MatrixUtilsTest {
         };
         MatrixUtils.checkSymmetric(MatrixUtils.createRealMatrix(dataNonSym), 
Math.ulp(1d));
     }
+    
+    @Test(expected=SingularMatrixException.class)
+    public void testInverseSingular() {
+        RealMatrix m = MatrixUtils.createRealMatrix(testData3x3Singular);
+        MatrixUtils.inverse(m);
+    }
+    
+    @Test(expected=NonSquareMatrixException.class)
+    public void testInverseNonSquare() {
+        RealMatrix m = MatrixUtils.createRealMatrix(testData3x4);
+        MatrixUtils.inverse(m);
+    }
+    
+    @Test
+    public void testInverseDiagonalMatrix() {
+        final double[] data = { 1, 2, 3 };
+        final RealMatrix m = new DiagonalMatrix(data);
+        final RealMatrix inverse = MatrixUtils.inverse(m);
+
+        final RealMatrix result = m.multiply(inverse);
+        TestUtils.assertEquals("MatrixUtils.inverse() returns wrong result",
+                MatrixUtils.createRealIdentityMatrix(data.length), result, 
Math.ulp(1d));
+    }
+
+    @Test
+    public void testInverseRealMatrix() {
+        RealMatrix m = MatrixUtils.createRealMatrix(testData);
+        final RealMatrix inverse = MatrixUtils.inverse(m);
+
+        final RealMatrix result = m.multiply(inverse);
+        TestUtils.assertEquals("MatrixUtils.inverse() returns wrong result",
+                MatrixUtils.createRealIdentityMatrix(testData.length), result, 
1e-12);
+    }
+
 }


Reply via email to