# Finding eigenvalues with the smallest magnitude using eigs

I have a large Hermitian sparse matrix, and I’d like to get a few of the eigenvalues with the smallest magnitude. I’m using the “eigs” function in Arpack however I get this error message:
“ZeroPivotException: factorization encountered one or more zero pivots. Consider switching to a pivoted LU factorization.”
Does anyone know how to get around this error? Is it possible to tell eigs to use pivoted LU factorization instead?

If you are getting zero pivots, then you know that the matrix is singular, and therefore the eigenvalue of smallest magnitude is `0`. Perhaps you could work around this with a `try`/`catch` block? (I am unfamiliar with Arpack.)

Thanks for your reply. It’s indeed true that the eigenvalue with the smallest magnitude is zero(Actually more than one). But why would that be a problem for the algorithm?
I’m unfamiliar with try/except block. Could you explain what it does?

See here in the docs: Control Flow · The Julia Language

A `try`/`catch` block (I misspoke when I wrote `try`/`except` earlier, which is the Python equivalent) basically says, “try doing this calculation, and if it produces an error `e`, do this other thing.” In your case, you would try the `eigs` function, and if it catches `ZeroPivotException`, return zero. Something like

``````function smallestmagnitudeeigenvalue(A)
try
return minimum(abs.(eigs(A)))
catch e
if isa(e, ZeroPivotException)
return 0.0
else
throw(e)
end
end
end
``````

I would say use a shift to calculate nonzero eigenvalues. Then, when you undo the shift, you can decide whether or not you are interested in the eigenvalues which would be zero or close to zero. It is possible that your matrix may have one or more zero eigenvalue, depending on the application.

1 Like

To elaborate: the algorithm for smallest magnitude eigenvalues is a shift-and-invert scheme. The default is to use a shift of zero, but if there are actually zero eigenvalues (or close enough to zero) this fails, so one should pick some other small shift. (If you know that your matrix is semi-definite, you should probably use “smallest real” instead.)

Similar question here:

With

``````ham = sparse([1, 3, 4, 1, 6, 1, 6, 3, 4, 6], [1, 1, 1, 3, 3, 4, 4, 6, 6, 6], [5.0, 1.0, -1.0, 1.0, 1.0, -1.0, -1.0, 1.0, -1.0, 5.0], 6, 6)
``````

this errors

``````eigs(ham, nev=1, which=:SM)
``````

but this works

``````eigs(ham, nev=1, which=:SR)
``````

Maybe consider using instead KrylovKit.jl or ArnoldiMethod.jl. These packages don’t implement the shift-and-invert method, but it is easy to write a function that does so as detailed here: Transformations · ArnoldiMethod.jl. The good thing is that you can choose the factorization that is used to solve the linear systems.

1 Like

Thanks!
Smallest real doesn’t work because the matrix has negative eigenvalues which are different than the eigenvalues with the smallest magnitude (These are the eigenvalues I’m interested in)

A quick search on google lead me to this post. It suggests this method:

``````using Arpack, SparseArrays

a=sprandn(100,100,0.01)+I; a[:,1].=0; dropzeros!(a);
maxev = eigs(a,nev=1, which=:LM)
_minev,minevec = eigs(a-maxev*I,nev=1, which=:LM)
minev = _minev+maxev
``````

should give you a `minev` that is approximately zero.