在 SymPy 中选择不同的表达分解

发布于 2024-11-26 19:52:06 字数 1052 浏览 3 评论 0原文

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

a*b*c + b*c + a*d

可以将其分解为:

b*(a*c + c) + (a*d)

或 as

c*(a*b + b) + (a*d)

或 as

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)

prints:

a*(b*c + d) + b*c
a*d + b*c*(a + 1)

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

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

Say I have an expression as follows:

a*b*c + b*c + a*d

One could factorize it as:

b*(a*c + c) + (a*d)

or as

c*(a*b + b) + (a*d)

or as

a*d + b*c*(a + 1)

among other possibilities.

For other expressions, the # of possibilities can be much larger.

My question is, does SymPy have any utility that allows the user to choose which of them to display? Is there a way to specify the common factor/s to use when factorizing / grouping terms in an expression?

EDIT: As @user772649 points out below, I can use collect for this. However, collect seems to give different outputs depending on the initial factorization of the mathematical expression e.g.:

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)

prints:

a*(b*c + d) + b*c
a*d + b*c*(a + 1)

The equations eq1 and eq2 are mathematically equivalent, but collect outputs a different factorization for each of them, despite of the fact that the call to the collect command was the same for both. This brings me to the following two questions:

  1. Is there a way to "expand" an expression before calling collect?
  2. Is there a way of "collecting" (factoring an expression) in a way that is invariant to the initial factorization without having to expand the expression first?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

请恋爱 2024-12-03 19:52:06

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

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

the output is:

a*d + b*(c + a*c)
a*d + c*(b + a*b)
a*d + b*c*(1 + a)
奶茶白久 2024-12-03 19:52:06

一件可能很好的事情是,如果给定多个符号,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

One thing that might be nice is if collect would collect on previously grouped sub-expressions if more than one symbol is given. But either giving a product to collect on (as @HYRY showed) or something like the following is possible:

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

gives

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
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文