/* * 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.decompose.impl.eigen; import mikera.matrixx.Matrix; import mikera.matrixx.decompose.impl.hessenberg.TridiagonalDecompositionHouseholder; import org.junit.Test; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertTrue; /** * @author Peter Abeles */ public class TestSymmetricQrAlgorithm { /** * There should no need to do anything in this case. */ @Test public void shouldNotChange() { double diag[] = new double[]{2,3,4,5,6}; double off[] = new double[diag.length-1]; SymmetricQrAlgorithm alg = new SymmetricQrAlgorithm(); assertTrue(alg.process(diag.length,diag,off)); for( int i = 0; i < diag.length; i++ ) { assertEquals(1,countNumFound(alg,diag[i],1e-4)); } } /** * The tridiagonal matrix has off diagonal terms now */ @Test public void hasOffDiagonal() { double diag[] = new double[]{2,3,4,5,6}; double off[] = new double[diag.length-1]; for( int i = 1; i < diag.length; i++ ) { off[i-1] = i+0.5; } SymmetricQrAlgorithm alg = new SymmetricQrAlgorithm(); assertTrue(alg.process(diag.length,diag,off)); assertEquals(1,countNumFound(alg,-1.26677,1e-4)); assertEquals(1,countNumFound(alg,0.93171,1e-4)); assertEquals(1,countNumFound(alg,3.11320,1e-4)); assertEquals(1,countNumFound(alg,6.20897,1e-4)); assertEquals(1,countNumFound(alg,11.01290,1e-4)); } /** * Test it against a matrix that has zeros along the diagonal but non zero values along * the off diagonal elements. */ @Test public void zeroDiagonalNotZeroOff() { int N = 5; double diag[] = new double[N]; double off[] = new double[N-1]; for( int i = 0; i < N-1; i++ ) { off[i] = i+0.5; } // A.print(); SymmetricQrAlgorithm alg = new SymmetricQrAlgorithm(); assertTrue(alg.process(N,diag,off)); assertEquals(1,countNumFound(alg,-4.39719,1e-4)); assertEquals(1,countNumFound(alg,-1.29023,1e-4)); assertEquals(1,countNumFound(alg,0,1e-4)); assertEquals(1,countNumFound(alg,1.29023,1e-4)); assertEquals(1,countNumFound(alg,4.39719,1e-4)); } /** * Provide a test case where the same eigenvalue is repeated a few times */ @Test public void multipleEigenvalues() { // DenseMatrix64F A = new DenseMatrix64F(5,5, true, 2.191140, -0.098491, -0.397037, 0.367426, -0.208338, -0.098491, 2.776741, 0.623341, 0.624798, 0.401906, -0.397037, 0.623341, 3.571302, -0.239631, -0.264573, 0.367426, 0.624798, -0.239631, 3.625034, -0.162896, -0.208338, 0.401906, -0.264573, -0.162896, 3.835783); Matrix A = Matrix.create(new double[][] {{2.191140, -0.098491, -0.397037, 0.367426, -0.208338}, {-0.098491, 2.776741, 0.623341, 0.624798, 0.401906}, {-0.397037, 0.623341, 3.571302, -0.239631, -0.264573}, {0.367426, 0.624798, -0.239631, 3.625034, -0.162896}, {-0.208338, 0.401906, -0.264573, -0.162896, 3.835783}}); TridiagonalDecompositionHouseholder tridiag = new TridiagonalDecompositionHouseholder(); tridiag.decompose(A); double diag[] = new double[5]; double off[] = new double[4]; tridiag.getDiagonal(diag,off); SymmetricQrAlgorithm alg = new SymmetricQrAlgorithm(); assertTrue(alg.process(5,diag,off)); assertEquals(3,countNumFound(alg,4,1e-4)); assertEquals(2,countNumFound(alg,2,1e-4)); } /** * Counts the number of times the specified eigenvalue appears. */ public int countNumFound( SymmetricQrAlgorithm alg , double val , double tol ) { int total = 0; for( int i = 0; i < alg.getNumberOfEigenvalues(); i++ ) { double a = alg.getEigenvalue(i); if( Math.abs(a-val) <= tol ) { total++; } } return total; } }