用定义的变量和系数将sympy表达式重写为三次多项式

时间:2018-07-19 17:08:12

标签: python-3.x math sympy

给出以sympy表示的表达式,如何将表达式重写为定义为[1]的多项式:

D11*(omega**2/k**2)**3 + D22*(omega**2/k**2)**2 + D33*(omega**2/k**2) + D44 = 0

请注意,这与此处提出的类似问题(Rewrite equation as polynomial)不同。 让

x=(omega**2/k**2)

然后

D11*x**3 + D22*x**2 + D33*x + D44 = 0

鉴于D11,我想找到D22D33D44x=omega**2/k**2

通常,collect函数(http://docs.sympy.org/latest/tutorial/simplification.html)会收集相似的术语,但是在这种情况下,它似乎不能很好地工作。

这是一个简单的示例,有助于说明我要完成的任务。输出应为D11*(omega**2/k**2)**3 + D22*(omega**2/k**2)**2 + D33*(omega**2/k**2) + D44 = 0

形式
from sympy import symbols, collect
from IPython.display import display
omega = symbols('omega')
k = symbols('k')
a = symbols('a')
b = symbols('b')
c = symbols('c')
D11 = a*b*c
D22 = c+b
D33 = a+c*b + b
D44 = a+b
x = omega**2/k**2
expr = (D11*x**3 + D22*x**2 + D33*x + D44)
expr0 = expr.expand()
expr1 = collect(expr0, x)
display(expr1)

输出为:

a*b*c*omega**6/k**6 + a + b + omega**2*(a + b*c + b)/k**2 + omega**4*(b + c)/k**4

尽管数值上正确,但我希望上面给出的形式为[1]的多项式,一旦它为形式,我想提取D11D22,{{1 }}和D33系数。

D44函数中使用evaluate=False使我离目标更近,因为输出现在变为:

collect

1 个答案:

答案 0 :(得分:1)

从expr1开始,

expr1 = a*b*c*omega**6/k**6 + a + b + omega**2*(a + b*c + b)/k**2 + omega**4*(b + c)/k**4

似乎最简单的获取系数的方法是至少将x暂时变成符号:

Poly(expr1.subs(x, Symbol('x')), Symbol('x')).all_coeffs()

返回[a*b*c, b + c, a + b*c + b, a + b](列出的系数以最高的度开始)。

我可能首先要使用x = Symbol('x'),并且仅在需要时使用expr.subs(x, omega**2/k**2)


SymPy的内部术语总和不能更改。 “重新排列” SymPy表达式意味着以一种更人性化的形式打印。这在很大程度上是一个字符串操作问题,因为我们不再产生SymPy对象。

str(Poly(expr1.subs(x, Symbol('x')), Symbol('x'))).replace('x', '(' + str(x) + ')')

返回Poly(a*b*c*(omega**2/k**2)**3 + (b + c)*(omega**2/k**2)**2 + (a + b*c + b)*(omega**2/k**2) + a + b, (omega**2/k**2), domain='ZZ[a,b,c]')

在上面添加.split(',')[0].replace('Poly(', '')会删除多项式的元数据,而剩下a*b*c*(omega**2/k**2)**3 + (b + c)*(omega**2/k**2)**2 + (a + b*c + b)*(omega**2/k**2) + a + b