/** Checks to see if all the real eigenvectors are linearly independent of each other. */ public void testVectorsLinearlyIndependent(SymmetricQRAlgorithmDecomposition alg) { int N = alg.getNumberOfEigenvalues(); // create a matrix out of the eigenvectors Matrix A = Matrix.create(N, N); int off = 0; for (int i = 0; i < N; i++) { AVector v = alg.getEigenVector(i); // it can only handle real eigenvectors if (v == null) off++; else { for (int j = 0; j < N; j++) { A.set(i - off, j, v.get(j)); } } } // see if there are any real eigenvectors if (N == off) return; // A.reshape(N-off,N, false); A = A.reshape(N - off, N); AltLU lu = new AltLU(); lu._decompose(A); assertFalse(lu.isSingular()); // assertTrue(MatrixFeatures.isRowsLinearIndependent(A)); }
/** * Preforms standard tests that can be performed on any decomposition without prior knowledge of * what the results should be. */ public void performStandardTests(SymmetricQRAlgorithmDecomposition alg, Matrix A, int numReal) { // basic sanity tests assertEquals(A.rowCount(), alg.getNumberOfEigenvalues()); if (numReal >= 0) { for (int i = 0; i < A.rowCount(); i++) { Vector2 v = alg.getEigenvalue(i); assertFalse(Double.isNaN(v.x)); if (v.y == 0) numReal--; else if (Math.abs(v.y) < 10 * EPS) numReal--; } // if there are more than the expected number of real eigenvalues this will // be negative assertEquals(0, numReal); } // checkCharacteristicEquation(alg,A); if (computeVectors) { testPairsConsistent(alg, A); testVectorsLinearlyIndependent(alg); } }
/** If the eigenvalues are all known, real, and the same this can be used to check them. */ public void testEigenvalues(SymmetricQRAlgorithmDecomposition alg, double expected) { for (int i = 0; i < alg.getNumberOfEigenvalues(); i++) { Vector2 c = alg.getEigenvalue(i); assertTrue(c.y == 0); assertEquals(expected, c.x, 1e-8); } }
public void checkAllZeros() { Matrix A = Matrix.create(5, 5); SymmetricQRAlgorithmDecomposition alg = createDecomposition(); assertNotNull(alg.decompose(A)); performStandardTests(alg, A, 5); testEigenvalues(alg, 0); }
/** * For some eigenvector algorithms this is a difficult matrix that requires a special check for. * If it fails that check it will either loop forever or exit before converging. */ public void checkExceptional() { Matrix A = Matrix.create( new double[][] { {0, 0, 0, 0, 1}, {1, 0, 0, 0, 0}, {0, 1, 0, 0, 0}, {0, 0, 1, 0, 0}, {0, 0, 0, 1, 0} }); SymmetricQRAlgorithmDecomposition alg = createDecomposition(); assertNotNull(alg.decompose(A)); performStandardTests(alg, A, 1); }
public void checkLargeValue(boolean symmetric) { for (int i = 0; i < 20; i++) { SymmetricQRAlgorithmDecomposition alg = createDecomposition(); Matrix z = Matrix.createRandom(3, 3); Matrix A = z.innerProduct(z.getTranspose()); // symmetric // CommonOps.scale(1e-200,A); // A.scale(1e100); assertNotNull(alg.decompose(A)); performStandardTests(alg, A, -1); } }
public void checkIdentity() { Matrix I = Matrix.createIdentity(4); SymmetricQRAlgorithmDecomposition alg = createDecomposition(); assertNotNull(alg.decompose(I)); performStandardTests(alg, I, 4); testForEigenpair(alg, 1, 0, 1, 0, 0, 0); testForEigenpair(alg, 1, 0, 0, 1, 0, 0); testForEigenpair(alg, 1, 0, 0, 0, 1, 0); testForEigenpair(alg, 1, 0, 0, 0, 0, 1); }
/** Check results against symmetric matrices that are randomly generated */ public void checkRandomSymmetric() { for (int N = 1; N <= 15; N++) { for (int i = 0; i < 20; i++) { // DenseMatrix64F A = RandomMatrices.createSymmetric(N,-1,1,rand); AMatrix z = Matrixx.createRandomMatrix(3, 3); AMatrix A = z.innerProduct(z.getTranspose()); SymmetricQRAlgorithmDecomposition alg = createDecomposition(); assertNotNull(alg.decompose(A)); performStandardTests(alg, A.toMatrix(), -1); } } }
/** Sees if it correctly computed the eigenvalues. Does not check eigenvectors. */ public void checkKnownSymmetric_JustValue() { Matrix A = Matrix.create( new double[][] { {0.98139, 0.78650, 0.78564}, {0.78650, 1.03207, 0.29794}, {0.78564, 0.29794, 0.91926} }); SymmetricQRAlgorithmDecomposition alg = createDecomposition(); assertNotNull(alg.decompose(A)); testForEigenvalue(alg, A, 0.00426, 0, 1); testForEigenvalue(alg, A, 0.67856, 0, 1); testForEigenvalue(alg, A, 2.24989, 0, 1); }
/** * Compare results against a simple matrix with known results where some the eigenvalues are real * and some are complex. */ public void checkKnownComplex() { Matrix A = Matrix.create( new double[][] { {-0.418284, 0.279875, 0.452912}, {-0.093748, -0.045179, 0.310949}, {0.250513, -0.304077, -0.031414} }); SymmetricQRAlgorithmDecomposition alg = createDecomposition(); assertNotNull(alg.decompose(A)); performStandardTests(alg, A, -1); testForEigenpair(alg, -0.39996, 0, 0.87010, 0.43425, -0.23314); testForEigenpair(alg, -0.04746, 0.02391); testForEigenpair(alg, -0.04746, -0.02391); }
public void testForEigenvalue( SymmetricQRAlgorithmDecomposition alg, Matrix A, double valueReal, double valueImg, int numMatched) { int N = alg.getNumberOfEigenvalues(); int numFound = 0; for (int i = 0; i < N; i++) { Vector2 c = alg.getEigenvalue(i); if (Math.abs(c.x - valueReal) < 1e-4 && Math.abs(c.y - valueImg) < 1e-4) { numFound++; } } assertEquals(numMatched, numFound); }
/** * Create a variety of different random matrices of different sizes and sees if they pass the * standard eigen decompositions tests. */ public void checkRandom() { int sizes[] = new int[] {1, 2, 5, 10, 20, 50, 100, 200}; SymmetricQRAlgorithmDecomposition alg = createDecomposition(); for (int s = 2; s < sizes.length; s++) { int N = sizes[s]; // System.out.println("N = "+N); for (int i = 0; i < 2; i++) { Matrix A = Matrix.createRandom(N, N); A.multiply(2); A.sub(1); assertNotNull(alg.decompose(A)); performStandardTests(alg, A, -1); } } }
/** See if eigenvalues cause the characteristic equation to have a value of zero */ public void checkCharacteristicEquation(SymmetricQRAlgorithmDecomposition alg, Matrix A) { int N = alg.getNumberOfEigenvalues(); Matrix a = Matrix.create(A); for (int i = 0; i < N; i++) { Vector2 c = alg.getEigenvalue(i); if (Math.abs(c.y - 0) < 1e-8) { // test using the characteristic equation Matrix temp = Matrix.createIdentity(A.columnCount()); temp.scale(c.x); temp.sub(a); double det = temp.determinant(); // extremely crude test. given perfect data this is probably considered a failure... // However, // its hard to tell what a good test value actually is. assertEquals(0, det, 0.1); } } }
/** Sees if the pair of eigenvalue and eigenvector was found in the decomposition. */ public void testForEigenpair( SymmetricQRAlgorithmDecomposition alg, double valueReal, double valueImg, double... vector) { int N = alg.getNumberOfEigenvalues(); int numMatched = 0; for (int i = 0; i < N; i++) { Vector2 c = alg.getEigenvalue(i); if (Math.abs(c.x - valueReal) < 1e-4 && Math.abs(c.y - valueImg) < 1e-4) { // if( c.isReal() ) { if (Math.abs(c.y - 0) < 1e-8) if (vector.length > 0) { AVector v = alg.getEigenVector(i); AMatrix e = Matrix.createFromRows(vector); e = e.getTranspose(); Matrix t = Matrix.create(v.length(), 1); t.setColumn(0, v); double error = diffNormF(e, t); // CommonOps.changeSign(e); e.multiply(-1); double error2 = diffNormF(e, t); if (error < 1e-3 || error2 < 1e-3) numMatched++; } else { numMatched++; } else if (Math.abs(c.y - 0) > 1e-8) { numMatched++; } } } assertEquals(1, numMatched); }
public SymmetricQRAlgorithmDecomposition createDecomposition() { SymmetricQRAlgorithmDecomposition alg = new SymmetricQRAlgorithmDecomposition(computeVectors); if (computeVectors) alg.setComputeVectorsWithValues(together); return alg; }
/** * Checks to see if an eigenvalue is complex then the eigenvector is null. If it is real it then * checks to see if the equation A*v = lambda*v holds true. */ public void testPairsConsistent(SymmetricQRAlgorithmDecomposition alg, Matrix A) { // // System.out.println("-------------------------------------------------------------------------"); int N = alg.getNumberOfEigenvalues(); for (int i = 0; i < N; i++) { Vector2 c = alg.getEigenvalue(i); AVector v = alg.getEigenVector(i); if (Double.isInfinite(c.x) || Double.isNaN(c.x) || Double.isInfinite(c.y) || Double.isNaN(c.y)) fail("Uncountable eigenvalue"); if (Math.abs(c.y) > 1e-20) { assertTrue(v == null); } else { assertTrue(v != null); // if( MatrixFeatures.hasUncountable(v)) { // throw new RuntimeException("Egads"); // } assertFalse(v.hasUncountable()); // CommonOps.mult(A,v,tempA); Matrix ta = Matrix.create(A.rowCount(), 1); ta.setColumn(0, (v)); AMatrix tempA = Multiplications.multiply(A, ta); // CommonOps.scale(c.real,v,tempB); Matrix tb = Matrix.create(v.length(), 1); tb.setColumn(0, v); AMatrix tempB = tb.multiplyCopy(c.x); // double max = NormOps.normPInf(A); double max = normPInf(A); if (max == 0) max = 1; double error = diffNormF(tempA, tempB) / max; if (error > 1e-12) { // System.out.println("Original matrix:"); // System.out.println(A); // A.print(); // System.out.println("Eigenvalue = "+c.x); // Eigenpair p = EigenOps.computeEigenVector(A,c.real); // p.vector.print(); // v.print(); // // // CommonOps.mult(A,p.vector,tempA); // CommonOps.scale(c.real,p.vector,tempB); // // max = NormOps.normPInf(A); // // System.out.println("error before = "+error); // error = SpecializedOps.diffNormF(tempA,tempB)/max; // System.out.println("error after = "+error); // A.print("%f"); // System.out.println(); fail("Error was too large"); } assertTrue(error <= 1e-12); } } }