使用sympy对一系列符号求和

huangapple go评论69阅读模式
英文:

Using sympy to sum over a range of symbols

问题

考虑两个具有m元素的集合i和j。假设我们有一个表达式,描述了一组项的总和。每个项可以被描述为i和j中元素的乘积。现在,我想对j的每个元素求和,其中每个元素的范围为[i1, i2, ..., im]

在Python和sympy的上下文中,这很困难,因为sympy的Sum(符号, 起始, 结束)来描述求和变量,这假定整数步长。

为了说明我的意思,考虑以下代码:

from sympy import *
i = symbols('i1, i2, i3, i4')  # 对于m = 4的情况
j = symbols('j1, j2, j3, j4')

在这里,我使用排列来设置表达式:

from itertools import permutations as perm
c = list(perm(range(4), 2))
a, b = c[0]
expr = i[a] * j[b]
for a, b in c[1:]:
    expr += i[a] * j[b]
print(expr)

现在,使用Sum对j的每个元素求和,其中范围为i,理想情况下,我可以编写以下之一:

s = Sum(expr, (j, i))
s = Sum(expr, (j1, i), (j2, i), ..., (jm, i))

但这与sympy文档不符。是否有其他方法可以用来解决这个问题?

编辑:
在这篇帖子中,我尝试通过仅在expr中使用元素ij来隔离问题。完整的上下文问题是,exprij的Kronecker Delta函数的总和,使用索引集j进行求和,其中j的每个元素的范围是i。例如:

from sympy import KroneckerDelta as KD
expr = KD(i[0], j[1])  # 仅对j[1]进行操作以减少混乱
print(expr)
s = Sum(expr, (j[1], i)).doit()
print(s)

这就是我以“对范围为ij的每个元素求和”这种方式表述我的问题的原因。

英文:

Consider two sets i,j which both have m elements. Say we have an expression which describes a sum of terms. Each term can be described as a product of an element of i and j. Now, I would like to sum over each element of j, where each element has the range [i1,i2,...,im].

In the context of python & sympy, this is difficult since sympy's Sum describes the summation variable with (symbol,start,stop), which assume integer steps.

To demonstrate what I mean, consider the following code:

>>> from sympy import *
>>> i = symbols('i1,i2,i3,i4') # for the case m = 4
>>> j = symbols('j1,j2,j3,j4')

Here I use permutations to setup the expression:

>>> from itertools import permutations as perm
>>> c = list(perm(range(4),2))
>>> a,b = c[0]
>>> expr = i[a]*j[b]
>>> for a,b in c[1:]:
>>>     expr += i[a]*j[b]
>>> print(expr)
i1*j2 + i1*j3 + i1*j4 + i2*j1 + i2*j3 + i2*j4 + i3*j1 + i3*j2 + i3*j4 + i4*j1 + i4*j2 + i4*j3

Now, using Sum over each j with range of i. It would be ideal if I could write one of the following:

>>> s = Sum(expr,(j,i))
>>> s = Sum(expr,(j1,i),(j2,i),...,(jm,i))

But that's not canonical with the sympy documentation. Are there any other methods which can be used to solve this problem?

Edit:
In this post, I tried to isolate the problem by only using elements i,j in expr. The full context problem is where expr is a sum of Kronecker Delta functions of i,j and using a sum over index set j, where each element of j has range i. For example:

>>> from sympy import KroneckerDelta as KD
>>> expr = KD(i[0],j[1]) # Only doing j[1] to reduce clutter
>>> print(expr)
KroneckerDelta(i1,j2)
>>> s = Sum(expr,(j[1],i)).doit() 
>>> print(s)
# Desired output to look like:
1 + KroneckerDelta(i1,i2) + KroneckerDelta(i1,i3) + KroneckerDelta(i1,i4)

This is the reason for which I phrased my question as: summing over each element of j with range i.

答案1

得分: 1

IndexedBase可以充当一个具有符号和整数索引的数组:

>>> from sympy import *
>>> from sympy.abc import k,l
>>> i,j = map(IndexedBase,'ij')
>>> Sum(i[k]*j[l],(k,1,2),(l,1,2)).doit().expand()
i[1]*j[1] + i[1]*j[2] + i[2]*j[1] + i[2]*j[2]
>>> Sum(Piecewise((i[k]*j[l],Ne(k,l)),(0,True)),(k,1,2),(l,1,2)).doit()
i[1]*j[2] + i[2]*j[1]

关于索引相同时是否需要包括交叉项,这不太清楚,因此两个版本都被显示出来。

英文:

IndexedBase can act as a symbolic, integer-indexed array:

>>> from sympy import *
>>> from sympy.abc import k,l
>>> i,j = map(IndexedBase,'ij')
>>> Sum(i[k]*j[l],(k,1,2),(l,1,2)).doit().expand()
i[1]*j[1] + i[1]*j[2] + i[2]*j[1] + i[2]*j[2]
>>> Sum(Piecewise((i[k]*j[l],Ne(k,l)),(0,True)),(k,1,2),(l,1,2)).doit()
i[1]*j[2] + i[2]*j[1]

It's not clear whether you want the cross terms when the indicices are the same, so both versions are shown.

huangapple
  • 本文由 发表于 2023年2月18日 22:11:43
  • 转载请务必保留本文链接:https://go.coder-hub.com/75493900.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定