You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@commons.apache.org by tn...@apache.org on 2013/10/18 23:19:18 UTC
svn commit: r1533638 - in /commons/proper/math/trunk/src: changes/
main/java/org/apache/commons/math3/linear/
test/java/org/apache/commons/math3/linear/
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);
+ }
+
}