Author: celestin
Date: Sat Sep 24 05:13:53 2011
New Revision: 1175108

URL: http://svn.apache.org/viewvc?rev=1175108&view=rev
Log:
Merged SingularValueDecomposition and SingularValueDecompositionImpl (see 
MATH-662).

Added:
    
commons/proper/math/trunk/src/main/java/org/apache/commons/math/linear/SingularValueDecomposition.java
      - copied, changed from r1175099, 
commons/proper/math/trunk/src/main/java/org/apache/commons/math/linear/SingularValueDecompositionImpl.java
    
commons/proper/math/trunk/src/test/java/org/apache/commons/math/linear/SingularValueDecompositionTest.java
      - copied, changed from r1175099, 
commons/proper/math/trunk/src/test/java/org/apache/commons/math/linear/SingularValueDecompositionImplTest.java
Removed:
    
commons/proper/math/trunk/src/main/java/org/apache/commons/math/linear/SingularValueDecompositionImpl.java
    
commons/proper/math/trunk/src/test/java/org/apache/commons/math/linear/SingularValueDecompositionImplTest.java
Modified:
    
commons/proper/math/trunk/src/test/java/org/apache/commons/math/linear/SingularValueSolverTest.java

Copied: 
commons/proper/math/trunk/src/main/java/org/apache/commons/math/linear/SingularValueDecomposition.java
 (from r1175099, 
commons/proper/math/trunk/src/main/java/org/apache/commons/math/linear/SingularValueDecompositionImpl.java)
URL: 
http://svn.apache.org/viewvc/commons/proper/math/trunk/src/main/java/org/apache/commons/math/linear/SingularValueDecomposition.java?p2=commons/proper/math/trunk/src/main/java/org/apache/commons/math/linear/SingularValueDecomposition.java&p1=commons/proper/math/trunk/src/main/java/org/apache/commons/math/linear/SingularValueDecompositionImpl.java&r1=1175099&r2=1175108&rev=1175108&view=diff
==============================================================================
--- 
commons/proper/math/trunk/src/main/java/org/apache/commons/math/linear/SingularValueDecompositionImpl.java
 (original)
+++ 
commons/proper/math/trunk/src/main/java/org/apache/commons/math/linear/SingularValueDecomposition.java
 Sat Sep 24 05:13:53 2011
@@ -31,10 +31,27 @@ import org.apache.commons.math.util.Math
  * n orthogonal matrix (hence V<sup>T</sup> is also orthogonal) where
  * p=min(m,n).
  * </p>
+ * <p>This class is similar to the class with similar name from the
+ * <a href="http://math.nist.gov/javanumerics/jama/";>JAMA</a> library, with the
+ * following changes:</p>
+ * <ul>
+ *   <li>the {@code norm2} method which has been renamed as {@link #getNorm()
+ *   getNorm},</li>
+ *   <li>the {@code cond} method which has been renamed as {@link
+ *   #getConditionNumber() getConditionNumber},</li>
+ *   <li>the {@code rank} method which has been renamed as {@link #getRank()
+ *   getRank},</li>
+ *   <li>a {@link #getUT() getUT} method has been added,</li>
+ *   <li>a {@link #getVT() getVT} method has been added,</li>
+ *   <li>a {@link #getSolver() getSolver} method has been added,</li>
+ *   <li>a {@link #getCovariance(double) getCovariance} method has been 
added.</li>
+ * </ul>
+ * @see <a 
href="http://mathworld.wolfram.com/SingularValueDecomposition.html";>MathWorld</a>
+ * @see <a 
href="http://en.wikipedia.org/wiki/Singular_value_decomposition";>Wikipedia</a>
  * @version $Id$
- * @since 2.0
+ * @since 2.0 (changed to concrete class in 3.0)
  */
-public class SingularValueDecompositionImpl implements 
SingularValueDecomposition {
+public class SingularValueDecomposition {
     /** Relative threshold for small singular values. */
     private static final double EPS = 0x1.0p-52;
     /** Absolute threshold for small singular values. */
@@ -68,7 +85,7 @@ public class SingularValueDecompositionI
      *
      * @param matrix Matrix to decompose.
      */
-    public SingularValueDecompositionImpl(final RealMatrix matrix) {
+    public SingularValueDecomposition(final RealMatrix matrix) {
         final double[][] A;
 
          // "m" is always the largest dimension.
@@ -459,14 +476,24 @@ public class SingularValueDecompositionI
         }
     }
 
-    /** {@inheritDoc} */
+    /**
+     * Returns the matrix U of the decomposition.
+     * <p>U is an orthogonal matrix, i.e. its transpose is also its 
inverse.</p>
+     * @return the U matrix
+     * @see #getUT()
+     */
     public RealMatrix getU() {
         // return the cached matrix
         return cachedU;
 
     }
 
-    /** {@inheritDoc} */
+    /**
+     * Returns the transpose of the matrix U of the decomposition.
+     * <p>U is an orthogonal matrix, i.e. its transpose is also its 
inverse.</p>
+     * @return the U matrix (or null if decomposed matrix is singular)
+     * @see #getU()
+     */
     public RealMatrix getUT() {
         if (cachedUt == null) {
             cachedUt = getU().transpose();
@@ -475,7 +502,12 @@ public class SingularValueDecompositionI
         return cachedUt;
     }
 
-    /** {@inheritDoc} */
+    /**
+     * Returns the diagonal matrix &Sigma; of the decomposition.
+     * <p>&Sigma; is a diagonal matrix. The singular values are provided in
+     * non-increasing order, for compatibility with Jama.</p>
+     * @return the &Sigma; matrix
+     */
     public RealMatrix getS() {
         if (cachedS == null) {
             // cache the matrix for subsequent calls
@@ -484,18 +516,33 @@ public class SingularValueDecompositionI
         return cachedS;
     }
 
-    /** {@inheritDoc} */
+    /**
+     * Returns the diagonal elements of the matrix &Sigma; of the 
decomposition.
+     * <p>The singular values are provided in non-increasing order, for
+     * compatibility with Jama.</p>
+     * @return the diagonal elements of the &Sigma; matrix
+     */
     public double[] getSingularValues() {
         return singularValues.clone();
     }
 
-    /** {@inheritDoc} */
+    /**
+     * Returns the matrix V of the decomposition.
+     * <p>V is an orthogonal matrix, i.e. its transpose is also its 
inverse.</p>
+     * @return the V matrix (or null if decomposed matrix is singular)
+     * @see #getVT()
+     */
     public RealMatrix getV() {
         // return the cached matrix
         return cachedV;
     }
 
-    /** {@inheritDoc} */
+    /**
+     * Returns the transpose of the matrix V of the decomposition.
+     * <p>V is an orthogonal matrix, i.e. its transpose is also its 
inverse.</p>
+     * @return the V matrix (or null if decomposed matrix is singular)
+     * @see #getV()
+     */
     public RealMatrix getVT() {
         if (cachedVt == null) {
             cachedVt = getV().transpose();
@@ -504,7 +551,17 @@ public class SingularValueDecompositionI
         return cachedVt;
     }
 
-    /** {@inheritDoc} */
+    /**
+     * Returns the n &times; n covariance matrix.
+     * <p>The covariance matrix is V &times; J &times; V<sup>T</sup>
+     * where J is the diagonal matrix of the inverse of the squares of
+     * the singular values.</p>
+     * @param minSingularValue value below which singular values are ignored
+     * (a 0 or negative value implies all singular value will be used)
+     * @return covariance matrix
+     * @exception IllegalArgumentException if minSingularValue is larger than
+     * the largest singular value, meaning all singular values are ignored
+     */
     public RealMatrix getCovariance(final double minSingularValue) {
         // get the number of singular values to consider
         final int p = singularValues.length;
@@ -533,12 +590,21 @@ public class SingularValueDecompositionI
         return jv.transpose().multiply(jv);
     }
 
-    /** {@inheritDoc} */
+    /**
+     * Returns the L<sub>2</sub> norm of the matrix.
+     * <p>The L<sub>2</sub> norm is max(|A &times; u|<sub>2</sub> /
+     * |u|<sub>2</sub>), where |.|<sub>2</sub> denotes the vectorial 2-norm
+     * (i.e. the traditional euclidian norm).</p>
+     * @return norm
+     */
     public double getNorm() {
         return singularValues[0];
     }
 
-    /** {@inheritDoc} */
+    /**
+     * Return the condition number of the matrix.
+     * @return condition number of the matrix
+     */
     public double getConditionNumber() {
         return singularValues[0] / singularValues[n - 1];
     }
@@ -554,7 +620,14 @@ public class SingularValueDecompositionI
         return singularValues[n - 1] / singularValues[0];
     }
 
-    /** {@inheritDoc} */
+    /**
+     * Return the effective numerical matrix rank.
+     * <p>The effective numerical rank is the number of non-negligible
+     * singular values. The threshold used to identify non-negligible
+     * terms is max(m,n) &times; ulp(s<sub>1</sub>) where ulp(s<sub>1</sub>)
+     * is the least significant bit of the largest singular value.</p>
+     * @return effective numerical matrix rank
+     */
     public int getRank() {
         int r = 0;
         for (int i = 0; i < singularValues.length; i++) {
@@ -565,7 +638,10 @@ public class SingularValueDecompositionI
         return r;
     }
 
-    /** {@inheritDoc} */
+    /**
+     * Get a solver for finding the A &times; X = B solution in least square 
sense.
+     * @return a solver
+     */
     public DecompositionSolver getSolver() {
         return new Solver(singularValues, getUT(), getV(), getRank() == m, 
tol);
     }

Copied: 
commons/proper/math/trunk/src/test/java/org/apache/commons/math/linear/SingularValueDecompositionTest.java
 (from r1175099, 
commons/proper/math/trunk/src/test/java/org/apache/commons/math/linear/SingularValueDecompositionImplTest.java)
URL: 
http://svn.apache.org/viewvc/commons/proper/math/trunk/src/test/java/org/apache/commons/math/linear/SingularValueDecompositionTest.java?p2=commons/proper/math/trunk/src/test/java/org/apache/commons/math/linear/SingularValueDecompositionTest.java&p1=commons/proper/math/trunk/src/test/java/org/apache/commons/math/linear/SingularValueDecompositionImplTest.java&r1=1175099&r2=1175108&rev=1175108&view=diff
==============================================================================
--- 
commons/proper/math/trunk/src/test/java/org/apache/commons/math/linear/SingularValueDecompositionImplTest.java
 (original)
+++ 
commons/proper/math/trunk/src/test/java/org/apache/commons/math/linear/SingularValueDecompositionTest.java
 Sat Sep 24 05:13:53 2011
@@ -27,7 +27,7 @@ import org.junit.Assert;
 import org.junit.Test;
 
 
-public class SingularValueDecompositionImplTest {
+public class SingularValueDecompositionTest {
 
     private double[][] testSquare = {
             { 24.0 / 25.0, 43.0 / 25.0 },
@@ -50,7 +50,7 @@ public class SingularValueDecompositionI
         final int columns = singularValues.length;
         Random r = new Random(15338437322523l);
         SingularValueDecomposition svd =
-            new SingularValueDecompositionImpl(createTestMatrix(r, rows, 
columns, singularValues));
+            new SingularValueDecomposition(createTestMatrix(r, rows, columns, 
singularValues));
         double[] computedSV = svd.getSingularValues();
         Assert.assertEquals(singularValues.length, computedSV.length);
         for (int i = 0; i < singularValues.length; ++i) {
@@ -65,7 +65,7 @@ public class SingularValueDecompositionI
         final int columns = singularValues.length + 2;
         Random r = new Random(732763225836210l);
         SingularValueDecomposition svd =
-            new SingularValueDecompositionImpl(createTestMatrix(r, rows, 
columns, singularValues));
+            new SingularValueDecomposition(createTestMatrix(r, rows, columns, 
singularValues));
         double[] computedSV = svd.getSingularValues();
         Assert.assertEquals(singularValues.length, computedSV.length);
         for (int i = 0; i < singularValues.length; ++i) {
@@ -79,7 +79,7 @@ public class SingularValueDecompositionI
         RealMatrix matrix = MatrixUtils.createRealMatrix(testSquare);
         final int m = matrix.getRowDimension();
         final int n = matrix.getColumnDimension();
-        SingularValueDecomposition svd = new 
SingularValueDecompositionImpl(matrix);
+        SingularValueDecomposition svd = new 
SingularValueDecomposition(matrix);
         Assert.assertEquals(m, svd.getU().getRowDimension());
         Assert.assertEquals(m, svd.getU().getColumnDimension());
         Assert.assertEquals(m, svd.getS().getColumnDimension());
@@ -98,7 +98,7 @@ public class SingularValueDecompositionI
                 { 9.0 / 2.0,  3.0 / 2.0, 15.0 / 2.0,  5.0 / 2.0 },
                 { 3.0 / 2.0,  9.0 / 2.0,  5.0 / 2.0, 15.0 / 2.0 }
         }, false);
-        SingularValueDecomposition svd = new 
SingularValueDecompositionImpl(matrix);
+        SingularValueDecomposition svd = new 
SingularValueDecomposition(matrix);
         Assert.assertEquals(16.0, svd.getSingularValues()[0], 1.0e-14);
         Assert.assertEquals( 8.0, svd.getSingularValues()[1], 1.0e-14);
         Assert.assertEquals( 4.0, svd.getSingularValues()[2], 1.0e-14);
@@ -135,7 +135,7 @@ public class SingularValueDecompositionI
     }
 
     public void checkAEqualUSVt(final RealMatrix matrix) {
-        SingularValueDecomposition svd = new 
SingularValueDecompositionImpl(matrix);
+        SingularValueDecomposition svd = new 
SingularValueDecomposition(matrix);
         RealMatrix u = svd.getU();
         RealMatrix s = svd.getS();
         RealMatrix v = svd.getV();
@@ -147,17 +147,17 @@ public class SingularValueDecompositionI
     /** test that U is orthogonal */
     @Test
     public void testUOrthogonal() {
-        checkOrthogonal(new 
SingularValueDecompositionImpl(MatrixUtils.createRealMatrix(testSquare)).getU());
-        checkOrthogonal(new 
SingularValueDecompositionImpl(MatrixUtils.createRealMatrix(testNonSquare)).getU());
-        checkOrthogonal(new 
SingularValueDecompositionImpl(MatrixUtils.createRealMatrix(testNonSquare).transpose()).getU());
+        checkOrthogonal(new 
SingularValueDecomposition(MatrixUtils.createRealMatrix(testSquare)).getU());
+        checkOrthogonal(new 
SingularValueDecomposition(MatrixUtils.createRealMatrix(testNonSquare)).getU());
+        checkOrthogonal(new 
SingularValueDecomposition(MatrixUtils.createRealMatrix(testNonSquare).transpose()).getU());
     }
 
     /** test that V is orthogonal */
     @Test
     public void testVOrthogonal() {
-        checkOrthogonal(new 
SingularValueDecompositionImpl(MatrixUtils.createRealMatrix(testSquare)).getV());
-        checkOrthogonal(new 
SingularValueDecompositionImpl(MatrixUtils.createRealMatrix(testNonSquare)).getV());
-        checkOrthogonal(new 
SingularValueDecompositionImpl(MatrixUtils.createRealMatrix(testNonSquare).transpose()).getV());
+        checkOrthogonal(new 
SingularValueDecomposition(MatrixUtils.createRealMatrix(testSquare)).getV());
+        checkOrthogonal(new 
SingularValueDecomposition(MatrixUtils.createRealMatrix(testNonSquare)).getV());
+        checkOrthogonal(new 
SingularValueDecomposition(MatrixUtils.createRealMatrix(testNonSquare).transpose()).getV());
     }
 
     public void checkOrthogonal(final RealMatrix m) {
@@ -171,7 +171,7 @@ public class SingularValueDecompositionI
     // together, the actual triplet (U,S,V) is not uniquely defined.
     public void testMatricesValues1() {
        SingularValueDecomposition svd =
-            new 
SingularValueDecompositionImpl(MatrixUtils.createRealMatrix(testSquare));
+            new 
SingularValueDecomposition(MatrixUtils.createRealMatrix(testSquare));
         RealMatrix uRef = MatrixUtils.createRealMatrix(new double[][] {
                 { 3.0 / 5.0, -4.0 / 5.0 },
                 { 4.0 / 5.0,  3.0 / 5.0 }
@@ -224,7 +224,7 @@ public class SingularValueDecompositionI
 
         // check values against known references
         SingularValueDecomposition svd =
-            new 
SingularValueDecompositionImpl(MatrixUtils.createRealMatrix(testNonSquare));
+            new 
SingularValueDecomposition(MatrixUtils.createRealMatrix(testNonSquare));
         RealMatrix u = svd.getU();
         Assert.assertEquals(0, u.subtract(uRef).getNorm(), normTolerance);
         RealMatrix s = svd.getS();
@@ -244,34 +244,34 @@ public class SingularValueDecompositionI
     public void testRank() {
         double[][] d = { { 1, 1, 1 }, { 0, 0, 0 }, { 1, 2, 3 } };
         RealMatrix m = new Array2DRowRealMatrix(d);
-        SingularValueDecomposition svd = new 
SingularValueDecompositionImpl(m);        
-        Assert.assertEquals(2, svd.getRank());        
+        SingularValueDecomposition svd = new SingularValueDecomposition(m);
+        Assert.assertEquals(2, svd.getRank());
     }
-    
+
     /** test MATH-583 */
     @Test
     public void testStability1() {
         RealMatrix m = new Array2DRowRealMatrix(201, 201);
         loadRealMatrix(m,"matrix1.csv");
         try {
-            new SingularValueDecompositionImpl(m);
+            new SingularValueDecomposition(m);
         } catch (Exception e) {
             Assert.fail("Exception whilst constructing SVD");
-        }      
+        }
     }
-    
+
     /** test MATH-327 */
     @Test
     public void testStability2() {
         RealMatrix m = new Array2DRowRealMatrix(7, 168);
         loadRealMatrix(m,"matrix2.csv");
         try {
-            new SingularValueDecompositionImpl(m);
+            new SingularValueDecomposition(m);
         } catch (Throwable e) {
             Assert.fail("Exception whilst constructing SVD");
-        }      
+        }
     }
-    
+
     private void loadRealMatrix(RealMatrix m, String resourceName) {
         try {
             DataInputStream in = new 
DataInputStream(getClass().getResourceAsStream(resourceName));
@@ -286,25 +286,25 @@ public class SingularValueDecompositionI
                 row++;
             }
             in.close();
-        } catch (IOException e) {}      
+        } catch (IOException e) {}
     }
-    
+
     /** test condition number */
     @Test
     public void testConditionNumber() {
-        SingularValueDecompositionImpl svd =
-            new 
SingularValueDecompositionImpl(MatrixUtils.createRealMatrix(testSquare));
+        SingularValueDecomposition svd =
+            new 
SingularValueDecomposition(MatrixUtils.createRealMatrix(testSquare));
         // replace 1.0e-15 with 1.5e-15
         Assert.assertEquals(3.0, svd.getConditionNumber(), 1.5e-15);
     }
 
     @Test
     public void testInverseConditionNumber() {
-        SingularValueDecompositionImpl svd =
-            new 
SingularValueDecompositionImpl(MatrixUtils.createRealMatrix(testSquare));
+        SingularValueDecomposition svd =
+            new 
SingularValueDecomposition(MatrixUtils.createRealMatrix(testSquare));
         Assert.assertEquals(1.0/3.0, svd.getInverseConditionNumber(), 1.5e-15);
     }
-    
+
     private RealMatrix createTestMatrix(final Random r, final int rows, final 
int columns,
                                         final double[] singularValues) {
         final RealMatrix u =

Modified: 
commons/proper/math/trunk/src/test/java/org/apache/commons/math/linear/SingularValueSolverTest.java
URL: 
http://svn.apache.org/viewvc/commons/proper/math/trunk/src/test/java/org/apache/commons/math/linear/SingularValueSolverTest.java?rev=1175108&r1=1175107&r2=1175108&view=diff
==============================================================================
--- 
commons/proper/math/trunk/src/test/java/org/apache/commons/math/linear/SingularValueSolverTest.java
 (original)
+++ 
commons/proper/math/trunk/src/test/java/org/apache/commons/math/linear/SingularValueSolverTest.java
 Sat Sep 24 05:13:53 2011
@@ -35,7 +35,7 @@ public class SingularValueSolverTest {
     @Test
     public void testSolveDimensionErrors() {
         DecompositionSolver solver =
-            new 
SingularValueDecompositionImpl(MatrixUtils.createRealMatrix(testSquare)).getSolver();
+            new 
SingularValueDecomposition(MatrixUtils.createRealMatrix(testSquare)).getSolver();
         RealMatrix b = MatrixUtils.createRealMatrix(new double[3][2]);
         try {
             solver.solve(b);
@@ -65,7 +65,7 @@ public class SingularValueSolverTest {
                                    { 1.0, 0.0 },
                                    { 0.0, 0.0 }
                                });
-        DecompositionSolver solver = new 
SingularValueDecompositionImpl(m).getSolver();
+        DecompositionSolver solver = new 
SingularValueDecomposition(m).getSolver();
         RealMatrix b = MatrixUtils.createRealMatrix(new double[][] {
             { 11, 12 }, { 21, 22 }
         });
@@ -86,7 +86,7 @@ public class SingularValueSolverTest {
     @Test
     public void testSolve() {
         DecompositionSolver solver =
-            new 
SingularValueDecompositionImpl(MatrixUtils.createRealMatrix(testSquare)).getSolver();
+            new 
SingularValueDecomposition(MatrixUtils.createRealMatrix(testSquare)).getSolver();
         RealMatrix b = MatrixUtils.createRealMatrix(new double[][] {
                 { 1, 2, 3 }, { 0, -5, 1 }
         });
@@ -119,8 +119,8 @@ public class SingularValueSolverTest {
     /** test condition number */
     @Test
     public void testConditionNumber() {
-        SingularValueDecompositionImpl svd =
-            new 
SingularValueDecompositionImpl(MatrixUtils.createRealMatrix(testSquare));
+        SingularValueDecomposition svd =
+            new 
SingularValueDecomposition(MatrixUtils.createRealMatrix(testSquare));
         // replace 1.0e-15 with 1.5e-15
         Assert.assertEquals(3.0, svd.getConditionNumber(), 1.5e-15);
     }
@@ -131,7 +131,7 @@ public class SingularValueSolverTest {
             { 1.0, 2.0 }, { 1.0, 2.0 }
         });
         SingularValueDecomposition svd =
-            new SingularValueDecompositionImpl(rm);
+            new SingularValueDecomposition(rm);
         RealMatrix recomposed = 
svd.getU().multiply(svd.getS()).multiply(svd.getVT());
         Assert.assertEquals(0.0, recomposed.subtract(rm).getNorm(), 2.0e-15);
     }


Reply via email to