hyper.py 37 KB

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