【问题标题】:Choosing between different expression factorizations in SymPy在 SymPy 中的不同表达式分解之间进行选择
【发布时间】:2011-07-29 21:30:07
【问题描述】:

假设我有一个表达式如下:

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)

方程eq1eq2 在数学上是等价的,但是collect 为它们中的每一个输出不同的因式分解,尽管对collect 命令的调用对于两者来说是相同的。这让我想到以下两个问题:

  1. 有没有办法在调用collect 之前“扩展”表达式?
  2. 是否有一种“收集”(对表达式进行因式分解)的方法,该方法对初始因式分解保持不变,而无需先扩展表达式?

【问题讨论】:

  • 你不能把它考虑到c * b * (a + 1) + (a * d)吗?
  • 是的,谢谢@TorelTwiddler。我将其添加到问题中。
  • @Don Roby: ??我正在处理非常大的表达式,并希望对一组特定的单项式进行因式分解。
  • 对不起,我误解了。我已经删除了我的愚蠢评论。与运算符优先级无关。

标签: python sympy


【解决方案1】:

使用收集():

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)

【讨论】:

  • 谢谢@user772649。有没有办法在调用collect 之前从表达式中“提取”符号?我在使用在函数中构建的表达式或使用我无法再访问的符号的表达式时遇到问题。例如,如果我调用collect(expression, Symbol('Variable')),其中表达式有多个Variable 实例,则它不起作用。
  • 你能举个例子吗?作为问题中的示例, collect(eq, Symbol("b")*Symbol("c")) 有效。
  • 是的@user772649。我已经更新了问题,我认为问题在于collect 为不同的(数学上等价的)表达式输出了不同的结果。
【解决方案2】:

如果给出多个符号,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

【讨论】:

    猜你喜欢
    • 2012-01-25
    • 2017-06-01
    • 1970-01-01
    • 1970-01-01
    • 2012-03-28
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多