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.

1341 lines
41 KiB

6 months ago
  1. from sympy.core import Add, S, sympify, Dummy, expand_func
  2. from sympy.core.expr import Expr
  3. from sympy.core.function import Function, ArgumentIndexError, PoleError
  4. from sympy.core.logic import fuzzy_and, fuzzy_not
  5. from sympy.core.numbers import Rational, pi, oo, I
  6. from sympy.core.power import Pow
  7. from sympy.functions.special.zeta_functions import zeta
  8. from sympy.functions.special.error_functions import erf, erfc, Ei
  9. from sympy.functions.elementary.complexes import re, unpolarify
  10. from sympy.functions.elementary.exponential import exp, log
  11. from sympy.functions.elementary.integers import ceiling, floor
  12. from sympy.functions.elementary.miscellaneous import sqrt
  13. from sympy.functions.elementary.trigonometric import sin, cos, cot
  14. from sympy.functions.combinatorial.numbers import bernoulli, harmonic
  15. from sympy.functions.combinatorial.factorials import factorial, rf, RisingFactorial
  16. from sympy.utilities.misc import as_int
  17. from mpmath import mp, workprec
  18. from mpmath.libmp.libmpf import prec_to_dps
  19. def intlike(n):
  20. try:
  21. as_int(n, strict=False)
  22. return True
  23. except ValueError:
  24. return False
  25. ###############################################################################
  26. ############################ COMPLETE GAMMA FUNCTION ##########################
  27. ###############################################################################
  28. class gamma(Function):
  29. r"""
  30. The gamma function
  31. .. math::
  32. \Gamma(x) := \int^{\infty}_{0} t^{x-1} e^{-t} \mathrm{d}t.
  33. Explanation
  34. ===========
  35. The ``gamma`` function implements the function which passes through the
  36. values of the factorial function (i.e., $\Gamma(n) = (n - 1)!$ when n is
  37. an integer). More generally, $\Gamma(z)$ is defined in the whole complex
  38. plane except at the negative integers where there are simple poles.
  39. Examples
  40. ========
  41. >>> from sympy import S, I, pi, gamma
  42. >>> from sympy.abc import x
  43. Several special values are known:
  44. >>> gamma(1)
  45. 1
  46. >>> gamma(4)
  47. 6
  48. >>> gamma(S(3)/2)
  49. sqrt(pi)/2
  50. The ``gamma`` function obeys the mirror symmetry:
  51. >>> from sympy import conjugate
  52. >>> conjugate(gamma(x))
  53. gamma(conjugate(x))
  54. Differentiation with respect to $x$ is supported:
  55. >>> from sympy import diff
  56. >>> diff(gamma(x), x)
  57. gamma(x)*polygamma(0, x)
  58. Series expansion is also supported:
  59. >>> from sympy import series
  60. >>> series(gamma(x), x, 0, 3)
  61. 1/x - EulerGamma + x*(EulerGamma**2/2 + pi**2/12) + x**2*(-EulerGamma*pi**2/12 + polygamma(2, 1)/6 - EulerGamma**3/6) + O(x**3)
  62. We can numerically evaluate the ``gamma`` function to arbitrary precision
  63. on the whole complex plane:
  64. >>> gamma(pi).evalf(40)
  65. 2.288037795340032417959588909060233922890
  66. >>> gamma(1+I).evalf(20)
  67. 0.49801566811835604271 - 0.15494982830181068512*I
  68. See Also
  69. ========
  70. lowergamma: Lower incomplete gamma function.
  71. uppergamma: Upper incomplete gamma function.
  72. polygamma: Polygamma function.
  73. loggamma: Log Gamma function.
  74. digamma: Digamma function.
  75. trigamma: Trigamma function.
  76. beta: Euler Beta function.
  77. References
  78. ==========
  79. .. [1] https://en.wikipedia.org/wiki/Gamma_function
  80. .. [2] http://dlmf.nist.gov/5
  81. .. [3] http://mathworld.wolfram.com/GammaFunction.html
  82. .. [4] http://functions.wolfram.com/GammaBetaErf/Gamma/
  83. """
  84. unbranched = True
  85. _singularities = (S.ComplexInfinity,)
  86. def fdiff(self, argindex=1):
  87. if argindex == 1:
  88. return self.func(self.args[0])*polygamma(0, self.args[0])
  89. else:
  90. raise ArgumentIndexError(self, argindex)
  91. @classmethod
  92. def eval(cls, arg):
  93. if arg.is_Number:
  94. if arg is S.NaN:
  95. return S.NaN
  96. elif arg is S.Infinity:
  97. return S.Infinity
  98. elif intlike(arg):
  99. if arg.is_positive:
  100. return factorial(arg - 1)
  101. else:
  102. return S.ComplexInfinity
  103. elif arg.is_Rational:
  104. if arg.q == 2:
  105. n = abs(arg.p) // arg.q
  106. if arg.is_positive:
  107. k, coeff = n, S.One
  108. else:
  109. n = k = n + 1
  110. if n & 1 == 0:
  111. coeff = S.One
  112. else:
  113. coeff = S.NegativeOne
  114. for i in range(3, 2*k, 2):
  115. coeff *= i
  116. if arg.is_positive:
  117. return coeff*sqrt(S.Pi) / 2**n
  118. else:
  119. return 2**n*sqrt(S.Pi) / coeff
  120. def _eval_expand_func(self, **hints):
  121. arg = self.args[0]
  122. if arg.is_Rational:
  123. if abs(arg.p) > arg.q:
  124. x = Dummy('x')
  125. n = arg.p // arg.q
  126. p = arg.p - n*arg.q
  127. return self.func(x + n)._eval_expand_func().subs(x, Rational(p, arg.q))
  128. if arg.is_Add:
  129. coeff, tail = arg.as_coeff_add()
  130. if coeff and coeff.q != 1:
  131. intpart = floor(coeff)
  132. tail = (coeff - intpart,) + tail
  133. coeff = intpart
  134. tail = arg._new_rawargs(*tail, reeval=False)
  135. return self.func(tail)*RisingFactorial(tail, coeff)
  136. return self.func(*self.args)
  137. def _eval_conjugate(self):
  138. return self.func(self.args[0].conjugate())
  139. def _eval_is_real(self):
  140. x = self.args[0]
  141. if x.is_nonpositive and x.is_integer:
  142. return False
  143. if intlike(x) and x <= 0:
  144. return False
  145. if x.is_positive or x.is_noninteger:
  146. return True
  147. def _eval_is_positive(self):
  148. x = self.args[0]
  149. if x.is_positive:
  150. return True
  151. elif x.is_noninteger:
  152. return floor(x).is_even
  153. def _eval_rewrite_as_tractable(self, z, limitvar=None, **kwargs):
  154. return exp(loggamma(z))
  155. def _eval_rewrite_as_factorial(self, z, **kwargs):
  156. return factorial(z - 1)
  157. def _eval_nseries(self, x, n, logx, cdir=0):
  158. x0 = self.args[0].limit(x, 0)
  159. if not (x0.is_Integer and x0 <= 0):
  160. return super()._eval_nseries(x, n, logx)
  161. t = self.args[0] - x0
  162. return (self.func(t + 1)/rf(self.args[0], -x0 + 1))._eval_nseries(x, n, logx)
  163. def _eval_as_leading_term(self, x, logx=None, cdir=0):
  164. arg = self.args[0]
  165. x0 = arg.subs(x, 0)
  166. if x0.is_integer and x0.is_nonpositive:
  167. n = -x0
  168. res = S.NegativeOne**n/self.func(n + 1)
  169. return res/(arg + n).as_leading_term(x)
  170. elif not x0.is_infinite:
  171. return self.func(x0)
  172. raise PoleError()
  173. ###############################################################################
  174. ################## LOWER and UPPER INCOMPLETE GAMMA FUNCTIONS #################
  175. ###############################################################################
  176. class lowergamma(Function):
  177. r"""
  178. The lower incomplete gamma function.
  179. Explanation
  180. ===========
  181. It can be defined as the meromorphic continuation of
  182. .. math::
  183. \gamma(s, x) := \int_0^x t^{s-1} e^{-t} \mathrm{d}t = \Gamma(s) - \Gamma(s, x).
  184. This can be shown to be the same as
  185. .. math::
  186. \gamma(s, x) = \frac{x^s}{s} {}_1F_1\left({s \atop s+1} \middle| -x\right),
  187. where ${}_1F_1$ is the (confluent) hypergeometric function.
  188. Examples
  189. ========
  190. >>> from sympy import lowergamma, S
  191. >>> from sympy.abc import s, x
  192. >>> lowergamma(s, x)
  193. lowergamma(s, x)
  194. >>> lowergamma(3, x)
  195. -2*(x**2/2 + x + 1)*exp(-x) + 2
  196. >>> lowergamma(-S(1)/2, x)
  197. -2*sqrt(pi)*erf(sqrt(x)) - 2*exp(-x)/sqrt(x)
  198. See Also
  199. ========
  200. gamma: Gamma function.
  201. uppergamma: Upper incomplete gamma function.
  202. polygamma: Polygamma function.
  203. loggamma: Log Gamma function.
  204. digamma: Digamma function.
  205. trigamma: Trigamma function.
  206. beta: Euler Beta function.
  207. References
  208. ==========
  209. .. [1] https://en.wikipedia.org/wiki/Incomplete_gamma_function#Lower_incomplete_Gamma_function
  210. .. [2] Abramowitz, Milton; Stegun, Irene A., eds. (1965), Chapter 6,
  211. Section 5, Handbook of Mathematical Functions with Formulas, Graphs,
  212. and Mathematical Tables
  213. .. [3] http://dlmf.nist.gov/8
  214. .. [4] http://functions.wolfram.com/GammaBetaErf/Gamma2/
  215. .. [5] http://functions.wolfram.com/GammaBetaErf/Gamma3/
  216. """
  217. def fdiff(self, argindex=2):
  218. from sympy.functions.special.hyper import meijerg
  219. if argindex == 2:
  220. a, z = self.args
  221. return exp(-unpolarify(z))*z**(a - 1)
  222. elif argindex == 1:
  223. a, z = self.args
  224. return gamma(a)*digamma(a) - log(z)*uppergamma(a, z) \
  225. - meijerg([], [1, 1], [0, 0, a], [], z)
  226. else:
  227. raise ArgumentIndexError(self, argindex)
  228. @classmethod
  229. def eval(cls, a, x):
  230. # For lack of a better place, we use this one to extract branching
  231. # information. The following can be
  232. # found in the literature (c/f references given above), albeit scattered:
  233. # 1) For fixed x != 0, lowergamma(s, x) is an entire function of s
  234. # 2) For fixed positive integers s, lowergamma(s, x) is an entire
  235. # function of x.
  236. # 3) For fixed non-positive integers s,
  237. # lowergamma(s, exp(I*2*pi*n)*x) =
  238. # 2*pi*I*n*(-1)**(-s)/factorial(-s) + lowergamma(s, x)
  239. # (this follows from lowergamma(s, x).diff(x) = x**(s-1)*exp(-x)).
  240. # 4) For fixed non-integral s,
  241. # lowergamma(s, x) = x**s*gamma(s)*lowergamma_unbranched(s, x),
  242. # where lowergamma_unbranched(s, x) is an entire function (in fact
  243. # of both s and x), i.e.
  244. # lowergamma(s, exp(2*I*pi*n)*x) = exp(2*pi*I*n*a)*lowergamma(a, x)
  245. if x is S.Zero:
  246. return S.Zero
  247. nx, n = x.extract_branch_factor()
  248. if a.is_integer and a.is_positive:
  249. nx = unpolarify(x)
  250. if nx != x:
  251. return lowergamma(a, nx)
  252. elif a.is_integer and a.is_nonpositive:
  253. if n != 0:
  254. return 2*pi*I*n*S.NegativeOne**(-a)/factorial(-a) + lowergamma(a, nx)
  255. elif n != 0:
  256. return exp(2*pi*I*n*a)*lowergamma(a, nx)
  257. # Special values.
  258. if a.is_Number:
  259. if a is S.One:
  260. return S.One - exp(-x)
  261. elif a is S.Half:
  262. return sqrt(pi)*erf(sqrt(x))
  263. elif a.is_Integer or (2*a).is_Integer:
  264. b = a - 1
  265. if b.is_positive:
  266. if a.is_integer:
  267. return factorial(b) - exp(-x) * factorial(b) * Add(*[x ** k / factorial(k) for k in range(a)])
  268. else:
  269. return gamma(a)*(lowergamma(S.Half, x)/sqrt(pi) - exp(-x)*Add(*[x**(k - S.Half)/gamma(S.Half + k) for k in range(1, a + S.Half)]))
  270. if not a.is_Integer:
  271. return S.NegativeOne**(S.Half - a)*pi*erf(sqrt(x))/gamma(1 - a) + exp(-x)*Add(*[x**(k + a - 1)*gamma(a)/gamma(a + k) for k in range(1, Rational(3, 2) - a)])
  272. if x.is_zero:
  273. return S.Zero
  274. def _eval_evalf(self, prec):
  275. if all(x.is_number for x in self.args):
  276. a = self.args[0]._to_mpmath(prec)
  277. z = self.args[1]._to_mpmath(prec)
  278. with workprec(prec):
  279. res = mp.gammainc(a, 0, z)
  280. return Expr._from_mpmath(res, prec)
  281. else:
  282. return self
  283. def _eval_conjugate(self):
  284. x = self.args[1]
  285. if x not in (S.Zero, S.NegativeInfinity):
  286. return self.func(self.args[0].conjugate(), x.conjugate())
  287. def _eval_is_meromorphic(self, x, a):
  288. # By https://en.wikipedia.org/wiki/Incomplete_gamma_function#Holomorphic_extension,
  289. # lowergamma(s, z) = z**s*gamma(s)*gammastar(s, z),
  290. # where gammastar(s, z) is holomorphic for all s and z.
  291. # Hence the singularities of lowergamma are z = 0 (branch
  292. # point) and nonpositive integer values of s (poles of gamma(s)).
  293. s, z = self.args
  294. args_merom = fuzzy_and([z._eval_is_meromorphic(x, a),
  295. s._eval_is_meromorphic(x, a)])
  296. if not args_merom:
  297. return args_merom
  298. z0 = z.subs(x, a)
  299. if s.is_integer:
  300. return fuzzy_and([s.is_positive, z0.is_finite])
  301. s0 = s.subs(x, a)
  302. return fuzzy_and([s0.is_finite, z0.is_finite, fuzzy_not(z0.is_zero)])
  303. def _eval_aseries(self, n, args0, x, logx):
  304. from sympy.series.order import O
  305. s, z = self.args
  306. if args0[0] is S.Infinity and not z.has(x):
  307. coeff = z**s*exp(-z)
  308. sum_expr = sum(z**k/rf(s, k + 1) for k in range(n - 1))
  309. o = O(z**s*s**(-n))
  310. return coeff*sum_expr + o
  311. return super()._eval_aseries(n, args0, x, logx)
  312. def _eval_rewrite_as_uppergamma(self, s, x, **kwargs):
  313. return gamma(s) - uppergamma(s, x)
  314. def _eval_rewrite_as_expint(self, s, x, **kwargs):
  315. from sympy.functions.special.error_functions import expint
  316. if s.is_integer and s.is_nonpositive:
  317. return self
  318. return self.rewrite(uppergamma).rewrite(expint)
  319. def _eval_is_zero(self):
  320. x = self.args[1]
  321. if x.is_zero:
  322. return True
  323. class uppergamma(Function):
  324. r"""
  325. The upper incomplete gamma function.
  326. Explanation
  327. ===========
  328. It can be defined as the meromorphic continuation of
  329. .. math::
  330. \Gamma(s, x) := \int_x^\infty t^{s-1} e^{-t} \mathrm{d}t = \Gamma(s) - \gamma(s, x).
  331. where $\gamma(s, x)$ is the lower incomplete gamma function,
  332. :class:`lowergamma`. This can be shown to be the same as
  333. .. math::
  334. \Gamma(s, x) = \Gamma(s) - \frac{x^s}{s} {}_1F_1\left({s \atop s+1} \middle| -x\right),
  335. where ${}_1F_1$ is the (confluent) hypergeometric function.
  336. The upper incomplete gamma function is also essentially equivalent to the
  337. generalized exponential integral:
  338. .. math::
  339. \operatorname{E}_{n}(x) = \int_{1}^{\infty}{\frac{e^{-xt}}{t^n} \, dt} = x^{n-1}\Gamma(1-n,x).
  340. Examples
  341. ========
  342. >>> from sympy import uppergamma, S
  343. >>> from sympy.abc import s, x
  344. >>> uppergamma(s, x)
  345. uppergamma(s, x)
  346. >>> uppergamma(3, x)
  347. 2*(x**2/2 + x + 1)*exp(-x)
  348. >>> uppergamma(-S(1)/2, x)
  349. -2*sqrt(pi)*erfc(sqrt(x)) + 2*exp(-x)/sqrt(x)
  350. >>> uppergamma(-2, x)
  351. expint(3, x)/x**2
  352. See Also
  353. ========
  354. gamma: Gamma function.
  355. lowergamma: Lower incomplete gamma function.
  356. polygamma: Polygamma function.
  357. loggamma: Log Gamma function.
  358. digamma: Digamma function.
  359. trigamma: Trigamma function.
  360. beta: Euler Beta function.
  361. References
  362. ==========
  363. .. [1] https://en.wikipedia.org/wiki/Incomplete_gamma_function#Upper_incomplete_Gamma_function
  364. .. [2] Abramowitz, Milton; Stegun, Irene A., eds. (1965), Chapter 6,
  365. Section 5, Handbook of Mathematical Functions with Formulas, Graphs,
  366. and Mathematical Tables
  367. .. [3] http://dlmf.nist.gov/8
  368. .. [4] http://functions.wolfram.com/GammaBetaErf/Gamma2/
  369. .. [5] http://functions.wolfram.com/GammaBetaErf/Gamma3/
  370. .. [6] https://en.wikipedia.org/wiki/Exponential_integral#Relation_with_other_functions
  371. """
  372. def fdiff(self, argindex=2):
  373. from sympy.functions.special.hyper import meijerg
  374. if argindex == 2:
  375. a, z = self.args
  376. return -exp(-unpolarify(z))*z**(a - 1)
  377. elif argindex == 1:
  378. a, z = self.args
  379. return uppergamma(a, z)*log(z) + meijerg([], [1, 1], [0, 0, a], [], z)
  380. else:
  381. raise ArgumentIndexError(self, argindex)
  382. def _eval_evalf(self, prec):
  383. if all(x.is_number for x in self.args):
  384. a = self.args[0]._to_mpmath(prec)
  385. z = self.args[1]._to_mpmath(prec)
  386. with workprec(prec):
  387. res = mp.gammainc(a, z, mp.inf)
  388. return Expr._from_mpmath(res, prec)
  389. return self
  390. @classmethod
  391. def eval(cls, a, z):
  392. from sympy.functions.special.error_functions import expint
  393. if z.is_Number:
  394. if z is S.NaN:
  395. return S.NaN
  396. elif z is S.Infinity:
  397. return S.Zero
  398. elif z.is_zero:
  399. if re(a).is_positive:
  400. return gamma(a)
  401. # We extract branching information here. C/f lowergamma.
  402. nx, n = z.extract_branch_factor()
  403. if a.is_integer and a.is_positive:
  404. nx = unpolarify(z)
  405. if z != nx:
  406. return uppergamma(a, nx)
  407. elif a.is_integer and a.is_nonpositive:
  408. if n != 0:
  409. return -2*pi*I*n*S.NegativeOne**(-a)/factorial(-a) + uppergamma(a, nx)
  410. elif n != 0:
  411. return gamma(a)*(1 - exp(2*pi*I*n*a)) + exp(2*pi*I*n*a)*uppergamma(a, nx)
  412. # Special values.
  413. if a.is_Number:
  414. if a is S.Zero and z.is_positive:
  415. return -Ei(-z)
  416. elif a is S.One:
  417. return exp(-z)
  418. elif a is S.Half:
  419. return sqrt(pi)*erfc(sqrt(z))
  420. elif a.is_Integer or (2*a).is_Integer:
  421. b = a - 1
  422. if b.is_positive:
  423. if a.is_integer:
  424. return exp(-z) * factorial(b) * Add(*[z**k / factorial(k)
  425. for k in range(a)])
  426. else:
  427. return (gamma(a) * erfc(sqrt(z)) +
  428. S.NegativeOne**(a - S(3)/2) * exp(-z) * sqrt(z)
  429. * Add(*[gamma(-S.Half - k) * (-z)**k / gamma(1-a)
  430. for k in range(a - S.Half)]))
  431. elif b.is_Integer:
  432. return expint(-b, z)*unpolarify(z)**(b + 1)
  433. if not a.is_Integer:
  434. return (S.NegativeOne**(S.Half - a) * pi*erfc(sqrt(z))/gamma(1-a)
  435. - z**a * exp(-z) * Add(*[z**k * gamma(a) / gamma(a+k+1)
  436. for k in range(S.Half - a)]))
  437. if a.is_zero and z.is_positive:
  438. return -Ei(-z)
  439. if z.is_zero and re(a).is_positive:
  440. return gamma(a)
  441. def _eval_conjugate(self):
  442. z = self.args[1]
  443. if z not in (S.Zero, S.NegativeInfinity):
  444. return self.func(self.args[0].conjugate(), z.conjugate())
  445. def _eval_is_meromorphic(self, x, a):
  446. return lowergamma._eval_is_meromorphic(self, x, a)
  447. def _eval_rewrite_as_lowergamma(self, s, x, **kwargs):
  448. return gamma(s) - lowergamma(s, x)
  449. def _eval_rewrite_as_tractable(self, s, x, **kwargs):
  450. return exp(loggamma(s)) - lowergamma(s, x)
  451. def _eval_rewrite_as_expint(self, s, x, **kwargs):
  452. from sympy.functions.special.error_functions import expint
  453. return expint(1 - s, x)*x**s
  454. ###############################################################################
  455. ###################### POLYGAMMA and LOGGAMMA FUNCTIONS #######################
  456. ###############################################################################
  457. class polygamma(Function):
  458. r"""
  459. The function ``polygamma(n, z)`` returns ``log(gamma(z)).diff(n + 1)``.
  460. Explanation
  461. ===========
  462. It is a meromorphic function on $\mathbb{C}$ and defined as the $(n+1)$-th
  463. derivative of the logarithm of the gamma function:
  464. .. math::
  465. \psi^{(n)} (z) := \frac{\mathrm{d}^{n+1}}{\mathrm{d} z^{n+1}} \log\Gamma(z).
  466. Examples
  467. ========
  468. Several special values are known:
  469. >>> from sympy import S, polygamma
  470. >>> polygamma(0, 1)
  471. -EulerGamma
  472. >>> polygamma(0, 1/S(2))
  473. -2*log(2) - EulerGamma
  474. >>> polygamma(0, 1/S(3))
  475. -log(3) - sqrt(3)*pi/6 - EulerGamma - log(sqrt(3))
  476. >>> polygamma(0, 1/S(4))
  477. -pi/2 - log(4) - log(2) - EulerGamma
  478. >>> polygamma(0, 2)
  479. 1 - EulerGamma
  480. >>> polygamma(0, 23)
  481. 19093197/5173168 - EulerGamma
  482. >>> from sympy import oo, I
  483. >>> polygamma(0, oo)
  484. oo
  485. >>> polygamma(0, -oo)
  486. oo
  487. >>> polygamma(0, I*oo)
  488. oo
  489. >>> polygamma(0, -I*oo)
  490. oo
  491. Differentiation with respect to $x$ is supported:
  492. >>> from sympy import Symbol, diff
  493. >>> x = Symbol("x")
  494. >>> diff(polygamma(0, x), x)
  495. polygamma(1, x)
  496. >>> diff(polygamma(0, x), x, 2)
  497. polygamma(2, x)
  498. >>> diff(polygamma(0, x), x, 3)
  499. polygamma(3, x)
  500. >>> diff(polygamma(1, x), x)
  501. polygamma(2, x)
  502. >>> diff(polygamma(1, x), x, 2)
  503. polygamma(3, x)
  504. >>> diff(polygamma(2, x), x)
  505. polygamma(3, x)
  506. >>> diff(polygamma(2, x), x, 2)
  507. polygamma(4, x)
  508. >>> n = Symbol("n")
  509. >>> diff(polygamma(n, x), x)
  510. polygamma(n + 1, x)
  511. >>> diff(polygamma(n, x), x, 2)
  512. polygamma(n + 2, x)
  513. We can rewrite ``polygamma`` functions in terms of harmonic numbers:
  514. >>> from sympy import harmonic
  515. >>> polygamma(0, x).rewrite(harmonic)
  516. harmonic(x - 1) - EulerGamma
  517. >>> polygamma(2, x).rewrite(harmonic)
  518. 2*harmonic(x - 1, 3) - 2*zeta(3)
  519. >>> ni = Symbol("n", integer=True)
  520. >>> polygamma(ni, x).rewrite(harmonic)
  521. (-1)**(n + 1)*(-harmonic(x - 1, n + 1) + zeta(n + 1))*factorial(n)
  522. See Also
  523. ========
  524. gamma: Gamma function.
  525. lowergamma: Lower incomplete gamma function.
  526. uppergamma: Upper incomplete gamma function.
  527. loggamma: Log Gamma function.
  528. digamma: Digamma function.
  529. trigamma: Trigamma function.
  530. beta: Euler Beta function.
  531. References
  532. ==========
  533. .. [1] https://en.wikipedia.org/wiki/Polygamma_function
  534. .. [2] http://mathworld.wolfram.com/PolygammaFunction.html
  535. .. [3] http://functions.wolfram.com/GammaBetaErf/PolyGamma/
  536. .. [4] http://functions.wolfram.com/GammaBetaErf/PolyGamma2/
  537. """
  538. def _eval_evalf(self, prec):
  539. n = self.args[0]
  540. # the mpmath polygamma implementation valid only for nonnegative integers
  541. if n.is_number and n.is_real:
  542. if (n.is_integer or n == int(n)) and n.is_nonnegative:
  543. return super()._eval_evalf(prec)
  544. def fdiff(self, argindex=2):
  545. if argindex == 2:
  546. n, z = self.args[:2]
  547. return polygamma(n + 1, z)
  548. else:
  549. raise ArgumentIndexError(self, argindex)
  550. def _eval_is_real(self):
  551. if self.args[0].is_positive and self.args[1].is_positive:
  552. return True
  553. def _eval_is_complex(self):
  554. z = self.args[1]
  555. is_negative_integer = fuzzy_and([z.is_negative, z.is_integer])
  556. return fuzzy_and([z.is_complex, fuzzy_not(is_negative_integer)])
  557. def _eval_is_positive(self):
  558. if self.args[0].is_positive and self.args[1].is_positive:
  559. return self.args[0].is_odd
  560. def _eval_is_negative(self):
  561. if self.args[0].is_positive and self.args[1].is_positive:
  562. return self.args[0].is_even
  563. def _eval_aseries(self, n, args0, x, logx):
  564. from sympy.series.order import Order
  565. if args0[1] != oo or not \
  566. (self.args[0].is_Integer and self.args[0].is_nonnegative):
  567. return super()._eval_aseries(n, args0, x, logx)
  568. z = self.args[1]
  569. N = self.args[0]
  570. if N == 0:
  571. # digamma function series
  572. # Abramowitz & Stegun, p. 259, 6.3.18
  573. r = log(z) - 1/(2*z)
  574. o = None
  575. if n < 2:
  576. o = Order(1/z, x)
  577. else:
  578. m = ceiling((n + 1)//2)
  579. l = [bernoulli(2*k) / (2*k*z**(2*k)) for k in range(1, m)]
  580. r -= Add(*l)
  581. o = Order(1/z**n, x)
  582. return r._eval_nseries(x, n, logx) + o
  583. else:
  584. # proper polygamma function
  585. # Abramowitz & Stegun, p. 260, 6.4.10
  586. # We return terms to order higher than O(x**n) on purpose
  587. # -- otherwise we would not be able to return any terms for
  588. # quite a long time!
  589. fac = gamma(N)
  590. e0 = fac + N*fac/(2*z)
  591. m = ceiling((n + 1)//2)
  592. for k in range(1, m):
  593. fac = fac*(2*k + N - 1)*(2*k + N - 2) / ((2*k)*(2*k - 1))
  594. e0 += bernoulli(2*k)*fac/z**(2*k)
  595. o = Order(1/z**(2*m), x)
  596. if n == 0:
  597. o = Order(1/z, x)
  598. elif n == 1:
  599. o = Order(1/z**2, x)
  600. r = e0._eval_nseries(z, n, logx) + o
  601. return (-1 * (-1/z)**N * r)._eval_nseries(x, n, logx)
  602. @classmethod
  603. def eval(cls, n, z):
  604. n, z = map(sympify, (n, z))
  605. if n.is_integer:
  606. if n.is_nonnegative:
  607. nz = unpolarify(z)
  608. if z != nz:
  609. return polygamma(n, nz)
  610. if n.is_positive:
  611. if z is S.Half:
  612. return S.NegativeOne**(n + 1)*factorial(n)*(2**(n + 1) - 1)*zeta(n + 1)
  613. if n is S.NegativeOne:
  614. return loggamma(z)
  615. else:
  616. if z.is_Number:
  617. if z is S.NaN:
  618. return S.NaN
  619. elif z is S.Infinity:
  620. if n.is_Number:
  621. if n.is_zero:
  622. return S.Infinity
  623. else:
  624. return S.Zero
  625. if n.is_zero:
  626. return S.Infinity
  627. elif z.is_Integer:
  628. if z.is_nonpositive:
  629. return S.ComplexInfinity
  630. else:
  631. if n.is_zero:
  632. return harmonic(z - 1, 1) - S.EulerGamma
  633. elif n.is_odd:
  634. return S.NegativeOne**(n + 1)*factorial(n)*zeta(n + 1, z)
  635. if n.is_zero:
  636. if z is S.NaN:
  637. return S.NaN
  638. elif z.is_Rational:
  639. p, q = z.as_numer_denom()
  640. # only expand for small denominators to avoid creating long expressions
  641. if q <= 5:
  642. return expand_func(polygamma(S.Zero, z, evaluate=False))
  643. elif z in (S.Infinity, S.NegativeInfinity):
  644. return S.Infinity
  645. else:
  646. t = z.extract_multiplicatively(S.ImaginaryUnit)
  647. if t in (S.Infinity, S.NegativeInfinity):
  648. return S.Infinity
  649. # TODO n == 1 also can do some rational z
  650. def _eval_expand_func(self, **hints):
  651. n, z = self.args
  652. if n.is_Integer and n.is_nonnegative:
  653. if z.is_Add:
  654. coeff = z.args[0]
  655. if coeff.is_Integer:
  656. e = -(n + 1)
  657. if coeff > 0:
  658. tail = Add(*[Pow(
  659. z - i, e) for i in range(1, int(coeff) + 1)])
  660. else:
  661. tail = -Add(*[Pow(
  662. z + i, e) for i in range(0, int(-coeff))])
  663. return polygamma(n, z - coeff) + S.NegativeOne**n*factorial(n)*tail
  664. elif z.is_Mul:
  665. coeff, z = z.as_two_terms()
  666. if coeff.is_Integer and coeff.is_positive:
  667. tail = [ polygamma(n, z + Rational(
  668. i, coeff)) for i in range(0, int(coeff)) ]
  669. if n == 0:
  670. return Add(*tail)/coeff + log(coeff)
  671. else:
  672. return Add(*tail)/coeff**(n + 1)
  673. z *= coeff
  674. if n == 0 and z.is_Rational:
  675. p, q = z.as_numer_denom()
  676. # Reference:
  677. # Values of the polygamma functions at rational arguments, J. Choi, 2007
  678. part_1 = -S.EulerGamma - pi * cot(p * pi / q) / 2 - log(q) + Add(
  679. *[cos(2 * k * pi * p / q) * log(2 * sin(k * pi / q)) for k in range(1, q)])
  680. if z > 0:
  681. n = floor(z)
  682. z0 = z - n
  683. return part_1 + Add(*[1 / (z0 + k) for k in range(n)])
  684. elif z < 0:
  685. n = floor(1 - z)
  686. z0 = z + n
  687. return part_1 - Add(*[1 / (z0 - 1 - k) for k in range(n)])
  688. return polygamma(n, z)
  689. def _eval_rewrite_as_zeta(self, n, z, **kwargs):
  690. if n.is_integer:
  691. if (n - S.One).is_nonnegative:
  692. return S.NegativeOne**(n + 1)*factorial(n)*zeta(n + 1, z)
  693. def _eval_rewrite_as_harmonic(self, n, z, **kwargs):
  694. if n.is_integer:
  695. if n.is_zero:
  696. return harmonic(z - 1) - S.EulerGamma
  697. else:
  698. return S.NegativeOne**(n+1) * factorial(n) * (zeta(n+1) - harmonic(z-1, n+1))
  699. def _eval_as_leading_term(self, x, logx=None, cdir=0):
  700. from sympy.series.order import Order
  701. n, z = [a.as_leading_term(x) for a in self.args]
  702. o = Order(z, x)
  703. if n == 0 and o.contains(1/x):
  704. return o.getn() * log(x)
  705. else:
  706. return self.func(n, z)
  707. class loggamma(Function):
  708. r"""
  709. The ``loggamma`` function implements the logarithm of the
  710. gamma function (i.e., $\log\Gamma(x)$).
  711. Examples
  712. ========
  713. Several special values are known. For numerical integral
  714. arguments we have:
  715. >>> from sympy import loggamma
  716. >>> loggamma(-2)
  717. oo
  718. >>> loggamma(0)
  719. oo
  720. >>> loggamma(1)
  721. 0
  722. >>> loggamma(2)
  723. 0
  724. >>> loggamma(3)
  725. log(2)
  726. And for symbolic values:
  727. >>> from sympy import Symbol
  728. >>> n = Symbol("n", integer=True, positive=True)
  729. >>> loggamma(n)
  730. log(gamma(n))
  731. >>> loggamma(-n)
  732. oo
  733. For half-integral values:
  734. >>> from sympy import S
  735. >>> loggamma(S(5)/2)
  736. log(3*sqrt(pi)/4)
  737. >>> loggamma(n/2)
  738. log(2**(1 - n)*sqrt(pi)*gamma(n)/gamma(n/2 + 1/2))
  739. And general rational arguments:
  740. >>> from sympy import expand_func
  741. >>> L = loggamma(S(16)/3)
  742. >>> expand_func(L).doit()
  743. -5*log(3) + loggamma(1/3) + log(4) + log(7) + log(10) + log(13)
  744. >>> L = loggamma(S(19)/4)
  745. >>> expand_func(L).doit()
  746. -4*log(4) + loggamma(3/4) + log(3) + log(7) + log(11) + log(15)
  747. >>> L = loggamma(S(23)/7)
  748. >>> expand_func(L).doit()
  749. -3*log(7) + log(2) + loggamma(2/7) + log(9) + log(16)
  750. The ``loggamma`` function has the following limits towards infinity:
  751. >>> from sympy import oo
  752. >>> loggamma(oo)
  753. oo
  754. >>> loggamma(-oo)
  755. zoo
  756. The ``loggamma`` function obeys the mirror symmetry
  757. if $x \in \mathbb{C} \setminus \{-\infty, 0\}$:
  758. >>> from sympy.abc import x
  759. >>> from sympy import conjugate
  760. >>> conjugate(loggamma(x))
  761. loggamma(conjugate(x))
  762. Differentiation with respect to $x$ is supported:
  763. >>> from sympy import diff
  764. >>> diff(loggamma(x), x)
  765. polygamma(0, x)
  766. Series expansion is also supported:
  767. >>> from sympy import series
  768. >>> series(loggamma(x), x, 0, 4).cancel()
  769. -log(x) - EulerGamma*x + pi**2*x**2/12 + x**3*polygamma(2, 1)/6 + O(x**4)
  770. We can numerically evaluate the ``gamma`` function to arbitrary precision
  771. on the whole complex plane:
  772. >>> from sympy import I
  773. >>> loggamma(5).evalf(30)
  774. 3.17805383034794561964694160130
  775. >>> loggamma(I).evalf(20)
  776. -0.65092319930185633889 - 1.8724366472624298171*I
  777. See Also
  778. ========
  779. gamma: Gamma function.
  780. lowergamma: Lower incomplete gamma function.
  781. uppergamma: Upper incomplete gamma function.
  782. polygamma: Polygamma function.
  783. digamma: Digamma function.
  784. trigamma: Trigamma function.
  785. beta: Euler Beta function.
  786. References
  787. ==========
  788. .. [1] https://en.wikipedia.org/wiki/Gamma_function
  789. .. [2] http://dlmf.nist.gov/5
  790. .. [3] http://mathworld.wolfram.com/LogGammaFunction.html
  791. .. [4] http://functions.wolfram.com/GammaBetaErf/LogGamma/
  792. """
  793. @classmethod
  794. def eval(cls, z):
  795. z = sympify(z)
  796. if z.is_integer:
  797. if z.is_nonpositive:
  798. return S.Infinity
  799. elif z.is_positive:
  800. return log(gamma(z))
  801. elif z.is_rational:
  802. p, q = z.as_numer_denom()
  803. # Half-integral values:
  804. if p.is_positive and q == 2:
  805. return log(sqrt(S.Pi) * 2**(1 - p) * gamma(p) / gamma((p + 1)*S.Half))
  806. if z is S.Infinity:
  807. return S.Infinity
  808. elif abs(z) is S.Infinity:
  809. return S.ComplexInfinity
  810. if z is S.NaN:
  811. return S.NaN
  812. def _eval_expand_func(self, **hints):
  813. from sympy.concrete.summations import Sum
  814. z = self.args[0]
  815. if z.is_Rational:
  816. p, q = z.as_numer_denom()
  817. # General rational arguments (u + p/q)
  818. # Split z as n + p/q with p < q
  819. n = p // q
  820. p = p - n*q
  821. if p.is_positive and q.is_positive and p < q:
  822. k = Dummy("k")
  823. if n.is_positive:
  824. return loggamma(p / q) - n*log(q) + Sum(log((k - 1)*q + p), (k, 1, n))
  825. elif n.is_negative:
  826. return loggamma(p / q) - n*log(q) + S.Pi*S.ImaginaryUnit*n - Sum(log(k*q - p), (k, 1, -n))
  827. elif n.is_zero:
  828. return loggamma(p / q)
  829. return self
  830. def _eval_nseries(self, x, n, logx=None, cdir=0):
  831. x0 = self.args[0].limit(x, 0)
  832. if x0.is_zero:
  833. f = self._eval_rewrite_as_intractable(*self.args)
  834. return f._eval_nseries(x, n, logx)
  835. return super()._eval_nseries(x, n, logx)
  836. def _eval_aseries(self, n, args0, x, logx):
  837. from sympy.series.order import Order
  838. if args0[0] != oo:
  839. return super()._eval_aseries(n, args0, x, logx)
  840. z = self.args[0]
  841. r = log(z)*(z - S.Half) - z + log(2*pi)/2
  842. l = [bernoulli(2*k) / (2*k*(2*k - 1)*z**(2*k - 1)) for k in range(1, n)]
  843. o = None
  844. if n == 0:
  845. o = Order(1, x)
  846. else:
  847. o = Order(1/z**n, x)
  848. # It is very inefficient to first add the order and then do the nseries
  849. return (r + Add(*l))._eval_nseries(x, n, logx) + o
  850. def _eval_rewrite_as_intractable(self, z, **kwargs):
  851. return log(gamma(z))
  852. def _eval_is_real(self):
  853. z = self.args[0]
  854. if z.is_positive:
  855. return True
  856. elif z.is_nonpositive:
  857. return False
  858. def _eval_conjugate(self):
  859. z = self.args[0]
  860. if z not in (S.Zero, S.NegativeInfinity):
  861. return self.func(z.conjugate())
  862. def fdiff(self, argindex=1):
  863. if argindex == 1:
  864. return polygamma(0, self.args[0])
  865. else:
  866. raise ArgumentIndexError(self, argindex)
  867. class digamma(Function):
  868. r"""
  869. The ``digamma`` function is the first derivative of the ``loggamma``
  870. function
  871. .. math::
  872. \psi(x) := \frac{\mathrm{d}}{\mathrm{d} z} \log\Gamma(z)
  873. = \frac{\Gamma'(z)}{\Gamma(z) }.
  874. In this case, ``digamma(z) = polygamma(0, z)``.
  875. Examples
  876. ========
  877. >>> from sympy import digamma
  878. >>> digamma(0)
  879. zoo
  880. >>> from sympy import Symbol
  881. >>> z = Symbol('z')
  882. >>> digamma(z)
  883. polygamma(0, z)
  884. To retain ``digamma`` as it is:
  885. >>> digamma(0, evaluate=False)
  886. digamma(0)
  887. >>> digamma(z, evaluate=False)
  888. digamma(z)
  889. See Also
  890. ========
  891. gamma: Gamma function.
  892. lowergamma: Lower incomplete gamma function.
  893. uppergamma: Upper incomplete gamma function.
  894. polygamma: Polygamma function.
  895. loggamma: Log Gamma function.
  896. trigamma: Trigamma function.
  897. beta: Euler Beta function.
  898. References
  899. ==========
  900. .. [1] https://en.wikipedia.org/wiki/Digamma_function
  901. .. [2] http://mathworld.wolfram.com/DigammaFunction.html
  902. .. [3] http://functions.wolfram.com/GammaBetaErf/PolyGamma2/
  903. """
  904. def _eval_evalf(self, prec):
  905. z = self.args[0]
  906. nprec = prec_to_dps(prec)
  907. return polygamma(0, z).evalf(n=nprec)
  908. def fdiff(self, argindex=1):
  909. z = self.args[0]
  910. return polygamma(0, z).fdiff()
  911. def _eval_is_real(self):
  912. z = self.args[0]
  913. return polygamma(0, z).is_real
  914. def _eval_is_positive(self):
  915. z = self.args[0]
  916. return polygamma(0, z).is_positive
  917. def _eval_is_negative(self):
  918. z = self.args[0]
  919. return polygamma(0, z).is_negative
  920. def _eval_aseries(self, n, args0, x, logx):
  921. as_polygamma = self.rewrite(polygamma)
  922. args0 = [S.Zero,] + args0
  923. return as_polygamma._eval_aseries(n, args0, x, logx)
  924. @classmethod
  925. def eval(cls, z):
  926. return polygamma(0, z)
  927. def _eval_expand_func(self, **hints):
  928. z = self.args[0]
  929. return polygamma(0, z).expand(func=True)
  930. def _eval_rewrite_as_harmonic(self, z, **kwargs):
  931. return harmonic(z - 1) - S.EulerGamma
  932. def _eval_rewrite_as_polygamma(self, z, **kwargs):
  933. return polygamma(0, z)
  934. def _eval_as_leading_term(self, x, logx=None, cdir=0):
  935. z = self.args[0]
  936. return polygamma(0, z).as_leading_term(x)
  937. class trigamma(Function):
  938. r"""
  939. The ``trigamma`` function is the second derivative of the ``loggamma``
  940. function
  941. .. math::
  942. \psi^{(1)}(z) := \frac{\mathrm{d}^{2}}{\mathrm{d} z^{2}} \log\Gamma(z).
  943. In this case, ``trigamma(z) = polygamma(1, z)``.
  944. Examples
  945. ========
  946. >>> from sympy import trigamma
  947. >>> trigamma(0)
  948. zoo
  949. >>> from sympy import Symbol
  950. >>> z = Symbol('z')
  951. >>> trigamma(z)
  952. polygamma(1, z)
  953. To retain ``trigamma`` as it is:
  954. >>> trigamma(0, evaluate=False)
  955. trigamma(0)
  956. >>> trigamma(z, evaluate=False)
  957. trigamma(z)
  958. See Also
  959. ========
  960. gamma: Gamma function.
  961. lowergamma: Lower incomplete gamma function.
  962. uppergamma: Upper incomplete gamma function.
  963. polygamma: Polygamma function.
  964. loggamma: Log Gamma function.
  965. digamma: Digamma function.
  966. beta: Euler Beta function.
  967. References
  968. ==========
  969. .. [1] https://en.wikipedia.org/wiki/Trigamma_function
  970. .. [2] http://mathworld.wolfram.com/TrigammaFunction.html
  971. .. [3] http://functions.wolfram.com/GammaBetaErf/PolyGamma2/
  972. """
  973. def _eval_evalf(self, prec):
  974. z = self.args[0]
  975. nprec = prec_to_dps(prec)
  976. return polygamma(1, z).evalf(n=nprec)
  977. def fdiff(self, argindex=1):
  978. z = self.args[0]
  979. return polygamma(1, z).fdiff()
  980. def _eval_is_real(self):
  981. z = self.args[0]
  982. return polygamma(1, z).is_real
  983. def _eval_is_positive(self):
  984. z = self.args[0]
  985. return polygamma(1, z).is_positive
  986. def _eval_is_negative(self):
  987. z = self.args[0]
  988. return polygamma(1, z).is_negative
  989. def _eval_aseries(self, n, args0, x, logx):
  990. as_polygamma = self.rewrite(polygamma)
  991. args0 = [S.One,] + args0
  992. return as_polygamma._eval_aseries(n, args0, x, logx)
  993. @classmethod
  994. def eval(cls, z):
  995. return polygamma(1, z)
  996. def _eval_expand_func(self, **hints):
  997. z = self.args[0]
  998. return polygamma(1, z).expand(func=True)
  999. def _eval_rewrite_as_zeta(self, z, **kwargs):
  1000. return zeta(2, z)
  1001. def _eval_rewrite_as_polygamma(self, z, **kwargs):
  1002. return polygamma(1, z)
  1003. def _eval_rewrite_as_harmonic(self, z, **kwargs):
  1004. return -harmonic(z - 1, 2) + S.Pi**2 / 6
  1005. def _eval_as_leading_term(self, x, logx=None, cdir=0):
  1006. z = self.args[0]
  1007. return polygamma(1, z).as_leading_term(x)
  1008. ###############################################################################
  1009. ##################### COMPLETE MULTIVARIATE GAMMA FUNCTION ####################
  1010. ###############################################################################
  1011. class multigamma(Function):
  1012. r"""
  1013. The multivariate gamma function is a generalization of the gamma function
  1014. .. math::
  1015. \Gamma_p(z) = \pi^{p(p-1)/4}\prod_{k=1}^p \Gamma[z + (1 - k)/2].
  1016. In a special case, ``multigamma(x, 1) = gamma(x)``.
  1017. Examples
  1018. ========
  1019. >>> from sympy import S, multigamma
  1020. >>> from sympy import Symbol
  1021. >>> x = Symbol('x')
  1022. >>> p = Symbol('p', positive=True, integer=True)
  1023. >>> multigamma(x, p)
  1024. pi**(p*(p - 1)/4)*Product(gamma(-_k/2 + x + 1/2), (_k, 1, p))
  1025. Several special values are known:
  1026. >>> multigamma(1, 1)
  1027. 1
  1028. >>> multigamma(4, 1)
  1029. 6
  1030. >>> multigamma(S(3)/2, 1)
  1031. sqrt(pi)/2
  1032. Writing ``multigamma`` in terms of the ``gamma`` function:
  1033. >>> multigamma(x, 1)
  1034. gamma(x)
  1035. >>> multigamma(x, 2)
  1036. sqrt(pi)*gamma(x)*gamma(x - 1/2)
  1037. >>> multigamma(x, 3)
  1038. pi**(3/2)*gamma(x)*gamma(x - 1)*gamma(x - 1/2)
  1039. Parameters
  1040. ==========
  1041. p : order or dimension of the multivariate gamma function
  1042. See Also
  1043. ========
  1044. gamma, lowergamma, uppergamma, polygamma, loggamma, digamma, trigamma,
  1045. beta
  1046. References
  1047. ==========
  1048. .. [1] https://en.wikipedia.org/wiki/Multivariate_gamma_function
  1049. """
  1050. unbranched = True
  1051. def fdiff(self, argindex=2):
  1052. from sympy.concrete.summations import Sum
  1053. if argindex == 2:
  1054. x, p = self.args
  1055. k = Dummy("k")
  1056. return self.func(x, p)*Sum(polygamma(0, x + (1 - k)/2), (k, 1, p))
  1057. else:
  1058. raise ArgumentIndexError(self, argindex)
  1059. @classmethod
  1060. def eval(cls, x, p):
  1061. from sympy.concrete.products import Product
  1062. x, p = map(sympify, (x, p))
  1063. if p.is_positive is False or p.is_integer is False:
  1064. raise ValueError('Order parameter p must be positive integer.')
  1065. k = Dummy("k")
  1066. return (pi**(p*(p - 1)/4)*Product(gamma(x + (1 - k)/2),
  1067. (k, 1, p))).doit()
  1068. def _eval_conjugate(self):
  1069. x, p = self.args
  1070. return self.func(x.conjugate(), p)
  1071. def _eval_is_real(self):
  1072. x, p = self.args
  1073. y = 2*x
  1074. if y.is_integer and (y <= (p - 1)) is True:
  1075. return False
  1076. if intlike(y) and (y <= (p - 1)):
  1077. return False
  1078. if y > (p - 1) or y.is_noninteger:
  1079. return True