Python – How do I properly replace index variables in sympy?

How do I properly replace index variables in sympy?… here is a solution to the problem.

How do I properly replace index variables in sympy?

I tried summing with IndexBase but don’t understand how to do sequence substitution:

A = sympy. IndexedBase('A')
i = sympy. Symbol('i', integer=True)
N = sympy. Symbol('N', integer=True)

S = sympy. Sum(A[i], (i, 0, N))
Trace = sympy. Sum(A[i, i], (i, 0, N))

S.subs([(A, range(3)), (N, 2)]).doit()  # python3 range
# result: 3

S.subs([(A, [8, 16, 32]), (N, 2)]).doit()
# result: A[0] + A[1] + A[2]

S.subs([(A, numpy.arange(3)), (N, 2)]).doit()
# result: A[0] + A[1] + A[2]

Trace.subs([(A, numpy.diag([2, 4, 8])), (N, 2)]).doit()
# result: A[0, 0] + A[1, 1] + A[2, 2]

The only feasible case is to replace the range. Can you explain, how to replace it in general?

Solution

It is common to replace Indexed objects A[i] instead of IndexedBase A. This method works if the sum is explicitly written out by doit before replacing.

S.subs(N, 2).doit().subs([(A[i], i**2) for i in range(3)])   # 5

or

values = [8, 16, 32]
S.subs(N, 2).doit().subs([(A[i], values[i]) for i in range(3)])  # 56

Similarly, Trace.subs(N, 2).doit().subs([(A[i, i]

, values[i]) for i in range(3)]) returns 56.


Python-scoped substitution is valid because it is simplified by subs to a Range object for SymPy, which can be part of a SymPy expression.

>>> S.subs([(A, range(3)), (N, 2)])
Sum(Range(0, 3, 1)[i], (i, 0, 2)) 

It looks like it should be possible to make a similar replacement with SymPy's SeqFormula object:

>>> n = sympy.symbols('n')
>>> S.subs([(A, sympy.sequence(n**2, (n, 0, 3))), (N, 3)]) 
Sum(SeqFormula(n**2, (n, 0, 3))[i], (i, 0, 3))

But then doit fails here, with SympifyError: None, which looks like an error.

Related Problems and Solutions