hyperexpand.py 83 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970197119721973197419751976197719781979198019811982198319841985198619871988198919901991199219931994199519961997199819992000200120022003200420052006200720082009201020112012201320142015201620172018201920202021202220232024202520262027202820292030203120322033203420352036203720382039204020412042204320442045204620472048204920502051205220532054205520562057205820592060206120622063206420652066206720682069207020712072207320742075207620772078207920802081208220832084208520862087208820892090209120922093209420952096209720982099210021012102210321042105210621072108210921102111211221132114211521162117211821192120212121222123212421252126212721282129213021312132213321342135213621372138213921402141214221432144214521462147214821492150215121522153215421552156215721582159216021612162216321642165216621672168216921702171217221732174217521762177217821792180218121822183218421852186218721882189219021912192219321942195219621972198219922002201220222032204220522062207220822092210221122122213221422152216221722182219222022212222222322242225222622272228222922302231223222332234223522362237223822392240224122422243224422452246224722482249225022512252225322542255225622572258225922602261226222632264226522662267226822692270227122722273227422752276227722782279228022812282228322842285228622872288228922902291229222932294229522962297229822992300230123022303230423052306230723082309231023112312231323142315231623172318231923202321232223232324232523262327232823292330233123322333233423352336233723382339234023412342234323442345234623472348234923502351235223532354235523562357235823592360236123622363236423652366236723682369237023712372237323742375237623772378237923802381238223832384238523862387238823892390239123922393239423952396239723982399240024012402240324042405240624072408240924102411241224132414241524162417241824192420242124222423242424252426242724282429243024312432243324342435243624372438243924402441244224432444244524462447244824492450245124522453245424552456245724582459246024612462246324642465246624672468246924702471247224732474247524762477247824792480248124822483248424852486248724882489249024912492249324942495249624972498249925002501250225032504250525062507250825092510251125122513251425152516
  1. """
  2. Expand Hypergeometric (and Meijer G) functions into named
  3. special functions.
  4. The algorithm for doing this uses a collection of lookup tables of
  5. hypergeometric functions, and various of their properties, to expand
  6. many hypergeometric functions in terms of special functions.
  7. It is based on the following paper:
  8. Kelly B. Roach. Meijer G Function Representations.
  9. In: Proceedings of the 1997 International Symposium on Symbolic and
  10. Algebraic Computation, pages 205-211, New York, 1997. ACM.
  11. It is described in great(er) detail in the Sphinx documentation.
  12. """
  13. # SUMMARY OF EXTENSIONS FOR MEIJER G FUNCTIONS
  14. #
  15. # o z**rho G(ap, bq; z) = G(ap + rho, bq + rho; z)
  16. #
  17. # o denote z*d/dz by D
  18. #
  19. # o It is helpful to keep in mind that ap and bq play essentially symmetric
  20. # roles: G(1/z) has slightly altered parameters, with ap and bq interchanged.
  21. #
  22. # o There are four shift operators:
  23. # A_J = b_J - D, J = 1, ..., n
  24. # B_J = 1 - a_j + D, J = 1, ..., m
  25. # C_J = -b_J + D, J = m+1, ..., q
  26. # D_J = a_J - 1 - D, J = n+1, ..., p
  27. #
  28. # A_J, C_J increment b_J
  29. # B_J, D_J decrement a_J
  30. #
  31. # o The corresponding four inverse-shift operators are defined if there
  32. # is no cancellation. Thus e.g. an index a_J (upper or lower) can be
  33. # incremented if a_J != b_i for i = 1, ..., q.
  34. #
  35. # o Order reduction: if b_j - a_i is a non-negative integer, where
  36. # j <= m and i > n, the corresponding quotient of gamma functions reduces
  37. # to a polynomial. Hence the G function can be expressed using a G-function
  38. # of lower order.
  39. # Similarly if j > m and i <= n.
  40. #
  41. # Secondly, there are paired index theorems [Adamchik, The evaluation of
  42. # integrals of Bessel functions via G-function identities]. Suppose there
  43. # are three parameters a, b, c, where a is an a_i, i <= n, b is a b_j,
  44. # j <= m and c is a denominator parameter (i.e. a_i, i > n or b_j, j > m).
  45. # Suppose further all three differ by integers.
  46. # Then the order can be reduced.
  47. # TODO work this out in detail.
  48. #
  49. # o An index quadruple is called suitable if its order cannot be reduced.
  50. # If there exists a sequence of shift operators transforming one index
  51. # quadruple into another, we say one is reachable from the other.
  52. #
  53. # o Deciding if one index quadruple is reachable from another is tricky. For
  54. # this reason, we use hand-built routines to match and instantiate formulas.
  55. #
  56. from collections import defaultdict
  57. from itertools import product
  58. from functools import reduce
  59. from sympy import SYMPY_DEBUG
  60. from sympy.core import (S, Dummy, symbols, sympify, Tuple, expand, I, pi, Mul,
  61. EulerGamma, oo, zoo, expand_func, Add, nan, Expr, Rational)
  62. from sympy.core.mod import Mod
  63. from sympy.core.sorting import default_sort_key
  64. from sympy.functions import (exp, sqrt, root, log, lowergamma, cos,
  65. besseli, gamma, uppergamma, expint, erf, sin, besselj, Ei, Ci, Si, Shi,
  66. sinh, cosh, Chi, fresnels, fresnelc, polar_lift, exp_polar, floor, ceiling,
  67. rf, factorial, lerchphi, Piecewise, re, elliptic_k, elliptic_e)
  68. from sympy.functions.elementary.complexes import polarify, unpolarify
  69. from sympy.functions.special.hyper import (hyper, HyperRep_atanh,
  70. HyperRep_power1, HyperRep_power2, HyperRep_log1, HyperRep_asin1,
  71. HyperRep_asin2, HyperRep_sqrts1, HyperRep_sqrts2, HyperRep_log2,
  72. HyperRep_cosasin, HyperRep_sinasin, meijerg)
  73. from sympy.polys import poly, Poly
  74. from sympy.simplify.powsimp import powdenest
  75. from sympy.utilities.iterables import sift
  76. # function to define "buckets"
  77. def _mod1(x):
  78. # TODO see if this can work as Mod(x, 1); this will require
  79. # different handling of the "buckets" since these need to
  80. # be sorted and that fails when there is a mixture of
  81. # integers and expressions with parameters. With the current
  82. # Mod behavior, Mod(k, 1) == Mod(1, 1) == 0 if k is an integer.
  83. # Although the sorting can be done with Basic.compare, this may
  84. # still require different handling of the sorted buckets.
  85. if x.is_Number:
  86. return Mod(x, 1)
  87. c, x = x.as_coeff_Add()
  88. return Mod(c, 1) + x
  89. # leave add formulae at the top for easy reference
  90. def add_formulae(formulae):
  91. """ Create our knowledge base. """
  92. from sympy.matrices import Matrix
  93. a, b, c, z = symbols('a b c, z', cls=Dummy)
  94. def add(ap, bq, res):
  95. func = Hyper_Function(ap, bq)
  96. formulae.append(Formula(func, z, res, (a, b, c)))
  97. def addb(ap, bq, B, C, M):
  98. func = Hyper_Function(ap, bq)
  99. formulae.append(Formula(func, z, None, (a, b, c), B, C, M))
  100. # Luke, Y. L. (1969), The Special Functions and Their Approximations,
  101. # Volume 1, section 6.2
  102. # 0F0
  103. add((), (), exp(z))
  104. # 1F0
  105. add((a, ), (), HyperRep_power1(-a, z))
  106. # 2F1
  107. addb((a, a - S.Half), (2*a, ),
  108. Matrix([HyperRep_power2(a, z),
  109. HyperRep_power2(a + S.Half, z)/2]),
  110. Matrix([[1, 0]]),
  111. Matrix([[(a - S.Half)*z/(1 - z), (S.Half - a)*z/(1 - z)],
  112. [a/(1 - z), a*(z - 2)/(1 - z)]]))
  113. addb((1, 1), (2, ),
  114. Matrix([HyperRep_log1(z), 1]), Matrix([[-1/z, 0]]),
  115. Matrix([[0, z/(z - 1)], [0, 0]]))
  116. addb((S.Half, 1), (S('3/2'), ),
  117. Matrix([HyperRep_atanh(z), 1]),
  118. Matrix([[1, 0]]),
  119. Matrix([[Rational(-1, 2), 1/(1 - z)/2], [0, 0]]))
  120. addb((S.Half, S.Half), (S('3/2'), ),
  121. Matrix([HyperRep_asin1(z), HyperRep_power1(Rational(-1, 2), z)]),
  122. Matrix([[1, 0]]),
  123. Matrix([[Rational(-1, 2), S.Half], [0, z/(1 - z)/2]]))
  124. addb((a, S.Half + a), (S.Half, ),
  125. Matrix([HyperRep_sqrts1(-a, z), -HyperRep_sqrts2(-a - S.Half, z)]),
  126. Matrix([[1, 0]]),
  127. Matrix([[0, -a],
  128. [z*(-2*a - 1)/2/(1 - z), S.Half - z*(-2*a - 1)/(1 - z)]]))
  129. # A. P. Prudnikov, Yu. A. Brychkov and O. I. Marichev (1990).
  130. # Integrals and Series: More Special Functions, Vol. 3,.
  131. # Gordon and Breach Science Publisher
  132. addb([a, -a], [S.Half],
  133. Matrix([HyperRep_cosasin(a, z), HyperRep_sinasin(a, z)]),
  134. Matrix([[1, 0]]),
  135. Matrix([[0, -a], [a*z/(1 - z), 1/(1 - z)/2]]))
  136. addb([1, 1], [3*S.Half],
  137. Matrix([HyperRep_asin2(z), 1]), Matrix([[1, 0]]),
  138. Matrix([[(z - S.Half)/(1 - z), 1/(1 - z)/2], [0, 0]]))
  139. # Complete elliptic integrals K(z) and E(z), both a 2F1 function
  140. addb([S.Half, S.Half], [S.One],
  141. Matrix([elliptic_k(z), elliptic_e(z)]),
  142. Matrix([[2/pi, 0]]),
  143. Matrix([[Rational(-1, 2), -1/(2*z-2)],
  144. [Rational(-1, 2), S.Half]]))
  145. addb([Rational(-1, 2), S.Half], [S.One],
  146. Matrix([elliptic_k(z), elliptic_e(z)]),
  147. Matrix([[0, 2/pi]]),
  148. Matrix([[Rational(-1, 2), -1/(2*z-2)],
  149. [Rational(-1, 2), S.Half]]))
  150. # 3F2
  151. addb([Rational(-1, 2), 1, 1], [S.Half, 2],
  152. Matrix([z*HyperRep_atanh(z), HyperRep_log1(z), 1]),
  153. Matrix([[Rational(-2, 3), -S.One/(3*z), Rational(2, 3)]]),
  154. Matrix([[S.Half, 0, z/(1 - z)/2],
  155. [0, 0, z/(z - 1)],
  156. [0, 0, 0]]))
  157. # actually the formula for 3/2 is much nicer ...
  158. addb([Rational(-1, 2), 1, 1], [2, 2],
  159. Matrix([HyperRep_power1(S.Half, z), HyperRep_log2(z), 1]),
  160. Matrix([[Rational(4, 9) - 16/(9*z), 4/(3*z), 16/(9*z)]]),
  161. Matrix([[z/2/(z - 1), 0, 0], [1/(2*(z - 1)), 0, S.Half], [0, 0, 0]]))
  162. # 1F1
  163. addb([1], [b], Matrix([z**(1 - b) * exp(z) * lowergamma(b - 1, z), 1]),
  164. Matrix([[b - 1, 0]]), Matrix([[1 - b + z, 1], [0, 0]]))
  165. addb([a], [2*a],
  166. Matrix([z**(S.Half - a)*exp(z/2)*besseli(a - S.Half, z/2)
  167. * gamma(a + S.Half)/4**(S.Half - a),
  168. z**(S.Half - a)*exp(z/2)*besseli(a + S.Half, z/2)
  169. * gamma(a + S.Half)/4**(S.Half - a)]),
  170. Matrix([[1, 0]]),
  171. Matrix([[z/2, z/2], [z/2, (z/2 - 2*a)]]))
  172. mz = polar_lift(-1)*z
  173. addb([a], [a + 1],
  174. Matrix([mz**(-a)*a*lowergamma(a, mz), a*exp(z)]),
  175. Matrix([[1, 0]]),
  176. Matrix([[-a, 1], [0, z]]))
  177. # This one is redundant.
  178. add([Rational(-1, 2)], [S.Half], exp(z) - sqrt(pi*z)*(-I)*erf(I*sqrt(z)))
  179. # Added to get nice results for Laplace transform of Fresnel functions
  180. # http://functions.wolfram.com/07.22.03.6437.01
  181. # Basic rule
  182. #add([1], [Rational(3, 4), Rational(5, 4)],
  183. # sqrt(pi) * (cos(2*sqrt(polar_lift(-1)*z))*fresnelc(2*root(polar_lift(-1)*z,4)/sqrt(pi)) +
  184. # sin(2*sqrt(polar_lift(-1)*z))*fresnels(2*root(polar_lift(-1)*z,4)/sqrt(pi)))
  185. # / (2*root(polar_lift(-1)*z,4)))
  186. # Manually tuned rule
  187. addb([1], [Rational(3, 4), Rational(5, 4)],
  188. Matrix([ sqrt(pi)*(I*sinh(2*sqrt(z))*fresnels(2*root(z, 4)*exp(I*pi/4)/sqrt(pi))
  189. + cosh(2*sqrt(z))*fresnelc(2*root(z, 4)*exp(I*pi/4)/sqrt(pi)))
  190. * exp(-I*pi/4)/(2*root(z, 4)),
  191. sqrt(pi)*root(z, 4)*(sinh(2*sqrt(z))*fresnelc(2*root(z, 4)*exp(I*pi/4)/sqrt(pi))
  192. + I*cosh(2*sqrt(z))*fresnels(2*root(z, 4)*exp(I*pi/4)/sqrt(pi)))
  193. *exp(-I*pi/4)/2,
  194. 1 ]),
  195. Matrix([[1, 0, 0]]),
  196. Matrix([[Rational(-1, 4), 1, Rational(1, 4)],
  197. [ z, Rational(1, 4), 0],
  198. [ 0, 0, 0]]))
  199. # 2F2
  200. addb([S.Half, a], [Rational(3, 2), a + 1],
  201. Matrix([a/(2*a - 1)*(-I)*sqrt(pi/z)*erf(I*sqrt(z)),
  202. a/(2*a - 1)*(polar_lift(-1)*z)**(-a)*
  203. lowergamma(a, polar_lift(-1)*z),
  204. a/(2*a - 1)*exp(z)]),
  205. Matrix([[1, -1, 0]]),
  206. Matrix([[Rational(-1, 2), 0, 1], [0, -a, 1], [0, 0, z]]))
  207. # We make a "basis" of four functions instead of three, and give EulerGamma
  208. # an extra slot (it could just be a coefficient to 1). The advantage is
  209. # that this way Polys will not see multivariate polynomials (it treats
  210. # EulerGamma as an indeterminate), which is *way* faster.
  211. addb([1, 1], [2, 2],
  212. Matrix([Ei(z) - log(z), exp(z), 1, EulerGamma]),
  213. Matrix([[1/z, 0, 0, -1/z]]),
  214. Matrix([[0, 1, -1, 0], [0, z, 0, 0], [0, 0, 0, 0], [0, 0, 0, 0]]))
  215. # 0F1
  216. add((), (S.Half, ), cosh(2*sqrt(z)))
  217. addb([], [b],
  218. Matrix([gamma(b)*z**((1 - b)/2)*besseli(b - 1, 2*sqrt(z)),
  219. gamma(b)*z**(1 - b/2)*besseli(b, 2*sqrt(z))]),
  220. Matrix([[1, 0]]), Matrix([[0, 1], [z, (1 - b)]]))
  221. # 0F3
  222. x = 4*z**Rational(1, 4)
  223. def fp(a, z):
  224. return besseli(a, x) + besselj(a, x)
  225. def fm(a, z):
  226. return besseli(a, x) - besselj(a, x)
  227. # TODO branching
  228. addb([], [S.Half, a, a + S.Half],
  229. Matrix([fp(2*a - 1, z), fm(2*a, z)*z**Rational(1, 4),
  230. fm(2*a - 1, z)*sqrt(z), fp(2*a, z)*z**Rational(3, 4)])
  231. * 2**(-2*a)*gamma(2*a)*z**((1 - 2*a)/4),
  232. Matrix([[1, 0, 0, 0]]),
  233. Matrix([[0, 1, 0, 0],
  234. [0, S.Half - a, 1, 0],
  235. [0, 0, S.Half, 1],
  236. [z, 0, 0, 1 - a]]))
  237. x = 2*(4*z)**Rational(1, 4)*exp_polar(I*pi/4)
  238. addb([], [a, a + S.Half, 2*a],
  239. (2*sqrt(polar_lift(-1)*z))**(1 - 2*a)*gamma(2*a)**2 *
  240. Matrix([besselj(2*a - 1, x)*besseli(2*a - 1, x),
  241. x*(besseli(2*a, x)*besselj(2*a - 1, x)
  242. - besseli(2*a - 1, x)*besselj(2*a, x)),
  243. x**2*besseli(2*a, x)*besselj(2*a, x),
  244. x**3*(besseli(2*a, x)*besselj(2*a - 1, x)
  245. + besseli(2*a - 1, x)*besselj(2*a, x))]),
  246. Matrix([[1, 0, 0, 0]]),
  247. Matrix([[0, Rational(1, 4), 0, 0],
  248. [0, (1 - 2*a)/2, Rational(-1, 2), 0],
  249. [0, 0, 1 - 2*a, Rational(1, 4)],
  250. [-32*z, 0, 0, 1 - a]]))
  251. # 1F2
  252. addb([a], [a - S.Half, 2*a],
  253. Matrix([z**(S.Half - a)*besseli(a - S.Half, sqrt(z))**2,
  254. z**(1 - a)*besseli(a - S.Half, sqrt(z))
  255. *besseli(a - Rational(3, 2), sqrt(z)),
  256. z**(Rational(3, 2) - a)*besseli(a - Rational(3, 2), sqrt(z))**2]),
  257. Matrix([[-gamma(a + S.Half)**2/4**(S.Half - a),
  258. 2*gamma(a - S.Half)*gamma(a + S.Half)/4**(1 - a),
  259. 0]]),
  260. Matrix([[1 - 2*a, 1, 0], [z/2, S.Half - a, S.Half], [0, z, 0]]))
  261. addb([S.Half], [b, 2 - b],
  262. pi*(1 - b)/sin(pi*b)*
  263. Matrix([besseli(1 - b, sqrt(z))*besseli(b - 1, sqrt(z)),
  264. sqrt(z)*(besseli(-b, sqrt(z))*besseli(b - 1, sqrt(z))
  265. + besseli(1 - b, sqrt(z))*besseli(b, sqrt(z))),
  266. besseli(-b, sqrt(z))*besseli(b, sqrt(z))]),
  267. Matrix([[1, 0, 0]]),
  268. Matrix([[b - 1, S.Half, 0],
  269. [z, 0, z],
  270. [0, S.Half, -b]]))
  271. addb([S.Half], [Rational(3, 2), Rational(3, 2)],
  272. Matrix([Shi(2*sqrt(z))/2/sqrt(z), sinh(2*sqrt(z))/2/sqrt(z),
  273. cosh(2*sqrt(z))]),
  274. Matrix([[1, 0, 0]]),
  275. Matrix([[Rational(-1, 2), S.Half, 0], [0, Rational(-1, 2), S.Half], [0, 2*z, 0]]))
  276. # FresnelS
  277. # Basic rule
  278. #add([Rational(3, 4)], [Rational(3, 2),Rational(7, 4)], 6*fresnels( exp(pi*I/4)*root(z,4)*2/sqrt(pi) ) / ( pi * (exp(pi*I/4)*root(z,4)*2/sqrt(pi))**3 ) )
  279. # Manually tuned rule
  280. addb([Rational(3, 4)], [Rational(3, 2), Rational(7, 4)],
  281. Matrix(
  282. [ fresnels(
  283. exp(
  284. pi*I/4)*root(
  285. z, 4)*2/sqrt(
  286. pi) ) / (
  287. pi * (exp(pi*I/4)*root(z, 4)*2/sqrt(pi))**3 ),
  288. sinh(2*sqrt(z))/sqrt(z),
  289. cosh(2*sqrt(z)) ]),
  290. Matrix([[6, 0, 0]]),
  291. Matrix([[Rational(-3, 4), Rational(1, 16), 0],
  292. [ 0, Rational(-1, 2), 1],
  293. [ 0, z, 0]]))
  294. # FresnelC
  295. # Basic rule
  296. #add([Rational(1, 4)], [S.Half,Rational(5, 4)], fresnelc( exp(pi*I/4)*root(z,4)*2/sqrt(pi) ) / ( exp(pi*I/4)*root(z,4)*2/sqrt(pi) ) )
  297. # Manually tuned rule
  298. addb([Rational(1, 4)], [S.Half, Rational(5, 4)],
  299. Matrix(
  300. [ sqrt(
  301. pi)*exp(
  302. -I*pi/4)*fresnelc(
  303. 2*root(z, 4)*exp(I*pi/4)/sqrt(pi))/(2*root(z, 4)),
  304. cosh(2*sqrt(z)),
  305. sinh(2*sqrt(z))*sqrt(z) ]),
  306. Matrix([[1, 0, 0]]),
  307. Matrix([[Rational(-1, 4), Rational(1, 4), 0 ],
  308. [ 0, 0, 1 ],
  309. [ 0, z, S.Half]]))
  310. # 2F3
  311. # XXX with this five-parameter formula is pretty slow with the current
  312. # Formula.find_instantiations (creates 2!*3!*3**(2+3) ~ 3000
  313. # instantiations ... But it's not too bad.
  314. addb([a, a + S.Half], [2*a, b, 2*a - b + 1],
  315. gamma(b)*gamma(2*a - b + 1) * (sqrt(z)/2)**(1 - 2*a) *
  316. Matrix([besseli(b - 1, sqrt(z))*besseli(2*a - b, sqrt(z)),
  317. sqrt(z)*besseli(b, sqrt(z))*besseli(2*a - b, sqrt(z)),
  318. sqrt(z)*besseli(b - 1, sqrt(z))*besseli(2*a - b + 1, sqrt(z)),
  319. besseli(b, sqrt(z))*besseli(2*a - b + 1, sqrt(z))]),
  320. Matrix([[1, 0, 0, 0]]),
  321. Matrix([[0, S.Half, S.Half, 0],
  322. [z/2, 1 - b, 0, z/2],
  323. [z/2, 0, b - 2*a, z/2],
  324. [0, S.Half, S.Half, -2*a]]))
  325. # (C/f above comment about eulergamma in the basis).
  326. addb([1, 1], [2, 2, Rational(3, 2)],
  327. Matrix([Chi(2*sqrt(z)) - log(2*sqrt(z)),
  328. cosh(2*sqrt(z)), sqrt(z)*sinh(2*sqrt(z)), 1, EulerGamma]),
  329. Matrix([[1/z, 0, 0, 0, -1/z]]),
  330. Matrix([[0, S.Half, 0, Rational(-1, 2), 0],
  331. [0, 0, 1, 0, 0],
  332. [0, z, S.Half, 0, 0],
  333. [0, 0, 0, 0, 0],
  334. [0, 0, 0, 0, 0]]))
  335. # 3F3
  336. # This is rule: http://functions.wolfram.com/07.31.03.0134.01
  337. # Initial reason to add it was a nice solution for
  338. # integrate(erf(a*z)/z**2, z) and same for erfc and erfi.
  339. # Basic rule
  340. # add([1, 1, a], [2, 2, a+1], (a/(z*(a-1)**2)) *
  341. # (1 - (-z)**(1-a) * (gamma(a) - uppergamma(a,-z))
  342. # - (a-1) * (EulerGamma + uppergamma(0,-z) + log(-z))
  343. # - exp(z)))
  344. # Manually tuned rule
  345. addb([1, 1, a], [2, 2, a+1],
  346. Matrix([a*(log(-z) + expint(1, -z) + EulerGamma)/(z*(a**2 - 2*a + 1)),
  347. a*(-z)**(-a)*(gamma(a) - uppergamma(a, -z))/(a - 1)**2,
  348. a*exp(z)/(a**2 - 2*a + 1),
  349. a/(z*(a**2 - 2*a + 1))]),
  350. Matrix([[1-a, 1, -1/z, 1]]),
  351. Matrix([[-1,0,-1/z,1],
  352. [0,-a,1,0],
  353. [0,0,z,0],
  354. [0,0,0,-1]]))
  355. def add_meijerg_formulae(formulae):
  356. from sympy.matrices import Matrix
  357. a, b, c, z = list(map(Dummy, 'abcz'))
  358. rho = Dummy('rho')
  359. def add(an, ap, bm, bq, B, C, M, matcher):
  360. formulae.append(MeijerFormula(an, ap, bm, bq, z, [a, b, c, rho],
  361. B, C, M, matcher))
  362. def detect_uppergamma(func):
  363. x = func.an[0]
  364. y, z = func.bm
  365. swapped = False
  366. if not _mod1((x - y).simplify()):
  367. swapped = True
  368. (y, z) = (z, y)
  369. if _mod1((x - z).simplify()) or x - z > 0:
  370. return None
  371. l = [y, x]
  372. if swapped:
  373. l = [x, y]
  374. return {rho: y, a: x - y}, G_Function([x], [], l, [])
  375. add([a + rho], [], [rho, a + rho], [],
  376. Matrix([gamma(1 - a)*z**rho*exp(z)*uppergamma(a, z),
  377. gamma(1 - a)*z**(a + rho)]),
  378. Matrix([[1, 0]]),
  379. Matrix([[rho + z, -1], [0, a + rho]]),
  380. detect_uppergamma)
  381. def detect_3113(func):
  382. """http://functions.wolfram.com/07.34.03.0984.01"""
  383. x = func.an[0]
  384. u, v, w = func.bm
  385. if _mod1((u - v).simplify()) == 0:
  386. if _mod1((v - w).simplify()) == 0:
  387. return
  388. sig = (S.Half, S.Half, S.Zero)
  389. x1, x2, y = u, v, w
  390. else:
  391. if _mod1((x - u).simplify()) == 0:
  392. sig = (S.Half, S.Zero, S.Half)
  393. x1, y, x2 = u, v, w
  394. else:
  395. sig = (S.Zero, S.Half, S.Half)
  396. y, x1, x2 = u, v, w
  397. if (_mod1((x - x1).simplify()) != 0 or
  398. _mod1((x - x2).simplify()) != 0 or
  399. _mod1((x - y).simplify()) != S.Half or
  400. x - x1 > 0 or x - x2 > 0):
  401. return
  402. return {a: x}, G_Function([x], [], [x - S.Half + t for t in sig], [])
  403. s = sin(2*sqrt(z))
  404. c_ = cos(2*sqrt(z))
  405. S_ = Si(2*sqrt(z)) - pi/2
  406. C = Ci(2*sqrt(z))
  407. add([a], [], [a, a, a - S.Half], [],
  408. Matrix([sqrt(pi)*z**(a - S.Half)*(c_*S_ - s*C),
  409. sqrt(pi)*z**a*(s*S_ + c_*C),
  410. sqrt(pi)*z**a]),
  411. Matrix([[-2, 0, 0]]),
  412. Matrix([[a - S.Half, -1, 0], [z, a, S.Half], [0, 0, a]]),
  413. detect_3113)
  414. def make_simp(z):
  415. """ Create a function that simplifies rational functions in ``z``. """
  416. def simp(expr):
  417. """ Efficiently simplify the rational function ``expr``. """
  418. numer, denom = expr.as_numer_denom()
  419. numer = numer.expand()
  420. # denom = denom.expand() # is this needed?
  421. c, numer, denom = poly(numer, z).cancel(poly(denom, z))
  422. return c * numer.as_expr() / denom.as_expr()
  423. return simp
  424. def debug(*args):
  425. if SYMPY_DEBUG:
  426. for a in args:
  427. print(a, end="")
  428. print()
  429. class Hyper_Function(Expr):
  430. """ A generalized hypergeometric function. """
  431. def __new__(cls, ap, bq):
  432. obj = super().__new__(cls)
  433. obj.ap = Tuple(*list(map(expand, ap)))
  434. obj.bq = Tuple(*list(map(expand, bq)))
  435. return obj
  436. @property
  437. def args(self):
  438. return (self.ap, self.bq)
  439. @property
  440. def sizes(self):
  441. return (len(self.ap), len(self.bq))
  442. @property
  443. def gamma(self):
  444. """
  445. Number of upper parameters that are negative integers
  446. This is a transformation invariant.
  447. """
  448. return sum(bool(x.is_integer and x.is_negative) for x in self.ap)
  449. def _hashable_content(self):
  450. return super()._hashable_content() + (self.ap,
  451. self.bq)
  452. def __call__(self, arg):
  453. return hyper(self.ap, self.bq, arg)
  454. def build_invariants(self):
  455. """
  456. Compute the invariant vector.
  457. Explanation
  458. ===========
  459. The invariant vector is:
  460. (gamma, ((s1, n1), ..., (sk, nk)), ((t1, m1), ..., (tr, mr)))
  461. where gamma is the number of integer a < 0,
  462. s1 < ... < sk
  463. nl is the number of parameters a_i congruent to sl mod 1
  464. t1 < ... < tr
  465. ml is the number of parameters b_i congruent to tl mod 1
  466. If the index pair contains parameters, then this is not truly an
  467. invariant, since the parameters cannot be sorted uniquely mod1.
  468. Examples
  469. ========
  470. >>> from sympy.simplify.hyperexpand import Hyper_Function
  471. >>> from sympy import S
  472. >>> ap = (S.Half, S.One/3, S(-1)/2, -2)
  473. >>> bq = (1, 2)
  474. Here gamma = 1,
  475. k = 3, s1 = 0, s2 = 1/3, s3 = 1/2
  476. n1 = 1, n2 = 1, n2 = 2
  477. r = 1, t1 = 0
  478. m1 = 2:
  479. >>> Hyper_Function(ap, bq).build_invariants()
  480. (1, ((0, 1), (1/3, 1), (1/2, 2)), ((0, 2),))
  481. """
  482. abuckets, bbuckets = sift(self.ap, _mod1), sift(self.bq, _mod1)
  483. def tr(bucket):
  484. bucket = list(bucket.items())
  485. if not any(isinstance(x[0], Mod) for x in bucket):
  486. bucket.sort(key=lambda x: default_sort_key(x[0]))
  487. bucket = tuple([(mod, len(values)) for mod, values in bucket if
  488. values])
  489. return bucket
  490. return (self.gamma, tr(abuckets), tr(bbuckets))
  491. def difficulty(self, func):
  492. """ Estimate how many steps it takes to reach ``func`` from self.
  493. Return -1 if impossible. """
  494. if self.gamma != func.gamma:
  495. return -1
  496. oabuckets, obbuckets, abuckets, bbuckets = [sift(params, _mod1) for
  497. params in (self.ap, self.bq, func.ap, func.bq)]
  498. diff = 0
  499. for bucket, obucket in [(abuckets, oabuckets), (bbuckets, obbuckets)]:
  500. for mod in set(list(bucket.keys()) + list(obucket.keys())):
  501. if (mod not in bucket) or (mod not in obucket) \
  502. or len(bucket[mod]) != len(obucket[mod]):
  503. return -1
  504. l1 = list(bucket[mod])
  505. l2 = list(obucket[mod])
  506. l1.sort()
  507. l2.sort()
  508. for i, j in zip(l1, l2):
  509. diff += abs(i - j)
  510. return diff
  511. def _is_suitable_origin(self):
  512. """
  513. Decide if ``self`` is a suitable origin.
  514. Explanation
  515. ===========
  516. A function is a suitable origin iff:
  517. * none of the ai equals bj + n, with n a non-negative integer
  518. * none of the ai is zero
  519. * none of the bj is a non-positive integer
  520. Note that this gives meaningful results only when none of the indices
  521. are symbolic.
  522. """
  523. for a in self.ap:
  524. for b in self.bq:
  525. if (a - b).is_integer and (a - b).is_negative is False:
  526. return False
  527. for a in self.ap:
  528. if a == 0:
  529. return False
  530. for b in self.bq:
  531. if b.is_integer and b.is_nonpositive:
  532. return False
  533. return True
  534. class G_Function(Expr):
  535. """ A Meijer G-function. """
  536. def __new__(cls, an, ap, bm, bq):
  537. obj = super().__new__(cls)
  538. obj.an = Tuple(*list(map(expand, an)))
  539. obj.ap = Tuple(*list(map(expand, ap)))
  540. obj.bm = Tuple(*list(map(expand, bm)))
  541. obj.bq = Tuple(*list(map(expand, bq)))
  542. return obj
  543. @property
  544. def args(self):
  545. return (self.an, self.ap, self.bm, self.bq)
  546. def _hashable_content(self):
  547. return super()._hashable_content() + self.args
  548. def __call__(self, z):
  549. return meijerg(self.an, self.ap, self.bm, self.bq, z)
  550. def compute_buckets(self):
  551. """
  552. Compute buckets for the fours sets of parameters.
  553. Explanation
  554. ===========
  555. We guarantee that any two equal Mod objects returned are actually the
  556. same, and that the buckets are sorted by real part (an and bq
  557. descendending, bm and ap ascending).
  558. Examples
  559. ========
  560. >>> from sympy.simplify.hyperexpand import G_Function
  561. >>> from sympy.abc import y
  562. >>> from sympy import S
  563. >>> a, b = [1, 3, 2, S(3)/2], [1 + y, y, 2, y + 3]
  564. >>> G_Function(a, b, [2], [y]).compute_buckets()
  565. ({0: [3, 2, 1], 1/2: [3/2]},
  566. {0: [2], y: [y, y + 1, y + 3]}, {0: [2]}, {y: [y]})
  567. """
  568. dicts = pan, pap, pbm, pbq = [defaultdict(list) for i in range(4)]
  569. for dic, lis in zip(dicts, (self.an, self.ap, self.bm, self.bq)):
  570. for x in lis:
  571. dic[_mod1(x)].append(x)
  572. for dic, flip in zip(dicts, (True, False, False, True)):
  573. for m, items in dic.items():
  574. x0 = items[0]
  575. items.sort(key=lambda x: x - x0, reverse=flip)
  576. dic[m] = items
  577. return tuple([dict(w) for w in dicts])
  578. @property
  579. def signature(self):
  580. return (len(self.an), len(self.ap), len(self.bm), len(self.bq))
  581. # Dummy variable.
  582. _x = Dummy('x')
  583. class Formula:
  584. """
  585. This class represents hypergeometric formulae.
  586. Explanation
  587. ===========
  588. Its data members are:
  589. - z, the argument
  590. - closed_form, the closed form expression
  591. - symbols, the free symbols (parameters) in the formula
  592. - func, the function
  593. - B, C, M (see _compute_basis)
  594. Examples
  595. ========
  596. >>> from sympy.abc import a, b, z
  597. >>> from sympy.simplify.hyperexpand import Formula, Hyper_Function
  598. >>> func = Hyper_Function((a/2, a/3 + b, (1+a)/2), (a, b, (a+b)/7))
  599. >>> f = Formula(func, z, None, [a, b])
  600. """
  601. def _compute_basis(self, closed_form):
  602. """
  603. Compute a set of functions B=(f1, ..., fn), a nxn matrix M
  604. and a 1xn matrix C such that:
  605. closed_form = C B
  606. z d/dz B = M B.
  607. """
  608. from sympy.matrices import Matrix, eye, zeros
  609. afactors = [_x + a for a in self.func.ap]
  610. bfactors = [_x + b - 1 for b in self.func.bq]
  611. expr = _x*Mul(*bfactors) - self.z*Mul(*afactors)
  612. poly = Poly(expr, _x)
  613. n = poly.degree() - 1
  614. b = [closed_form]
  615. for _ in range(n):
  616. b.append(self.z*b[-1].diff(self.z))
  617. self.B = Matrix(b)
  618. self.C = Matrix([[1] + [0]*n])
  619. m = eye(n)
  620. m = m.col_insert(0, zeros(n, 1))
  621. l = poly.all_coeffs()[1:]
  622. l.reverse()
  623. self.M = m.row_insert(n, -Matrix([l])/poly.all_coeffs()[0])
  624. def __init__(self, func, z, res, symbols, B=None, C=None, M=None):
  625. z = sympify(z)
  626. res = sympify(res)
  627. symbols = [x for x in sympify(symbols) if func.has(x)]
  628. self.z = z
  629. self.symbols = symbols
  630. self.B = B
  631. self.C = C
  632. self.M = M
  633. self.func = func
  634. # TODO with symbolic parameters, it could be advantageous
  635. # (for prettier answers) to compute a basis only *after*
  636. # instantiation
  637. if res is not None:
  638. self._compute_basis(res)
  639. @property
  640. def closed_form(self):
  641. return reduce(lambda s,m: s+m[0]*m[1], zip(self.C, self.B), S.Zero)
  642. def find_instantiations(self, func):
  643. """
  644. Find substitutions of the free symbols that match ``func``.
  645. Return the substitution dictionaries as a list. Note that the returned
  646. instantiations need not actually match, or be valid!
  647. """
  648. from sympy.solvers import solve
  649. ap = func.ap
  650. bq = func.bq
  651. if len(ap) != len(self.func.ap) or len(bq) != len(self.func.bq):
  652. raise TypeError('Cannot instantiate other number of parameters')
  653. symbol_values = []
  654. for a in self.symbols:
  655. if a in self.func.ap.args:
  656. symbol_values.append(ap)
  657. elif a in self.func.bq.args:
  658. symbol_values.append(bq)
  659. else:
  660. raise ValueError("At least one of the parameters of the "
  661. "formula must be equal to %s" % (a,))
  662. base_repl = [dict(list(zip(self.symbols, values)))
  663. for values in product(*symbol_values)]
  664. abuckets, bbuckets = [sift(params, _mod1) for params in [ap, bq]]
  665. a_inv, b_inv = [{a: len(vals) for a, vals in bucket.items()}
  666. for bucket in [abuckets, bbuckets]]
  667. critical_values = [[0] for _ in self.symbols]
  668. result = []
  669. _n = Dummy()
  670. for repl in base_repl:
  671. symb_a, symb_b = [sift(params, lambda x: _mod1(x.xreplace(repl)))
  672. for params in [self.func.ap, self.func.bq]]
  673. for bucket, obucket in [(abuckets, symb_a), (bbuckets, symb_b)]:
  674. for mod in set(list(bucket.keys()) + list(obucket.keys())):
  675. if (mod not in bucket) or (mod not in obucket) \
  676. or len(bucket[mod]) != len(obucket[mod]):
  677. break
  678. for a, vals in zip(self.symbols, critical_values):
  679. if repl[a].free_symbols:
  680. continue
  681. exprs = [expr for expr in obucket[mod] if expr.has(a)]
  682. repl0 = repl.copy()
  683. repl0[a] += _n
  684. for expr in exprs:
  685. for target in bucket[mod]:
  686. n0, = solve(expr.xreplace(repl0) - target, _n)
  687. if n0.free_symbols:
  688. raise ValueError("Value should not be true")
  689. vals.append(n0)
  690. else:
  691. values = []
  692. for a, vals in zip(self.symbols, critical_values):
  693. a0 = repl[a]
  694. min_ = floor(min(vals))
  695. max_ = ceiling(max(vals))
  696. values.append([a0 + n for n in range(min_, max_ + 1)])
  697. result.extend(dict(list(zip(self.symbols, l))) for l in product(*values))
  698. return result
  699. class FormulaCollection:
  700. """ A collection of formulae to use as origins. """
  701. def __init__(self):
  702. """ Doing this globally at module init time is a pain ... """
  703. self.symbolic_formulae = {}
  704. self.concrete_formulae = {}
  705. self.formulae = []
  706. add_formulae(self.formulae)
  707. # Now process the formulae into a helpful form.
  708. # These dicts are indexed by (p, q).
  709. for f in self.formulae:
  710. sizes = f.func.sizes
  711. if len(f.symbols) > 0:
  712. self.symbolic_formulae.setdefault(sizes, []).append(f)
  713. else:
  714. inv = f.func.build_invariants()
  715. self.concrete_formulae.setdefault(sizes, {})[inv] = f
  716. def lookup_origin(self, func):
  717. """
  718. Given the suitable target ``func``, try to find an origin in our
  719. knowledge base.
  720. Examples
  721. ========
  722. >>> from sympy.simplify.hyperexpand import (FormulaCollection,
  723. ... Hyper_Function)
  724. >>> f = FormulaCollection()
  725. >>> f.lookup_origin(Hyper_Function((), ())).closed_form
  726. exp(_z)
  727. >>> f.lookup_origin(Hyper_Function([1], ())).closed_form
  728. HyperRep_power1(-1, _z)
  729. >>> from sympy import S
  730. >>> i = Hyper_Function([S('1/4'), S('3/4 + 4')], [S.Half])
  731. >>> f.lookup_origin(i).closed_form
  732. HyperRep_sqrts1(-1/4, _z)
  733. """
  734. inv = func.build_invariants()
  735. sizes = func.sizes
  736. if sizes in self.concrete_formulae and \
  737. inv in self.concrete_formulae[sizes]:
  738. return self.concrete_formulae[sizes][inv]
  739. # We don't have a concrete formula. Try to instantiate.
  740. if sizes not in self.symbolic_formulae:
  741. return None # Too bad...
  742. possible = []
  743. for f in self.symbolic_formulae[sizes]:
  744. repls = f.find_instantiations(func)
  745. for repl in repls:
  746. func2 = f.func.xreplace(repl)
  747. if not func2._is_suitable_origin():
  748. continue
  749. diff = func2.difficulty(func)
  750. if diff == -1:
  751. continue
  752. possible.append((diff, repl, f, func2))
  753. # find the nearest origin
  754. possible.sort(key=lambda x: x[0])
  755. for _, repl, f, func2 in possible:
  756. f2 = Formula(func2, f.z, None, [], f.B.subs(repl),
  757. f.C.subs(repl), f.M.subs(repl))
  758. if not any(e.has(S.NaN, oo, -oo, zoo) for e in [f2.B, f2.M, f2.C]):
  759. return f2
  760. return None
  761. class MeijerFormula:
  762. """
  763. This class represents a Meijer G-function formula.
  764. Its data members are:
  765. - z, the argument
  766. - symbols, the free symbols (parameters) in the formula
  767. - func, the function
  768. - B, C, M (c/f ordinary Formula)
  769. """
  770. def __init__(self, an, ap, bm, bq, z, symbols, B, C, M, matcher):
  771. an, ap, bm, bq = [Tuple(*list(map(expand, w))) for w in [an, ap, bm, bq]]
  772. self.func = G_Function(an, ap, bm, bq)
  773. self.z = z
  774. self.symbols = symbols
  775. self._matcher = matcher
  776. self.B = B
  777. self.C = C
  778. self.M = M
  779. @property
  780. def closed_form(self):
  781. return reduce(lambda s,m: s+m[0]*m[1], zip(self.C, self.B), S.Zero)
  782. def try_instantiate(self, func):
  783. """
  784. Try to instantiate the current formula to (almost) match func.
  785. This uses the _matcher passed on init.
  786. """
  787. if func.signature != self.func.signature:
  788. return None
  789. res = self._matcher(func)
  790. if res is not None:
  791. subs, newfunc = res
  792. return MeijerFormula(newfunc.an, newfunc.ap, newfunc.bm, newfunc.bq,
  793. self.z, [],
  794. self.B.subs(subs), self.C.subs(subs),
  795. self.M.subs(subs), None)
  796. class MeijerFormulaCollection:
  797. """
  798. This class holds a collection of meijer g formulae.
  799. """
  800. def __init__(self):
  801. formulae = []
  802. add_meijerg_formulae(formulae)
  803. self.formulae = defaultdict(list)
  804. for formula in formulae:
  805. self.formulae[formula.func.signature].append(formula)
  806. self.formulae = dict(self.formulae)
  807. def lookup_origin(self, func):
  808. """ Try to find a formula that matches func. """
  809. if func.signature not in self.formulae:
  810. return None
  811. for formula in self.formulae[func.signature]:
  812. res = formula.try_instantiate(func)
  813. if res is not None:
  814. return res
  815. class Operator:
  816. """
  817. Base class for operators to be applied to our functions.
  818. Explanation
  819. ===========
  820. These operators are differential operators. They are by convention
  821. expressed in the variable D = z*d/dz (although this base class does
  822. not actually care).
  823. Note that when the operator is applied to an object, we typically do
  824. *not* blindly differentiate but instead use a different representation
  825. of the z*d/dz operator (see make_derivative_operator).
  826. To subclass from this, define a __init__ method that initializes a
  827. self._poly variable. This variable stores a polynomial. By convention
  828. the generator is z*d/dz, and acts to the right of all coefficients.
  829. Thus this poly
  830. x**2 + 2*z*x + 1
  831. represents the differential operator
  832. (z*d/dz)**2 + 2*z**2*d/dz.
  833. This class is used only in the implementation of the hypergeometric
  834. function expansion algorithm.
  835. """
  836. def apply(self, obj, op):
  837. """
  838. Apply ``self`` to the object ``obj``, where the generator is ``op``.
  839. Examples
  840. ========
  841. >>> from sympy.simplify.hyperexpand import Operator
  842. >>> from sympy.polys.polytools import Poly
  843. >>> from sympy.abc import x, y, z
  844. >>> op = Operator()
  845. >>> op._poly = Poly(x**2 + z*x + y, x)
  846. >>> op.apply(z**7, lambda f: f.diff(z))
  847. y*z**7 + 7*z**7 + 42*z**5
  848. """
  849. coeffs = self._poly.all_coeffs()
  850. coeffs.reverse()
  851. diffs = [obj]
  852. for c in coeffs[1:]:
  853. diffs.append(op(diffs[-1]))
  854. r = coeffs[0]*diffs[0]
  855. for c, d in zip(coeffs[1:], diffs[1:]):
  856. r += c*d
  857. return r
  858. class MultOperator(Operator):
  859. """ Simply multiply by a "constant" """
  860. def __init__(self, p):
  861. self._poly = Poly(p, _x)
  862. class ShiftA(Operator):
  863. """ Increment an upper index. """
  864. def __init__(self, ai):
  865. ai = sympify(ai)
  866. if ai == 0:
  867. raise ValueError('Cannot increment zero upper index.')
  868. self._poly = Poly(_x/ai + 1, _x)
  869. def __str__(self):
  870. return '<Increment upper %s.>' % (1/self._poly.all_coeffs()[0])
  871. class ShiftB(Operator):
  872. """ Decrement a lower index. """
  873. def __init__(self, bi):
  874. bi = sympify(bi)
  875. if bi == 1:
  876. raise ValueError('Cannot decrement unit lower index.')
  877. self._poly = Poly(_x/(bi - 1) + 1, _x)
  878. def __str__(self):
  879. return '<Decrement lower %s.>' % (1/self._poly.all_coeffs()[0] + 1)
  880. class UnShiftA(Operator):
  881. """ Decrement an upper index. """
  882. def __init__(self, ap, bq, i, z):
  883. """ Note: i counts from zero! """
  884. ap, bq, i = list(map(sympify, [ap, bq, i]))
  885. self._ap = ap
  886. self._bq = bq
  887. self._i = i
  888. ap = list(ap)
  889. bq = list(bq)
  890. ai = ap.pop(i) - 1
  891. if ai == 0:
  892. raise ValueError('Cannot decrement unit upper index.')
  893. m = Poly(z*ai, _x)
  894. for a in ap:
  895. m *= Poly(_x + a, _x)
  896. A = Dummy('A')
  897. n = D = Poly(ai*A - ai, A)
  898. for b in bq:
  899. n *= D + (b - 1).as_poly(A)
  900. b0 = -n.nth(0)
  901. if b0 == 0:
  902. raise ValueError('Cannot decrement upper index: '
  903. 'cancels with lower')
  904. n = Poly(Poly(n.all_coeffs()[:-1], A).as_expr().subs(A, _x/ai + 1), _x)
  905. self._poly = Poly((n - m)/b0, _x)
  906. def __str__(self):
  907. return '<Decrement upper index #%s of %s, %s.>' % (self._i,
  908. self._ap, self._bq)
  909. class UnShiftB(Operator):
  910. """ Increment a lower index. """
  911. def __init__(self, ap, bq, i, z):
  912. """ Note: i counts from zero! """
  913. ap, bq, i = list(map(sympify, [ap, bq, i]))
  914. self._ap = ap
  915. self._bq = bq
  916. self._i = i
  917. ap = list(ap)
  918. bq = list(bq)
  919. bi = bq.pop(i) + 1
  920. if bi == 0:
  921. raise ValueError('Cannot increment -1 lower index.')
  922. m = Poly(_x*(bi - 1), _x)
  923. for b in bq:
  924. m *= Poly(_x + b - 1, _x)
  925. B = Dummy('B')
  926. D = Poly((bi - 1)*B - bi + 1, B)
  927. n = Poly(z, B)
  928. for a in ap:
  929. n *= (D + a.as_poly(B))
  930. b0 = n.nth(0)
  931. if b0 == 0:
  932. raise ValueError('Cannot increment index: cancels with upper')
  933. n = Poly(Poly(n.all_coeffs()[:-1], B).as_expr().subs(
  934. B, _x/(bi - 1) + 1), _x)
  935. self._poly = Poly((m - n)/b0, _x)
  936. def __str__(self):
  937. return '<Increment lower index #%s of %s, %s.>' % (self._i,
  938. self._ap, self._bq)
  939. class MeijerShiftA(Operator):
  940. """ Increment an upper b index. """
  941. def __init__(self, bi):
  942. bi = sympify(bi)
  943. self._poly = Poly(bi - _x, _x)
  944. def __str__(self):
  945. return '<Increment upper b=%s.>' % (self._poly.all_coeffs()[1])
  946. class MeijerShiftB(Operator):
  947. """ Decrement an upper a index. """
  948. def __init__(self, bi):
  949. bi = sympify(bi)
  950. self._poly = Poly(1 - bi + _x, _x)
  951. def __str__(self):
  952. return '<Decrement upper a=%s.>' % (1 - self._poly.all_coeffs()[1])
  953. class MeijerShiftC(Operator):
  954. """ Increment a lower b index. """
  955. def __init__(self, bi):
  956. bi = sympify(bi)
  957. self._poly = Poly(-bi + _x, _x)
  958. def __str__(self):
  959. return '<Increment lower b=%s.>' % (-self._poly.all_coeffs()[1])
  960. class MeijerShiftD(Operator):
  961. """ Decrement a lower a index. """
  962. def __init__(self, bi):
  963. bi = sympify(bi)
  964. self._poly = Poly(bi - 1 - _x, _x)
  965. def __str__(self):
  966. return '<Decrement lower a=%s.>' % (self._poly.all_coeffs()[1] + 1)
  967. class MeijerUnShiftA(Operator):
  968. """ Decrement an upper b index. """
  969. def __init__(self, an, ap, bm, bq, i, z):
  970. """ Note: i counts from zero! """
  971. an, ap, bm, bq, i = list(map(sympify, [an, ap, bm, bq, i]))
  972. self._an = an
  973. self._ap = ap
  974. self._bm = bm
  975. self._bq = bq
  976. self._i = i
  977. an = list(an)
  978. ap = list(ap)
  979. bm = list(bm)
  980. bq = list(bq)
  981. bi = bm.pop(i) - 1
  982. m = Poly(1, _x)
  983. for b in bm:
  984. m *= Poly(b - _x, _x)
  985. for b in bq:
  986. m *= Poly(_x - b, _x)
  987. A = Dummy('A')
  988. D = Poly(bi - A, A)
  989. n = Poly(z, A)
  990. for a in an:
  991. n *= (D + 1 - a)
  992. for a in ap:
  993. n *= (-D + a - 1)
  994. b0 = n.nth(0)
  995. if b0 == 0:
  996. raise ValueError('Cannot decrement upper b index (cancels)')
  997. n = Poly(Poly(n.all_coeffs()[:-1], A).as_expr().subs(A, bi - _x), _x)
  998. self._poly = Poly((m - n)/b0, _x)
  999. def __str__(self):
  1000. return '<Decrement upper b index #%s of %s, %s, %s, %s.>' % (self._i,
  1001. self._an, self._ap, self._bm, self._bq)
  1002. class MeijerUnShiftB(Operator):
  1003. """ Increment an upper a index. """
  1004. def __init__(self, an, ap, bm, bq, i, z):
  1005. """ Note: i counts from zero! """
  1006. an, ap, bm, bq, i = list(map(sympify, [an, ap, bm, bq, i]))
  1007. self._an = an
  1008. self._ap = ap
  1009. self._bm = bm
  1010. self._bq = bq
  1011. self._i = i
  1012. an = list(an)
  1013. ap = list(ap)
  1014. bm = list(bm)
  1015. bq = list(bq)
  1016. ai = an.pop(i) + 1
  1017. m = Poly(z, _x)
  1018. for a in an:
  1019. m *= Poly(1 - a + _x, _x)
  1020. for a in ap:
  1021. m *= Poly(a - 1 - _x, _x)
  1022. B = Dummy('B')
  1023. D = Poly(B + ai - 1, B)
  1024. n = Poly(1, B)
  1025. for b in bm:
  1026. n *= (-D + b)
  1027. for b in bq:
  1028. n *= (D - b)
  1029. b0 = n.nth(0)
  1030. if b0 == 0:
  1031. raise ValueError('Cannot increment upper a index (cancels)')
  1032. n = Poly(Poly(n.all_coeffs()[:-1], B).as_expr().subs(
  1033. B, 1 - ai + _x), _x)
  1034. self._poly = Poly((m - n)/b0, _x)
  1035. def __str__(self):
  1036. return '<Increment upper a index #%s of %s, %s, %s, %s.>' % (self._i,
  1037. self._an, self._ap, self._bm, self._bq)
  1038. class MeijerUnShiftC(Operator):
  1039. """ Decrement a lower b index. """
  1040. # XXX this is "essentially" the same as MeijerUnShiftA. This "essentially"
  1041. # can be made rigorous using the functional equation G(1/z) = G'(z),
  1042. # where G' denotes a G function of slightly altered parameters.
  1043. # However, sorting out the details seems harder than just coding it
  1044. # again.
  1045. def __init__(self, an, ap, bm, bq, i, z):
  1046. """ Note: i counts from zero! """
  1047. an, ap, bm, bq, i = list(map(sympify, [an, ap, bm, bq, i]))
  1048. self._an = an
  1049. self._ap = ap
  1050. self._bm = bm
  1051. self._bq = bq
  1052. self._i = i
  1053. an = list(an)
  1054. ap = list(ap)
  1055. bm = list(bm)
  1056. bq = list(bq)
  1057. bi = bq.pop(i) - 1
  1058. m = Poly(1, _x)
  1059. for b in bm:
  1060. m *= Poly(b - _x, _x)
  1061. for b in bq:
  1062. m *= Poly(_x - b, _x)
  1063. C = Dummy('C')
  1064. D = Poly(bi + C, C)
  1065. n = Poly(z, C)
  1066. for a in an:
  1067. n *= (D + 1 - a)
  1068. for a in ap:
  1069. n *= (-D + a - 1)
  1070. b0 = n.nth(0)
  1071. if b0 == 0:
  1072. raise ValueError('Cannot decrement lower b index (cancels)')
  1073. n = Poly(Poly(n.all_coeffs()[:-1], C).as_expr().subs(C, _x - bi), _x)
  1074. self._poly = Poly((m - n)/b0, _x)
  1075. def __str__(self):
  1076. return '<Decrement lower b index #%s of %s, %s, %s, %s.>' % (self._i,
  1077. self._an, self._ap, self._bm, self._bq)
  1078. class MeijerUnShiftD(Operator):
  1079. """ Increment a lower a index. """
  1080. # XXX This is essentially the same as MeijerUnShiftA.
  1081. # See comment at MeijerUnShiftC.
  1082. def __init__(self, an, ap, bm, bq, i, z):
  1083. """ Note: i counts from zero! """
  1084. an, ap, bm, bq, i = list(map(sympify, [an, ap, bm, bq, i]))
  1085. self._an = an
  1086. self._ap = ap
  1087. self._bm = bm
  1088. self._bq = bq
  1089. self._i = i
  1090. an = list(an)
  1091. ap = list(ap)
  1092. bm = list(bm)
  1093. bq = list(bq)
  1094. ai = ap.pop(i) + 1
  1095. m = Poly(z, _x)
  1096. for a in an:
  1097. m *= Poly(1 - a + _x, _x)
  1098. for a in ap:
  1099. m *= Poly(a - 1 - _x, _x)
  1100. B = Dummy('B') # - this is the shift operator `D_I`
  1101. D = Poly(ai - 1 - B, B)
  1102. n = Poly(1, B)
  1103. for b in bm:
  1104. n *= (-D + b)
  1105. for b in bq:
  1106. n *= (D - b)
  1107. b0 = n.nth(0)
  1108. if b0 == 0:
  1109. raise ValueError('Cannot increment lower a index (cancels)')
  1110. n = Poly(Poly(n.all_coeffs()[:-1], B).as_expr().subs(
  1111. B, ai - 1 - _x), _x)
  1112. self._poly = Poly((m - n)/b0, _x)
  1113. def __str__(self):
  1114. return '<Increment lower a index #%s of %s, %s, %s, %s.>' % (self._i,
  1115. self._an, self._ap, self._bm, self._bq)
  1116. class ReduceOrder(Operator):
  1117. """ Reduce Order by cancelling an upper and a lower index. """
  1118. def __new__(cls, ai, bj):
  1119. """ For convenience if reduction is not possible, return None. """
  1120. ai = sympify(ai)
  1121. bj = sympify(bj)
  1122. n = ai - bj
  1123. if not n.is_Integer or n < 0:
  1124. return None
  1125. if bj.is_integer and bj.is_nonpositive:
  1126. return None
  1127. expr = Operator.__new__(cls)
  1128. p = S.One
  1129. for k in range(n):
  1130. p *= (_x + bj + k)/(bj + k)
  1131. expr._poly = Poly(p, _x)
  1132. expr._a = ai
  1133. expr._b = bj
  1134. return expr
  1135. @classmethod
  1136. def _meijer(cls, b, a, sign):
  1137. """ Cancel b + sign*s and a + sign*s
  1138. This is for meijer G functions. """
  1139. b = sympify(b)
  1140. a = sympify(a)
  1141. n = b - a
  1142. if n.is_negative or not n.is_Integer:
  1143. return None
  1144. expr = Operator.__new__(cls)
  1145. p = S.One
  1146. for k in range(n):
  1147. p *= (sign*_x + a + k)
  1148. expr._poly = Poly(p, _x)
  1149. if sign == -1:
  1150. expr._a = b
  1151. expr._b = a
  1152. else:
  1153. expr._b = Add(1, a - 1, evaluate=False)
  1154. expr._a = Add(1, b - 1, evaluate=False)
  1155. return expr
  1156. @classmethod
  1157. def meijer_minus(cls, b, a):
  1158. return cls._meijer(b, a, -1)
  1159. @classmethod
  1160. def meijer_plus(cls, a, b):
  1161. return cls._meijer(1 - a, 1 - b, 1)
  1162. def __str__(self):
  1163. return '<Reduce order by cancelling upper %s with lower %s.>' % \
  1164. (self._a, self._b)
  1165. def _reduce_order(ap, bq, gen, key):
  1166. """ Order reduction algorithm used in Hypergeometric and Meijer G """
  1167. ap = list(ap)
  1168. bq = list(bq)
  1169. ap.sort(key=key)
  1170. bq.sort(key=key)
  1171. nap = []
  1172. # we will edit bq in place
  1173. operators = []
  1174. for a in ap:
  1175. op = None
  1176. for i in range(len(bq)):
  1177. op = gen(a, bq[i])
  1178. if op is not None:
  1179. bq.pop(i)
  1180. break
  1181. if op is None:
  1182. nap.append(a)
  1183. else:
  1184. operators.append(op)
  1185. return nap, bq, operators
  1186. def reduce_order(func):
  1187. """
  1188. Given the hypergeometric function ``func``, find a sequence of operators to
  1189. reduces order as much as possible.
  1190. Explanation
  1191. ===========
  1192. Return (newfunc, [operators]), where applying the operators to the
  1193. hypergeometric function newfunc yields func.
  1194. Examples
  1195. ========
  1196. >>> from sympy.simplify.hyperexpand import reduce_order, Hyper_Function
  1197. >>> reduce_order(Hyper_Function((1, 2), (3, 4)))
  1198. (Hyper_Function((1, 2), (3, 4)), [])
  1199. >>> reduce_order(Hyper_Function((1,), (1,)))
  1200. (Hyper_Function((), ()), [<Reduce order by cancelling upper 1 with lower 1.>])
  1201. >>> reduce_order(Hyper_Function((2, 4), (3, 3)))
  1202. (Hyper_Function((2,), (3,)), [<Reduce order by cancelling
  1203. upper 4 with lower 3.>])
  1204. """
  1205. nap, nbq, operators = _reduce_order(func.ap, func.bq, ReduceOrder, default_sort_key)
  1206. return Hyper_Function(Tuple(*nap), Tuple(*nbq)), operators
  1207. def reduce_order_meijer(func):
  1208. """
  1209. Given the Meijer G function parameters, ``func``, find a sequence of
  1210. operators that reduces order as much as possible.
  1211. Return newfunc, [operators].
  1212. Examples
  1213. ========
  1214. >>> from sympy.simplify.hyperexpand import (reduce_order_meijer,
  1215. ... G_Function)
  1216. >>> reduce_order_meijer(G_Function([3, 4], [5, 6], [3, 4], [1, 2]))[0]
  1217. G_Function((4, 3), (5, 6), (3, 4), (2, 1))
  1218. >>> reduce_order_meijer(G_Function([3, 4], [5, 6], [3, 4], [1, 8]))[0]
  1219. G_Function((3,), (5, 6), (3, 4), (1,))
  1220. >>> reduce_order_meijer(G_Function([3, 4], [5, 6], [7, 5], [1, 5]))[0]
  1221. G_Function((3,), (), (), (1,))
  1222. >>> reduce_order_meijer(G_Function([3, 4], [5, 6], [7, 5], [5, 3]))[0]
  1223. G_Function((), (), (), ())
  1224. """
  1225. nan, nbq, ops1 = _reduce_order(func.an, func.bq, ReduceOrder.meijer_plus,
  1226. lambda x: default_sort_key(-x))
  1227. nbm, nap, ops2 = _reduce_order(func.bm, func.ap, ReduceOrder.meijer_minus,
  1228. default_sort_key)
  1229. return G_Function(nan, nap, nbm, nbq), ops1 + ops2
  1230. def make_derivative_operator(M, z):
  1231. """ Create a derivative operator, to be passed to Operator.apply. """
  1232. def doit(C):
  1233. r = z*C.diff(z) + C*M
  1234. r = r.applyfunc(make_simp(z))
  1235. return r
  1236. return doit
  1237. def apply_operators(obj, ops, op):
  1238. """
  1239. Apply the list of operators ``ops`` to object ``obj``, substituting
  1240. ``op`` for the generator.
  1241. """
  1242. res = obj
  1243. for o in reversed(ops):
  1244. res = o.apply(res, op)
  1245. return res
  1246. def devise_plan(target, origin, z):
  1247. """
  1248. Devise a plan (consisting of shift and un-shift operators) to be applied
  1249. to the hypergeometric function ``target`` to yield ``origin``.
  1250. Returns a list of operators.
  1251. Examples
  1252. ========
  1253. >>> from sympy.simplify.hyperexpand import devise_plan, Hyper_Function
  1254. >>> from sympy.abc import z
  1255. Nothing to do:
  1256. >>> devise_plan(Hyper_Function((1, 2), ()), Hyper_Function((1, 2), ()), z)
  1257. []
  1258. >>> devise_plan(Hyper_Function((), (1, 2)), Hyper_Function((), (1, 2)), z)
  1259. []
  1260. Very simple plans:
  1261. >>> devise_plan(Hyper_Function((2,), ()), Hyper_Function((1,), ()), z)
  1262. [<Increment upper 1.>]
  1263. >>> devise_plan(Hyper_Function((), (2,)), Hyper_Function((), (1,)), z)
  1264. [<Increment lower index #0 of [], [1].>]
  1265. Several buckets:
  1266. >>> from sympy import S
  1267. >>> devise_plan(Hyper_Function((1, S.Half), ()),
  1268. ... Hyper_Function((2, S('3/2')), ()), z) #doctest: +NORMALIZE_WHITESPACE
  1269. [<Decrement upper index #0 of [3/2, 1], [].>,
  1270. <Decrement upper index #0 of [2, 3/2], [].>]
  1271. A slightly more complicated plan:
  1272. >>> devise_plan(Hyper_Function((1, 3), ()), Hyper_Function((2, 2), ()), z)
  1273. [<Increment upper 2.>, <Decrement upper index #0 of [2, 2], [].>]
  1274. Another more complicated plan: (note that the ap have to be shifted first!)
  1275. >>> devise_plan(Hyper_Function((1, -1), (2,)), Hyper_Function((3, -2), (4,)), z)
  1276. [<Decrement lower 3.>, <Decrement lower 4.>,
  1277. <Decrement upper index #1 of [-1, 2], [4].>,
  1278. <Decrement upper index #1 of [-1, 3], [4].>, <Increment upper -2.>]
  1279. """
  1280. abuckets, bbuckets, nabuckets, nbbuckets = [sift(params, _mod1) for
  1281. params in (target.ap, target.bq, origin.ap, origin.bq)]
  1282. if len(list(abuckets.keys())) != len(list(nabuckets.keys())) or \
  1283. len(list(bbuckets.keys())) != len(list(nbbuckets.keys())):
  1284. raise ValueError('%s not reachable from %s' % (target, origin))
  1285. ops = []
  1286. def do_shifts(fro, to, inc, dec):
  1287. ops = []
  1288. for i in range(len(fro)):
  1289. if to[i] - fro[i] > 0:
  1290. sh = inc
  1291. ch = 1
  1292. else:
  1293. sh = dec
  1294. ch = -1
  1295. while to[i] != fro[i]:
  1296. ops += [sh(fro, i)]
  1297. fro[i] += ch
  1298. return ops
  1299. def do_shifts_a(nal, nbk, al, aother, bother):
  1300. """ Shift us from (nal, nbk) to (al, nbk). """
  1301. return do_shifts(nal, al, lambda p, i: ShiftA(p[i]),
  1302. lambda p, i: UnShiftA(p + aother, nbk + bother, i, z))
  1303. def do_shifts_b(nal, nbk, bk, aother, bother):
  1304. """ Shift us from (nal, nbk) to (nal, bk). """
  1305. return do_shifts(nbk, bk,
  1306. lambda p, i: UnShiftB(nal + aother, p + bother, i, z),
  1307. lambda p, i: ShiftB(p[i]))
  1308. for r in sorted(list(abuckets.keys()) + list(bbuckets.keys()), key=default_sort_key):
  1309. al = ()
  1310. nal = ()
  1311. bk = ()
  1312. nbk = ()
  1313. if r in abuckets:
  1314. al = abuckets[r]
  1315. nal = nabuckets[r]
  1316. if r in bbuckets:
  1317. bk = bbuckets[r]
  1318. nbk = nbbuckets[r]
  1319. if len(al) != len(nal) or len(bk) != len(nbk):
  1320. raise ValueError('%s not reachable from %s' % (target, origin))
  1321. al, nal, bk, nbk = [sorted(list(w), key=default_sort_key)
  1322. for w in [al, nal, bk, nbk]]
  1323. def others(dic, key):
  1324. l = []
  1325. for k, value in dic.items():
  1326. if k != key:
  1327. l += list(dic[k])
  1328. return l
  1329. aother = others(nabuckets, r)
  1330. bother = others(nbbuckets, r)
  1331. if len(al) == 0:
  1332. # there can be no complications, just shift the bs as we please
  1333. ops += do_shifts_b([], nbk, bk, aother, bother)
  1334. elif len(bk) == 0:
  1335. # there can be no complications, just shift the as as we please
  1336. ops += do_shifts_a(nal, [], al, aother, bother)
  1337. else:
  1338. namax = nal[-1]
  1339. amax = al[-1]
  1340. if nbk[0] - namax <= 0 or bk[0] - amax <= 0:
  1341. raise ValueError('Non-suitable parameters.')
  1342. if namax - amax > 0:
  1343. # we are going to shift down - first do the as, then the bs
  1344. ops += do_shifts_a(nal, nbk, al, aother, bother)
  1345. ops += do_shifts_b(al, nbk, bk, aother, bother)
  1346. else:
  1347. # we are going to shift up - first do the bs, then the as
  1348. ops += do_shifts_b(nal, nbk, bk, aother, bother)
  1349. ops += do_shifts_a(nal, bk, al, aother, bother)
  1350. nabuckets[r] = al
  1351. nbbuckets[r] = bk
  1352. ops.reverse()
  1353. return ops
  1354. def try_shifted_sum(func, z):
  1355. """ Try to recognise a hypergeometric sum that starts from k > 0. """
  1356. abuckets, bbuckets = sift(func.ap, _mod1), sift(func.bq, _mod1)
  1357. if len(abuckets[S.Zero]) != 1:
  1358. return None
  1359. r = abuckets[S.Zero][0]
  1360. if r <= 0:
  1361. return None
  1362. if S.Zero not in bbuckets:
  1363. return None
  1364. l = list(bbuckets[S.Zero])
  1365. l.sort()
  1366. k = l[0]
  1367. if k <= 0:
  1368. return None
  1369. nap = list(func.ap)
  1370. nap.remove(r)
  1371. nbq = list(func.bq)
  1372. nbq.remove(k)
  1373. k -= 1
  1374. nap = [x - k for x in nap]
  1375. nbq = [x - k for x in nbq]
  1376. ops = []
  1377. for n in range(r - 1):
  1378. ops.append(ShiftA(n + 1))
  1379. ops.reverse()
  1380. fac = factorial(k)/z**k
  1381. for a in nap:
  1382. fac /= rf(a, k)
  1383. for b in nbq:
  1384. fac *= rf(b, k)
  1385. ops += [MultOperator(fac)]
  1386. p = 0
  1387. for n in range(k):
  1388. m = z**n/factorial(n)
  1389. for a in nap:
  1390. m *= rf(a, n)
  1391. for b in nbq:
  1392. m /= rf(b, n)
  1393. p += m
  1394. return Hyper_Function(nap, nbq), ops, -p
  1395. def try_polynomial(func, z):
  1396. """ Recognise polynomial cases. Returns None if not such a case.
  1397. Requires order to be fully reduced. """
  1398. abuckets, bbuckets = sift(func.ap, _mod1), sift(func.bq, _mod1)
  1399. a0 = abuckets[S.Zero]
  1400. b0 = bbuckets[S.Zero]
  1401. a0.sort()
  1402. b0.sort()
  1403. al0 = [x for x in a0 if x <= 0]
  1404. bl0 = [x for x in b0 if x <= 0]
  1405. if bl0 and all(a < bl0[-1] for a in al0):
  1406. return oo
  1407. if not al0:
  1408. return None
  1409. a = al0[-1]
  1410. fac = 1
  1411. res = S.One
  1412. for n in Tuple(*list(range(-a))):
  1413. fac *= z
  1414. fac /= n + 1
  1415. for a in func.ap:
  1416. fac *= a + n
  1417. for b in func.bq:
  1418. fac /= b + n
  1419. res += fac
  1420. return res
  1421. def try_lerchphi(func):
  1422. """
  1423. Try to find an expression for Hyper_Function ``func`` in terms of Lerch
  1424. Transcendents.
  1425. Return None if no such expression can be found.
  1426. """
  1427. # This is actually quite simple, and is described in Roach's paper,
  1428. # section 18.
  1429. # We don't need to implement the reduction to polylog here, this
  1430. # is handled by expand_func.
  1431. from sympy.matrices import Matrix, zeros
  1432. from sympy.polys import apart
  1433. # First we need to figure out if the summation coefficient is a rational
  1434. # function of the summation index, and construct that rational function.
  1435. abuckets, bbuckets = sift(func.ap, _mod1), sift(func.bq, _mod1)
  1436. paired = {}
  1437. for key, value in abuckets.items():
  1438. if key != 0 and key not in bbuckets:
  1439. return None
  1440. bvalue = bbuckets[key]
  1441. paired[key] = (list(value), list(bvalue))
  1442. bbuckets.pop(key, None)
  1443. if bbuckets != {}:
  1444. return None
  1445. if S.Zero not in abuckets:
  1446. return None
  1447. aints, bints = paired[S.Zero]
  1448. # Account for the additional n! in denominator
  1449. paired[S.Zero] = (aints, bints + [1])
  1450. t = Dummy('t')
  1451. numer = S.One
  1452. denom = S.One
  1453. for key, (avalue, bvalue) in paired.items():
  1454. if len(avalue) != len(bvalue):
  1455. return None
  1456. # Note that since order has been reduced fully, all the b are
  1457. # bigger than all the a they differ from by an integer. In particular
  1458. # if there are any negative b left, this function is not well-defined.
  1459. for a, b in zip(avalue, bvalue):
  1460. if (a - b).is_positive:
  1461. k = a - b
  1462. numer *= rf(b + t, k)
  1463. denom *= rf(b, k)
  1464. else:
  1465. k = b - a
  1466. numer *= rf(a, k)
  1467. denom *= rf(a + t, k)
  1468. # Now do a partial fraction decomposition.
  1469. # We assemble two structures: a list monomials of pairs (a, b) representing
  1470. # a*t**b (b a non-negative integer), and a dict terms, where
  1471. # terms[a] = [(b, c)] means that there is a term b/(t-a)**c.
  1472. part = apart(numer/denom, t)
  1473. args = Add.make_args(part)
  1474. monomials = []
  1475. terms = {}
  1476. for arg in args:
  1477. numer, denom = arg.as_numer_denom()
  1478. if not denom.has(t):
  1479. p = Poly(numer, t)
  1480. if not p.is_monomial:
  1481. raise TypeError("p should be monomial")
  1482. ((b, ), a) = p.LT()
  1483. monomials += [(a/denom, b)]
  1484. continue
  1485. if numer.has(t):
  1486. raise NotImplementedError('Need partial fraction decomposition'
  1487. ' with linear denominators')
  1488. indep, [dep] = denom.as_coeff_mul(t)
  1489. n = 1
  1490. if dep.is_Pow:
  1491. n = dep.exp
  1492. dep = dep.base
  1493. if dep == t:
  1494. a == 0
  1495. elif dep.is_Add:
  1496. a, tmp = dep.as_independent(t)
  1497. b = 1
  1498. if tmp != t:
  1499. b, _ = tmp.as_independent(t)
  1500. if dep != b*t + a:
  1501. raise NotImplementedError('unrecognised form %s' % dep)
  1502. a /= b
  1503. indep *= b**n
  1504. else:
  1505. raise NotImplementedError('unrecognised form of partial fraction')
  1506. terms.setdefault(a, []).append((numer/indep, n))
  1507. # Now that we have this information, assemble our formula. All the
  1508. # monomials yield rational functions and go into one basis element.
  1509. # The terms[a] are related by differentiation. If the largest exponent is
  1510. # n, we need lerchphi(z, k, a) for k = 1, 2, ..., n.
  1511. # deriv maps a basis to its derivative, expressed as a C(z)-linear
  1512. # combination of other basis elements.
  1513. deriv = {}
  1514. coeffs = {}
  1515. z = Dummy('z')
  1516. monomials.sort(key=lambda x: x[1])
  1517. mon = {0: 1/(1 - z)}
  1518. if monomials:
  1519. for k in range(monomials[-1][1]):
  1520. mon[k + 1] = z*mon[k].diff(z)
  1521. for a, n in monomials:
  1522. coeffs.setdefault(S.One, []).append(a*mon[n])
  1523. for a, l in terms.items():
  1524. for c, k in l:
  1525. coeffs.setdefault(lerchphi(z, k, a), []).append(c)
  1526. l.sort(key=lambda x: x[1])
  1527. for k in range(2, l[-1][1] + 1):
  1528. deriv[lerchphi(z, k, a)] = [(-a, lerchphi(z, k, a)),
  1529. (1, lerchphi(z, k - 1, a))]
  1530. deriv[lerchphi(z, 1, a)] = [(-a, lerchphi(z, 1, a)),
  1531. (1/(1 - z), S.One)]
  1532. trans = {}
  1533. for n, b in enumerate([S.One] + list(deriv.keys())):
  1534. trans[b] = n
  1535. basis = [expand_func(b) for (b, _) in sorted(list(trans.items()),
  1536. key=lambda x:x[1])]
  1537. B = Matrix(basis)
  1538. C = Matrix([[0]*len(B)])
  1539. for b, c in coeffs.items():
  1540. C[trans[b]] = Add(*c)
  1541. M = zeros(len(B))
  1542. for b, l in deriv.items():
  1543. for c, b2 in l:
  1544. M[trans[b], trans[b2]] = c
  1545. return Formula(func, z, None, [], B, C, M)
  1546. def build_hypergeometric_formula(func):
  1547. """
  1548. Create a formula object representing the hypergeometric function ``func``.
  1549. """
  1550. # We know that no `ap` are negative integers, otherwise "detect poly"
  1551. # would have kicked in. However, `ap` could be empty. In this case we can
  1552. # use a different basis.
  1553. # I'm not aware of a basis that works in all cases.
  1554. from sympy.matrices.dense import (Matrix, eye, zeros)
  1555. z = Dummy('z')
  1556. if func.ap:
  1557. afactors = [_x + a for a in func.ap]
  1558. bfactors = [_x + b - 1 for b in func.bq]
  1559. expr = _x*Mul(*bfactors) - z*Mul(*afactors)
  1560. poly = Poly(expr, _x)
  1561. n = poly.degree()
  1562. basis = []
  1563. M = zeros(n)
  1564. for k in range(n):
  1565. a = func.ap[0] + k
  1566. basis += [hyper([a] + list(func.ap[1:]), func.bq, z)]
  1567. if k < n - 1:
  1568. M[k, k] = -a
  1569. M[k, k + 1] = a
  1570. B = Matrix(basis)
  1571. C = Matrix([[1] + [0]*(n - 1)])
  1572. derivs = [eye(n)]
  1573. for k in range(n):
  1574. derivs.append(M*derivs[k])
  1575. l = poly.all_coeffs()
  1576. l.reverse()
  1577. res = [0]*n
  1578. for k, c in enumerate(l):
  1579. for r, d in enumerate(C*derivs[k]):
  1580. res[r] += c*d
  1581. for k, c in enumerate(res):
  1582. M[n - 1, k] = -c/derivs[n - 1][0, n - 1]/poly.all_coeffs()[0]
  1583. return Formula(func, z, None, [], B, C, M)
  1584. else:
  1585. # Since there are no `ap`, none of the `bq` can be non-positive
  1586. # integers.
  1587. basis = []
  1588. bq = list(func.bq[:])
  1589. for i in range(len(bq)):
  1590. basis += [hyper([], bq, z)]
  1591. bq[i] += 1
  1592. basis += [hyper([], bq, z)]
  1593. B = Matrix(basis)
  1594. n = len(B)
  1595. C = Matrix([[1] + [0]*(n - 1)])
  1596. M = zeros(n)
  1597. M[0, n - 1] = z/Mul(*func.bq)
  1598. for k in range(1, n):
  1599. M[k, k - 1] = func.bq[k - 1]
  1600. M[k, k] = -func.bq[k - 1]
  1601. return Formula(func, z, None, [], B, C, M)
  1602. def hyperexpand_special(ap, bq, z):
  1603. """
  1604. Try to find a closed-form expression for hyper(ap, bq, z), where ``z``
  1605. is supposed to be a "special" value, e.g. 1.
  1606. This function tries various of the classical summation formulae
  1607. (Gauss, Saalschuetz, etc).
  1608. """
  1609. # This code is very ad-hoc. There are many clever algorithms
  1610. # (notably Zeilberger's) related to this problem.
  1611. # For now we just want a few simple cases to work.
  1612. p, q = len(ap), len(bq)
  1613. z_ = z
  1614. z = unpolarify(z)
  1615. if z == 0:
  1616. return S.One
  1617. from sympy.simplify.simplify import simplify
  1618. if p == 2 and q == 1:
  1619. # 2F1
  1620. a, b, c = ap + bq
  1621. if z == 1:
  1622. # Gauss
  1623. return gamma(c - a - b)*gamma(c)/gamma(c - a)/gamma(c - b)
  1624. if z == -1 and simplify(b - a + c) == 1:
  1625. b, a = a, b
  1626. if z == -1 and simplify(a - b + c) == 1:
  1627. # Kummer
  1628. if b.is_integer and b.is_negative:
  1629. return 2*cos(pi*b/2)*gamma(-b)*gamma(b - a + 1) \
  1630. /gamma(-b/2)/gamma(b/2 - a + 1)
  1631. else:
  1632. return gamma(b/2 + 1)*gamma(b - a + 1) \
  1633. /gamma(b + 1)/gamma(b/2 - a + 1)
  1634. # TODO tons of more formulae
  1635. # investigate what algorithms exist
  1636. return hyper(ap, bq, z_)
  1637. _collection = None
  1638. def _hyperexpand(func, z, ops0=[], z0=Dummy('z0'), premult=1, prem=0,
  1639. rewrite='default'):
  1640. """
  1641. Try to find an expression for the hypergeometric function ``func``.
  1642. Explanation
  1643. ===========
  1644. The result is expressed in terms of a dummy variable ``z0``. Then it
  1645. is multiplied by ``premult``. Then ``ops0`` is applied.
  1646. ``premult`` must be a*z**prem for some a independent of ``z``.
  1647. """
  1648. if z.is_zero:
  1649. return S.One
  1650. from sympy.simplify.simplify import simplify
  1651. z = polarify(z, subs=False)
  1652. if rewrite == 'default':
  1653. rewrite = 'nonrepsmall'
  1654. def carryout_plan(f, ops):
  1655. C = apply_operators(f.C.subs(f.z, z0), ops,
  1656. make_derivative_operator(f.M.subs(f.z, z0), z0))
  1657. from sympy.matrices.dense import eye
  1658. C = apply_operators(C, ops0,
  1659. make_derivative_operator(f.M.subs(f.z, z0)
  1660. + prem*eye(f.M.shape[0]), z0))
  1661. if premult == 1:
  1662. C = C.applyfunc(make_simp(z0))
  1663. r = reduce(lambda s,m: s+m[0]*m[1], zip(C, f.B.subs(f.z, z0)), S.Zero)*premult
  1664. res = r.subs(z0, z)
  1665. if rewrite:
  1666. res = res.rewrite(rewrite)
  1667. return res
  1668. # TODO
  1669. # The following would be possible:
  1670. # *) PFD Duplication (see Kelly Roach's paper)
  1671. # *) In a similar spirit, try_lerchphi() can be generalised considerably.
  1672. global _collection
  1673. if _collection is None:
  1674. _collection = FormulaCollection()
  1675. debug('Trying to expand hypergeometric function ', func)
  1676. # First reduce order as much as possible.
  1677. func, ops = reduce_order(func)
  1678. if ops:
  1679. debug(' Reduced order to ', func)
  1680. else:
  1681. debug(' Could not reduce order.')
  1682. # Now try polynomial cases
  1683. res = try_polynomial(func, z0)
  1684. if res is not None:
  1685. debug(' Recognised polynomial.')
  1686. p = apply_operators(res, ops, lambda f: z0*f.diff(z0))
  1687. p = apply_operators(p*premult, ops0, lambda f: z0*f.diff(z0))
  1688. return unpolarify(simplify(p).subs(z0, z))
  1689. # Try to recognise a shifted sum.
  1690. p = S.Zero
  1691. res = try_shifted_sum(func, z0)
  1692. if res is not None:
  1693. func, nops, p = res
  1694. debug(' Recognised shifted sum, reduced order to ', func)
  1695. ops += nops
  1696. # apply the plan for poly
  1697. p = apply_operators(p, ops, lambda f: z0*f.diff(z0))
  1698. p = apply_operators(p*premult, ops0, lambda f: z0*f.diff(z0))
  1699. p = simplify(p).subs(z0, z)
  1700. # Try special expansions early.
  1701. if unpolarify(z) in [1, -1] and (len(func.ap), len(func.bq)) == (2, 1):
  1702. f = build_hypergeometric_formula(func)
  1703. r = carryout_plan(f, ops).replace(hyper, hyperexpand_special)
  1704. if not r.has(hyper):
  1705. return r + p
  1706. # Try to find a formula in our collection
  1707. formula = _collection.lookup_origin(func)
  1708. # Now try a lerch phi formula
  1709. if formula is None:
  1710. formula = try_lerchphi(func)
  1711. if formula is None:
  1712. debug(' Could not find an origin. ',
  1713. 'Will return answer in terms of '
  1714. 'simpler hypergeometric functions.')
  1715. formula = build_hypergeometric_formula(func)
  1716. debug(' Found an origin: ', formula.closed_form, ' ', formula.func)
  1717. # We need to find the operators that convert formula into func.
  1718. ops += devise_plan(func, formula.func, z0)
  1719. # Now carry out the plan.
  1720. r = carryout_plan(formula, ops) + p
  1721. return powdenest(r, polar=True).replace(hyper, hyperexpand_special)
  1722. def devise_plan_meijer(fro, to, z):
  1723. """
  1724. Find operators to convert G-function ``fro`` into G-function ``to``.
  1725. Explanation
  1726. ===========
  1727. It is assumed that ``fro`` and ``to`` have the same signatures, and that in fact
  1728. any corresponding pair of parameters differs by integers, and a direct path
  1729. is possible. I.e. if there are parameters a1 b1 c1 and a2 b2 c2 it is
  1730. assumed that a1 can be shifted to a2, etc. The only thing this routine
  1731. determines is the order of shifts to apply, nothing clever will be tried.
  1732. It is also assumed that ``fro`` is suitable.
  1733. Examples
  1734. ========
  1735. >>> from sympy.simplify.hyperexpand import (devise_plan_meijer,
  1736. ... G_Function)
  1737. >>> from sympy.abc import z
  1738. Empty plan:
  1739. >>> devise_plan_meijer(G_Function([1], [2], [3], [4]),
  1740. ... G_Function([1], [2], [3], [4]), z)
  1741. []
  1742. Very simple plans:
  1743. >>> devise_plan_meijer(G_Function([0], [], [], []),
  1744. ... G_Function([1], [], [], []), z)
  1745. [<Increment upper a index #0 of [0], [], [], [].>]
  1746. >>> devise_plan_meijer(G_Function([0], [], [], []),
  1747. ... G_Function([-1], [], [], []), z)
  1748. [<Decrement upper a=0.>]
  1749. >>> devise_plan_meijer(G_Function([], [1], [], []),
  1750. ... G_Function([], [2], [], []), z)
  1751. [<Increment lower a index #0 of [], [1], [], [].>]
  1752. Slightly more complicated plans:
  1753. >>> devise_plan_meijer(G_Function([0], [], [], []),
  1754. ... G_Function([2], [], [], []), z)
  1755. [<Increment upper a index #0 of [1], [], [], [].>,
  1756. <Increment upper a index #0 of [0], [], [], [].>]
  1757. >>> devise_plan_meijer(G_Function([0], [], [0], []),
  1758. ... G_Function([-1], [], [1], []), z)
  1759. [<Increment upper b=0.>, <Decrement upper a=0.>]
  1760. Order matters:
  1761. >>> devise_plan_meijer(G_Function([0], [], [0], []),
  1762. ... G_Function([1], [], [1], []), z)
  1763. [<Increment upper a index #0 of [0], [], [1], [].>, <Increment upper b=0.>]
  1764. """
  1765. # TODO for now, we use the following simple heuristic: inverse-shift
  1766. # when possible, shift otherwise. Give up if we cannot make progress.
  1767. def try_shift(f, t, shifter, diff, counter):
  1768. """ Try to apply ``shifter`` in order to bring some element in ``f``
  1769. nearer to its counterpart in ``to``. ``diff`` is +/- 1 and
  1770. determines the effect of ``shifter``. Counter is a list of elements
  1771. blocking the shift.
  1772. Return an operator if change was possible, else None.
  1773. """
  1774. for idx, (a, b) in enumerate(zip(f, t)):
  1775. if (
  1776. (a - b).is_integer and (b - a)/diff > 0 and
  1777. all(a != x for x in counter)):
  1778. sh = shifter(idx)
  1779. f[idx] += diff
  1780. return sh
  1781. fan = list(fro.an)
  1782. fap = list(fro.ap)
  1783. fbm = list(fro.bm)
  1784. fbq = list(fro.bq)
  1785. ops = []
  1786. change = True
  1787. while change:
  1788. change = False
  1789. op = try_shift(fan, to.an,
  1790. lambda i: MeijerUnShiftB(fan, fap, fbm, fbq, i, z),
  1791. 1, fbm + fbq)
  1792. if op is not None:
  1793. ops += [op]
  1794. change = True
  1795. continue
  1796. op = try_shift(fap, to.ap,
  1797. lambda i: MeijerUnShiftD(fan, fap, fbm, fbq, i, z),
  1798. 1, fbm + fbq)
  1799. if op is not None:
  1800. ops += [op]
  1801. change = True
  1802. continue
  1803. op = try_shift(fbm, to.bm,
  1804. lambda i: MeijerUnShiftA(fan, fap, fbm, fbq, i, z),
  1805. -1, fan + fap)
  1806. if op is not None:
  1807. ops += [op]
  1808. change = True
  1809. continue
  1810. op = try_shift(fbq, to.bq,
  1811. lambda i: MeijerUnShiftC(fan, fap, fbm, fbq, i, z),
  1812. -1, fan + fap)
  1813. if op is not None:
  1814. ops += [op]
  1815. change = True
  1816. continue
  1817. op = try_shift(fan, to.an, lambda i: MeijerShiftB(fan[i]), -1, [])
  1818. if op is not None:
  1819. ops += [op]
  1820. change = True
  1821. continue
  1822. op = try_shift(fap, to.ap, lambda i: MeijerShiftD(fap[i]), -1, [])
  1823. if op is not None:
  1824. ops += [op]
  1825. change = True
  1826. continue
  1827. op = try_shift(fbm, to.bm, lambda i: MeijerShiftA(fbm[i]), 1, [])
  1828. if op is not None:
  1829. ops += [op]
  1830. change = True
  1831. continue
  1832. op = try_shift(fbq, to.bq, lambda i: MeijerShiftC(fbq[i]), 1, [])
  1833. if op is not None:
  1834. ops += [op]
  1835. change = True
  1836. continue
  1837. if fan != list(to.an) or fap != list(to.ap) or fbm != list(to.bm) or \
  1838. fbq != list(to.bq):
  1839. raise NotImplementedError('Could not devise plan.')
  1840. ops.reverse()
  1841. return ops
  1842. _meijercollection = None
  1843. def _meijergexpand(func, z0, allow_hyper=False, rewrite='default',
  1844. place=None):
  1845. """
  1846. Try to find an expression for the Meijer G function specified
  1847. by the G_Function ``func``. If ``allow_hyper`` is True, then returning
  1848. an expression in terms of hypergeometric functions is allowed.
  1849. Currently this just does Slater's theorem.
  1850. If expansions exist both at zero and at infinity, ``place``
  1851. can be set to ``0`` or ``zoo`` for the preferred choice.
  1852. """
  1853. global _meijercollection
  1854. if _meijercollection is None:
  1855. _meijercollection = MeijerFormulaCollection()
  1856. if rewrite == 'default':
  1857. rewrite = None
  1858. func0 = func
  1859. debug('Try to expand Meijer G function corresponding to ', func)
  1860. # We will play games with analytic continuation - rather use a fresh symbol
  1861. z = Dummy('z')
  1862. func, ops = reduce_order_meijer(func)
  1863. if ops:
  1864. debug(' Reduced order to ', func)
  1865. else:
  1866. debug(' Could not reduce order.')
  1867. # Try to find a direct formula
  1868. f = _meijercollection.lookup_origin(func)
  1869. if f is not None:
  1870. debug(' Found a Meijer G formula: ', f.func)
  1871. ops += devise_plan_meijer(f.func, func, z)
  1872. # Now carry out the plan.
  1873. C = apply_operators(f.C.subs(f.z, z), ops,
  1874. make_derivative_operator(f.M.subs(f.z, z), z))
  1875. C = C.applyfunc(make_simp(z))
  1876. r = C*f.B.subs(f.z, z)
  1877. r = r[0].subs(z, z0)
  1878. return powdenest(r, polar=True)
  1879. debug(" Could not find a direct formula. Trying Slater's theorem.")
  1880. # TODO the following would be possible:
  1881. # *) Paired Index Theorems
  1882. # *) PFD Duplication
  1883. # (See Kelly Roach's paper for details on either.)
  1884. #
  1885. # TODO Also, we tend to create combinations of gamma functions that can be
  1886. # simplified.
  1887. def can_do(pbm, pap):
  1888. """ Test if slater applies. """
  1889. for i in pbm:
  1890. if len(pbm[i]) > 1:
  1891. l = 0
  1892. if i in pap:
  1893. l = len(pap[i])
  1894. if l + 1 < len(pbm[i]):
  1895. return False
  1896. return True
  1897. def do_slater(an, bm, ap, bq, z, zfinal):
  1898. # zfinal is the value that will eventually be substituted for z.
  1899. # We pass it to _hyperexpand to improve performance.
  1900. from sympy.series import residue
  1901. func = G_Function(an, bm, ap, bq)
  1902. _, pbm, pap, _ = func.compute_buckets()
  1903. if not can_do(pbm, pap):
  1904. return S.Zero, False
  1905. cond = len(an) + len(ap) < len(bm) + len(bq)
  1906. if len(an) + len(ap) == len(bm) + len(bq):
  1907. cond = abs(z) < 1
  1908. if cond is False:
  1909. return S.Zero, False
  1910. res = S.Zero
  1911. for m in pbm:
  1912. if len(pbm[m]) == 1:
  1913. bh = pbm[m][0]
  1914. fac = 1
  1915. bo = list(bm)
  1916. bo.remove(bh)
  1917. for bj in bo:
  1918. fac *= gamma(bj - bh)
  1919. for aj in an:
  1920. fac *= gamma(1 + bh - aj)
  1921. for bj in bq:
  1922. fac /= gamma(1 + bh - bj)
  1923. for aj in ap:
  1924. fac /= gamma(aj - bh)
  1925. nap = [1 + bh - a for a in list(an) + list(ap)]
  1926. nbq = [1 + bh - b for b in list(bo) + list(bq)]
  1927. k = polar_lift(S.NegativeOne**(len(ap) - len(bm)))
  1928. harg = k*zfinal
  1929. # NOTE even though k "is" +-1, this has to be t/k instead of
  1930. # t*k ... we are using polar numbers for consistency!
  1931. premult = (t/k)**bh
  1932. hyp = _hyperexpand(Hyper_Function(nap, nbq), harg, ops,
  1933. t, premult, bh, rewrite=None)
  1934. res += fac * hyp
  1935. else:
  1936. b_ = pbm[m][0]
  1937. ki = [bi - b_ for bi in pbm[m][1:]]
  1938. u = len(ki)
  1939. li = [ai - b_ for ai in pap[m][:u + 1]]
  1940. bo = list(bm)
  1941. for b in pbm[m]:
  1942. bo.remove(b)
  1943. ao = list(ap)
  1944. for a in pap[m][:u]:
  1945. ao.remove(a)
  1946. lu = li[-1]
  1947. di = [l - k for (l, k) in zip(li, ki)]
  1948. # We first work out the integrand:
  1949. s = Dummy('s')
  1950. integrand = z**s
  1951. for b in bm:
  1952. if not Mod(b, 1) and b.is_Number:
  1953. b = int(round(b))
  1954. integrand *= gamma(b - s)
  1955. for a in an:
  1956. integrand *= gamma(1 - a + s)
  1957. for b in bq:
  1958. integrand /= gamma(1 - b + s)
  1959. for a in ap:
  1960. integrand /= gamma(a - s)
  1961. # Now sum the finitely many residues:
  1962. # XXX This speeds up some cases - is it a good idea?
  1963. integrand = expand_func(integrand)
  1964. for r in range(int(round(lu))):
  1965. resid = residue(integrand, s, b_ + r)
  1966. resid = apply_operators(resid, ops, lambda f: z*f.diff(z))
  1967. res -= resid
  1968. # Now the hypergeometric term.
  1969. au = b_ + lu
  1970. k = polar_lift(S.NegativeOne**(len(ao) + len(bo) + 1))
  1971. harg = k*zfinal
  1972. premult = (t/k)**au
  1973. nap = [1 + au - a for a in list(an) + list(ap)] + [1]
  1974. nbq = [1 + au - b for b in list(bm) + list(bq)]
  1975. hyp = _hyperexpand(Hyper_Function(nap, nbq), harg, ops,
  1976. t, premult, au, rewrite=None)
  1977. C = S.NegativeOne**(lu)/factorial(lu)
  1978. for i in range(u):
  1979. C *= S.NegativeOne**di[i]/rf(lu - li[i] + 1, di[i])
  1980. for a in an:
  1981. C *= gamma(1 - a + au)
  1982. for b in bo:
  1983. C *= gamma(b - au)
  1984. for a in ao:
  1985. C /= gamma(a - au)
  1986. for b in bq:
  1987. C /= gamma(1 - b + au)
  1988. res += C*hyp
  1989. return res, cond
  1990. t = Dummy('t')
  1991. slater1, cond1 = do_slater(func.an, func.bm, func.ap, func.bq, z, z0)
  1992. def tr(l):
  1993. return [1 - x for x in l]
  1994. for op in ops:
  1995. op._poly = Poly(op._poly.subs({z: 1/t, _x: -_x}), _x)
  1996. slater2, cond2 = do_slater(tr(func.bm), tr(func.an), tr(func.bq), tr(func.ap),
  1997. t, 1/z0)
  1998. slater1 = powdenest(slater1.subs(z, z0), polar=True)
  1999. slater2 = powdenest(slater2.subs(t, 1/z0), polar=True)
  2000. if not isinstance(cond2, bool):
  2001. cond2 = cond2.subs(t, 1/z)
  2002. m = func(z)
  2003. if m.delta > 0 or \
  2004. (m.delta == 0 and len(m.ap) == len(m.bq) and
  2005. (re(m.nu) < -1) is not False and polar_lift(z0) == polar_lift(1)):
  2006. # The condition delta > 0 means that the convergence region is
  2007. # connected. Any expression we find can be continued analytically
  2008. # to the entire convergence region.
  2009. # The conditions delta==0, p==q, re(nu) < -1 imply that G is continuous
  2010. # on the positive reals, so the values at z=1 agree.
  2011. if cond1 is not False:
  2012. cond1 = True
  2013. if cond2 is not False:
  2014. cond2 = True
  2015. if cond1 is True:
  2016. slater1 = slater1.rewrite(rewrite or 'nonrep')
  2017. else:
  2018. slater1 = slater1.rewrite(rewrite or 'nonrepsmall')
  2019. if cond2 is True:
  2020. slater2 = slater2.rewrite(rewrite or 'nonrep')
  2021. else:
  2022. slater2 = slater2.rewrite(rewrite or 'nonrepsmall')
  2023. if cond1 is not False and cond2 is not False:
  2024. # If one condition is False, there is no choice.
  2025. if place == 0:
  2026. cond2 = False
  2027. if place == zoo:
  2028. cond1 = False
  2029. if not isinstance(cond1, bool):
  2030. cond1 = cond1.subs(z, z0)
  2031. if not isinstance(cond2, bool):
  2032. cond2 = cond2.subs(z, z0)
  2033. def weight(expr, cond):
  2034. if cond is True:
  2035. c0 = 0
  2036. elif cond is False:
  2037. c0 = 1
  2038. else:
  2039. c0 = 2
  2040. if expr.has(oo, zoo, -oo, nan):
  2041. # XXX this actually should not happen, but consider
  2042. # S('meijerg(((0, -1/2, 0, -1/2, 1/2), ()), ((0,),
  2043. # (-1/2, -1/2, -1/2, -1)), exp_polar(I*pi))/4')
  2044. c0 = 3
  2045. return (c0, expr.count(hyper), expr.count_ops())
  2046. w1 = weight(slater1, cond1)
  2047. w2 = weight(slater2, cond2)
  2048. if min(w1, w2) <= (0, 1, oo):
  2049. if w1 < w2:
  2050. return slater1
  2051. else:
  2052. return slater2
  2053. if max(w1[0], w2[0]) <= 1 and max(w1[1], w2[1]) <= 1:
  2054. return Piecewise((slater1, cond1), (slater2, cond2), (func0(z0), True))
  2055. # We couldn't find an expression without hypergeometric functions.
  2056. # TODO it would be helpful to give conditions under which the integral
  2057. # is known to diverge.
  2058. r = Piecewise((slater1, cond1), (slater2, cond2), (func0(z0), True))
  2059. if r.has(hyper) and not allow_hyper:
  2060. debug(' Could express using hypergeometric functions, '
  2061. 'but not allowed.')
  2062. if not r.has(hyper) or allow_hyper:
  2063. return r
  2064. return func0(z0)
  2065. def hyperexpand(f, allow_hyper=False, rewrite='default', place=None):
  2066. """
  2067. Expand hypergeometric functions. If allow_hyper is True, allow partial
  2068. simplification (that is a result different from input,
  2069. but still containing hypergeometric functions).
  2070. If a G-function has expansions both at zero and at infinity,
  2071. ``place`` can be set to ``0`` or ``zoo`` to indicate the
  2072. preferred choice.
  2073. Examples
  2074. ========
  2075. >>> from sympy.simplify.hyperexpand import hyperexpand
  2076. >>> from sympy.functions import hyper
  2077. >>> from sympy.abc import z
  2078. >>> hyperexpand(hyper([], [], z))
  2079. exp(z)
  2080. Non-hyperegeometric parts of the expression and hypergeometric expressions
  2081. that are not recognised are left unchanged:
  2082. >>> hyperexpand(1 + hyper([1, 1, 1], [], z))
  2083. hyper((1, 1, 1), (), z) + 1
  2084. """
  2085. f = sympify(f)
  2086. def do_replace(ap, bq, z):
  2087. r = _hyperexpand(Hyper_Function(ap, bq), z, rewrite=rewrite)
  2088. if r is None:
  2089. return hyper(ap, bq, z)
  2090. else:
  2091. return r
  2092. def do_meijer(ap, bq, z):
  2093. r = _meijergexpand(G_Function(ap[0], ap[1], bq[0], bq[1]), z,
  2094. allow_hyper, rewrite=rewrite, place=place)
  2095. if not r.has(nan, zoo, oo, -oo):
  2096. return r
  2097. return f.replace(hyper, do_replace).replace(meijerg, do_meijer)