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:
parent
2924cfdf77
commit
543a3ca57e
|
@ -255,6 +255,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() {
|
||||
refValues = new double[] {
|
||||
|
|
Loading…
Reference in New Issue