如何在Python中绘制表示符号函数的特征值?

时间:2019-04-22 20:47:16

标签: python plot linear-algebra sympy symbolic-math

我需要计算8x8矩阵的特征值,并绘制矩阵中出现的符号变量的每个特征值。对于矩阵,我使用8个不同的特征值,每个特征值均以“ W”表示一个函数,这是我的符号变量。

我使用python我尝试使用Scipy和Sympy计算特征值,但是结果以一种奇怪的方式存储(至少对我而言,到目前为止还不了解很多编程知识),但我没有发现一种仅提取一个特征值以进行绘制的方法。

import numpy as np
import sympy as sp

W = sp.Symbol('W')

w0=1/780
wl=1/1064

# This is my 8x8-matrix
A= sp.Matrix([[w0+3*wl, 2*W, 0, 0, 0, np.sqrt(3)*W, 0, 0],
    [2*W, 4*wl, 0, 0, 0, 0, 0, 0],
    [0, 0, 2*wl+w0, np.sqrt(3)*W, 0, 0, 0, np.sqrt(2)*W],
    [0, 0, np.sqrt(3)*W, 3*wl, 0, 0, 0, 0],
    [0, 0, 0, 0, wl+w0, np.sqrt(2)*W, 0, 0],
    [np.sqrt(3)*W, 0, 0, 0, np.sqrt(2)*W, 2*wl, 0, 0],
    [0, 0, 0, 0, 0, 0, w0, W],
    [0, 0, np.sqrt(2)*W, 0, 0, 0, W, wl]])

# Calculating eigenvalues
eva = A.eigenvals()
evaRR = np.array(list(eva.keys()))
eva1p = evaRR[0]   # <- this is my try to refer to the first eigenvalue

最后,我希望得到一个关于“ W”的图,有趣的范围是[-0.002 0.002]。对于感兴趣的人来说,它是关于原子物理学的,W是狂犬病的频率,我正在研究所谓的着装状态。

1 个答案:

答案 0 :(得分:0)

您没有做任何不正确的事情-我想您只是被赶上了,因为您的特征值看起来是如此混乱和复杂。

import numpy as np
import sympy as sp
import matplotlib.pyplot as plt

W = sp.Symbol('W')

w0=1/780
wl=1/1064

# This is my 8x8-matrix
A= sp.Matrix([[w0+3*wl, 2*W, 0, 0, 0, np.sqrt(3)*W, 0, 0],
    [2*W, 4*wl, 0, 0, 0, 0, 0, 0],
    [0, 0, 2*wl+w0, np.sqrt(3)*W, 0, 0, 0, np.sqrt(2)*W],
    [0, 0, np.sqrt(3)*W, 3*wl, 0, 0, 0, 0],
    [0, 0, 0, 0, wl+w0, np.sqrt(2)*W, 0, 0],
    [np.sqrt(3)*W, 0, 0, 0, np.sqrt(2)*W, 2*wl, 0, 0],
    [0, 0, 0, 0, 0, 0, w0, W],
    [0, 0, np.sqrt(2)*W, 0, 0, 0, W, wl]])

# Calculating eigenvalues
eva = A.eigenvals()
evaRR = np.array(list(eva.keys()))
# The above is copied from your question
# We have to answer what exactly the eigenvalue is in this case
print(type(evaRR[0])) # >>> Piecewise
# Okay, so it's a piecewise function (link to documentation below).
# In the documentation we see that we can use the .subs method to evaluate
# the piecewise function by substituting a symbol for a value. For instance,

print(evaRR[0].subs(W, 0)) # Will substitute 0 for W
# This prints out something really nasty with tons of fractions.. 
# We can evaluate this mess with sympy's numerical evaluation method, N
print(sp.N(evaRR[0].subs(W, 0))) 
# >>> 0.00222190090611143 - 6.49672880062804e-34*I

# That's looking more like it! Notice the e-34 exponent on the imaginary part...
# I think it's safe to assume we can just trim that off.
# This is done by setting the chop keyword to True when using N:
print(sp.N(evaRR[0].subs(W, 0), chop=True)) # >>> 0.00222190090611143


# Now let's try to plot each of the eigenvalues over your specified range
fig, ax = plt.subplots(3, 3) # 3x3 grid of plots (for our 8 e.vals)
ax = ax.flatten() # This is so we can index the axes easier

plot_range = np.linspace(-0.002, 0.002, 10) # Range from -0.002 to 0.002 with 10 steps
for n in range(8):
    current_eigenval = evaRR[n]
    # There may be a way to vectorize this computation, but I'm not familiar enough with sympy.
    evaluated_array = np.zeros(np.size(plot_range))
    # This will be our Y-axis (or W-value). It is set to be the same shape as
    # plot_range and is initally filled with all zeros.

    for i in range(np.size(plot_range)):
        evaluated_array[i] = sp.N(current_eigenval.subs(W, plot_range[i]), 
                                  chop=True)
        # The above line is evaluating your eigenvalue at a specific point,
        # approximating it numerically, and then chopping off the imaginary.
    ax[n].plot(plot_range, evaluated_array, "c-")
    ax[n].set_title("Eigenvalue #{}".format(n))
    ax[n].grid()

plt.tight_layout()
plt.show()

Result

还有承诺的Piecewise文档。