使用SymPy简化索引指数

时间:2018-10-24 11:55:48

标签: python sympy

我正在尝试使用SymPy处理一些求和和乘积,但是我无法让SymPy简化涉及索引符号的表达式。

这是一个简单的例子:

A = symbols('A', real=True)
A_i = Indexed(A, i)

expr_1 = exp(-1/A)**A
expr_2 = exp(-1/A_i)**A_i

然后,运行powsimp(expr_1)将按预期返回e ^ -1,但powsimp(expr_2)仅返回原始的未简化表达式。

尝试简化索引变量时,正确的方法是什么?

注意:由于这是我要执行的实际求和,因此运行powsimp(summation(expr_1, (i, 1, I)))会按预期返回I / e,但是powsimp(summation(expr_2, (i, 1, I)))仍会返回未简化的表达式。

1 个答案:

答案 0 :(得分:1)

如果A是实数,则表达式exp(-1/A)**A等于exp(-1),但通常不是。例如,

a = symbols('a')
expr = (exp(-1/a)**a).subs(a, I/(2*pi))    # returns 1

(这里I是内置的SymPy常数I,虚数单位)。

因此,为简化起见,必须假设真实存在。而目前(v1.3)SymPy does not support assumptions on indexed symbols。尽管powsimp具有标志force=True,该标志旨在通过忽略假设来强制简化,但这对exp(-1/a)**a无效。

作为一种解决方法,我提供了一个函数powsimp_indexed,该函数带有一个表达式和可选参数:如上所述的forceindexed_assumptions。表达式中所有索引的符号都被indexed_assumptions替换为“假人”,进行了简化,然后撤消了替换。

示例:

>>> powsimp_indexed(expr_2)
exp(-1/A[i])**A[i]
>>> powsimp_indexed(expr_2, real=True)
exp(-1)
>>> powsimp_indexed(Sum(expr_2, (i, 1, M)), real=True).doit()
exp(-1)*M

在后者中,需要在求和之前进行简化:因此,Sum是一个惰性(未求值)求和,首先将其简化,然后doit()执行求和。

def powsimp_indexed(expr, force=False, **indexed_assumptions):
    indexed_syms = {t for t in expr_2.free_symbols if isinstance(t, Indexed)}
    subs = {}
    inverse_subs = {}
    for s in indexed_syms:
        d = Dummy('xi', **indexed_assumptions)
        subs[s] = d
        inverse_subs[d] = s
    return powsimp(expr.xreplace(subs), force=force).xreplace(inverse_subs)