m2m模型翻译
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

236 lines
8.1 KiB

6 months ago
  1. from sympy.core import S, sympify, oo, diff
  2. from sympy.core.function import Function, ArgumentIndexError
  3. from sympy.core.logic import fuzzy_not
  4. from sympy.core.relational import Eq
  5. from sympy.functions.elementary.complexes import im
  6. from sympy.functions.elementary.piecewise import Piecewise
  7. from sympy.functions.special.delta_functions import Heaviside
  8. ###############################################################################
  9. ############################# SINGULARITY FUNCTION ############################
  10. ###############################################################################
  11. class SingularityFunction(Function):
  12. r"""
  13. Singularity functions are a class of discontinuous functions.
  14. Explanation
  15. ===========
  16. Singularity functions take a variable, an offset, and an exponent as
  17. arguments. These functions are represented using Macaulay brackets as:
  18. SingularityFunction(x, a, n) := <x - a>^n
  19. The singularity function will automatically evaluate to
  20. ``Derivative(DiracDelta(x - a), x, -n - 1)`` if ``n < 0``
  21. and ``(x - a)**n*Heaviside(x - a)`` if ``n >= 0``.
  22. Examples
  23. ========
  24. >>> from sympy import SingularityFunction, diff, Piecewise, DiracDelta, Heaviside, Symbol
  25. >>> from sympy.abc import x, a, n
  26. >>> SingularityFunction(x, a, n)
  27. SingularityFunction(x, a, n)
  28. >>> y = Symbol('y', positive=True)
  29. >>> n = Symbol('n', nonnegative=True)
  30. >>> SingularityFunction(y, -10, n)
  31. (y + 10)**n
  32. >>> y = Symbol('y', negative=True)
  33. >>> SingularityFunction(y, 10, n)
  34. 0
  35. >>> SingularityFunction(x, 4, -1).subs(x, 4)
  36. oo
  37. >>> SingularityFunction(x, 10, -2).subs(x, 10)
  38. oo
  39. >>> SingularityFunction(4, 1, 5)
  40. 243
  41. >>> diff(SingularityFunction(x, 1, 5) + SingularityFunction(x, 1, 4), x)
  42. 4*SingularityFunction(x, 1, 3) + 5*SingularityFunction(x, 1, 4)
  43. >>> diff(SingularityFunction(x, 4, 0), x, 2)
  44. SingularityFunction(x, 4, -2)
  45. >>> SingularityFunction(x, 4, 5).rewrite(Piecewise)
  46. Piecewise(((x - 4)**5, x > 4), (0, True))
  47. >>> expr = SingularityFunction(x, a, n)
  48. >>> y = Symbol('y', positive=True)
  49. >>> n = Symbol('n', nonnegative=True)
  50. >>> expr.subs({x: y, a: -10, n: n})
  51. (y + 10)**n
  52. The methods ``rewrite(DiracDelta)``, ``rewrite(Heaviside)``, and
  53. ``rewrite('HeavisideDiracDelta')`` returns the same output. One can use any
  54. of these methods according to their choice.
  55. >>> expr = SingularityFunction(x, 4, 5) + SingularityFunction(x, -3, -1) - SingularityFunction(x, 0, -2)
  56. >>> expr.rewrite(Heaviside)
  57. (x - 4)**5*Heaviside(x - 4) + DiracDelta(x + 3) - DiracDelta(x, 1)
  58. >>> expr.rewrite(DiracDelta)
  59. (x - 4)**5*Heaviside(x - 4) + DiracDelta(x + 3) - DiracDelta(x, 1)
  60. >>> expr.rewrite('HeavisideDiracDelta')
  61. (x - 4)**5*Heaviside(x - 4) + DiracDelta(x + 3) - DiracDelta(x, 1)
  62. See Also
  63. ========
  64. DiracDelta, Heaviside
  65. References
  66. ==========
  67. .. [1] https://en.wikipedia.org/wiki/Singularity_function
  68. """
  69. is_real = True
  70. def fdiff(self, argindex=1):
  71. """
  72. Returns the first derivative of a DiracDelta Function.
  73. Explanation
  74. ===========
  75. The difference between ``diff()`` and ``fdiff()`` is: ``diff()`` is the
  76. user-level function and ``fdiff()`` is an object method. ``fdiff()`` is
  77. a convenience method available in the ``Function`` class. It returns
  78. the derivative of the function without considering the chain rule.
  79. ``diff(function, x)`` calls ``Function._eval_derivative`` which in turn
  80. calls ``fdiff()`` internally to compute the derivative of the function.
  81. """
  82. if argindex == 1:
  83. x = sympify(self.args[0])
  84. a = sympify(self.args[1])
  85. n = sympify(self.args[2])
  86. if n in (S.Zero, S.NegativeOne):
  87. return self.func(x, a, n-1)
  88. elif n.is_positive:
  89. return n*self.func(x, a, n-1)
  90. else:
  91. raise ArgumentIndexError(self, argindex)
  92. @classmethod
  93. def eval(cls, variable, offset, exponent):
  94. """
  95. Returns a simplified form or a value of Singularity Function depending
  96. on the argument passed by the object.
  97. Explanation
  98. ===========
  99. The ``eval()`` method is automatically called when the
  100. ``SingularityFunction`` class is about to be instantiated and it
  101. returns either some simplified instance or the unevaluated instance
  102. depending on the argument passed. In other words, ``eval()`` method is
  103. not needed to be called explicitly, it is being called and evaluated
  104. once the object is called.
  105. Examples
  106. ========
  107. >>> from sympy import SingularityFunction, Symbol, nan
  108. >>> from sympy.abc import x, a, n
  109. >>> SingularityFunction(x, a, n)
  110. SingularityFunction(x, a, n)
  111. >>> SingularityFunction(5, 3, 2)
  112. 4
  113. >>> SingularityFunction(x, a, nan)
  114. nan
  115. >>> SingularityFunction(x, 3, 0).subs(x, 3)
  116. 1
  117. >>> SingularityFunction(x, a, n).eval(3, 5, 1)
  118. 0
  119. >>> SingularityFunction(x, a, n).eval(4, 1, 5)
  120. 243
  121. >>> x = Symbol('x', positive = True)
  122. >>> a = Symbol('a', negative = True)
  123. >>> n = Symbol('n', nonnegative = True)
  124. >>> SingularityFunction(x, a, n)
  125. (-a + x)**n
  126. >>> x = Symbol('x', negative = True)
  127. >>> a = Symbol('a', positive = True)
  128. >>> SingularityFunction(x, a, n)
  129. 0
  130. """
  131. x = sympify(variable)
  132. a = sympify(offset)
  133. n = sympify(exponent)
  134. shift = (x - a)
  135. if fuzzy_not(im(shift).is_zero):
  136. raise ValueError("Singularity Functions are defined only for Real Numbers.")
  137. if fuzzy_not(im(n).is_zero):
  138. raise ValueError("Singularity Functions are not defined for imaginary exponents.")
  139. if shift is S.NaN or n is S.NaN:
  140. return S.NaN
  141. if (n + 2).is_negative:
  142. raise ValueError("Singularity Functions are not defined for exponents less than -2.")
  143. if shift.is_extended_negative:
  144. return S.Zero
  145. if n.is_nonnegative and shift.is_extended_nonnegative:
  146. return (x - a)**n
  147. if n in (S.NegativeOne, -2):
  148. if shift.is_negative or shift.is_extended_positive:
  149. return S.Zero
  150. if shift.is_zero:
  151. return S.Infinity
  152. def _eval_rewrite_as_Piecewise(self, *args, **kwargs):
  153. '''
  154. Converts a Singularity Function expression into its Piecewise form.
  155. '''
  156. x = self.args[0]
  157. a = self.args[1]
  158. n = sympify(self.args[2])
  159. if n in (S.NegativeOne, -2):
  160. return Piecewise((oo, Eq((x - a), 0)), (0, True))
  161. elif n.is_nonnegative:
  162. return Piecewise(((x - a)**n, (x - a) > 0), (0, True))
  163. def _eval_rewrite_as_Heaviside(self, *args, **kwargs):
  164. '''
  165. Rewrites a Singularity Function expression using Heavisides and DiracDeltas.
  166. '''
  167. x = self.args[0]
  168. a = self.args[1]
  169. n = sympify(self.args[2])
  170. if n == -2:
  171. return diff(Heaviside(x - a), x.free_symbols.pop(), 2)
  172. if n == -1:
  173. return diff(Heaviside(x - a), x.free_symbols.pop(), 1)
  174. if n.is_nonnegative:
  175. return (x - a)**n*Heaviside(x - a)
  176. def _eval_as_leading_term(self, x, logx=None, cdir=0):
  177. z, a, n = self.args
  178. shift = (z - a).subs(x, 0)
  179. if n < 0:
  180. return S.Zero
  181. elif n.is_zero and shift.is_zero:
  182. return S.Zero if cdir == -1 else S.One
  183. elif shift.is_positive:
  184. return shift**n
  185. return S.Zero
  186. def _eval_nseries(self, x, n, logx=None, cdir=0):
  187. z, a, n = self.args
  188. shift = (z - a).subs(x, 0)
  189. if n < 0:
  190. return S.Zero
  191. elif n.is_zero and shift.is_zero:
  192. return S.Zero if cdir == -1 else S.One
  193. elif shift.is_positive:
  194. return ((z - a)**n)._eval_nseries(x, n, logx=logx, cdir=cdir)
  195. return S.Zero
  196. _eval_rewrite_as_DiracDelta = _eval_rewrite_as_Heaviside
  197. _eval_rewrite_as_HeavisideDiracDelta = _eval_rewrite_as_Heaviside