Sympy的subs限制

2024-06-16 10:06:09 发布

您现在位置:Python中文网/ 问答频道 /正文

我正在处理一些长的方程,但并不复杂,我想用symphy来简化和“分解”它们。但是我遇到了一些问题。以下是一些最小的示例:

问题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:因子分解表达式

表达式的某些部分是因式分解的,当我展开表达式时,它们得到了简化,因此不可能进行替换。例如

^{pr2}$

会给x^2+x+1我要找的是y+2-x。在

问题

有没有办法解决这些问题?或者我应该用另一个符号数学工具?欢迎提出任何建议。在


Tags: fromimport示例表达式future因子divisionsubs
3条回答

以下是解决您问题的可能方法:

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

SymPy中有一个主要的问题,那就是,由于Python的工作方式,number/number给出了一个浮点(如果使用python2而不使用from __future__ import division),则进行整数除法。在

在第一种情况下,在原始表达式中,Python从左到右计算1/12*b1/12由Python计算得出0.08333333333333333,然后乘以{}。在第二种情况下,b*1被计算为b。然后,b/12被SymPy求值(因为b是一个SymPy对象),得到{}。在

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

这个问题还有更多的讨论here。作为一种解决方法,您应该避免直接integer/integer而不以某种方式包装它,这样SymPy就可以创建一个rational。以下都将创建一个理性的:

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**2),替换将始终有效,2*x将取消,留下任何{}项(在本例中,-x)。在

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

关于问题2,您提供的subs规则不明确。{cd7>特别地,代换规则意味着^代换。然而,这个等式有很多解释,例如

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)

-x + y + 2

相关问题 更多 >