I'm trying to compute eigenvalues of a symbolic complex matrix M
of size 3x3
. In some cases, eigenvals()
works perfectly. For example, the following code:
import sympy as sp
kx = sp.symbols('kx')
x = 0.
M = sp.Matrix([[0., 0., 0.], [0., 0., 0.], [0., 0., 0.]])
M[0, 0] = 1.
M[0, 1] = 2./3.
M[0, 2] = 2./3.
M[1, 0] = sp.exp(1j*kx) * 1./6. + x
M[1, 1] = sp.exp(1j*kx) * 2./3.
M[1, 2] = sp.exp(1j*kx) * -1./3.
M[2, 0] = sp.exp(-1j*kx) * 1./6.
M[2, 1] = sp.exp(-1j*kx) * -1./3.
M[2, 2] = sp.exp(-1j*kx) * 2./3.
dict_eig = M.eigenvals()
returns me 3 correct complex symbolic eigenvalues of M
. However, when I set x=1.
, I get the following error:
raise MatrixError("Could not compute eigenvalues for {}".format(self))
I also tried to compute eigenvalues as follows:
lam = sp.symbols('lambda')
cp = sp.det(M - lam * sp.eye(3))
eigs = sp.solveset(cp, lam)
but it returns me a ConditionSet
in any case, even when eigenvals()
can do the job.
Does anyone know how to properly solve this eigenvalue problem, for any value of x
?
Your definition of M made life too hard for SymPy because it introduced floating point numbers. When you want a symbolic solution, floats are to be avoided. That means:
1./3.
(Python's floating point number) usesp.Rational(1, 3)
(SymPy's rational number) orsp.S(1)/3
which has the same effect but is easier to type.1j
(Python's imaginary unit) usesp.I
(SymPy's imaginary unit)x = 1.
, writex = 1
(Python 2.7 habits and SymPy go poorly together).With these changes either
solveset
orsolve
find the eigenvalues, althoughsolve
gets them much faster. Also, you can make a Poly object and applyroots
to it, which is probably most efficient:(It would be easier to do
from sympy import *
than type all these sp.)I'm not quite clear on why SymPy's eigenvals method reports failure even with the above modifications. As you can see in the source, it doesn't do much more than what the above code does: call
roots
on the characteristic polynomial. The difference appears to be in the way this polynomial is created:M.charpoly(lam)
returnswith mysterious (to me)
domain='EX'
. Subsequently, an application ofroots
returns{}
, no roots found. Looks like a deficiency of the implementation.