You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@commons.apache.org by er...@apache.org on 2012/10/30 01:29:06 UTC

svn commit: r1403590 - in /commons/proper/math/trunk/src: changes/changes.xml main/java/org/apache/commons/math3/linear/EigenDecomposition.java test/java/org/apache/commons/math3/linear/EigenDecompositionTest.java

Author: erans
Date: Tue Oct 30 00:29:06 2012
New Revision: 1403590

URL: http://svn.apache.org/viewvc?rev=1403590&view=rev
Log:
MATH-883
Added "getSquareRoot()" method. Implementation only supports symmetric,
diagonalizable matrices.

Modified:
    commons/proper/math/trunk/src/changes/changes.xml
    commons/proper/math/trunk/src/main/java/org/apache/commons/math3/linear/EigenDecomposition.java
    commons/proper/math/trunk/src/test/java/org/apache/commons/math3/linear/EigenDecompositionTest.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=1403590&r1=1403589&r2=1403590&view=diff
==============================================================================
--- commons/proper/math/trunk/src/changes/changes.xml (original)
+++ commons/proper/math/trunk/src/changes/changes.xml Tue Oct 30 00:29:06 2012
@@ -52,6 +52,10 @@ If the output is not quite correct, chec
   <body>
     <release version="3.1" date="TBD" description="
 ">
+      <action dev="erans" type="add" issue="MATH-883">
+        New "getSquareRoot" method in class "EigenDecomposition" (package
+        "o.a.c.m.linear").
+      </action>
       <action dev="erans" type="update" issue="MATH-884">
         Added "isSymmetric" and "checkSymmetric" in "MatrixUtils" (package
         "o.a.c.m.linear").

Modified: commons/proper/math/trunk/src/main/java/org/apache/commons/math3/linear/EigenDecomposition.java
URL: http://svn.apache.org/viewvc/commons/proper/math/trunk/src/main/java/org/apache/commons/math3/linear/EigenDecomposition.java?rev=1403590&r1=1403589&r2=1403590&view=diff
==============================================================================
--- commons/proper/math/trunk/src/main/java/org/apache/commons/math3/linear/EigenDecomposition.java (original)
+++ commons/proper/math/trunk/src/main/java/org/apache/commons/math3/linear/EigenDecomposition.java Tue Oct 30 00:29:06 2012
@@ -100,6 +100,8 @@ public class EigenDecomposition {
     private RealMatrix cachedD;
     /** Cached value of Vt. */
     private RealMatrix cachedVt;
+    /** Whether the matrix is symmetric. */
+    private final boolean isSymmetric;
 
     /**
      * Calculates the eigen decomposition of the given real matrix.
@@ -113,7 +115,8 @@ public class EigenDecomposition {
      */
     public EigenDecomposition(final RealMatrix matrix)
         throws MathArithmeticException {
-        if (isSymmetric(matrix, false)) {
+        isSymmetric = isSymmetric(matrix, false);
+        if (isSymmetric) {
             transformToTridiagonal(matrix);
             findEigenVectors(transformer.getQ().getData());
         } else {
@@ -149,6 +152,7 @@ public class EigenDecomposition {
      * @throws MaxCountExceededException if the algorithm fails to converge.
      */
     public EigenDecomposition(final double[] main, final double[] secondary) {
+        isSymmetric = true;
         this.main      = main.clone();
         this.secondary = secondary.clone();
         transformer    = null;
@@ -386,6 +390,35 @@ public class EigenDecomposition {
     }
 
     /**
+     * Computes the square-root of the matrix.
+     * This implementation assumes that the matrix is symmetric and postive
+     * definite.
+     *
+     * @return the square-root of the matrix.
+     * @throws MathUnsupportedOperationException if the matrix is not
+     * symmetric or not positive definite.
+     */
+    public RealMatrix getSquareRoot() {
+        if (!isSymmetric) {
+            throw new MathUnsupportedOperationException();
+        }
+
+        final double[] sqrtEigenValues = new double[realEigenvalues.length];
+        for (int i = 0; i < realEigenvalues.length; i++) {
+            final double eigen = realEigenvalues[i];
+            if (eigen <= 0) {
+                throw new MathUnsupportedOperationException();
+            }
+            sqrtEigenValues[i] = FastMath.sqrt(eigen);
+        }
+        final RealMatrix sqrtEigen = MatrixUtils.createRealDiagonalMatrix(sqrtEigenValues);
+        final RealMatrix v = getV();
+        final RealMatrix vT = getVT();
+
+        return v.multiply(sqrtEigen).multiply(vT);
+    }
+
+    /**
      * Gets a solver for finding the A &times; X = B solution in exact
      * linear sense.
      * <p>

Modified: commons/proper/math/trunk/src/test/java/org/apache/commons/math3/linear/EigenDecompositionTest.java
URL: http://svn.apache.org/viewvc/commons/proper/math/trunk/src/test/java/org/apache/commons/math3/linear/EigenDecompositionTest.java?rev=1403590&r1=1403589&r2=1403590&view=diff
==============================================================================
--- commons/proper/math/trunk/src/test/java/org/apache/commons/math3/linear/EigenDecompositionTest.java (original)
+++ commons/proper/math/trunk/src/test/java/org/apache/commons/math3/linear/EigenDecompositionTest.java Tue Oct 30 00:29:06 2012
@@ -24,6 +24,7 @@ import java.util.Random;
 import org.apache.commons.math3.distribution.NormalDistribution;
 import org.apache.commons.math3.util.FastMath;
 import org.apache.commons.math3.util.Precision;
+import org.apache.commons.math3.exception.MathUnsupportedOperationException;
 import org.junit.After;
 import org.junit.Assert;
 import org.junit.Before;
@@ -337,6 +338,53 @@ public class EigenDecompositionTest {
     }
 
     @Test
+    public void testSquareRoot() {
+        final double[][] data = {
+            { 33, 24,  7 },
+            { 24, 57, 11 },
+            {  7, 11,  9 }
+        };
+
+        final EigenDecomposition dec = new EigenDecomposition(MatrixUtils.createRealMatrix(data));
+        final RealMatrix sqrtM = dec.getSquareRoot();
+
+        // Reconstruct initial matrix.
+        final RealMatrix m = sqrtM.multiply(sqrtM);
+
+        final int dim = data.length;
+        for (int r = 0; r < dim; r++) {
+            for (int c = 0; c < dim; c++) {
+                Assert.assertEquals("m[" + r + "][" + c + "]",
+                                    data[r][c], m.getEntry(r, c), 1e-13);
+            }
+        }
+    }
+
+    @Test(expected=MathUnsupportedOperationException.class)
+    public void testSquareRootNonSymmetric() {
+        final double[][] data = {
+            { 1,  2, 4 },
+            { 2,  3, 5 },
+            { 11, 5, 9 }
+        };
+
+        final EigenDecomposition dec = new EigenDecomposition(MatrixUtils.createRealMatrix(data));
+        final RealMatrix sqrtM = dec.getSquareRoot();
+    }
+
+    @Test(expected=MathUnsupportedOperationException.class)
+    public void testSquareRootNonPositiveDefinite() {
+        final double[][] data = {
+            { 1, 2,  4 },
+            { 2, 3,  5 },
+            { 4, 5, -9 }
+        };
+
+        final EigenDecomposition dec = new EigenDecomposition(MatrixUtils.createRealMatrix(data));
+        final RealMatrix sqrtM = dec.getSquareRoot();
+    }
+
+    @Test
     public void testUnsymmetric() {
         // Vandermonde matrix V(x;i,j) = x_i^{n - j} with x = (-1,-2,3,4)
         double[][] vData = { { -1.0, 1.0, -1.0, 1.0 },