Package mikera.matrixx.decompose.impl.qr

Source Code of mikera.matrixx.decompose.impl.qr.TestHouseholderQR$DebugQR

package mikera.matrixx.decompose.impl.qr;

import java.util.Random;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;
import mikera.matrixx.AMatrix;
import mikera.matrixx.Matrix;
import mikera.matrixx.algo.Multiplications;
import mikera.matrixx.decompose.IQRResult;
import mikera.matrixx.decompose.impl.qr.HouseholderQR;
import mikera.matrixx.impl.AStridedMatrix;
import mikera.matrixx.impl.IdentityMatrix;
import mikera.matrixx.impl.ZeroMatrix;

import org.junit.Test;

public class TestHouseholderQR extends GenericQrCheck {
   
    Random rand = new Random(0xff);


    @Override
    protected QRDecomposition createQRDecomposition(boolean compact) {
        return new HouseholderQR(compact);
    }

    /**
     * Internally several house holder operations are performed.  This
     * checks to see if the householder operations and the expected result for all the
     * submatrices.
     */
    @Test
    public void householder() {
        int width = 5;

        for( int i = 0; i < width; i++ ) {
            checkSubHouse(i , width);
        }
    }

    private void checkSubHouse(int w , int width) {
        DebugQR qr = new DebugQR(width,width);

        Matrix A = Matrix.createRandom(width, width);

        qr.householder(w,A);

//        SimpleMatrix U = new SimpleMatrix(width,1, true, qr.getU()).extractMatrix(w,width,0,1);
        Matrix temp = Matrix.create(width,1);
        temp.setElements(qr.getU());
        AStridedMatrix U = temp.subMatrix(w, width-w, 0, 1);

        Matrix I = Matrix.createIdentity(width-w);
//      SimpleMatrix Q = I.minus(U.mult(U.transpose()).scale(qr.getGamma()));
        Matrix temp1 = Multiplications.multiply(U, U.getTranspose());
        temp1.scale(qr.getGamma());
        I.sub(temp1);
        Matrix Q = I;


        // check the expected properties of Q
        assertTrue(Q.epsilonEquals(Q.getTranspose(),1e-6));
        assertTrue(Q.epsilonEquals(Q.inverse(),1e-6));

//        SimpleMatrix result = Q.mult(A.extractMatrix(w,width,w,width));
        AStridedMatrix result = Multiplications.multiply(Q, A.subMatrix(w,width-w,w,width-w));

        for( int i = 1; i < width-w; i++ ) {
            assertEquals(0,result.get(i,0),1e-5);
        }
    }

    /**
     * Check the results of this function against basic matrix operations
     * which are equivalent.
     */
    @Test
    public void updateA() {
        int width = 5;

        for( int i = 0; i < width; i++ )
            checkSubMatrix(width,i);
    }

    private void checkSubMatrix(int width , int w ) {
        DebugQR qr = new DebugQR(width,width);

        double gamma = 0.2;
        double tau = 0.75;

        Matrix U = Matrix.createRandom(width, 1);
        Matrix A = Matrix.createRandom(width, width);

        qr.getQR().set(A);

        // compute the results using standard matrix operations
        Matrix I = Matrix.createIdentity(width-w);

//        SimpleMatrix u_sub = U.extractMatrix(w,width,0,1);
        AStridedMatrix u_sub = U.subMatrix(w, width-w, 0, 1);
//        SimpleMatrix A_sub = A.extractMatrix(w,width,w,width);
        AStridedMatrix A_sub = A.subMatrix(w,width-w,w,width-w);
//        SimpleMatrix expected = I.minus(u_sub.mult(u_sub.transpose()).scale(gamma)).mult(A_sub);
        Matrix temp1 = Multiplications.multiply(u_sub, u_sub.getTranspose());
        temp1.scale(gamma);
        I.sub(temp1);
        Matrix expected = Multiplications.multiply(I, A_sub);

        qr.updateA(w,U.asDoubleArray(),gamma,tau);

        AMatrix found = qr.getQR();

        assertEquals(-tau,found.get(w,w),1e-8);

        for( int i = w+1; i < width; i++ ) {
            assertEquals(U.get(i,0),found.get(i,w),1e-8);
        }

        // the right should be the same
        for( int i = w; i < width; i++ ) {
            for( int j = w+1; j < width; j++ ) {
                double a = expected.get(i-w,j-w);
                double b = found.get(i,j);

                assertEquals(a,b,1e-6);
            }
        }
    }

  @Test
  public void testDecompose() {
    double[][] dataA = { { 0, 3, 1 }, { 0, 4, -2 }, { 2, 1, 1 } };
    Matrix A = Matrix.create(dataA);
    HouseholderQR alg = new HouseholderQR(false);
    IQRResult result = alg.decompose(A);
   
    AMatrix Q = result.getQ();
    AMatrix R = result.getR();

    Matrix expectQ = Matrix.create(new double[][] { { 0, -0.6, 0.8 },
        { 0, -0.8, -0.6 }, { -1, 0, 0 } });
    Matrix expectR = Matrix.create(new double[][] { { -2, -1, -1 },
        { 0, -5, 1 }, { 0, 0, 2 } });
    assertEquals(Q, expectQ);
    assertEquals(R, expectR);

    A = Matrix.create(dataA);
    alg = new HouseholderQR(true);
    result = alg.decompose(A);
    Q = result.getQ();
    R = result.getR();

    assertEquals(Q, expectQ);
    assertEquals(R, expectR);
    validateQR(A, result);
  }

  @Test
  public void testZeroDecompose() {
    AMatrix a = ZeroMatrix.create(4, 3);
    HouseholderQR alg = new HouseholderQR(false);
    IQRResult result = alg.decompose(a);
    AMatrix q = result.getQ();
    AMatrix r = result.getR();

    assertEquals(IdentityMatrix.create(3), q.subMatrix(0, 3, 0, 3));
    assertTrue(r.isZero());
    validateQR(a, result);
  }

  @Test
  public void testZeroDecomposeSquare() {
    AMatrix a = ZeroMatrix.create(3, 3);
    HouseholderQR alg = new HouseholderQR(false);
    IQRResult result = alg.decompose(a);
    AMatrix q = result.getQ();
    AMatrix r = result.getR();

    assertEquals(IdentityMatrix.create(3), q);

    assertTrue(r.isZero());
    validateQR(a, result);
  }

  /**
   * Validate that a QR result is correct for a given input matrix
   *
   * @param a
   * @param result
   */
  public void validateQR(AMatrix a, IQRResult result) {
    AMatrix q = result.getQ();
    AMatrix r = result.getR();
    assertTrue(r.isUpperTriangular());
    assertTrue(q.innerProduct(r).epsilonEquals(a));
    assertTrue(q.hasOrthonormalColumns());
   
  }
 
  private static class DebugQR extends HouseholderQR
    {

        public DebugQR(int numRows, int numCols) {
            super(false);
            setExpectedMaxSize(numRows,numCols);
            this.numRows = numRows;
            this.numCols = numCols;
        }

        private void setExpectedMaxSize(int numRows, int numCols)
        {
            error = false;

            this.numCols = numCols;
            this.numRows = numRows;
            minLength = Math.min(numRows,numCols);
            int maxLength = Math.max(numRows,numCols);

            QR = Matrix.create(numRows, numCols);
            u = new double[ maxLength ];
            v = new double[ maxLength ];

            dataQR = QR.data;

            gammas = new double[ minLength ];
        }

        public void householder( int j , Matrix A ) {
            this.QR.set(A);

            super.householder(j);
        }

        public void updateA( int w , double u[] , double gamma , double tau ) {
            System.arraycopy(u,0,this.u,0,this.u.length);
            this.gamma = gamma;
            this.tau = tau;

            super.updateA(w);
        }

        public double[] getU() {
            return u;
        }

        public double getGamma() {
            return gamma;
        }
    }
}
TOP

Related Classes of mikera.matrixx.decompose.impl.qr.TestHouseholderQR$DebugQR

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.