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