繁体   English   中英

Sympy的订阅限制

[英]Sympy's subs limitations

我正在处理一些较长的方程式,但并不是很复杂,我想使用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

有办法解决这些问题吗? 还是我应该使用其他符号数学工具? 任何建议都欢迎。

SymPy中有一个主要的陷阱,就是由于Python的工作方式, number/number会给出一个浮点数(如果使用Python 2而不是from __future__ import division则整数from __future__ import division )。

在第一种情况下,在您的原始表达式中,Python从左到右求值1/12*b Python将1/12评估为0.08333333333333333 ,然后将其乘以b 在第二种情况下, b*1被评估为b 然后b/12由SymPy评估(因为b是SymPy对象),从而给出Rational(1, 12)*b 1,12 Rational(1, 12)*b

由于浮点数的不精确特性,SymPy认为浮点数0.08333333333333333等于有理数1/12

有这个问题的一些更多的讨论在这里 解决方法是,应避免直接integer/integer而不以某种方式包装它,以便SymPy可以创建有理数。 以下将创建一个合理的:

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不出现正好在表达式中,即x**2 + x + 1 SymPy通常只替换它所看到的东西。

看来您不介意加减x来进行替换。 所以我建议改为(((x+1)**2-x).expand()).subs(x**2, y+1 - 2*x) 通过仅替换单个项( x**2 ),替换将始终有效,并且2*x将抵消,从而剩下x项(在本例中为-x )。

这是您的问题的可能解决方案:

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))

关于问题1,请注意, 1/12*bb*1/12 1/12在sympy中不是同一件事。 第一个是由符号组成的浮点数,而第二个是精确的符号表达式(您可以通过简单的print语句将其检出)。 由于expr包含expr 1/12*b ,因此第二subs不起作用也就不足为奇了。

关于问题2,您提供的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

因此,我认为sympy拒绝执行替换实际上是一种正确的方法。

如果它是您想要的第一个解释,则最好在subs规则中明确提供它,即

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

-x + y + 2

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM