Sympy 表达式简化
Sympy expression simplification
我正在求解矩阵和特征向量随时间变化的特征值问题。该矩阵的维度为 8x8,并且是埃尔米特矩阵。时间相关矩阵的形式为:
import sympy as sp
t, lbd = sp.symbols(r't,\lambda', real=True)
Had = ...
print(repr(Had))
Matrix([[2*t,0, 0, 0, 0, 0, 0,0],
[ 0,-2*t, 2*t*(1 - t), 0, 0, 0,0,0],
[0, 2*t*(1 - t),0,0, 2 - 2*t, 0,0,0],
[0,0,0,0, 0, 2 - 2*t, 0,0],
[0,0,2 - 2*t,0,0,0,0,0],
[0,0,0, 2 - 2*t,0,0, 2*t*(1 - t),0],
[0,0,0,0,0, 2*t*(1 - t),-2*t,0],
[0,0,0,0,0,0,0,2*t]])
现在特征多项式有以下:
P = p.simplify(sp.collect(sp.factor(Had.charpoly(lbd).as_expr()),lbd))
并得到
然后我选择第二项并找到 lambda 的解决方案:
P_list = sp.factor_list(P)
a,b = P_list[1]
eq,exp = sp.simplify(b)
sol = sp.solve(eq)
有了这个,我得到了一个列表中的根:
r_list = []
for i in range(len(sol)):
a = list(sol[i].values())
r_list.append(a[0])
使用sp.eigenvecs解决问题:
val_mult_vec = Had.eigenvects()
e_vals = []
mults = []
e_vecs = []
for i in range(len(val_mult_vec)):
val, mult, [vec_i, vec_j] = val_mult_vec[i]
e_vals.append(val)
e_vals.append(val)
mults.append(mult)
e_vecs.append(vec_i)
e_vecs.append(vec_j)
求解特征向量我得到像这样的复杂表达式:
但我知道这个复杂的表达式可以用特征多项式中第二项的解来表示,如下所示:
其中 r1 是该方程的根之一。有了特征多项式的解决方案,我怎样才能像使用 sympy 的最后一张图像那样以简化的方式重写特征向量?根据 r_list[j]
重写 e_vec[i]
您似乎想要获得特征向量的紧凑版本。
接收:
- 我们可以创建与特征值数量一样多的符号。每个符号代表一个特征值。
- 遍历特征向量,并为其每个元素用相应的符号替换长特征值表达式。
r_symbols = symbols("r0:%s" % len(e_vals))
final_evecs = []
for vec, val, s in zip(e_vecs, e_vals, r_symbols):
final_evecs.append(
vec.applyfunc(lambda t: t.subs(val, s))
)
final_evecs
是一个包含紧凑符号的特征向量的列表。
让我们测试一个输出:
final_evecs[7]
我正在求解矩阵和特征向量随时间变化的特征值问题。该矩阵的维度为 8x8,并且是埃尔米特矩阵。时间相关矩阵的形式为:
import sympy as sp
t, lbd = sp.symbols(r't,\lambda', real=True)
Had = ...
print(repr(Had))
Matrix([[2*t,0, 0, 0, 0, 0, 0,0],
[ 0,-2*t, 2*t*(1 - t), 0, 0, 0,0,0],
[0, 2*t*(1 - t),0,0, 2 - 2*t, 0,0,0],
[0,0,0,0, 0, 2 - 2*t, 0,0],
[0,0,2 - 2*t,0,0,0,0,0],
[0,0,0, 2 - 2*t,0,0, 2*t*(1 - t),0],
[0,0,0,0,0, 2*t*(1 - t),-2*t,0],
[0,0,0,0,0,0,0,2*t]])
现在特征多项式有以下:
P = p.simplify(sp.collect(sp.factor(Had.charpoly(lbd).as_expr()),lbd))
并得到
然后我选择第二项并找到 lambda 的解决方案:
P_list = sp.factor_list(P)
a,b = P_list[1]
eq,exp = sp.simplify(b)
sol = sp.solve(eq)
有了这个,我得到了一个列表中的根:
r_list = []
for i in range(len(sol)):
a = list(sol[i].values())
r_list.append(a[0])
使用sp.eigenvecs解决问题:
val_mult_vec = Had.eigenvects()
e_vals = []
mults = []
e_vecs = []
for i in range(len(val_mult_vec)):
val, mult, [vec_i, vec_j] = val_mult_vec[i]
e_vals.append(val)
e_vals.append(val)
mults.append(mult)
e_vecs.append(vec_i)
e_vecs.append(vec_j)
求解特征向量我得到像这样的复杂表达式:
但我知道这个复杂的表达式可以用特征多项式中第二项的解来表示,如下所示:
其中 r1 是该方程的根之一。有了特征多项式的解决方案,我怎样才能像使用 sympy 的最后一张图像那样以简化的方式重写特征向量?根据 r_list[j]
e_vec[i]
您似乎想要获得特征向量的紧凑版本。
接收:
- 我们可以创建与特征值数量一样多的符号。每个符号代表一个特征值。
- 遍历特征向量,并为其每个元素用相应的符号替换长特征值表达式。
r_symbols = symbols("r0:%s" % len(e_vals))
final_evecs = []
for vec, val, s in zip(e_vecs, e_vals, r_symbols):
final_evecs.append(
vec.applyfunc(lambda t: t.subs(val, s))
)
final_evecs
是一个包含紧凑符号的特征向量的列表。
让我们测试一个输出:
final_evecs[7]