简体   繁体   中英

Simplifying indexed exponents with SymPy

I am trying to use SymPy to work with some summations and products but I cannot get SymPy to simplify the expressions involving indexed symbols.

Here is a simple example:

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

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

Then, running powsimp(expr_1) returns e^-1 as expected but powsimp(expr_2) just returns the original unsimplified expression.

What is the right way to work with indexed variables when trying to simplify them?

Note: Bringing in an actual summation since that is what I am trying to do, running powsimp(summation(expr_1, (i, 1, I))) returns I/e as expected but powsimp(summation(expr_2, (i, 1, I))) still returns the unsimplified expression.

The expression exp(-1/A)**A is equal to exp(-1) if A is real, but not in general. For example,

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

(here I is a built-in SymPy constant I , the imaginary unit).

So the assumption of being real is necessary for simplification. And at present (v1.3) SymPy does not support assumptions on indexed symbols . Although powsimp has a flag force=True meant to force simplification by ignoring assumptions, this does not have an effect on exp(-1/a)**a .

As a workaround, I offer a function powsimp_indexed which takes an expression and optional parameters: force as above, and indexed_assumptions . All indexed symbols in the expression are replaced by "dummies" with indexed_assumptions , simplification is made, and then the substitution is undone.

Examples:

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

In the latter, simplification needs to happen before summation: hence, the Sum is an inert (non-evaluated) sum, it first gets simplified, and then doit() performs summation.

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)

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM