indexed_integrals.py 2.1 KB

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