Sympy提取系数仅对部分符号生效,原因何在?
SymPy系数提取异常问题解答
问题重现
运行以下代码时,提取x00的系数返回0,但提取px0的系数结果正确:
import sympy as sp x00, x01, x02 = sp.symbols('x_{00} x_{01} x_{02}') x10, x11, x12 = sp.symbols('x_{10} x_{11} x_{12}') x20, x21, x22 = sp.symbols('x_{20} x_{21} x_{22}') px0, px1, px2 = sp.symbols('p_{x0} p_{x1} p_{x2}') py0, py1, py2 = sp.symbols('p_{y0} p_{y1} p_{y2}') Z = sp.Matrix([ [x00, x01, x02], [x10, x11, x12], [x20, x21, x22]]) px = sp.Matrix([px0, px1, px2]) py = sp.Matrix([py0, py1, py2]) expr = (py.T * Z * px)[0, 0] print(expr.coeff(x00)) print(expr.coeff(px0))
输出:
0 p_{y0}*x_{00} + p_{y1}*x_{10} + p_{y2}*x_{20}
原因分析
问题出在符号名称的LaTeX格式大括号上:当用sp.symbols('x_{00}')定义符号时,SymPy对带有大括号的符号名称的匹配逻辑存在异常(或旧版本SymPy的bug),导致coeff方法无法正确识别表达式中的x00符号,进而返回0。
而px0能正确返回系数,是因为其在表达式中的项结构更易被匹配逻辑识别,属于巧合情况。
解决方案
有三种可行的解决方式:
修改符号命名规则:改用下划线替代大括号定义符号,避免LaTeX格式的干扰:
x00, x01, x02 = sp.symbols('x_00 x_01 x_02') x10, x11, x12 = sp.symbols('x_10 x_11 x_12') x20, x21, x22 = sp.symbols('x_20 x_21 x_22') px0, px1, px2 = sp.symbols('p_x0 p_x1 p_x2') py0, py1, py2 = sp.symbols('p_y0 p_y1 p_y2')此时
expr.coeff(x00)会正确返回p_x0*p_y0。直接传入符号字符串匹配:如果需要保留LaTeX格式的符号显示,调用
coeff时直接传入符号的字符串定义:print(expr.coeff(sp.symbols('x_{00}'))) # 返回 p_{x0}*p_{y0}升级SymPy版本:更新到最新版SymPy,新版本已修复此类符号匹配问题。
内容的提问来源于stack exchange,提问作者TheIdealis
相关产品推荐
相关产品推荐

