英文:
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
中使用元素i
和j
来隔离问题。完整的上下文问题是,expr
是i
和j
的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)
这就是我以“对范围为i
的j
的每个元素求和”这种方式表述我的问题的原因。
英文:
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.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论