josdejong / mathjs

An extensive math library for JavaScript and Node.js
https://mathjs.org
Apache License 2.0
14.32k stars 1.24k forks source link

3x3 matrix where eigenvalues fail to converge #3036

Open gwhitney opened 11 months ago

gwhitney commented 11 months ago

Describe the bug Exercise 7.7.103 of https://web.uvic.ca/~tbazett/diffyqs/sec_multeigen.html produces "The eigenvalues failed to converge" error. I feel mathjs should be able to handle elementary textbook examples, especially for such a small matrix. Admittedly, this is a case where all three eigenvalues are equal, and the current method relies on differences of eigenvalues to converge, so it was sort of doomed, but really mathjs should have alternate methods to use in such a case.

To Reproduce math.eigs([[2, 0, 0], [-1, -1, 9], [0, -1, 5]])

Note further that although this is a case of a defective matrix (the algebraic multiplicity of eigenvalue 2 is three, but its geometric multiplicity is only one), this error is independent of #2879: it occurs before eigenvalues have even been determined, and so the code to search for eigenvectors is never even invoked. If we can get mathjs to realize that 2 is an eigenvalue of algebraic multiplicity three, then the findEigenvectors code might (or might not) properly discover the unique eigenvector proportional to [0, 3, 1].

gwhitney commented 11 months ago

The situation will be much improved by the merging of #3037; there, one can go up to config.epsilon precision and beyond (although it doesn't make the eigenvalues any closer beyond that) and get the eigenvalues to match to within 6 parts in a million. That's still not very accurate for double precision arithmetic, and not accurate enough to realize there is only one eigenvector. So this still needs improvement someday, either by switching to the full Francis implicit QR iteration, or using better shifts, or both, or by using some other eigenvalue algorithm, or by using a better-optimized library rather than implementing eigenvectors directly within mathjs.