Sympy的潜在限制

时间:2016-09-05 15:18:07

标签: python sympy substitution symbolic-math

我正在使用一些长方程但不是很复杂,我想使用 sympy 来简化和“分解”它们。但我遇到了一些问题。以下是一些最小例子的列表:

问题1:对称性

from sympy import *
from __future__ import division
a = symbols('a')
b = symbols('b')
expr = 1/12*b + 1
expr.subs(1/12*b, a)
expr.subs(b*1/12, a)

第一行给出预期结果(即a+1),而第二行没有替换。

问题2:分解表达式

表达式的某些部分是分解的,当我扩展表达式时,它们会被简化,从而无法进行替换。例如

(((x+1)**2-x).expand()).subs(x**2+2*x, y+1)

将提供x^2+x+1,我正在寻找的是y+2-x

问题

有没有办法解决这些问题?或许我应该使用另一个象征性的数学工具?欢迎任何建议。

3 个答案:

答案 0 :(得分:5)

SymPy中存在一个主要问题,即由于Python的工作方式,number/number给出了一个浮点(如果使用Python 2并且不是{{1},则会进行整数除法}})。

在第一种情况和原始表达式中,Python从左到右评估from __future__ import division。 Python会对1/12*b进行评估,以提供1/12,然后乘以0.08333333333333333。在第二种情况下,b被评估为b*1。然后由SymPy评估b(因为b/12是SymPy对象),以提供b

由于浮点数的不精确性,SymPy看不到浮点Rational(1, 12)*b等于理性0.08333333333333333

有关此问题的更多讨论here。作为一种解决方法,你应该避免直接1/12而不以某种方式包装它,以便SymPy可以创建一个理性的。以下都将创造一个理性:

integer/integer

对于b/12 Rational(1, 12)*b S(1)/12*b ,问题是(((x+1)**2-x).expand()).subs(x**2+2*x, y+1)并未完全出现在表达式x**2 + 2*x中。 SymPy通常只替换它看到的东西。

您似乎不介意添加和减去x**2 + x + 1以进行替换工作。所以我建议改为x。通过仅替换单个术语((((x+1)**2-x).expand()).subs(x**2, y+1 - 2*x)),替换将始终有效,并且x**2将取消以留下任何2*x个术语(在这种情况下,x )。

答案 1 :(得分:1)

这是解决问题的可能方法:

from sympy import *

a = symbols('a')
b = symbols('b')
expr = 1 / 12 * b + 1
print(expr.subs((1 / 12) * b, a))
print(expr.subs(b * (1 / 12), a))

x = symbols('x')
y = symbols('y')
expr = ((x + 1)**2 - x).expand()
print(expr.subs(x**2 + x, y - x + 1))

答案 2 :(得分:1)

关于问题1,请注意clickThing1/12*b 同样的事情。第一个是由符号多次浮动的浮点数,而第二个是精确的符号表达式(您可以通过简单的print语句检查它)。由于b*1/12包含expr,因此第二个1/12*b不起作用就不足为奇了。

关于问题2,您提供的subs规则不明确。特别是替换规则意味着等式subs。然而,这个等式有许多解释,例如,

x**2+2*x==y+1(这是您考虑的那个),

x**2 == y + 1 - 2*x

x**2 + x == y + 1 - x

出于这个原因,我认为同意拒绝执行替换实际上是一种正确的方法。

如果这是您想要的第一个解释,最好在x == (y + 1 - x**2)/2规则中明确提供,即

subs
  

(((x+1)**2-x).expand()).subs(x**2, -2*x + y + 1)