简化表达

时间:2014-03-11 12:21:07

标签: math expression sympy

我的表达方式如下:

a*b*c + d*e + f - g*h*h + i*a

换句话说:术语可以加或减,每个术语都是某些符号的乘积。

有没有办法提出一个最小/更简单的表达式,基本上是扩展的反向?我尝试了simplifyfactor,但我无法让它们发挥作用。例如:

a**4 - 4*a**3*b + 6*a**2*b**2 - 4*a*b**3 - a + b**4

应该变成:

(a - b)**4 - a

但使用上述命令时保持不变。

PS:如果这是SymPy根本无法做到的事情,你能否建议一个替代方案呢?

2 个答案:

答案 0 :(得分:1)

如果您事先知道该功能,那么您可以使用更强大的软件包(如Maple)在将表达式放入计算机代码之前减少表达式。 Maple中有一个优化包,它将表达式简化为子表达式,以便利用表达式中的重复操作。您也可以以非常可靠的方式分解非常复杂的表达式。

此外,此类软件还可以创建编程代码作为输出,您可以直接粘贴到程序中。如果您无法访问Maple或Mathematica软件,您还可以使用名为maxima的免费(但功能强大)软件。 http://maxima.sourceforge.net/

答案 1 :(得分:1)

sympy factor simple relationship。 SymPy的factor只知道如何计算整个表达式,但是如果你知道要用术语重写的术语,你可以使用sub的技巧,如:

>>> expr = a**4 - 4*a**3*b + 6*a**2*b**2 - 4*a*b**3 - a + b**4
>>> expr.subs(a, x + b).expand()
-b + x**4 - x
>>> expr.subs(a, x + b).expand().subs(x, a - b)
-a + (a - b)**4

基本上,让x = a - ba = x + b。然后将a替换为x + b,展开,然后将其替换回来。

对于更复杂的示例,SymPy实际上足够智能,可以正确替换表达式中的a*b

>>> expr = (a*b - c*d)**2 - a
>>> expr = expr.expand()
>>> expr
a**2*b**2 - 2*a*b*c*d - a + c**2*d**2
>>> expr.subs(a*b, x + c*d)
-a + c**2*d**2 - 2*c*d*(c*d + x) + (c*d + x)**2
>>> expr.subs(a*b, x + c*d).expand()
-a + x**2
>>> expr.subs(a*b, x + c*d).expand().subs(x, a*b - c*d)
-a + (a*b - c*d)**2

解决这个问题的另一种可能方法是尝试在表达式中使用因子子集的因子(itertools.combinations在这里很有用)。例如,尝试将所有术语的所有组合分解为原始表达式中的一个:

>>> args = Add.make_args(expr)
>>> for comb in combinations(args, len(args) - 1):
...    print(factor(Add(*comb)) + Add(*(set(args) - set(comb))))
...
a**4 - 4*a**3*b + 6*a**2*b**2 - 4*a*b**3 - a + b**4
a**4 - 4*a**3*b + 6*a**2*b**2 - 4*a*b**3 - a + b**4
a**4 - 4*a**3*b + 6*a**2*b**2 - 4*a*b**3 - a + b**4
a**4 - 4*a**3*b + 6*a**2*b**2 - 4*a*b**3 - a + b**4
-a + (a - b)**4
a*(a**3 - 4*a**2*b + 6*a*b**2 - 4*b**3 - 1) + b**4

您可以检查not isinstance(factored_expr, Add)以过滤掉未计算因素的{{1}}。