Author: luc
Date: Sun Jan 4 10:08:50 2009
New Revision: 731308
URL: http://svn.apache.org/viewvc?rev=731308&view=rev
Log:
simplified tests
added new tests
Modified:
commons/proper/math/trunk/src/test/org/apache/commons/math/linear/QRDecompositionImplTest.java
commons/proper/math/trunk/src/test/org/apache/commons/math/linear/QRSolverTest.java
Modified:
commons/proper/math/trunk/src/test/org/apache/commons/math/linear/QRDecompositionImplTest.java
URL:
http://svn.apache.org/viewvc/commons/proper/math/trunk/src/test/org/apache/commons/math/linear/QRDecompositionImplTest.java?rev=731308&r1=731307&r2=731308&view=diff
==============================================================================
---
commons/proper/math/trunk/src/test/org/apache/commons/math/linear/QRDecompositionImplTest.java
(original)
+++
commons/proper/math/trunk/src/test/org/apache/commons/math/linear/QRDecompositionImplTest.java
Sun Jan 4 10:08:50 2009
@@ -17,6 +17,8 @@
package org.apache.commons.math.linear;
+import java.util.Random;
+
import junit.framework.Test;
import junit.framework.TestCase;
import junit.framework.TestSuite;
@@ -59,143 +61,152 @@
/** test dimensions */
public void testDimensions() {
- RealMatrix matrix =
MatrixUtils.createRealMatrix(testData3x3NonSingular);
- QRDecomposition qr = new QRDecompositionImpl(matrix);
- assertEquals("3x3 Q size", qr.getQ().getRowDimension(), 3);
- assertEquals("3x3 Q size", qr.getQ().getColumnDimension(), 3);
- assertEquals("3x3 R size", qr.getR().getRowDimension(), 3);
- assertEquals("3x3 R size", qr.getR().getColumnDimension(), 3);
+ checkDimension(MatrixUtils.createRealMatrix(testData3x3NonSingular));
- matrix = MatrixUtils.createRealMatrix(testData4x3);
- qr = new QRDecompositionImpl(matrix);
- assertEquals("4x3 Q size", qr.getQ().getRowDimension(), 4);
- assertEquals("4x3 Q size", qr.getQ().getColumnDimension(), 4);
- assertEquals("4x3 R size", qr.getR().getRowDimension(), 4);
- assertEquals("4x3 R size", qr.getR().getColumnDimension(), 3);
+ checkDimension(MatrixUtils.createRealMatrix(testData4x3));
- matrix = MatrixUtils.createRealMatrix(testData3x4);
- qr = new QRDecompositionImpl(matrix);
- assertEquals("3x4 Q size", qr.getQ().getRowDimension(), 3);
- assertEquals("3x4 Q size", qr.getQ().getColumnDimension(), 3);
- assertEquals("3x4 R size", qr.getR().getRowDimension(), 3);
- assertEquals("3x4 R size", qr.getR().getColumnDimension(), 4);
+ checkDimension(MatrixUtils.createRealMatrix(testData3x4));
+
+ Random r = new Random(643895747384642l);
+ int p = (5 * DenseRealMatrix.BLOCK_SIZE) / 4;
+ int q = (7 * DenseRealMatrix.BLOCK_SIZE) / 4;
+ checkDimension(createTestMatrix(r, p, q));
+ checkDimension(createTestMatrix(r, q, p));
+
+ }
+
+ private void checkDimension(RealMatrix m) {
+ int rows = m.getRowDimension();
+ int columns = m.getColumnDimension();
+ QRDecomposition qr = new QRDecompositionImpl(m);
+ assertEquals(rows, qr.getQ().getRowDimension());
+ assertEquals(rows, qr.getQ().getColumnDimension());
+ assertEquals(rows, qr.getR().getRowDimension());
+ assertEquals(columns, qr.getR().getColumnDimension());
}
/** test A = QR */
public void testAEqualQR() {
- RealMatrix A = MatrixUtils.createRealMatrix(testData3x3NonSingular);
- QRDecomposition qr = new QRDecompositionImpl(A);
- RealMatrix Q = qr.getQ();
- RealMatrix R = qr.getR();
- double norm = Q.multiply(R).subtract(A).getNorm();
- assertEquals("3x3 nonsingular A = QR", 0, norm, normTolerance);
-
- RealMatrix matrix = MatrixUtils.createRealMatrix(testData3x3Singular);
- qr = new QRDecompositionImpl(matrix);
- norm = qr.getQ().multiply(qr.getR()).subtract(matrix).getNorm();
- assertEquals("3x3 singular A = QR", 0, norm, normTolerance);
+ checkAEqualQR(MatrixUtils.createRealMatrix(testData3x3NonSingular));
- matrix = MatrixUtils.createRealMatrix(testData3x4);
- qr = new QRDecompositionImpl(matrix);
- norm = qr.getQ().multiply(qr.getR()).subtract(matrix).getNorm();
- assertEquals("3x4 A = QR", 0, norm, normTolerance);
+ checkAEqualQR(MatrixUtils.createRealMatrix(testData3x3Singular));
+
+ checkAEqualQR(MatrixUtils.createRealMatrix(testData3x4));
+
+ checkAEqualQR(MatrixUtils.createRealMatrix(testData4x3));
+
+ Random r = new Random(643895747384642l);
+ int p = (5 * DenseRealMatrix.BLOCK_SIZE) / 4;
+ int q = (7 * DenseRealMatrix.BLOCK_SIZE) / 4;
+ checkAEqualQR(createTestMatrix(r, p, q));
+
+ checkAEqualQR(createTestMatrix(r, q, p));
- matrix = MatrixUtils.createRealMatrix(testData4x3);
- qr = new QRDecompositionImpl(matrix);
- norm = qr.getQ().multiply(qr.getR()).subtract(matrix).getNorm();
- assertEquals("4x3 A = QR", 0, norm, normTolerance);
+ }
+
+ private void checkAEqualQR(RealMatrix m) {
+ QRDecomposition qr = new QRDecompositionImpl(m);
+ double norm = qr.getQ().multiply(qr.getR()).subtract(m).getNorm();
+ assertEquals(0, norm, normTolerance);
}
/** test the orthogonality of Q */
public void testQOrthogonal() {
- RealMatrix matrix =
MatrixUtils.createRealMatrix(testData3x3NonSingular);
- RealMatrix q = new QRDecompositionImpl(matrix).getQ();
- RealMatrix qT = new QRDecompositionImpl(matrix).getQT();
- RealMatrix eye = MatrixUtils.createRealIdentityMatrix(3);
- double norm = qT.multiply(q).subtract(eye).getNorm();
- assertEquals("3x3 nonsingular Q'Q = I", 0, norm, normTolerance);
+ checkQOrthogonal(MatrixUtils.createRealMatrix(testData3x3NonSingular));
- matrix = MatrixUtils.createRealMatrix(testData3x3Singular);
- q = new QRDecompositionImpl(matrix).getQ();
- qT = new QRDecompositionImpl(matrix).getQT();
- eye = MatrixUtils.createRealIdentityMatrix(3);
- norm = qT.multiply(q).subtract(eye).getNorm();
- assertEquals("3x3 singular Q'Q = I", 0, norm, normTolerance);
+ checkQOrthogonal(MatrixUtils.createRealMatrix(testData3x3Singular));
- matrix = MatrixUtils.createRealMatrix(testData3x4);
- q = new QRDecompositionImpl(matrix).getQ();
- qT = new QRDecompositionImpl(matrix).getQT();
- eye = MatrixUtils.createRealIdentityMatrix(3);
- norm = qT.multiply(q).subtract(eye).getNorm();
- assertEquals("3x4 Q'Q = I", 0, norm, normTolerance);
+ checkQOrthogonal(MatrixUtils.createRealMatrix(testData3x4));
+
+ checkQOrthogonal(MatrixUtils.createRealMatrix(testData4x3));
+
+ Random r = new Random(643895747384642l);
+ int p = (5 * DenseRealMatrix.BLOCK_SIZE) / 4;
+ int q = (7 * DenseRealMatrix.BLOCK_SIZE) / 4;
+ checkQOrthogonal(createTestMatrix(r, p, q));
+
+ checkQOrthogonal(createTestMatrix(r, q, p));
- matrix = MatrixUtils.createRealMatrix(testData4x3);
- q = new QRDecompositionImpl(matrix).getQ();
- qT = new QRDecompositionImpl(matrix).getQT();
- eye = MatrixUtils.createRealIdentityMatrix(4);
- norm = qT.multiply(q).subtract(eye).getNorm();
- assertEquals("4x3 Q'Q = I", 0, norm, normTolerance);
+ }
+
+ private void checkQOrthogonal(RealMatrix m) {
+ QRDecomposition qr = new QRDecompositionImpl(m);
+ RealMatrix eye =
MatrixUtils.createRealIdentityMatrix(m.getRowDimension());
+ double norm = qr.getQT().multiply(qr.getQ()).subtract(eye).getNorm();
+ assertEquals(0, norm, normTolerance);
}
/** test that R is upper triangular */
public void testRUpperTriangular() {
RealMatrix matrix =
MatrixUtils.createRealMatrix(testData3x3NonSingular);
- RealMatrix R = new QRDecompositionImpl(matrix).getR();
- for (int i = 0; i < R.getRowDimension(); i++)
- for (int j = 0; j < i; j++)
- assertEquals("R lower triangle", R.getEntry(i, j), 0,
- entryTolerance);
+ checkUpperTriangular(new QRDecompositionImpl(matrix).getR());
matrix = MatrixUtils.createRealMatrix(testData3x3Singular);
- R = new QRDecompositionImpl(matrix).getR();
- for (int i = 0; i < R.getRowDimension(); i++)
- for (int j = 0; j < i; j++)
- assertEquals("R lower triangle", R.getEntry(i, j), 0,
- entryTolerance);
+ checkUpperTriangular(new QRDecompositionImpl(matrix).getR());
matrix = MatrixUtils.createRealMatrix(testData3x4);
- R = new QRDecompositionImpl(matrix).getR();
- for (int i = 0; i < R.getRowDimension(); i++)
- for (int j = 0; j < i; j++)
- assertEquals("R lower triangle", R.getEntry(i, j), 0,
- entryTolerance);
+ checkUpperTriangular(new QRDecompositionImpl(matrix).getR());
matrix = MatrixUtils.createRealMatrix(testData4x3);
- R = new QRDecompositionImpl(matrix).getR();
- for (int i = 0; i < R.getRowDimension(); i++)
- for (int j = 0; j < i; j++)
- assertEquals("R lower triangle", R.getEntry(i, j), 0,
- entryTolerance);
+ checkUpperTriangular(new QRDecompositionImpl(matrix).getR());
+
+ Random r = new Random(643895747384642l);
+ int p = (5 * DenseRealMatrix.BLOCK_SIZE) / 4;
+ int q = (7 * DenseRealMatrix.BLOCK_SIZE) / 4;
+ matrix = createTestMatrix(r, p, q);
+ checkUpperTriangular(new QRDecompositionImpl(matrix).getR());
+
+ matrix = createTestMatrix(r, p, q);
+ checkUpperTriangular(new QRDecompositionImpl(matrix).getR());
+
+ }
+
+ private void checkUpperTriangular(RealMatrix m) {
+ m.walkInOptimizedOrder(new DefaultRealMatrixPreservingVisitor() {
+ private static final long serialVersionUID = -7685630069569815930L;
+ public void visit(int row, int column, double value) {
+ if (column < row) {
+ assertEquals(0.0, value, entryTolerance);
+ }
+ }
+ });
}
/** test that H is trapezoidal */
public void testHTrapezoidal() {
RealMatrix matrix =
MatrixUtils.createRealMatrix(testData3x3NonSingular);
- RealMatrix H = new QRDecompositionImpl(matrix).getH();
- for (int i = 0; i < H.getRowDimension(); i++)
- for (int j = i + 1; j < H.getColumnDimension(); j++)
- assertEquals(H.getEntry(i, j), 0, entryTolerance);
+ checkTrapezoidal(new QRDecompositionImpl(matrix).getH());
matrix = MatrixUtils.createRealMatrix(testData3x3Singular);
- H = new QRDecompositionImpl(matrix).getH();
- for (int i = 0; i < H.getRowDimension(); i++)
- for (int j = i + 1; j < H.getColumnDimension(); j++)
- assertEquals(H.getEntry(i, j), 0, entryTolerance);
+ checkTrapezoidal(new QRDecompositionImpl(matrix).getH());
matrix = MatrixUtils.createRealMatrix(testData3x4);
- H = new QRDecompositionImpl(matrix).getH();
- for (int i = 0; i < H.getRowDimension(); i++)
- for (int j = i + 1; j < H.getColumnDimension(); j++)
- assertEquals(H.getEntry(i, j), 0, entryTolerance);
+ checkTrapezoidal(new QRDecompositionImpl(matrix).getH());
matrix = MatrixUtils.createRealMatrix(testData4x3);
- H = new QRDecompositionImpl(matrix).getH();
- for (int i = 0; i < H.getRowDimension(); i++)
- for (int j = i + 1; j < H.getColumnDimension(); j++)
- assertEquals(H.getEntry(i, j), 0, entryTolerance);
+ checkTrapezoidal(new QRDecompositionImpl(matrix).getH());
+
+ Random r = new Random(643895747384642l);
+ int p = (5 * DenseRealMatrix.BLOCK_SIZE) / 4;
+ int q = (7 * DenseRealMatrix.BLOCK_SIZE) / 4;
+ matrix = createTestMatrix(r, p, q);
+ checkTrapezoidal(new QRDecompositionImpl(matrix).getH());
+
+ matrix = createTestMatrix(r, p, q);
+ checkTrapezoidal(new QRDecompositionImpl(matrix).getH());
}
+ private void checkTrapezoidal(RealMatrix m) {
+ m.walkInOptimizedOrder(new DefaultRealMatrixPreservingVisitor() {
+ private static final long serialVersionUID = -43649044361860701L;
+ public void visit(int row, int column, double value) {
+ if (column > row) {
+ assertEquals(0.0, value, entryTolerance);
+ }
+ }
+ });
+ }
/** test matrices values */
public void testMatricesValues() {
QRDecomposition qr =
@@ -233,4 +244,16 @@
}
+ private RealMatrix createTestMatrix(final Random r, final int rows, final
int columns) {
+ RealMatrix m = MatrixUtils.createRealMatrix(rows, columns);
+ m.walkInOptimizedOrder(new DefaultRealMatrixChangingVisitor(){
+ private static final long serialVersionUID = -556118291433400034L;
+ public double visit(int row, int column, double value)
+ throws MatrixVisitorException {
+ return 2.0 * r.nextDouble() - 1.0;
+ }
+ });
+ return m;
+ }
+
}
Modified:
commons/proper/math/trunk/src/test/org/apache/commons/math/linear/QRSolverTest.java
URL:
http://svn.apache.org/viewvc/commons/proper/math/trunk/src/test/org/apache/commons/math/linear/QRSolverTest.java?rev=731308&r1=731307&r2=731308&view=diff
==============================================================================
---
commons/proper/math/trunk/src/test/org/apache/commons/math/linear/QRSolverTest.java
(original)
+++
commons/proper/math/trunk/src/test/org/apache/commons/math/linear/QRSolverTest.java
Sun Jan 4 10:08:50 2009
@@ -17,31 +17,37 @@
package org.apache.commons.math.linear;
+import java.util.Random;
+
import junit.framework.Test;
import junit.framework.TestCase;
import junit.framework.TestSuite;
public class QRSolverTest extends TestCase {
double[][] testData3x3NonSingular = {
- { 12, -51, 4 },
- { 6, 167, -68 },
- { -4, 24, -41 }, };
+ { 12, -51, 4 },
+ { 6, 167, -68 },
+ { -4, 24, -41 }
+ };
double[][] testData3x3Singular = {
- { 1, 4, 7, },
- { 2, 5, 8, },
- { 3, 6, 9, }, };
+ { 1, 2, 2 },
+ { 2, 4, 6 },
+ { 4, 8, 12 }
+ };
double[][] testData3x4 = {
- { 12, -51, 4, 1 },
- { 6, 167, -68, 2 },
- { -4, 24, -41, 3 }, };
+ { 12, -51, 4, 1 },
+ { 6, 167, -68, 2 },
+ { -4, 24, -41, 3 }
+ };
double[][] testData4x3 = {
- { 12, -51, 4, },
- { 6, 167, -68, },
- { -4, 24, -41, },
- { -5, 34, 7, }, };
+ { 12, -51, 4 },
+ { 6, 167, -68 },
+ { -4, 24, -41 },
+ { -5, 34, 7 }
+ };
public QRSolverTest(String name) {
super(name);
@@ -55,25 +61,25 @@
/** test rank */
public void testRank() {
- QRSolver solver =
- new QRSolver(new
QRDecompositionImpl(MatrixUtils.createRealMatrix(testData3x3NonSingular)));
+ DecompositionSolver solver =
+ new
QRDecompositionImpl(MatrixUtils.createRealMatrix(testData3x3NonSingular)).getSolver();
assertTrue(solver.isNonSingular());
- solver = new QRSolver(new
QRDecompositionImpl(MatrixUtils.createRealMatrix(testData3x3Singular)));
+ solver = new
QRDecompositionImpl(MatrixUtils.createRealMatrix(testData3x3Singular)).getSolver();
assertFalse(solver.isNonSingular());
- solver = new QRSolver(new
QRDecompositionImpl(MatrixUtils.createRealMatrix(testData3x4)));
- assertFalse(solver.isNonSingular());
+ solver = new
QRDecompositionImpl(MatrixUtils.createRealMatrix(testData3x4)).getSolver();
+ assertTrue(solver.isNonSingular());
- solver = new QRSolver(new
QRDecompositionImpl(MatrixUtils.createRealMatrix(testData4x3)));
+ solver = new
QRDecompositionImpl(MatrixUtils.createRealMatrix(testData4x3)).getSolver();
assertTrue(solver.isNonSingular());
}
/** test solve dimension errors */
public void testSolveDimensionErrors() {
- QRSolver solver =
- new QRSolver(new
QRDecompositionImpl(MatrixUtils.createRealMatrix(testData3x3NonSingular)));
+ DecompositionSolver solver =
+ new
QRDecompositionImpl(MatrixUtils.createRealMatrix(testData3x3NonSingular)).getSolver();
RealMatrix b = MatrixUtils.createRealMatrix(new double[2][2]);
try {
solver.solve(b);
@@ -103,8 +109,8 @@
/** test solve rank errors */
public void testSolveRankErrors() {
- QRSolver solver =
- new QRSolver(new
QRDecompositionImpl(MatrixUtils.createRealMatrix(testData3x3Singular)));
+ DecompositionSolver solver =
+ new
QRDecompositionImpl(MatrixUtils.createRealMatrix(testData3x3Singular)).getSolver();
RealMatrix b = MatrixUtils.createRealMatrix(new double[3][2]);
try {
solver.solve(b);
@@ -134,8 +140,9 @@
/** test solve */
public void testSolve() {
- QRSolver solver =
- new QRSolver(new
QRDecompositionImpl(MatrixUtils.createRealMatrix(testData3x3NonSingular)));
+ QRDecomposition decomposition =
+ new
QRDecompositionImpl(MatrixUtils.createRealMatrix(testData3x3NonSingular));
+ DecompositionSolver solver = decomposition.getSolver();
RealMatrix b = MatrixUtils.createRealMatrix(new double[][] {
{ -102, 12250 }, { 544, 24500 }, { 167, -36750 }
});
@@ -144,31 +151,82 @@
});
// using RealMatrix
- assertEquals(0, solver.solve(b).subtract(xRef).getNorm(), 1.0e-13);
+ assertEquals(0, solver.solve(b).subtract(xRef).getNorm(), 2.0e-16 *
xRef.getNorm());
// using double[]
for (int i = 0; i < b.getColumnDimension(); ++i) {
- assertEquals(0,
- new
RealVectorImpl(solver.solve(b.getColumn(i))).subtract(xRef.getColumnVector(i)).getNorm(),
- 1.0e-13);
+ final double[] x = solver.solve(b.getColumn(i));
+ final double error = new
RealVectorImpl(x).subtract(xRef.getColumnVector(i)).getNorm();
+ assertEquals(0, error, 3.0e-16 *
xRef.getColumnVector(i).getNorm());
}
// using RealVectorImpl
for (int i = 0; i < b.getColumnDimension(); ++i) {
- assertEquals(0,
-
solver.solve(b.getColumnVector(i)).subtract(xRef.getColumnVector(i)).getNorm(),
- 1.0e-13);
+ final RealVector x = solver.solve(b.getColumnVector(i));
+ final double error = x.subtract(xRef.getColumnVector(i)).getNorm();
+ assertEquals(0, error, 3.0e-16 *
xRef.getColumnVector(i).getNorm());
}
// using RealVector with an alternate implementation
for (int i = 0; i < b.getColumnDimension(); ++i) {
RealVectorImplTest.RealVectorTestImpl v =
new RealVectorImplTest.RealVectorTestImpl(b.getColumn(i));
- assertEquals(0,
-
solver.solve(v).subtract(xRef.getColumnVector(i)).getNorm(),
- 1.0e-13);
+ final RealVector x = solver.solve(v);
+ final double error = x.subtract(xRef.getColumnVector(i)).getNorm();
+ assertEquals(0, error, 3.0e-16 *
xRef.getColumnVector(i).getNorm());
}
}
+ public void testOverdetermined() {
+ final Random r = new Random(5559252868205245l);
+ int p = (7 * DenseRealMatrix.BLOCK_SIZE) / 4;
+ int q = (5 * DenseRealMatrix.BLOCK_SIZE) / 4;
+ RealMatrix a = createTestMatrix(r, p, q);
+ RealMatrix xRef = createTestMatrix(r, q, DenseRealMatrix.BLOCK_SIZE
+ 3);
+
+ // build a perturbed system: A.X + noise = B
+ RealMatrix b = a.multiply(xRef);
+ final double noise = 0.001;
+ b.walkInOptimizedOrder(new DefaultRealMatrixChangingVisitor() {
+ private static final long serialVersionUID = 3533849820776962636L;
+ public double visit(int row, int column, double value) {
+ return value * (1.0 + noise * (2 * r.nextDouble() - 1));
+ }
+ });
+
+ // despite perturbation, the least square solution should be pretty
good
+ RealMatrix x = new QRDecompositionImpl(a).getSolver().solve(b);
+ assertEquals(0, x.subtract(xRef).getNorm(), 0.01 * noise * p * q);
+
+ }
+
+ public void testUnderdetermined() {
+ final Random r = new Random(42185006424567123l);
+ int p = (5 * DenseRealMatrix.BLOCK_SIZE) / 4;
+ int q = (7 * DenseRealMatrix.BLOCK_SIZE) / 4;
+ RealMatrix a = createTestMatrix(r, p, q);
+ RealMatrix xRef = createTestMatrix(r, q, DenseRealMatrix.BLOCK_SIZE
+ 3);
+ RealMatrix b = a.multiply(xRef);
+ RealMatrix x = new QRDecompositionImpl(a).getSolver().solve(b);
+
+ // too many equations, the system cannot be solved at all
+ assertTrue(x.subtract(xRef).getNorm() / (p * q) > 0.01);
+
+ // the last unknown should have been set to 0
+ assertEquals(0.0, x.getSubMatrix(p, q - 1, 0, x.getColumnDimension() -
1).getNorm());
+
+ }
+
+ private RealMatrix createTestMatrix(final Random r, final int rows, final
int columns) {
+ RealMatrix m = MatrixUtils.createRealMatrix(rows, columns);
+ m.walkInOptimizedOrder(new DefaultRealMatrixChangingVisitor(){
+ private static final long serialVersionUID = -556118291433400034L;
+ public double visit(int row, int column, double value)
+ throws MatrixVisitorException {
+ return 2.0 * r.nextDouble() - 1.0;
+ }
+ });
+ return m;
+ }
}