/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You 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 org.apache.commons.math.linear;
import java.util.Arrays;
import java.util.Random;
import org.apache.commons.math.linear.EigenDecomposition;
import org.apache.commons.math.linear.EigenDecompositionImpl;
import org.apache.commons.math.linear.MatrixUtils;
import org.apache.commons.math.linear.RealMatrix;
import org.apache.commons.math.linear.RealVector;
import org.apache.commons.math.linear.TriDiagonalTransformer;
import org.apache.commons.math.util.MathUtils;
import junit.framework.Test;
import junit.framework.TestCase;
import junit.framework.TestSuite;
public class EigenDecompositionImplTest extends TestCase {
private double[] refValues;
private RealMatrix matrix;
public EigenDecompositionImplTest(String name) {
super(name);
}
public static Test suite() {
TestSuite suite = new TestSuite(EigenDecompositionImplTest.class);
suite.setName("EigenDecompositionImpl Tests");
return suite;
}
public void testDimension1() {
RealMatrix matrix =
MatrixUtils.createRealMatrix(new double[][] { { 1.5 } });
EigenDecomposition ed = new EigenDecompositionImpl(matrix, MathUtils.SAFE_MIN);
assertEquals(1.5, ed.getRealEigenvalue(0), 1.0e-15);
}
public void testDimension2() {
RealMatrix matrix =
MatrixUtils.createRealMatrix(new double[][] {
{ 59.0, 12.0 },
{ 12.0, 66.0 }
});
EigenDecomposition ed = new EigenDecompositionImpl(matrix, MathUtils.SAFE_MIN);
assertEquals(75.0, ed.getRealEigenvalue(0), 1.0e-15);
assertEquals(50.0, ed.getRealEigenvalue(1), 1.0e-15);
}
public void testDimension3() {
RealMatrix matrix =
MatrixUtils.createRealMatrix(new double[][] {
{ 39632.0, -4824.0, -16560.0 },
{ -4824.0, 8693.0, 7920.0 },
{ -16560.0, 7920.0, 17300.0 }
});
EigenDecomposition ed = new EigenDecompositionImpl(matrix, MathUtils.SAFE_MIN);
assertEquals(50000.0, ed.getRealEigenvalue(0), 3.0e-11);
assertEquals(12500.0, ed.getRealEigenvalue(1), 3.0e-11);
assertEquals( 3125.0, ed.getRealEigenvalue(2), 3.0e-11);
}
public void testDimension4WithSplit() {
RealMatrix matrix =
MatrixUtils.createRealMatrix(new double[][] {
{ 0.784, -0.288, 0.000, 0.000 },
{ -0.288, 0.616, 0.000, 0.000 },
{ 0.000, 0.000, 0.164, -0.048 },
{ 0.000, 0.000, -0.048, 0.136 }
});
EigenDecomposition ed = new EigenDecompositionImpl(matrix, MathUtils.SAFE_MIN);
assertEquals(1.0, ed.getRealEigenvalue(0), 1.0e-15);
assertEquals(0.4, ed.getRealEigenvalue(1), 1.0e-15);
assertEquals(0.2, ed.getRealEigenvalue(2), 1.0e-15);
assertEquals(0.1, ed.getRealEigenvalue(3), 1.0e-15);
}
public void testDimension4WithoutSplit() {
RealMatrix matrix =
MatrixUtils.createRealMatrix(new double[][] {
{ 0.5608, -0.2016, 0.1152, -0.2976 },
{ -0.2016, 0.4432, -0.2304, 0.1152 },
{ 0.1152, -0.2304, 0.3088, -0.1344 },
{ -0.2976, 0.1152, -0.1344, 0.3872 }
});
EigenDecomposition ed = new EigenDecompositionImpl(matrix, MathUtils.SAFE_MIN);
assertEquals(1.0, ed.getRealEigenvalue(0), 1.0e-15);
assertEquals(0.4, ed.getRealEigenvalue(1), 1.0e-15);
assertEquals(0.2, ed.getRealEigenvalue(2), 1.0e-15);
assertEquals(0.1, ed.getRealEigenvalue(3), 1.0e-15);
}
/** test a matrix already in tridiagonal form. */
public void testTridiagonal() {
Random r = new Random(4366663527842l);
double[] ref = new double[30];
for (int i = 0; i < ref.length; ++i) {
if (i < 5) {
ref[i] = 2 * r.nextDouble() - 1;
} else {
ref[i] = 0.0001 * r.nextDouble() + 6;
}
}
Arrays.sort(ref);
TriDiagonalTransformer t =
new TriDiagonalTransformer(createTestMatrix(r, ref));
EigenDecomposition ed =
new EigenDecompositionImpl(t.getMainDiagonalRef(),
t.getSecondaryDiagonalRef(),
MathUtils.SAFE_MIN);
double[] eigenValues = ed.getRealEigenvalues();
assertEquals(ref.length, eigenValues.length);
for (int i = 0; i < ref.length; ++i) {
assertEquals(ref[ref.length - i - 1], eigenValues[i], 2.0e-14);
}
}
/** test dimensions */
public void testDimensions() {
final int m = matrix.getRowDimension();
EigenDecomposition ed = new EigenDecompositionImpl(matrix, MathUtils.SAFE_MIN);
assertEquals(m, ed.getV().getRowDimension());
assertEquals(m, ed.getV().getColumnDimension());
assertEquals(m, ed.getD().getColumnDimension());
assertEquals(m, ed.getD().getColumnDimension());
assertEquals(m, ed.getVT().getRowDimension());
assertEquals(m, ed.getVT().getColumnDimension());
}
/** test eigenvalues */
public void testEigenvalues() {
EigenDecomposition ed = new EigenDecompositionImpl(matrix, MathUtils.SAFE_MIN);
double[] eigenValues = ed.getRealEigenvalues();
assertEquals(refValues.length, eigenValues.length);
for (int i = 0; i < refValues.length; ++i) {
assertEquals(refValues[i], eigenValues[i], 3.0e-15);
}
}
/** test eigenvalues for a big matrix. */
public void testBigMatrix() {
Random r = new Random(17748333525117l);
double[] bigValues = new double[200];
for (int i = 0; i < bigValues.length; ++i) {
bigValues[i] = 2 * r.nextDouble() - 1;
}
Arrays.sort(bigValues);
EigenDecomposition ed =
new EigenDecompositionImpl(createTestMatrix(r, bigValues), MathUtils.SAFE_MIN);
double[] eigenValues = ed.getRealEigenvalues();
assertEquals(bigValues.length, eigenValues.length);
for (int i = 0; i < bigValues.length; ++i) {
assertEquals(bigValues[bigValues.length - i - 1], eigenValues[i], 2.0e-14);
}
}
/** test eigenvectors */
public void testEigenvectors() {
EigenDecomposition ed = new EigenDecompositionImpl(matrix, MathUtils.SAFE_MIN);
for (int i = 0; i < matrix.getRowDimension(); ++i) {
double lambda = ed.getRealEigenvalue(i);
RealVector v = ed.getEigenvector(i);
RealVector mV = matrix.operate(v);
assertEquals(0, mV.subtract(v.mapMultiplyToSelf(lambda)).getNorm(), 1.0e-13);
}
}
/** test A = VDVt */
public void testAEqualVDVt() {
EigenDecomposition ed = new EigenDecompositionImpl(matrix, MathUtils.SAFE_MIN);
RealMatrix v = ed.getV();
RealMatrix d = ed.getD();
RealMatrix vT = ed.getVT();
double norm = v.multiply(d).multiply(vT).sub