hyper.py 36 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152
  1. """Hypergeometric and Meijer G-functions"""
  2. from functools import reduce
  3. from sympy.core import S, ilcm, Mod
  4. from sympy.core.add import Add
  5. from sympy.core.expr import Expr
  6. from sympy.core.function import Function, Derivative, ArgumentIndexError
  7. from sympy.core.containers import Tuple
  8. from sympy.core.mul import Mul
  9. from sympy.core.numbers import I, pi, oo, zoo
  10. from sympy.core.relational import Ne
  11. from sympy.core.sorting import default_sort_key
  12. from sympy.core.symbol import Dummy
  13. from sympy.functions import (sqrt, exp, log, sin, cos, asin, atan,
  14. sinh, cosh, asinh, acosh, atanh, acoth)
  15. from sympy.functions import factorial, RisingFactorial
  16. from sympy.functions.elementary.complexes import Abs, re, unpolarify
  17. from sympy.functions.elementary.exponential import exp_polar
  18. from sympy.functions.elementary.integers import ceiling
  19. from sympy.functions.elementary.piecewise import Piecewise
  20. from sympy.logic.boolalg import (And, Or)
  21. class TupleArg(Tuple):
  22. def limit(self, x, xlim, dir='+'):
  23. """ Compute limit x->xlim.
  24. """
  25. from sympy.series.limits import limit
  26. return TupleArg(*[limit(f, x, xlim, dir) for f in self.args])
  27. # TODO should __new__ accept **options?
  28. # TODO should constructors should check if parameters are sensible?
  29. def _prep_tuple(v):
  30. """
  31. Turn an iterable argument *v* into a tuple and unpolarify, since both
  32. hypergeometric and meijer g-functions are unbranched in their parameters.
  33. Examples
  34. ========
  35. >>> from sympy.functions.special.hyper import _prep_tuple
  36. >>> _prep_tuple([1, 2, 3])
  37. (1, 2, 3)
  38. >>> _prep_tuple((4, 5))
  39. (4, 5)
  40. >>> _prep_tuple((7, 8, 9))
  41. (7, 8, 9)
  42. """
  43. return TupleArg(*[unpolarify(x) for x in v])
  44. class TupleParametersBase(Function):
  45. """ Base class that takes care of differentiation, when some of
  46. the arguments are actually tuples. """
  47. # This is not deduced automatically since there are Tuples as arguments.
  48. is_commutative = True
  49. def _eval_derivative(self, s):
  50. try:
  51. res = 0
  52. if self.args[0].has(s) or self.args[1].has(s):
  53. for i, p in enumerate(self._diffargs):
  54. m = self._diffargs[i].diff(s)
  55. if m != 0:
  56. res += self.fdiff((1, i))*m
  57. return res + self.fdiff(3)*self.args[2].diff(s)
  58. except (ArgumentIndexError, NotImplementedError):
  59. return Derivative(self, s)
  60. class hyper(TupleParametersBase):
  61. r"""
  62. The generalized hypergeometric function is defined by a series where
  63. the ratios of successive terms are a rational function of the summation
  64. index. When convergent, it is continued analytically to the largest
  65. possible domain.
  66. Explanation
  67. ===========
  68. The hypergeometric function depends on two vectors of parameters, called
  69. the numerator parameters $a_p$, and the denominator parameters
  70. $b_q$. It also has an argument $z$. The series definition is
  71. .. math ::
  72. {}_pF_q\left(\begin{matrix} a_1, \cdots, a_p \\ b_1, \cdots, b_q \end{matrix}
  73. \middle| z \right)
  74. = \sum_{n=0}^\infty \frac{(a_1)_n \cdots (a_p)_n}{(b_1)_n \cdots (b_q)_n}
  75. \frac{z^n}{n!},
  76. where $(a)_n = (a)(a+1)\cdots(a+n-1)$ denotes the rising factorial.
  77. If one of the $b_q$ is a non-positive integer then the series is
  78. undefined unless one of the $a_p$ is a larger (i.e., smaller in
  79. magnitude) non-positive integer. If none of the $b_q$ is a
  80. non-positive integer and one of the $a_p$ is a non-positive
  81. integer, then the series reduces to a polynomial. To simplify the
  82. following discussion, we assume that none of the $a_p$ or
  83. $b_q$ is a non-positive integer. For more details, see the
  84. references.
  85. The series converges for all $z$ if $p \le q$, and thus
  86. defines an entire single-valued function in this case. If $p =
  87. q+1$ the series converges for $|z| < 1$, and can be continued
  88. analytically into a half-plane. If $p > q+1$ the series is
  89. divergent for all $z$.
  90. Please note the hypergeometric function constructor currently does *not*
  91. check if the parameters actually yield a well-defined function.
  92. Examples
  93. ========
  94. The parameters $a_p$ and $b_q$ can be passed as arbitrary
  95. iterables, for example:
  96. >>> from sympy import hyper
  97. >>> from sympy.abc import x, n, a
  98. >>> hyper((1, 2, 3), [3, 4], x)
  99. hyper((1, 2, 3), (3, 4), x)
  100. There is also pretty printing (it looks better using Unicode):
  101. >>> from sympy import pprint
  102. >>> pprint(hyper((1, 2, 3), [3, 4], x), use_unicode=False)
  103. _
  104. |_ /1, 2, 3 | \
  105. | | | x|
  106. 3 2 \ 3, 4 | /
  107. The parameters must always be iterables, even if they are vectors of
  108. length one or zero:
  109. >>> hyper((1, ), [], x)
  110. hyper((1,), (), x)
  111. But of course they may be variables (but if they depend on $x$ then you
  112. should not expect much implemented functionality):
  113. >>> hyper((n, a), (n**2,), x)
  114. hyper((n, a), (n**2,), x)
  115. The hypergeometric function generalizes many named special functions.
  116. The function ``hyperexpand()`` tries to express a hypergeometric function
  117. using named special functions. For example:
  118. >>> from sympy import hyperexpand
  119. >>> hyperexpand(hyper([], [], x))
  120. exp(x)
  121. You can also use ``expand_func()``:
  122. >>> from sympy import expand_func
  123. >>> expand_func(x*hyper([1, 1], [2], -x))
  124. log(x + 1)
  125. More examples:
  126. >>> from sympy import S
  127. >>> hyperexpand(hyper([], [S(1)/2], -x**2/4))
  128. cos(x)
  129. >>> hyperexpand(x*hyper([S(1)/2, S(1)/2], [S(3)/2], x**2))
  130. asin(x)
  131. We can also sometimes ``hyperexpand()`` parametric functions:
  132. >>> from sympy.abc import a
  133. >>> hyperexpand(hyper([-a], [], x))
  134. (1 - x)**a
  135. See Also
  136. ========
  137. sympy.simplify.hyperexpand
  138. gamma
  139. meijerg
  140. References
  141. ==========
  142. .. [1] Luke, Y. L. (1969), The Special Functions and Their Approximations,
  143. Volume 1
  144. .. [2] https://en.wikipedia.org/wiki/Generalized_hypergeometric_function
  145. """
  146. def __new__(cls, ap, bq, z, **kwargs):
  147. # TODO should we check convergence conditions?
  148. return Function.__new__(cls, _prep_tuple(ap), _prep_tuple(bq), z, **kwargs)
  149. @classmethod
  150. def eval(cls, ap, bq, z):
  151. if len(ap) <= len(bq) or (len(ap) == len(bq) + 1 and (Abs(z) <= 1) == True):
  152. nz = unpolarify(z)
  153. if z != nz:
  154. return hyper(ap, bq, nz)
  155. def fdiff(self, argindex=3):
  156. if argindex != 3:
  157. raise ArgumentIndexError(self, argindex)
  158. nap = Tuple(*[a + 1 for a in self.ap])
  159. nbq = Tuple(*[b + 1 for b in self.bq])
  160. fac = Mul(*self.ap)/Mul(*self.bq)
  161. return fac*hyper(nap, nbq, self.argument)
  162. def _eval_expand_func(self, **hints):
  163. from sympy.functions.special.gamma_functions import gamma
  164. from sympy.simplify.hyperexpand import hyperexpand
  165. if len(self.ap) == 2 and len(self.bq) == 1 and self.argument == 1:
  166. a, b = self.ap
  167. c = self.bq[0]
  168. return gamma(c)*gamma(c - a - b)/gamma(c - a)/gamma(c - b)
  169. return hyperexpand(self)
  170. def _eval_rewrite_as_Sum(self, ap, bq, z, **kwargs):
  171. from sympy.concrete.summations import Sum
  172. n = Dummy("n", integer=True)
  173. rfap = [RisingFactorial(a, n) for a in ap]
  174. rfbq = [RisingFactorial(b, n) for b in bq]
  175. coeff = Mul(*rfap) / Mul(*rfbq)
  176. return Piecewise((Sum(coeff * z**n / factorial(n), (n, 0, oo)),
  177. self.convergence_statement), (self, True))
  178. def _eval_as_leading_term(self, x, logx=None, cdir=0):
  179. arg = self.args[2]
  180. x0 = arg.subs(x, 0)
  181. if x0 is S.NaN:
  182. x0 = arg.limit(x, 0, dir='-' if re(cdir).is_negative else '+')
  183. if x0 is S.Zero:
  184. return S.One
  185. return super()._eval_as_leading_term(x, logx=logx, cdir=cdir)
  186. def _eval_nseries(self, x, n, logx, cdir=0):
  187. from sympy.series.order import Order
  188. arg = self.args[2]
  189. x0 = arg.limit(x, 0)
  190. ap = self.args[0]
  191. bq = self.args[1]
  192. if x0 != 0:
  193. return super()._eval_nseries(x, n, logx)
  194. terms = []
  195. for i in range(n):
  196. num = Mul(*[RisingFactorial(a, i) for a in ap])
  197. den = Mul(*[RisingFactorial(b, i) for b in bq])
  198. terms.append(((num/den) * (arg**i)) / factorial(i))
  199. return (Add(*terms) + Order(x**n,x))
  200. @property
  201. def argument(self):
  202. """ Argument of the hypergeometric function. """
  203. return self.args[2]
  204. @property
  205. def ap(self):
  206. """ Numerator parameters of the hypergeometric function. """
  207. return Tuple(*self.args[0])
  208. @property
  209. def bq(self):
  210. """ Denominator parameters of the hypergeometric function. """
  211. return Tuple(*self.args[1])
  212. @property
  213. def _diffargs(self):
  214. return self.ap + self.bq
  215. @property
  216. def eta(self):
  217. """ A quantity related to the convergence of the series. """
  218. return sum(self.ap) - sum(self.bq)
  219. @property
  220. def radius_of_convergence(self):
  221. """
  222. Compute the radius of convergence of the defining series.
  223. Explanation
  224. ===========
  225. Note that even if this is not ``oo``, the function may still be
  226. evaluated outside of the radius of convergence by analytic
  227. continuation. But if this is zero, then the function is not actually
  228. defined anywhere else.
  229. Examples
  230. ========
  231. >>> from sympy import hyper
  232. >>> from sympy.abc import z
  233. >>> hyper((1, 2), [3], z).radius_of_convergence
  234. 1
  235. >>> hyper((1, 2, 3), [4], z).radius_of_convergence
  236. 0
  237. >>> hyper((1, 2), (3, 4), z).radius_of_convergence
  238. oo
  239. """
  240. if any(a.is_integer and (a <= 0) == True for a in self.ap + self.bq):
  241. aints = [a for a in self.ap if a.is_Integer and (a <= 0) == True]
  242. bints = [a for a in self.bq if a.is_Integer and (a <= 0) == True]
  243. if len(aints) < len(bints):
  244. return S.Zero
  245. popped = False
  246. for b in bints:
  247. cancelled = False
  248. while aints:
  249. a = aints.pop()
  250. if a >= b:
  251. cancelled = True
  252. break
  253. popped = True
  254. if not cancelled:
  255. return S.Zero
  256. if aints or popped:
  257. # There are still non-positive numerator parameters.
  258. # This is a polynomial.
  259. return oo
  260. if len(self.ap) == len(self.bq) + 1:
  261. return S.One
  262. elif len(self.ap) <= len(self.bq):
  263. return oo
  264. else:
  265. return S.Zero
  266. @property
  267. def convergence_statement(self):
  268. """ Return a condition on z under which the series converges. """
  269. R = self.radius_of_convergence
  270. if R == 0:
  271. return False
  272. if R == oo:
  273. return True
  274. # The special functions and their approximations, page 44
  275. e = self.eta
  276. z = self.argument
  277. c1 = And(re(e) < 0, abs(z) <= 1)
  278. c2 = And(0 <= re(e), re(e) < 1, abs(z) <= 1, Ne(z, 1))
  279. c3 = And(re(e) >= 1, abs(z) < 1)
  280. return Or(c1, c2, c3)
  281. def _eval_simplify(self, **kwargs):
  282. from sympy.simplify.hyperexpand import hyperexpand
  283. return hyperexpand(self)
  284. class meijerg(TupleParametersBase):
  285. r"""
  286. The Meijer G-function is defined by a Mellin-Barnes type integral that
  287. resembles an inverse Mellin transform. It generalizes the hypergeometric
  288. functions.
  289. Explanation
  290. ===========
  291. The Meijer G-function depends on four sets of parameters. There are
  292. "*numerator parameters*"
  293. $a_1, \ldots, a_n$ and $a_{n+1}, \ldots, a_p$, and there are
  294. "*denominator parameters*"
  295. $b_1, \ldots, b_m$ and $b_{m+1}, \ldots, b_q$.
  296. Confusingly, it is traditionally denoted as follows (note the position
  297. of $m$, $n$, $p$, $q$, and how they relate to the lengths of the four
  298. parameter vectors):
  299. .. math ::
  300. G_{p,q}^{m,n} \left(\begin{matrix}a_1, \cdots, a_n & a_{n+1}, \cdots, a_p \\
  301. b_1, \cdots, b_m & b_{m+1}, \cdots, b_q
  302. \end{matrix} \middle| z \right).
  303. However, in SymPy the four parameter vectors are always available
  304. separately (see examples), so that there is no need to keep track of the
  305. decorating sub- and super-scripts on the G symbol.
  306. The G function is defined as the following integral:
  307. .. math ::
  308. \frac{1}{2 \pi i} \int_L \frac{\prod_{j=1}^m \Gamma(b_j - s)
  309. \prod_{j=1}^n \Gamma(1 - a_j + s)}{\prod_{j=m+1}^q \Gamma(1- b_j +s)
  310. \prod_{j=n+1}^p \Gamma(a_j - s)} z^s \mathrm{d}s,
  311. where $\Gamma(z)$ is the gamma function. There are three possible
  312. contours which we will not describe in detail here (see the references).
  313. If the integral converges along more than one of them, the definitions
  314. agree. The contours all separate the poles of $\Gamma(1-a_j+s)$
  315. from the poles of $\Gamma(b_k-s)$, so in particular the G function
  316. is undefined if $a_j - b_k \in \mathbb{Z}_{>0}$ for some
  317. $j \le n$ and $k \le m$.
  318. The conditions under which one of the contours yields a convergent integral
  319. are complicated and we do not state them here, see the references.
  320. Please note currently the Meijer G-function constructor does *not* check any
  321. convergence conditions.
  322. Examples
  323. ========
  324. You can pass the parameters either as four separate vectors:
  325. >>> from sympy import meijerg, Tuple, pprint
  326. >>> from sympy.abc import x, a
  327. >>> pprint(meijerg((1, 2), (a, 4), (5,), [], x), use_unicode=False)
  328. __1, 2 /1, 2 a, 4 | \
  329. /__ | | x|
  330. \_|4, 1 \ 5 | /
  331. Or as two nested vectors:
  332. >>> pprint(meijerg([(1, 2), (3, 4)], ([5], Tuple()), x), use_unicode=False)
  333. __1, 2 /1, 2 3, 4 | \
  334. /__ | | x|
  335. \_|4, 1 \ 5 | /
  336. As with the hypergeometric function, the parameters may be passed as
  337. arbitrary iterables. Vectors of length zero and one also have to be
  338. passed as iterables. The parameters need not be constants, but if they
  339. depend on the argument then not much implemented functionality should be
  340. expected.
  341. All the subvectors of parameters are available:
  342. >>> from sympy import pprint
  343. >>> g = meijerg([1], [2], [3], [4], x)
  344. >>> pprint(g, use_unicode=False)
  345. __1, 1 /1 2 | \
  346. /__ | | x|
  347. \_|2, 2 \3 4 | /
  348. >>> g.an
  349. (1,)
  350. >>> g.ap
  351. (1, 2)
  352. >>> g.aother
  353. (2,)
  354. >>> g.bm
  355. (3,)
  356. >>> g.bq
  357. (3, 4)
  358. >>> g.bother
  359. (4,)
  360. The Meijer G-function generalizes the hypergeometric functions.
  361. In some cases it can be expressed in terms of hypergeometric functions,
  362. using Slater's theorem. For example:
  363. >>> from sympy import hyperexpand
  364. >>> from sympy.abc import a, b, c
  365. >>> hyperexpand(meijerg([a], [], [c], [b], x), allow_hyper=True)
  366. x**c*gamma(-a + c + 1)*hyper((-a + c + 1,),
  367. (-b + c + 1,), -x)/gamma(-b + c + 1)
  368. Thus the Meijer G-function also subsumes many named functions as special
  369. cases. You can use ``expand_func()`` or ``hyperexpand()`` to (try to)
  370. rewrite a Meijer G-function in terms of named special functions. For
  371. example:
  372. >>> from sympy import expand_func, S
  373. >>> expand_func(meijerg([[],[]], [[0],[]], -x))
  374. exp(x)
  375. >>> hyperexpand(meijerg([[],[]], [[S(1)/2],[0]], (x/2)**2))
  376. sin(x)/sqrt(pi)
  377. See Also
  378. ========
  379. hyper
  380. sympy.simplify.hyperexpand
  381. References
  382. ==========
  383. .. [1] Luke, Y. L. (1969), The Special Functions and Their Approximations,
  384. Volume 1
  385. .. [2] https://en.wikipedia.org/wiki/Meijer_G-function
  386. """
  387. def __new__(cls, *args, **kwargs):
  388. if len(args) == 5:
  389. args = [(args[0], args[1]), (args[2], args[3]), args[4]]
  390. if len(args) != 3:
  391. raise TypeError("args must be either as, as', bs, bs', z or "
  392. "as, bs, z")
  393. def tr(p):
  394. if len(p) != 2:
  395. raise TypeError("wrong argument")
  396. return TupleArg(_prep_tuple(p[0]), _prep_tuple(p[1]))
  397. arg0, arg1 = tr(args[0]), tr(args[1])
  398. if Tuple(arg0, arg1).has(oo, zoo, -oo):
  399. raise ValueError("G-function parameters must be finite")
  400. if any((a - b).is_Integer and a - b > 0
  401. for a in arg0[0] for b in arg1[0]):
  402. raise ValueError("no parameter a1, ..., an may differ from "
  403. "any b1, ..., bm by a positive integer")
  404. # TODO should we check convergence conditions?
  405. return Function.__new__(cls, arg0, arg1, args[2], **kwargs)
  406. def fdiff(self, argindex=3):
  407. if argindex != 3:
  408. return self._diff_wrt_parameter(argindex[1])
  409. if len(self.an) >= 1:
  410. a = list(self.an)
  411. a[0] -= 1
  412. G = meijerg(a, self.aother, self.bm, self.bother, self.argument)
  413. return 1/self.argument * ((self.an[0] - 1)*self + G)
  414. elif len(self.bm) >= 1:
  415. b = list(self.bm)
  416. b[0] += 1
  417. G = meijerg(self.an, self.aother, b, self.bother, self.argument)
  418. return 1/self.argument * (self.bm[0]*self - G)
  419. else:
  420. return S.Zero
  421. def _diff_wrt_parameter(self, idx):
  422. # Differentiation wrt a parameter can only be done in very special
  423. # cases. In particular, if we want to differentiate with respect to
  424. # `a`, all other gamma factors have to reduce to rational functions.
  425. #
  426. # Let MT denote mellin transform. Suppose T(-s) is the gamma factor
  427. # appearing in the definition of G. Then
  428. #
  429. # MT(log(z)G(z)) = d/ds T(s) = d/da T(s) + ...
  430. #
  431. # Thus d/da G(z) = log(z)G(z) - ...
  432. # The ... can be evaluated as a G function under the above conditions,
  433. # the formula being most easily derived by using
  434. #
  435. # d Gamma(s + n) Gamma(s + n) / 1 1 1 \
  436. # -- ------------ = ------------ | - + ---- + ... + --------- |
  437. # ds Gamma(s) Gamma(s) \ s s + 1 s + n - 1 /
  438. #
  439. # which follows from the difference equation of the digamma function.
  440. # (There is a similar equation for -n instead of +n).
  441. # We first figure out how to pair the parameters.
  442. an = list(self.an)
  443. ap = list(self.aother)
  444. bm = list(self.bm)
  445. bq = list(self.bother)
  446. if idx < len(an):
  447. an.pop(idx)
  448. else:
  449. idx -= len(an)
  450. if idx < len(ap):
  451. ap.pop(idx)
  452. else:
  453. idx -= len(ap)
  454. if idx < len(bm):
  455. bm.pop(idx)
  456. else:
  457. bq.pop(idx - len(bm))
  458. pairs1 = []
  459. pairs2 = []
  460. for l1, l2, pairs in [(an, bq, pairs1), (ap, bm, pairs2)]:
  461. while l1:
  462. x = l1.pop()
  463. found = None
  464. for i, y in enumerate(l2):
  465. if not Mod((x - y).simplify(), 1):
  466. found = i
  467. break
  468. if found is None:
  469. raise NotImplementedError('Derivative not expressible '
  470. 'as G-function?')
  471. y = l2[i]
  472. l2.pop(i)
  473. pairs.append((x, y))
  474. # Now build the result.
  475. res = log(self.argument)*self
  476. for a, b in pairs1:
  477. sign = 1
  478. n = a - b
  479. base = b
  480. if n < 0:
  481. sign = -1
  482. n = b - a
  483. base = a
  484. for k in range(n):
  485. res -= sign*meijerg(self.an + (base + k + 1,), self.aother,
  486. self.bm, self.bother + (base + k + 0,),
  487. self.argument)
  488. for a, b in pairs2:
  489. sign = 1
  490. n = b - a
  491. base = a
  492. if n < 0:
  493. sign = -1
  494. n = a - b
  495. base = b
  496. for k in range(n):
  497. res -= sign*meijerg(self.an, self.aother + (base + k + 1,),
  498. self.bm + (base + k + 0,), self.bother,
  499. self.argument)
  500. return res
  501. def get_period(self):
  502. """
  503. Return a number $P$ such that $G(x*exp(I*P)) == G(x)$.
  504. Examples
  505. ========
  506. >>> from sympy import meijerg, pi, S
  507. >>> from sympy.abc import z
  508. >>> meijerg([1], [], [], [], z).get_period()
  509. 2*pi
  510. >>> meijerg([pi], [], [], [], z).get_period()
  511. oo
  512. >>> meijerg([1, 2], [], [], [], z).get_period()
  513. oo
  514. >>> meijerg([1,1], [2], [1, S(1)/2, S(1)/3], [1], z).get_period()
  515. 12*pi
  516. """
  517. # This follows from slater's theorem.
  518. def compute(l):
  519. # first check that no two differ by an integer
  520. for i, b in enumerate(l):
  521. if not b.is_Rational:
  522. return oo
  523. for j in range(i + 1, len(l)):
  524. if not Mod((b - l[j]).simplify(), 1):
  525. return oo
  526. return reduce(ilcm, (x.q for x in l), 1)
  527. beta = compute(self.bm)
  528. alpha = compute(self.an)
  529. p, q = len(self.ap), len(self.bq)
  530. if p == q:
  531. if oo in (alpha, beta):
  532. return oo
  533. return 2*pi*ilcm(alpha, beta)
  534. elif p < q:
  535. return 2*pi*beta
  536. else:
  537. return 2*pi*alpha
  538. def _eval_expand_func(self, **hints):
  539. from sympy.simplify.hyperexpand import hyperexpand
  540. return hyperexpand(self)
  541. def _eval_evalf(self, prec):
  542. # The default code is insufficient for polar arguments.
  543. # mpmath provides an optional argument "r", which evaluates
  544. # G(z**(1/r)). I am not sure what its intended use is, but we hijack it
  545. # here in the following way: to evaluate at a number z of |argument|
  546. # less than (say) n*pi, we put r=1/n, compute z' = root(z, n)
  547. # (carefully so as not to loose the branch information), and evaluate
  548. # G(z'**(1/r)) = G(z'**n) = G(z).
  549. import mpmath
  550. znum = self.argument._eval_evalf(prec)
  551. if znum.has(exp_polar):
  552. znum, branch = znum.as_coeff_mul(exp_polar)
  553. if len(branch) != 1:
  554. return
  555. branch = branch[0].args[0]/I
  556. else:
  557. branch = S.Zero
  558. n = ceiling(abs(branch/pi)) + 1
  559. znum = znum**(S.One/n)*exp(I*branch / n)
  560. # Convert all args to mpf or mpc
  561. try:
  562. [z, r, ap, bq] = [arg._to_mpmath(prec)
  563. for arg in [znum, 1/n, self.args[0], self.args[1]]]
  564. except ValueError:
  565. return
  566. with mpmath.workprec(prec):
  567. v = mpmath.meijerg(ap, bq, z, r)
  568. return Expr._from_mpmath(v, prec)
  569. def _eval_as_leading_term(self, x, logx=None, cdir=0):
  570. from sympy.simplify.hyperexpand import hyperexpand
  571. return hyperexpand(self).as_leading_term(x, logx=logx, cdir=cdir)
  572. def integrand(self, s):
  573. """ Get the defining integrand D(s). """
  574. from sympy.functions.special.gamma_functions import gamma
  575. return self.argument**s \
  576. * Mul(*(gamma(b - s) for b in self.bm)) \
  577. * Mul(*(gamma(1 - a + s) for a in self.an)) \
  578. / Mul(*(gamma(1 - b + s) for b in self.bother)) \
  579. / Mul(*(gamma(a - s) for a in self.aother))
  580. @property
  581. def argument(self):
  582. """ Argument of the Meijer G-function. """
  583. return self.args[2]
  584. @property
  585. def an(self):
  586. """ First set of numerator parameters. """
  587. return Tuple(*self.args[0][0])
  588. @property
  589. def ap(self):
  590. """ Combined numerator parameters. """
  591. return Tuple(*(self.args[0][0] + self.args[0][1]))
  592. @property
  593. def aother(self):
  594. """ Second set of numerator parameters. """
  595. return Tuple(*self.args[0][1])
  596. @property
  597. def bm(self):
  598. """ First set of denominator parameters. """
  599. return Tuple(*self.args[1][0])
  600. @property
  601. def bq(self):
  602. """ Combined denominator parameters. """
  603. return Tuple(*(self.args[1][0] + self.args[1][1]))
  604. @property
  605. def bother(self):
  606. """ Second set of denominator parameters. """
  607. return Tuple(*self.args[1][1])
  608. @property
  609. def _diffargs(self):
  610. return self.ap + self.bq
  611. @property
  612. def nu(self):
  613. """ A quantity related to the convergence region of the integral,
  614. c.f. references. """
  615. return sum(self.bq) - sum(self.ap)
  616. @property
  617. def delta(self):
  618. """ A quantity related to the convergence region of the integral,
  619. c.f. references. """
  620. return len(self.bm) + len(self.an) - S(len(self.ap) + len(self.bq))/2
  621. @property
  622. def is_number(self):
  623. """ Returns true if expression has numeric data only. """
  624. return not self.free_symbols
  625. class HyperRep(Function):
  626. """
  627. A base class for "hyper representation functions".
  628. This is used exclusively in ``hyperexpand()``, but fits more logically here.
  629. pFq is branched at 1 if p == q+1. For use with slater-expansion, we want
  630. define an "analytic continuation" to all polar numbers, which is
  631. continuous on circles and on the ray t*exp_polar(I*pi). Moreover, we want
  632. a "nice" expression for the various cases.
  633. This base class contains the core logic, concrete derived classes only
  634. supply the actual functions.
  635. """
  636. @classmethod
  637. def eval(cls, *args):
  638. newargs = tuple(map(unpolarify, args[:-1])) + args[-1:]
  639. if args != newargs:
  640. return cls(*newargs)
  641. @classmethod
  642. def _expr_small(cls, x):
  643. """ An expression for F(x) which holds for |x| < 1. """
  644. raise NotImplementedError
  645. @classmethod
  646. def _expr_small_minus(cls, x):
  647. """ An expression for F(-x) which holds for |x| < 1. """
  648. raise NotImplementedError
  649. @classmethod
  650. def _expr_big(cls, x, n):
  651. """ An expression for F(exp_polar(2*I*pi*n)*x), |x| > 1. """
  652. raise NotImplementedError
  653. @classmethod
  654. def _expr_big_minus(cls, x, n):
  655. """ An expression for F(exp_polar(2*I*pi*n + pi*I)*x), |x| > 1. """
  656. raise NotImplementedError
  657. def _eval_rewrite_as_nonrep(self, *args, **kwargs):
  658. x, n = self.args[-1].extract_branch_factor(allow_half=True)
  659. minus = False
  660. newargs = self.args[:-1] + (x,)
  661. if not n.is_Integer:
  662. minus = True
  663. n -= S.Half
  664. newerargs = newargs + (n,)
  665. if minus:
  666. small = self._expr_small_minus(*newargs)
  667. big = self._expr_big_minus(*newerargs)
  668. else:
  669. small = self._expr_small(*newargs)
  670. big = self._expr_big(*newerargs)
  671. if big == small:
  672. return small
  673. return Piecewise((big, abs(x) > 1), (small, True))
  674. def _eval_rewrite_as_nonrepsmall(self, *args, **kwargs):
  675. x, n = self.args[-1].extract_branch_factor(allow_half=True)
  676. args = self.args[:-1] + (x,)
  677. if not n.is_Integer:
  678. return self._expr_small_minus(*args)
  679. return self._expr_small(*args)
  680. class HyperRep_power1(HyperRep):
  681. """ Return a representative for hyper([-a], [], z) == (1 - z)**a. """
  682. @classmethod
  683. def _expr_small(cls, a, x):
  684. return (1 - x)**a
  685. @classmethod
  686. def _expr_small_minus(cls, a, x):
  687. return (1 + x)**a
  688. @classmethod
  689. def _expr_big(cls, a, x, n):
  690. if a.is_integer:
  691. return cls._expr_small(a, x)
  692. return (x - 1)**a*exp((2*n - 1)*pi*I*a)
  693. @classmethod
  694. def _expr_big_minus(cls, a, x, n):
  695. if a.is_integer:
  696. return cls._expr_small_minus(a, x)
  697. return (1 + x)**a*exp(2*n*pi*I*a)
  698. class HyperRep_power2(HyperRep):
  699. """ Return a representative for hyper([a, a - 1/2], [2*a], z). """
  700. @classmethod
  701. def _expr_small(cls, a, x):
  702. return 2**(2*a - 1)*(1 + sqrt(1 - x))**(1 - 2*a)
  703. @classmethod
  704. def _expr_small_minus(cls, a, x):
  705. return 2**(2*a - 1)*(1 + sqrt(1 + x))**(1 - 2*a)
  706. @classmethod
  707. def _expr_big(cls, a, x, n):
  708. sgn = -1
  709. if n.is_odd:
  710. sgn = 1
  711. n -= 1
  712. return 2**(2*a - 1)*(1 + sgn*I*sqrt(x - 1))**(1 - 2*a) \
  713. *exp(-2*n*pi*I*a)
  714. @classmethod
  715. def _expr_big_minus(cls, a, x, n):
  716. sgn = 1
  717. if n.is_odd:
  718. sgn = -1
  719. return sgn*2**(2*a - 1)*(sqrt(1 + x) + sgn)**(1 - 2*a)*exp(-2*pi*I*a*n)
  720. class HyperRep_log1(HyperRep):
  721. """ Represent -z*hyper([1, 1], [2], z) == log(1 - z). """
  722. @classmethod
  723. def _expr_small(cls, x):
  724. return log(1 - x)
  725. @classmethod
  726. def _expr_small_minus(cls, x):
  727. return log(1 + x)
  728. @classmethod
  729. def _expr_big(cls, x, n):
  730. return log(x - 1) + (2*n - 1)*pi*I
  731. @classmethod
  732. def _expr_big_minus(cls, x, n):
  733. return log(1 + x) + 2*n*pi*I
  734. class HyperRep_atanh(HyperRep):
  735. """ Represent hyper([1/2, 1], [3/2], z) == atanh(sqrt(z))/sqrt(z). """
  736. @classmethod
  737. def _expr_small(cls, x):
  738. return atanh(sqrt(x))/sqrt(x)
  739. def _expr_small_minus(cls, x):
  740. return atan(sqrt(x))/sqrt(x)
  741. def _expr_big(cls, x, n):
  742. if n.is_even:
  743. return (acoth(sqrt(x)) + I*pi/2)/sqrt(x)
  744. else:
  745. return (acoth(sqrt(x)) - I*pi/2)/sqrt(x)
  746. def _expr_big_minus(cls, x, n):
  747. if n.is_even:
  748. return atan(sqrt(x))/sqrt(x)
  749. else:
  750. return (atan(sqrt(x)) - pi)/sqrt(x)
  751. class HyperRep_asin1(HyperRep):
  752. """ Represent hyper([1/2, 1/2], [3/2], z) == asin(sqrt(z))/sqrt(z). """
  753. @classmethod
  754. def _expr_small(cls, z):
  755. return asin(sqrt(z))/sqrt(z)
  756. @classmethod
  757. def _expr_small_minus(cls, z):
  758. return asinh(sqrt(z))/sqrt(z)
  759. @classmethod
  760. def _expr_big(cls, z, n):
  761. return S.NegativeOne**n*((S.Half - n)*pi/sqrt(z) + I*acosh(sqrt(z))/sqrt(z))
  762. @classmethod
  763. def _expr_big_minus(cls, z, n):
  764. return S.NegativeOne**n*(asinh(sqrt(z))/sqrt(z) + n*pi*I/sqrt(z))
  765. class HyperRep_asin2(HyperRep):
  766. """ Represent hyper([1, 1], [3/2], z) == asin(sqrt(z))/sqrt(z)/sqrt(1-z). """
  767. # TODO this can be nicer
  768. @classmethod
  769. def _expr_small(cls, z):
  770. return HyperRep_asin1._expr_small(z) \
  771. /HyperRep_power1._expr_small(S.Half, z)
  772. @classmethod
  773. def _expr_small_minus(cls, z):
  774. return HyperRep_asin1._expr_small_minus(z) \
  775. /HyperRep_power1._expr_small_minus(S.Half, z)
  776. @classmethod
  777. def _expr_big(cls, z, n):
  778. return HyperRep_asin1._expr_big(z, n) \
  779. /HyperRep_power1._expr_big(S.Half, z, n)
  780. @classmethod
  781. def _expr_big_minus(cls, z, n):
  782. return HyperRep_asin1._expr_big_minus(z, n) \
  783. /HyperRep_power1._expr_big_minus(S.Half, z, n)
  784. class HyperRep_sqrts1(HyperRep):
  785. """ Return a representative for hyper([-a, 1/2 - a], [1/2], z). """
  786. @classmethod
  787. def _expr_small(cls, a, z):
  788. return ((1 - sqrt(z))**(2*a) + (1 + sqrt(z))**(2*a))/2
  789. @classmethod
  790. def _expr_small_minus(cls, a, z):
  791. return (1 + z)**a*cos(2*a*atan(sqrt(z)))
  792. @classmethod
  793. def _expr_big(cls, a, z, n):
  794. if n.is_even:
  795. return ((sqrt(z) + 1)**(2*a)*exp(2*pi*I*n*a) +
  796. (sqrt(z) - 1)**(2*a)*exp(2*pi*I*(n - 1)*a))/2
  797. else:
  798. n -= 1
  799. return ((sqrt(z) - 1)**(2*a)*exp(2*pi*I*a*(n + 1)) +
  800. (sqrt(z) + 1)**(2*a)*exp(2*pi*I*a*n))/2
  801. @classmethod
  802. def _expr_big_minus(cls, a, z, n):
  803. if n.is_even:
  804. return (1 + z)**a*exp(2*pi*I*n*a)*cos(2*a*atan(sqrt(z)))
  805. else:
  806. return (1 + z)**a*exp(2*pi*I*n*a)*cos(2*a*atan(sqrt(z)) - 2*pi*a)
  807. class HyperRep_sqrts2(HyperRep):
  808. """ Return a representative for
  809. sqrt(z)/2*[(1-sqrt(z))**2a - (1 + sqrt(z))**2a]
  810. == -2*z/(2*a+1) d/dz hyper([-a - 1/2, -a], [1/2], z)"""
  811. @classmethod
  812. def _expr_small(cls, a, z):
  813. return sqrt(z)*((1 - sqrt(z))**(2*a) - (1 + sqrt(z))**(2*a))/2
  814. @classmethod
  815. def _expr_small_minus(cls, a, z):
  816. return sqrt(z)*(1 + z)**a*sin(2*a*atan(sqrt(z)))
  817. @classmethod
  818. def _expr_big(cls, a, z, n):
  819. if n.is_even:
  820. return sqrt(z)/2*((sqrt(z) - 1)**(2*a)*exp(2*pi*I*a*(n - 1)) -
  821. (sqrt(z) + 1)**(2*a)*exp(2*pi*I*a*n))
  822. else:
  823. n -= 1
  824. return sqrt(z)/2*((sqrt(z) - 1)**(2*a)*exp(2*pi*I*a*(n + 1)) -
  825. (sqrt(z) + 1)**(2*a)*exp(2*pi*I*a*n))
  826. def _expr_big_minus(cls, a, z, n):
  827. if n.is_even:
  828. return (1 + z)**a*exp(2*pi*I*n*a)*sqrt(z)*sin(2*a*atan(sqrt(z)))
  829. else:
  830. return (1 + z)**a*exp(2*pi*I*n*a)*sqrt(z) \
  831. *sin(2*a*atan(sqrt(z)) - 2*pi*a)
  832. class HyperRep_log2(HyperRep):
  833. """ Represent log(1/2 + sqrt(1 - z)/2) == -z/4*hyper([3/2, 1, 1], [2, 2], z) """
  834. @classmethod
  835. def _expr_small(cls, z):
  836. return log(S.Half + sqrt(1 - z)/2)
  837. @classmethod
  838. def _expr_small_minus(cls, z):
  839. return log(S.Half + sqrt(1 + z)/2)
  840. @classmethod
  841. def _expr_big(cls, z, n):
  842. if n.is_even:
  843. return (n - S.Half)*pi*I + log(sqrt(z)/2) + I*asin(1/sqrt(z))
  844. else:
  845. return (n - S.Half)*pi*I + log(sqrt(z)/2) - I*asin(1/sqrt(z))
  846. def _expr_big_minus(cls, z, n):
  847. if n.is_even:
  848. return pi*I*n + log(S.Half + sqrt(1 + z)/2)
  849. else:
  850. return pi*I*n + log(sqrt(1 + z)/2 - S.Half)
  851. class HyperRep_cosasin(HyperRep):
  852. """ Represent hyper([a, -a], [1/2], z) == cos(2*a*asin(sqrt(z))). """
  853. # Note there are many alternative expressions, e.g. as powers of a sum of
  854. # square roots.
  855. @classmethod
  856. def _expr_small(cls, a, z):
  857. return cos(2*a*asin(sqrt(z)))
  858. @classmethod
  859. def _expr_small_minus(cls, a, z):
  860. return cosh(2*a*asinh(sqrt(z)))
  861. @classmethod
  862. def _expr_big(cls, a, z, n):
  863. return cosh(2*a*acosh(sqrt(z)) + a*pi*I*(2*n - 1))
  864. @classmethod
  865. def _expr_big_minus(cls, a, z, n):
  866. return cosh(2*a*asinh(sqrt(z)) + 2*a*pi*I*n)
  867. class HyperRep_sinasin(HyperRep):
  868. """ Represent 2*a*z*hyper([1 - a, 1 + a], [3/2], z)
  869. == sqrt(z)/sqrt(1-z)*sin(2*a*asin(sqrt(z))) """
  870. @classmethod
  871. def _expr_small(cls, a, z):
  872. return sqrt(z)/sqrt(1 - z)*sin(2*a*asin(sqrt(z)))
  873. @classmethod
  874. def _expr_small_minus(cls, a, z):
  875. return -sqrt(z)/sqrt(1 + z)*sinh(2*a*asinh(sqrt(z)))
  876. @classmethod
  877. def _expr_big(cls, a, z, n):
  878. return -1/sqrt(1 - 1/z)*sinh(2*a*acosh(sqrt(z)) + a*pi*I*(2*n - 1))
  879. @classmethod
  880. def _expr_big_minus(cls, a, z, n):
  881. return -1/sqrt(1 + 1/z)*sinh(2*a*asinh(sqrt(z)) + 2*a*pi*I*n)
  882. class appellf1(Function):
  883. r"""
  884. This is the Appell hypergeometric function of two variables as:
  885. .. math ::
  886. F_1(a,b_1,b_2,c,x,y) = \sum_{m=0}^{\infty} \sum_{n=0}^{\infty}
  887. \frac{(a)_{m+n} (b_1)_m (b_2)_n}{(c)_{m+n}}
  888. \frac{x^m y^n}{m! n!}.
  889. Examples
  890. ========
  891. >>> from sympy import appellf1, symbols
  892. >>> x, y, a, b1, b2, c = symbols('x y a b1 b2 c')
  893. >>> appellf1(2., 1., 6., 4., 5., 6.)
  894. 0.0063339426292673
  895. >>> appellf1(12., 12., 6., 4., 0.5, 0.12)
  896. 172870711.659936
  897. >>> appellf1(40, 2, 6, 4, 15, 60)
  898. appellf1(40, 2, 6, 4, 15, 60)
  899. >>> appellf1(20., 12., 10., 3., 0.5, 0.12)
  900. 15605338197184.4
  901. >>> appellf1(40, 2, 6, 4, x, y)
  902. appellf1(40, 2, 6, 4, x, y)
  903. >>> appellf1(a, b1, b2, c, x, y)
  904. appellf1(a, b1, b2, c, x, y)
  905. References
  906. ==========
  907. .. [1] https://en.wikipedia.org/wiki/Appell_series
  908. .. [2] https://functions.wolfram.com/HypergeometricFunctions/AppellF1/
  909. """
  910. @classmethod
  911. def eval(cls, a, b1, b2, c, x, y):
  912. if default_sort_key(b1) > default_sort_key(b2):
  913. b1, b2 = b2, b1
  914. x, y = y, x
  915. return cls(a, b1, b2, c, x, y)
  916. elif b1 == b2 and default_sort_key(x) > default_sort_key(y):
  917. x, y = y, x
  918. return cls(a, b1, b2, c, x, y)
  919. if x == 0 and y == 0:
  920. return S.One
  921. def fdiff(self, argindex=5):
  922. a, b1, b2, c, x, y = self.args
  923. if argindex == 5:
  924. return (a*b1/c)*appellf1(a + 1, b1 + 1, b2, c + 1, x, y)
  925. elif argindex == 6:
  926. return (a*b2/c)*appellf1(a + 1, b1, b2 + 1, c + 1, x, y)
  927. elif argindex in (1, 2, 3, 4):
  928. return Derivative(self, self.args[argindex-1])
  929. else:
  930. raise ArgumentIndexError(self, argindex)