Spaces:
Sleeping
Sleeping
File size: 2,141 Bytes
6a86ad5 |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 |
from sympy.tensor import Indexed
from sympy.core.containers import Tuple
from sympy.core.symbol import Dummy
from sympy.core.sympify import sympify
from sympy.integrals.integrals import Integral
class IndexedIntegral(Integral):
"""
Experimental class to test integration by indexed variables.
Usage is analogue to ``Integral``, it simply adds awareness of
integration over indices.
Contraction of non-identical index symbols referring to the same
``IndexedBase`` is not yet supported.
Examples
========
>>> from sympy.sandbox.indexed_integrals import IndexedIntegral
>>> from sympy import IndexedBase, symbols
>>> A = IndexedBase('A')
>>> i, j = symbols('i j', integer=True)
>>> ii = IndexedIntegral(A[i], A[i])
>>> ii
Integral(_A[i], _A[i])
>>> ii.doit()
A[i]**2/2
If the indices are different, indexed objects are considered to be
different variables:
>>> i2 = IndexedIntegral(A[j], A[i])
>>> i2
Integral(A[j], _A[i])
>>> i2.doit()
A[i]*A[j]
"""
def __new__(cls, function, *limits, **assumptions):
repl, limits = IndexedIntegral._indexed_process_limits(limits)
function = sympify(function)
function = function.xreplace(repl)
obj = Integral.__new__(cls, function, *limits, **assumptions)
obj._indexed_repl = repl
obj._indexed_reverse_repl = {val: key for key, val in repl.items()}
return obj
def doit(self):
res = super().doit()
return res.xreplace(self._indexed_reverse_repl)
@staticmethod
def _indexed_process_limits(limits):
repl = {}
newlimits = []
for i in limits:
if isinstance(i, (tuple, list, Tuple)):
v = i[0]
vrest = i[1:]
else:
v = i
vrest = ()
if isinstance(v, Indexed):
if v not in repl:
r = Dummy(str(v))
repl[v] = r
newlimits.append((r,)+vrest)
else:
newlimits.append(i)
return repl, newlimits
|