hyper.py 38 KB

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