如何正确地在Sympy中将索引变量归类?

时间:2018-07-18 13:52:25

标签: python sympy

我尝试使用IndexBase进行求和,但不了解如何进行序列替换:

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]

唯一可行的情况是替换range。您能解释一下,在一般情况下如何将其归位吗?

1 个答案:

答案 0 :(得分:0)

通常,一个代替索引对象A[i]而不是IndexedBase A。如果在替换之前用doit明确写出了总和,这将起作用。

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

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

类似地,Trace.subs(N, 2).doit().subs([(A[i, i], values[i]) for i in range(3)])返回56。


使用Python范围进行替换是有效的,因为它由subs表示为SymPy的Range对象,该对象可以是SymPy表达式的一部分。

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

看起来应该可以用SymPy的SeqFormula对象类似地替代:

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

但是随后的doit在这里失败,并带有SympifyError: None,看起来像个错误。