Reputation: 2856
Trying to solve generalized eigenvalues on the form:
A*V = B*V*D
By using OjAlgo. According to the documentation here A
and B
bust be real symmetric or complex Hermitian and B is positive definite. In this case, both A
and B
are symmetrical and positive definitive.
OjAlgo is the only Java math library that can solve generalized eigenvalue problems. So this must work. But why does my output says that I can't solve it?
public class Eig {
static Logger logger = LoggerFactory.getLogger(Eig.class);
// A*V = B*D*V - Find D and V - Will not work for current OjAlgo version
static public void eig(MatrixStore<Double> Sb, MatrixStore<Double> Sw, Primitive64Store D, Primitive64Store V, long dim) {
// Create eigA and eigB from symmetrical positive definitive A and B
Primitive64Matrix eigA = Primitive64Matrix.FACTORY.rows(Sb.toRawCopy2D());
Primitive64Matrix eigB = Primitive64Matrix.FACTORY.rows(Sw.toRawCopy2D());
System.out.println("Check if eigA and eigB are symmetrical:");
System.out.println(eigA.isSymmetric());
System.out.println(eigB.isSymmetric());
System.out.println("Check if eigA and eigB are positive definitive:");
Primitive64Matrix z = Primitive64Matrix.FACTORY.makeFilled(dim, 1, new Weibull(5, 2));
System.out.println("Positive definitive:");
System.out.println(z.transpose().multiply(eigA).multiply(z).get(0, 0)); // z^T*eigA*z
System.out.println(z.transpose().multiply(eigB).multiply(z).get(0, 0)); // z^T*eigB*z
// Perform [A][V] = [B][V][D]
Eigenvalue.Generalised<Double> eig = Eigenvalue.PRIMITIVE.makeGeneralised(eigA, Generalisation.A_B);
boolean success = eig.computeValuesOnly(eigA, eigB);
if (success == false)
logger.error("Could not perform eigenvalue decomposition!");
System.out.println("Check if D and V are null");
System.out.println(eig.getD() == null);
System.out.println(eig.getV() == null);
// Copy over to D, V
D.fillColumn(0, eig.getD().sliceDiagonal());
double[][] eigV = eig.getV().toRawCopy2D();
for (int i = 0; i < dim; i++) {
V.fillRow(i, Access1D.wrap(eigV[i]));
}
// Sort eigenvalues and eigenvectors descending by eigenvalue
if(eig.isOrdered() == false)
Sort.sortdescended(V, D, dim);
}
}
What have I missed?
Check if eigA and eigB are symmetrical:
true
true
Check if eigA and eigB are positive definitive:
Positive definitive:
1.0766814686417156E10
1.1248634208301022E9
Check if D and V are null:
true
true
Update 1:
The procedure will work If both A
and B
have only positive real values.
Primitive64Store mtrxA = Primitive64Store.FACTORY.makeSPD((int) dim);
Primitive64Matrix eigA = Primitive64Matrix.FACTORY.rows(mtrxA.toRawCopy2D());
Primitive64Store mtrxB = Primitive64Store.FACTORY.makeSPD((int) dim);
Primitive64Matrix eigB = Primitive64Matrix.FACTORY.rows(mtrxB.toRawCopy2D());
PrintMatrix.printMatrix(eigB);
/*
* There are several generalisations. 3 are supported by ojAlgo, specified by the enum:
* Eigenvalue.Generalisation This factory method returns the most common alternative.
*/
Eigenvalue.Generalised<Double> generalisedEvD = Eigenvalue.PRIMITIVE.makeGeneralised(eigA);
// Generalisation: [A][V] = [B][V][D]
// Use 2-args alternative
generalisedEvD.decompose(eigA, eigB);
System.out.println("Check if D and V are null");
System.out.println(generalisedEvD.getD() == null); // false
System.out.println(generalisedEvD.getV() == null); // false
Update 2:
I did run a test with GNU Octave at it seems that all eigenvalues are positive and the rest are negative, but extreamly close to zero.
Here is an output. It's the same data I have used in GNU Octave as in OjAlgo. I think that e-18 can count as a zero.
I build my A
and B
as they should be symmetrical and positive definitive. Is this caused by floating values?
2.7414e+04
9.4155e+03
4.1295e+03
3.1429e+03
-8.4338e-16
-1.6409e-15
Inf
Inf
Inf
Inf
Inf
Inf
Inf
Inf
Inf
Inf
3.4910e-15
-8.7739e-16
-3.1775e-15
-2.8213e-18
-5.0274e-16
1.7329e-18
-1.1330e-15
3.1024e-18
2.3226e-15
-1.6151e-16
-6.8453e-16
1.6111e-17
-1.7850e-18
-1.3411e-18
-2.3916e-18
Upvotes: 0
Views: 156
Reputation: 1320
In the first code example you call:
eig.computeValuesOnly(eigA, eigB);
which will give you the eigenvalues only (no vectors or matrices). In the second example you instead call the usual:
generalisedEvD.decompose(eigA, eigB);
Upvotes: 1