5

I would like to get eigenvectors of a sparse symmetric matrix with the best precision affordable in a given time.
Currently I use the following with scipy.sparse.eigsh:

evals, evecs = eigsh(MyMatrix, 2,which='LM' ,tol=1.e-15, maxiter=1000000)

If it does not converge to tol precision by maxiter iterations, it raises an ArpackNoConvergence error which contains the eigenvectors/values that have converged, but not the ones that did not. Yet, I prefer to have the vector with precision 1.e-14 instead of 1.e-15 rather than no vector at all. Is there a way to force returning the eigenvectors that have not converged yet (perhaps with another library) ?
Like in Matlab, where the eigs function returns the eigenvectors anyway, with just an additional Warning if the desired precision is not reached.

Thanks !

denis
  • 21,378
  • 10
  • 65
  • 88
Ant Plante
  • 93
  • 8

1 Answers1

1

The ArpackNoConvergence exception has .eigenvalues and .eigenvectors attributes that contain the partial results:

import numpy as np
from scipy.sparse.linalg import eigsh, ArpackNoConvergence

M = np.random.RandomState(0).randn(100, 100)

try:
    w, v = eigsh(M, 5, maxiter=20)
except ArpackNoConvergence as e:
    print(e)
    w = e.eigenvalues
    v = e.eigenvectors
    print(w.shape, v.shape)

Prints:

ARPACK error -1: No convergence (21 iterations, 2/5 eigenvectors converged)
((2,), (100, 2))
ali_m
  • 71,714
  • 23
  • 223
  • 298
  • Thanks! But what I want is to access the eingenvalue/vector that was being calculated and did not fully converge. The exception only contains the ones that have converged to the required precision. I would like to have the best precision available in a given number of iterations. – Ant Plante Nov 02 '15 at 12:46
  • 1
    I suppose that one quick workaround would be to iteratively reduce the tolerance until `eigs` no longer converges within the specified number of iterations. Aside from that, I think it ought to be possible to get the partially converged eigenvalues/vectors by manually constructing a [`scipy.sparse.linalg.arpack._SymmetricArpackParams`](https://github.com/scipy/scipy/blob/master/scipy/sparse/linalg/eigen/arpack/arpack.py#L370-L585) object, calling `.iterate()` on it, then recovering the eigenvalues/vectors using `.extract()` when the iteration fails. – ali_m Nov 02 '15 at 13:03
  • Yes, I thought about that quickaround. Okay, thanks a lot ! – Ant Plante Nov 03 '15 at 17:50
  • @AntPlante @ali_m The discussion above looks very helpful. Just wanted to check if there are any updates on this question. I was still not able to get a non-converged answer. The `extract()` method does not even generate a partially converged answer. – eafit Feb 27 '17 at 19:44
  • 1
    @eafit No update so far for me. The fix I use is to set the number of Lanczos vectors (`ncv` keyword argument of eigsh) higher than default, which makes it converge but run longer in my problem, `eigsh(MyMatrix, 2, which='LM', tol=1.e-15, ncv=15)` – Ant Plante Mar 01 '17 at 09:06