/*
* Copyright (c) 2009-2013, Peter Abeles. All Rights Reserved.
*
* This file is part of Efficient Java Matrix Library (EJML).
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package mikera.matrixx.solve.impl.qr;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;
import mikera.matrixx.AMatrix;
import mikera.matrixx.Matrix;
import mikera.matrixx.impl.DiagonalMatrix;
import org.junit.Test;
/**
* Contains a series of tests where it solves equations from a known set problems.
*
* @author Peter Abeles
*/
public class TestQRHouseColSolve {
protected double tol = 1e-8;
/**
* Checks to see if the modifyA() flag is set correctly
*/
@Test
public void modifiesA() {
Matrix A_orig = Matrix.createRandom(4,4);
Matrix A = A_orig.copy();
QRHouseColSolver solver = new QRHouseColSolver();
assertTrue(solver.setA(A));
assertTrue(A_orig.epsilonEquals(A));
}
/**
* Checks to see if the modifyB() flag is set correctly
*/
@Test
public void modifiesB() {
Matrix A = Matrix.createRandom(4,4);
QRHouseColSolver solver = new QRHouseColSolver();
assertTrue(solver.setA(A));
Matrix B = Matrix.createRandom(4,2);
Matrix B_orig = B.copy();
solver.solve(B);
assertTrue(B_orig.epsilonEquals(B));
}
/**
* See if a matrix that is more singular has a lower quality.
*/
@Test
public void checkQuality() {
Matrix A_good = DiagonalMatrix.create(4,3,2,1).toMatrix();
Matrix A_bad = DiagonalMatrix.create(4,3,2,0.1).toMatrix();
QRHouseColSolver solver = new QRHouseColSolver();
assertTrue(solver.setA(A_good));
double q_good;
try {
q_good = solver.quality();
} catch( IllegalArgumentException e ) {
// quality is not supported
return;
}
solver = new QRHouseColSolver();
assertTrue(solver.setA(A_bad));
double q_bad = solver.quality();
assertTrue(q_bad < q_good);
assertEquals(q_bad*10.0,q_good,1e-8);
}
/**
* See if quality is scale invariant
*/
@Test
public void checkQuality_scale() {
Matrix A = DiagonalMatrix.create(4,3,2,1).toMatrix();
Matrix Asmall = A.copy();
Asmall.scale(0.01);
QRHouseColSolver solver = new QRHouseColSolver();
assertTrue(solver.setA(A));
double q;
try {
q = solver.quality();
} catch( IllegalArgumentException e ) {
// quality is not supported
return;
}
assertTrue(solver.setA(Asmall));
double q_small = solver.quality();
assertEquals(q_small,q,1e-8);
}
/**
* A very easy matrix to decompose
*/
@Test
public void square_trivial() {
Matrix A = Matrix.create(new double[][] {{5, 2, 3}, {1.5, -2, 8}, {-3, 4.7, -0.5}});
Matrix b = Matrix.create(new double[][] {{18}, {21.5}, {4.9000}});
QRHouseColSolver solver = new QRHouseColSolver();
assertTrue(solver.setA(A));
AMatrix x = solver.solve(b);
Matrix x_expected = Matrix.create(new double[][] {{1}, {2}, {3}});
assertTrue(x_expected.epsilonEquals(x,1e-8));
}
/**
* This test checks to see if it can solve a system that will require some algorithms to
* perform a pivot. Pivots can change the data structure and can cause solve to fail if not
* handled correctly.
*/
@Test
public void square_pivot() {
Matrix A = Matrix.create(new double[][] {{0, 1, 2}, {-2, 4, 9}, {0.5, 0, 5}});
Matrix b = Matrix.create(new double[][] {{8}, {33}, {15.5}});
QRHouseColSolver solver = new QRHouseColSolver();
assertTrue(solver.setA(A));
Matrix x = solver.solve(b).toMatrix();
Matrix x_expected = Matrix.create(new double[][] {{1}, {2}, {3}});
assertTrue(x_expected.epsilonEquals(x,1e-6));
}
/**
* Have it solve for the coefficients in a polynomial
*/
@Test
public void rectangular() {
double t[][] = new double[][]{{-1},{-0.75},{-0.5},{0},{0.25},{0.5},{0.75}};
double vals[][] = new double[7][1];
double a=1,b=1.5,c=1.7;
for( int i = 0; i < t.length; i++ ) {
vals[i][0] = a + b*t[i][0] + c*t[i][0]*t[i][0];
}
Matrix B = Matrix.create(vals);
Matrix A = createPolyA(t,3);
QRHouseColSolver solver = new QRHouseColSolver();
assertTrue(solver.setA(A));
AMatrix x = solver.solve(B);
assertEquals(a,x.get(0,0),tol);
assertEquals(b,x.get(1,0),tol);
assertEquals(c,x.get(2,0),tol);
}
private Matrix createPolyA( double t[][] , int dof ) {
Matrix A = Matrix.create(t.length,3);
for( int j = 0; j < t.length; j++ ) {
double val = t[j][0];
for( int i = 0; i < dof; i++ ) {
A.set(j,i,Math.pow(val,i));
}
}
return A;
}
}