在SymPy中选择不同的表达式因式分解
假设我有一个这样的表达式:
a*b*c + b*c + a*d
我们可以把它分解成:
b*(a*c + c) + (a*d)
或者可以分解成
c*(a*b + b) + (a*d)
或者可以分解成
a*d + b*c*(a + 1)
还有其他的可能性。
对于其他表达式,可能的分解方式会更多。
我想问的是,SymPy这个工具有没有什么功能,可以让用户选择显示哪种分解方式?有没有办法在分解或组合表达式中的项时,指定要使用的公因子?
编辑:正如@user772649下面提到的,我可以使用collect
来实现这个功能。不过,collect
的输出似乎会根据数学表达式的初始分解不同而有所不同,例如:
a,b,c,d = symbols("a,b,c,d")
# These two equations are mathematically equivalent:
eq1 = a*b*c + b*c + a*d
eq2 = a*d + b*c*(a + 1)
print collect(eq1, a)
print collect(eq2, a)
输出:
a*(b*c + d) + b*c
a*d + b*c*(a + 1)
方程eq1
和eq2
在数学上是等价的,但collect
对它们的分解输出却不同,尽管对这两个方程调用collect
的方式是一样的。这让我产生了以下两个问题:
- 有没有办法在调用
collect
之前“展开”一个表达式? - 有没有一种“收集”(分解一个表达式)的方法,可以在不先展开表达式的情况下,对初始分解保持不变?
2 个回答
0
有一点可能会比较好,就是如果给多个符号的话,collect
可以在之前分组的子表达式上进行收集。不过,像 @HYRY 展示的那样,给一个乘积进行收集,或者像下面这样做也是可以的:
def separatevars_additively(expr, symbols=[]):
from sympy import factor_terms
free = set(symbols) or expr.free_symbols
d = {}
while free:
f = free.pop()
expr, dep = expr.as_independent(f, as_Add=True)
if dep.has(*free):
return None
d[f] = factor_terms(dep)
if expr:
d[0] = expr
return d
var('a:d')
eq = a*b*c + b*c + a*d
def do(i):
return sum(separatevars_additively(eq,[i]).values())
for i in eq.free_symbols:
print('%s: %s' % (i, do(i)))
结果是
b: a*d + b*c*(a + 1)
a: a*(b*c + d) + b*c
c: a*d + b*c*(a + 1)
d: a*b*c + a*d + b*c
5
使用 collect() 方法:
from sympy import *
a,b,c,d = symbols("a,b,c,d")
eq = a * b * c + b * c + a * d
print collect(eq, b)
print collect(eq, c)
print collect(eq, b*c)
输出结果是:
a*d + b*(c + a*c)
a*d + c*(b + a*b)
a*d + b*c*(1 + a)