Return-Path: X-Original-To: apmail-commons-commits-archive@minotaur.apache.org Delivered-To: apmail-commons-commits-archive@minotaur.apache.org Received: from mail.apache.org (hermes.apache.org [140.211.11.3]) by minotaur.apache.org (Postfix) with SMTP id 1C802DBA7 for ; Tue, 30 Oct 2012 00:29:52 +0000 (UTC) Received: (qmail 73486 invoked by uid 500); 30 Oct 2012 00:29:51 -0000 Delivered-To: apmail-commons-commits-archive@commons.apache.org Received: (qmail 73410 invoked by uid 500); 30 Oct 2012 00:29:51 -0000 Mailing-List: contact commits-help@commons.apache.org; run by ezmlm Precedence: bulk List-Help: List-Unsubscribe: List-Post: List-Id: Reply-To: dev@commons.apache.org Delivered-To: mailing list commits@commons.apache.org Received: (qmail 73402 invoked by uid 99); 30 Oct 2012 00:29:51 -0000 Received: from athena.apache.org (HELO athena.apache.org) (140.211.11.136) by apache.org (qpsmtpd/0.29) with ESMTP; Tue, 30 Oct 2012 00:29:51 +0000 X-ASF-Spam-Status: No, hits=-2000.0 required=5.0 tests=ALL_TRUSTED X-Spam-Check-By: apache.org Received: from [140.211.11.4] (HELO eris.apache.org) (140.211.11.4) by apache.org (qpsmtpd/0.29) with ESMTP; Tue, 30 Oct 2012 00:29:50 +0000 Received: from eris.apache.org (localhost [127.0.0.1]) by eris.apache.org (Postfix) with ESMTP id E61B923888FD for ; Tue, 30 Oct 2012 00:29:06 +0000 (UTC) Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit Subject: 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 Date: Tue, 30 Oct 2012 00:29:06 -0000 To: commits@commons.apache.org From: erans@apache.org X-Mailer: svnmailer-1.0.8-patched Message-Id: <20121030002906.E61B923888FD@eris.apache.org> X-Virus-Checked: Checked by ClamAV on apache.org 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 + + New "getSquareRoot" method in class "EigenDecomposition" (package + "o.a.c.m.linear"). + 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 × X = B solution in exact * linear sense. *

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 },