Added rigging for checking eigenvalues and eigenvectors and some easy test cases.

git-svn-id: https://svn.apache.org/repos/asf/commons/proper/math/branches/MATH_2_0@721943 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
Phil Steitz 2008-12-01 01:34:56 +00:00
parent 2924cfdf77
commit 543a3ca57e
1 changed files with 101 additions and 0 deletions

View File

@ -256,6 +256,107 @@ public class EigenDecompositionImplTest extends TestCase {
} }
/**
* Matrix with eigenvalues {8, -1, -1}
*/
public void testRepeatedEigenvalue() {
RealMatrix repeated = new RealMatrixImpl(new double[][] {
{3, 2, 4},
{2, 0, 2},
{4, 2, 3}
});
EigenDecomposition ed = new EigenDecompositionImpl(repeated);
checkEigenValues((new double[] {8, -1, -1}), ed, 1E-12);
checkEigenVector((new double[] {2, 1, 2}), ed, 1E-12);
}
/**
* Matrix with eigenvalues {2, 0, 12}
*/
public void testDistinctEigenvalues() {
RealMatrix distinct = new RealMatrixImpl(new double[][] {
{3, 1, -4},
{1, 3, -4},
{-4, -4, 8}
});
EigenDecomposition ed = new EigenDecompositionImpl(distinct);
checkEigenValues((new double[] {2, 0, 12}), ed, 1E-12);
checkEigenVector((new double[] {1, -1, 0}), ed, 1E-12);
checkEigenVector((new double[] {1, 1, 1}), ed, 1E-12);
checkEigenVector((new double[] {-1, -1, 2}), ed, 1E-12);
}
/**
* Verifies that the given EigenDecomposition has eigenvalues equivalent to
* the targetValues, ignoring the order of the values and allowing
* values to differ by tolerance.
*/
protected void checkEigenValues(double[] targetValues,
EigenDecomposition ed, double tolerance) {
double[] observed = ed.getEigenvalues();
for (int i = 0; i < observed.length; i++) {
assertTrue(isIncludedValue(observed[i], targetValues, tolerance));
assertTrue(isIncludedValue(targetValues[i], observed, tolerance));
}
}
/**
* Returns true iff there is an entry within tolerance of value in
* searchArray.
*/
private boolean isIncludedValue(double value, double[] searchArray,
double tolerance) {
boolean found = false;
int i = 0;
while (!found && i < searchArray.length) {
if (Math.abs(value - searchArray[i]) < tolerance) {
found = true;
}
i++;
}
return found;
}
/**
* Returns true iff eigenVector is a scalar multiple of one of the columns
* of ed.getV(). Does not try linear combinations - i.e., should only be
* used to find vectors in one-dimensional eigenspaces.
*/
protected void checkEigenVector(double[] eigenVector,
EigenDecomposition ed, double tolerance) {
assertTrue(isIncludedColumn(eigenVector, ed.getV(), tolerance));
}
/**
* Returns true iff there is a column that is a scalar multiple of column
* in searchMatrix (modulo tolerance)
*/
private boolean isIncludedColumn(double[] column, RealMatrix searchMatrix,
double tolerance) {
boolean found = false;
int i = 0;
while (!found && i < searchMatrix.getColumnDimension()) {
double multiplier = 1d;
boolean matching = true;
int j = 0;
while (matching && j < searchMatrix.getRowDimension()) {
double colEntry = searchMatrix.getEntry(j, i);
// Use the first entry where both are non-zero as scalar
if (multiplier == 1d && Math.abs(colEntry) > 1E-14
&& Math.abs(column[j]) > 1e-14) {
multiplier = colEntry / column[j];
}
if (Math.abs(column[j] * multiplier - colEntry) > tolerance) {
matching = false;
}
j++;
}
found = matching;
i++;
}
return found;
}
public void setUp() { public void setUp() {
refValues = new double[] { refValues = new double[] {
2.003, 2.002, 2.001, 1.001, 1.000, 0.001 2.003, 2.002, 2.001, 1.001, 1.000, 0.001