Author: celestin Date: Sat Sep 24 04:47:38 2011 New Revision: 1175100 URL: http://svn.apache.org/viewvc?rev=1175100&view=rev Log: Merged QRDecomposition and QRDecompositionImpl (see MATH-662).
Added: commons/proper/math/trunk/src/main/java/org/apache/commons/math/linear/QRDecomposition.java - copied, changed from r1175099, commons/proper/math/trunk/src/main/java/org/apache/commons/math/linear/QRDecompositionImpl.java commons/proper/math/trunk/src/test/java/org/apache/commons/math/linear/QRDecompositionTest.java - copied, changed from r1175099, commons/proper/math/trunk/src/test/java/org/apache/commons/math/linear/QRDecompositionImplTest.java Removed: commons/proper/math/trunk/src/main/java/org/apache/commons/math/linear/QRDecompositionImpl.java commons/proper/math/trunk/src/test/java/org/apache/commons/math/linear/QRDecompositionImplTest.java Modified: commons/proper/math/trunk/src/main/java/org/apache/commons/math/ode/nonstiff/AdamsNordsieckTransformer.java commons/proper/math/trunk/src/main/java/org/apache/commons/math/optimization/general/GaussNewtonOptimizer.java commons/proper/math/trunk/src/main/java/org/apache/commons/math/stat/regression/OLSMultipleLinearRegression.java commons/proper/math/trunk/src/test/java/org/apache/commons/math/linear/QRSolverTest.java Copied: commons/proper/math/trunk/src/main/java/org/apache/commons/math/linear/QRDecomposition.java (from r1175099, commons/proper/math/trunk/src/main/java/org/apache/commons/math/linear/QRDecompositionImpl.java) URL: http://svn.apache.org/viewvc/commons/proper/math/trunk/src/main/java/org/apache/commons/math/linear/QRDecomposition.java?p2=commons/proper/math/trunk/src/main/java/org/apache/commons/math/linear/QRDecomposition.java&p1=commons/proper/math/trunk/src/main/java/org/apache/commons/math/linear/QRDecompositionImpl.java&r1=1175099&r2=1175100&rev=1175100&view=diff ============================================================================== --- commons/proper/math/trunk/src/main/java/org/apache/commons/math/linear/QRDecompositionImpl.java (original) +++ commons/proper/math/trunk/src/main/java/org/apache/commons/math/linear/QRDecomposition.java Sat Sep 24 04:47:38 2011 @@ -32,14 +32,23 @@ import org.apache.commons.math.util.Fast * <p>For efficiency purposes, the decomposition in packed form is transposed. * This allows inner loop to iterate inside rows, which is much more cache-efficient * in Java.</p> + * <p>This class is based on 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>a {@link #getQT() getQT} method has been added,</li> + * <li>the {@code solve} and {@code isFullRank} methods have been replaced + * by a {@link #getSolver() getSolver} method and the equivalent methods + * provided by the returned {@link DecompositionSolver}.</li> + * </ul> * * @see <a href="http://mathworld.wolfram.com/QRDecomposition.html">MathWorld</a> * @see <a href="http://en.wikipedia.org/wiki/QR_decomposition">Wikipedia</a> * * @version $Id$ - * @since 1.2 + * @since 1.2 (changed to concrete class in 3.0) */ -public class QRDecompositionImpl implements QRDecomposition { +public class QRDecomposition { /** * A packed TRANSPOSED representation of the QR decomposition. @@ -68,7 +77,7 @@ public class QRDecompositionImpl impleme * Calculates the QR-decomposition of the given matrix. * @param matrix The matrix to decompose. */ - public QRDecompositionImpl(RealMatrix matrix) { + public QRDecomposition(RealMatrix matrix) { final int m = matrix.getRowDimension(); final int n = matrix.getColumnDimension(); @@ -144,7 +153,11 @@ public class QRDecompositionImpl impleme } } - /** {@inheritDoc} */ + /** + * Returns the matrix R of the decomposition. + * <p>R is an upper-triangular matrix</p> + * @return the R matrix + */ public RealMatrix getR() { if (cachedR == null) { @@ -167,7 +180,11 @@ public class QRDecompositionImpl impleme return cachedR; } - /** {@inheritDoc} */ + /** + * Returns the matrix Q of the decomposition. + * <p>Q is an orthogonal matrix</p> + * @return the Q matrix + */ public RealMatrix getQ() { if (cachedQ == null) { cachedQ = getQT().transpose(); @@ -175,7 +192,11 @@ public class QRDecompositionImpl impleme return cachedQ; } - /** {@inheritDoc} */ + /** + * Returns the transpose of the matrix Q of the decomposition. + * <p>Q is an orthogonal matrix</p> + * @return the Q matrix + */ public RealMatrix getQT() { if (cachedQT == null) { @@ -216,7 +237,13 @@ public class QRDecompositionImpl impleme return cachedQT; } - /** {@inheritDoc} */ + /** + * Returns the Householder reflector vectors. + * <p>H is a lower trapezoidal matrix whose columns represent + * each successive Householder reflector vector. This matrix is used + * to compute Q.</p> + * @return a matrix containing the Householder reflector vectors + */ public RealMatrix getH() { if (cachedH == null) { @@ -234,7 +261,10 @@ public class QRDecompositionImpl impleme return cachedH; } - /** {@inheritDoc} */ + /** + * Get a solver for finding the A × X = B solution in least square sense. + * @return a solver + */ public DecompositionSolver getSolver() { return new Solver(qrt, rDiag); } Modified: commons/proper/math/trunk/src/main/java/org/apache/commons/math/ode/nonstiff/AdamsNordsieckTransformer.java URL: http://svn.apache.org/viewvc/commons/proper/math/trunk/src/main/java/org/apache/commons/math/ode/nonstiff/AdamsNordsieckTransformer.java?rev=1175100&r1=1175099&r2=1175100&view=diff ============================================================================== --- commons/proper/math/trunk/src/main/java/org/apache/commons/math/ode/nonstiff/AdamsNordsieckTransformer.java (original) +++ commons/proper/math/trunk/src/main/java/org/apache/commons/math/ode/nonstiff/AdamsNordsieckTransformer.java Sat Sep 24 04:47:38 2011 @@ -30,7 +30,6 @@ import org.apache.commons.math.linear.Fi import org.apache.commons.math.linear.FieldMatrix; import org.apache.commons.math.linear.MatrixUtils; import org.apache.commons.math.linear.QRDecomposition; -import org.apache.commons.math.linear.QRDecompositionImpl; import org.apache.commons.math.linear.RealMatrix; /** Transformer to Nordsieck vectors for Adams integrators. @@ -291,7 +290,8 @@ public class AdamsNordsieckTransformer { // solve the rectangular system in the least square sense // to get the best estimate of the Nordsieck vector [s2 ... sk] - QRDecomposition decomposition = new QRDecompositionImpl(new Array2DRowRealMatrix(a, false)); + QRDecomposition decomposition; + decomposition = new QRDecomposition(new Array2DRowRealMatrix(a, false)); RealMatrix x = decomposition.getSolver().solve(new Array2DRowRealMatrix(b, false)); return new Array2DRowRealMatrix(x.getData(), false); } Modified: commons/proper/math/trunk/src/main/java/org/apache/commons/math/optimization/general/GaussNewtonOptimizer.java URL: http://svn.apache.org/viewvc/commons/proper/math/trunk/src/main/java/org/apache/commons/math/optimization/general/GaussNewtonOptimizer.java?rev=1175100&r1=1175099&r2=1175100&view=diff ============================================================================== --- commons/proper/math/trunk/src/main/java/org/apache/commons/math/optimization/general/GaussNewtonOptimizer.java (original) +++ commons/proper/math/trunk/src/main/java/org/apache/commons/math/optimization/general/GaussNewtonOptimizer.java Sat Sep 24 04:47:38 2011 @@ -23,7 +23,7 @@ import org.apache.commons.math.linear.Ar import org.apache.commons.math.linear.BlockRealMatrix; import org.apache.commons.math.linear.DecompositionSolver; import org.apache.commons.math.linear.LUDecomposition; -import org.apache.commons.math.linear.QRDecompositionImpl; +import org.apache.commons.math.linear.QRDecomposition; import org.apache.commons.math.linear.RealMatrix; import org.apache.commons.math.linear.SingularMatrixException; import org.apache.commons.math.optimization.ConvergenceChecker; @@ -145,7 +145,7 @@ public class GaussNewtonOptimizer extend RealMatrix mA = new BlockRealMatrix(a); DecompositionSolver solver = useLU ? new LUDecomposition(mA).getSolver() : - new QRDecompositionImpl(mA).getSolver(); + new QRDecomposition(mA).getSolver(); final double[] dX = solver.solve(new ArrayRealVector(b, false)).toArray(); // update the estimated parameters for (int i = 0; i < cols; ++i) { Modified: commons/proper/math/trunk/src/main/java/org/apache/commons/math/stat/regression/OLSMultipleLinearRegression.java URL: http://svn.apache.org/viewvc/commons/proper/math/trunk/src/main/java/org/apache/commons/math/stat/regression/OLSMultipleLinearRegression.java?rev=1175100&r1=1175099&r2=1175100&view=diff ============================================================================== --- commons/proper/math/trunk/src/main/java/org/apache/commons/math/stat/regression/OLSMultipleLinearRegression.java (original) +++ commons/proper/math/trunk/src/main/java/org/apache/commons/math/stat/regression/OLSMultipleLinearRegression.java Sat Sep 24 04:47:38 2011 @@ -19,7 +19,6 @@ package org.apache.commons.math.stat.reg import org.apache.commons.math.linear.Array2DRowRealMatrix; import org.apache.commons.math.linear.LUDecomposition; import org.apache.commons.math.linear.QRDecomposition; -import org.apache.commons.math.linear.QRDecompositionImpl; import org.apache.commons.math.linear.RealMatrix; import org.apache.commons.math.linear.RealVector; import org.apache.commons.math.stat.StatUtils; @@ -33,7 +32,7 @@ import org.apache.commons.math.stat.desc * <pre><code> X<sup>T</sup> X b = X<sup>T</sup> y </code></pre></p> * * <p>To solve the normal equations, this implementation uses QR decomposition - * of the <code>X</code> matrix. (See {@link QRDecompositionImpl} for details on the + * of the <code>X</code> matrix. (See {@link QRDecomposition} for details on the * decomposition algorithm.) The <code>X</code> matrix, also known as the <i>design matrix,</i> * has rows corresponding to sample observations and columns corresponding to independent * variables. When the model is estimated using an intercept term (i.e. when @@ -79,7 +78,7 @@ public class OLSMultipleLinearRegression @Override public void newSampleData(double[] data, int nobs, int nvars) { super.newSampleData(data, nobs, nvars); - qr = new QRDecompositionImpl(X); + qr = new QRDecomposition(X); } /** @@ -198,7 +197,7 @@ public class OLSMultipleLinearRegression @Override protected void newXSampleData(double[][] x) { super.newXSampleData(x); - qr = new QRDecompositionImpl(X); + qr = new QRDecomposition(X); } /** Copied: commons/proper/math/trunk/src/test/java/org/apache/commons/math/linear/QRDecompositionTest.java (from r1175099, commons/proper/math/trunk/src/test/java/org/apache/commons/math/linear/QRDecompositionImplTest.java) URL: http://svn.apache.org/viewvc/commons/proper/math/trunk/src/test/java/org/apache/commons/math/linear/QRDecompositionTest.java?p2=commons/proper/math/trunk/src/test/java/org/apache/commons/math/linear/QRDecompositionTest.java&p1=commons/proper/math/trunk/src/test/java/org/apache/commons/math/linear/QRDecompositionImplTest.java&r1=1175099&r2=1175100&rev=1175100&view=diff ============================================================================== --- commons/proper/math/trunk/src/test/java/org/apache/commons/math/linear/QRDecompositionImplTest.java (original) +++ commons/proper/math/trunk/src/test/java/org/apache/commons/math/linear/QRDecompositionTest.java Sat Sep 24 04:47:38 2011 @@ -23,7 +23,7 @@ import org.junit.Assert; import org.junit.Test; -public class QRDecompositionImplTest { +public class QRDecompositionTest { double[][] testData3x3NonSingular = { { 12, -51, 4 }, { 6, 167, -68 }, @@ -69,7 +69,7 @@ public class QRDecompositionImplTest { private void checkDimension(RealMatrix m) { int rows = m.getRowDimension(); int columns = m.getColumnDimension(); - QRDecomposition qr = new QRDecompositionImpl(m); + QRDecomposition qr = new QRDecomposition(m); Assert.assertEquals(rows, qr.getQ().getRowDimension()); Assert.assertEquals(rows, qr.getQ().getColumnDimension()); Assert.assertEquals(rows, qr.getR().getRowDimension()); @@ -97,7 +97,7 @@ public class QRDecompositionImplTest { } private void checkAEqualQR(RealMatrix m) { - QRDecomposition qr = new QRDecompositionImpl(m); + QRDecomposition qr = new QRDecomposition(m); double norm = qr.getQ().multiply(qr.getR()).subtract(m).getNorm(); Assert.assertEquals(0, norm, normTolerance); } @@ -123,7 +123,7 @@ public class QRDecompositionImplTest { } private void checkQOrthogonal(RealMatrix m) { - QRDecomposition qr = new QRDecompositionImpl(m); + QRDecomposition qr = new QRDecomposition(m); RealMatrix eye = MatrixUtils.createRealIdentityMatrix(m.getRowDimension()); double norm = qr.getQT().multiply(qr.getQ()).subtract(eye).getNorm(); Assert.assertEquals(0, norm, normTolerance); @@ -133,25 +133,25 @@ public class QRDecompositionImplTest { @Test public void testRUpperTriangular() { RealMatrix matrix = MatrixUtils.createRealMatrix(testData3x3NonSingular); - checkUpperTriangular(new QRDecompositionImpl(matrix).getR()); + checkUpperTriangular(new QRDecomposition(matrix).getR()); matrix = MatrixUtils.createRealMatrix(testData3x3Singular); - checkUpperTriangular(new QRDecompositionImpl(matrix).getR()); + checkUpperTriangular(new QRDecomposition(matrix).getR()); matrix = MatrixUtils.createRealMatrix(testData3x4); - checkUpperTriangular(new QRDecompositionImpl(matrix).getR()); + checkUpperTriangular(new QRDecomposition(matrix).getR()); matrix = MatrixUtils.createRealMatrix(testData4x3); - checkUpperTriangular(new QRDecompositionImpl(matrix).getR()); + checkUpperTriangular(new QRDecomposition(matrix).getR()); Random r = new Random(643895747384642l); int p = (5 * BlockRealMatrix.BLOCK_SIZE) / 4; int q = (7 * BlockRealMatrix.BLOCK_SIZE) / 4; matrix = createTestMatrix(r, p, q); - checkUpperTriangular(new QRDecompositionImpl(matrix).getR()); + checkUpperTriangular(new QRDecomposition(matrix).getR()); matrix = createTestMatrix(r, p, q); - checkUpperTriangular(new QRDecompositionImpl(matrix).getR()); + checkUpperTriangular(new QRDecomposition(matrix).getR()); } @@ -170,25 +170,25 @@ public class QRDecompositionImplTest { @Test public void testHTrapezoidal() { RealMatrix matrix = MatrixUtils.createRealMatrix(testData3x3NonSingular); - checkTrapezoidal(new QRDecompositionImpl(matrix).getH()); + checkTrapezoidal(new QRDecomposition(matrix).getH()); matrix = MatrixUtils.createRealMatrix(testData3x3Singular); - checkTrapezoidal(new QRDecompositionImpl(matrix).getH()); + checkTrapezoidal(new QRDecomposition(matrix).getH()); matrix = MatrixUtils.createRealMatrix(testData3x4); - checkTrapezoidal(new QRDecompositionImpl(matrix).getH()); + checkTrapezoidal(new QRDecomposition(matrix).getH()); matrix = MatrixUtils.createRealMatrix(testData4x3); - checkTrapezoidal(new QRDecompositionImpl(matrix).getH()); + checkTrapezoidal(new QRDecomposition(matrix).getH()); Random r = new Random(643895747384642l); int p = (5 * BlockRealMatrix.BLOCK_SIZE) / 4; int q = (7 * BlockRealMatrix.BLOCK_SIZE) / 4; matrix = createTestMatrix(r, p, q); - checkTrapezoidal(new QRDecompositionImpl(matrix).getH()); + checkTrapezoidal(new QRDecomposition(matrix).getH()); matrix = createTestMatrix(r, p, q); - checkTrapezoidal(new QRDecompositionImpl(matrix).getH()); + checkTrapezoidal(new QRDecomposition(matrix).getH()); } @@ -206,7 +206,7 @@ public class QRDecompositionImplTest { @Test public void testMatricesValues() { QRDecomposition qr = - new QRDecompositionImpl(MatrixUtils.createRealMatrix(testData3x3NonSingular)); + new QRDecomposition(MatrixUtils.createRealMatrix(testData3x3NonSingular)); RealMatrix qRef = MatrixUtils.createRealMatrix(new double[][] { { -12.0 / 14.0, 69.0 / 175.0, -58.0 / 175.0 }, { -6.0 / 14.0, -158.0 / 175.0, 6.0 / 175.0 }, Modified: commons/proper/math/trunk/src/test/java/org/apache/commons/math/linear/QRSolverTest.java URL: http://svn.apache.org/viewvc/commons/proper/math/trunk/src/test/java/org/apache/commons/math/linear/QRSolverTest.java?rev=1175100&r1=1175099&r2=1175100&view=diff ============================================================================== --- commons/proper/math/trunk/src/test/java/org/apache/commons/math/linear/QRSolverTest.java (original) +++ commons/proper/math/trunk/src/test/java/org/apache/commons/math/linear/QRSolverTest.java Sat Sep 24 04:47:38 2011 @@ -54,16 +54,16 @@ public class QRSolverTest { @Test public void testRank() { DecompositionSolver solver = - new QRDecompositionImpl(MatrixUtils.createRealMatrix(testData3x3NonSingular)).getSolver(); + new QRDecomposition(MatrixUtils.createRealMatrix(testData3x3NonSingular)).getSolver(); Assert.assertTrue(solver.isNonSingular()); - solver = new QRDecompositionImpl(MatrixUtils.createRealMatrix(testData3x3Singular)).getSolver(); + solver = new QRDecomposition(MatrixUtils.createRealMatrix(testData3x3Singular)).getSolver(); Assert.assertFalse(solver.isNonSingular()); - solver = new QRDecompositionImpl(MatrixUtils.createRealMatrix(testData3x4)).getSolver(); + solver = new QRDecomposition(MatrixUtils.createRealMatrix(testData3x4)).getSolver(); Assert.assertTrue(solver.isNonSingular()); - solver = new QRDecompositionImpl(MatrixUtils.createRealMatrix(testData4x3)).getSolver(); + solver = new QRDecomposition(MatrixUtils.createRealMatrix(testData4x3)).getSolver(); Assert.assertTrue(solver.isNonSingular()); } @@ -72,7 +72,7 @@ public class QRSolverTest { @Test public void testSolveDimensionErrors() { DecompositionSolver solver = - new QRDecompositionImpl(MatrixUtils.createRealMatrix(testData3x3NonSingular)).getSolver(); + new QRDecomposition(MatrixUtils.createRealMatrix(testData3x3NonSingular)).getSolver(); RealMatrix b = MatrixUtils.createRealMatrix(new double[2][2]); try { solver.solve(b); @@ -92,7 +92,7 @@ public class QRSolverTest { @Test public void testSolveRankErrors() { DecompositionSolver solver = - new QRDecompositionImpl(MatrixUtils.createRealMatrix(testData3x3Singular)).getSolver(); + new QRDecomposition(MatrixUtils.createRealMatrix(testData3x3Singular)).getSolver(); RealMatrix b = MatrixUtils.createRealMatrix(new double[3][2]); try { solver.solve(b); @@ -112,7 +112,7 @@ public class QRSolverTest { @Test public void testSolve() { QRDecomposition decomposition = - new QRDecompositionImpl(MatrixUtils.createRealMatrix(testData3x3NonSingular)); + new QRDecomposition(MatrixUtils.createRealMatrix(testData3x3NonSingular)); DecompositionSolver solver = decomposition.getSolver(); RealMatrix b = MatrixUtils.createRealMatrix(new double[][] { { -102, 12250 }, { 544, 24500 }, { 167, -36750 } @@ -161,7 +161,7 @@ public class QRSolverTest { }); // despite perturbation, the least square solution should be pretty good - RealMatrix x = new QRDecompositionImpl(a).getSolver().solve(b); + RealMatrix x = new QRDecomposition(a).getSolver().solve(b); Assert.assertEquals(0, x.subtract(xRef).getNorm(), 0.01 * noise * p * q); } @@ -174,7 +174,7 @@ public class QRSolverTest { RealMatrix a = createTestMatrix(r, p, q); RealMatrix xRef = createTestMatrix(r, q, BlockRealMatrix.BLOCK_SIZE + 3); RealMatrix b = a.multiply(xRef); - RealMatrix x = new QRDecompositionImpl(a).getSolver().solve(b); + RealMatrix x = new QRDecomposition(a).getSolver().solve(b); // too many equations, the system cannot be solved at all Assert.assertTrue(x.subtract(xRef).getNorm() / (p * q) > 0.01);