test_holonomic.py 35 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851
  1. from sympy.holonomic import (DifferentialOperator, HolonomicFunction,
  2. DifferentialOperators, from_hyper,
  3. from_meijerg, expr_to_holonomic)
  4. from sympy.holonomic.recurrence import RecurrenceOperators, HolonomicSequence
  5. from sympy.core import EulerGamma
  6. from sympy.core.numbers import (I, Rational, pi)
  7. from sympy.core.singleton import S
  8. from sympy.core.symbol import (Symbol, symbols)
  9. from sympy.functions.elementary.exponential import (exp, log)
  10. from sympy.functions.elementary.hyperbolic import (asinh, cosh)
  11. from sympy.functions.elementary.miscellaneous import sqrt
  12. from sympy.functions.elementary.trigonometric import (cos, sin)
  13. from sympy.functions.special.bessel import besselj
  14. from sympy.functions.special.beta_functions import beta
  15. from sympy.functions.special.error_functions import (Ci, Si, erf, erfc)
  16. from sympy.functions.special.gamma_functions import gamma
  17. from sympy.functions.special.hyper import (hyper, meijerg)
  18. from sympy.printing.str import sstr
  19. from sympy.series.order import O
  20. from sympy.simplify.hyperexpand import hyperexpand
  21. from sympy.polys.domains.integerring import ZZ
  22. from sympy.polys.domains.rationalfield import QQ
  23. from sympy.polys.domains.realfield import RR
  24. def test_DifferentialOperator():
  25. x = symbols('x')
  26. R, Dx = DifferentialOperators(QQ.old_poly_ring(x), 'Dx')
  27. assert Dx == R.derivative_operator
  28. assert Dx == DifferentialOperator([R.base.zero, R.base.one], R)
  29. assert x * Dx + x**2 * Dx**2 == DifferentialOperator([0, x, x**2], R)
  30. assert (x**2 + 1) + Dx + x * \
  31. Dx**5 == DifferentialOperator([x**2 + 1, 1, 0, 0, 0, x], R)
  32. assert (x * Dx + x**2 + 1 - Dx * (x**3 + x))**3 == (-48 * x**6) + \
  33. (-57 * x**7) * Dx + (-15 * x**8) * Dx**2 + (-x**9) * Dx**3
  34. p = (x * Dx**2 + (x**2 + 3) * Dx**5) * (Dx + x**2)
  35. q = (2 * x) + (4 * x**2) * Dx + (x**3) * Dx**2 + \
  36. (20 * x**2 + x + 60) * Dx**3 + (10 * x**3 + 30 * x) * Dx**4 + \
  37. (x**4 + 3 * x**2) * Dx**5 + (x**2 + 3) * Dx**6
  38. assert p == q
  39. def test_HolonomicFunction_addition():
  40. x = symbols('x')
  41. R, Dx = DifferentialOperators(ZZ.old_poly_ring(x), 'Dx')
  42. p = HolonomicFunction(Dx**2 * x, x)
  43. q = HolonomicFunction((2) * Dx + (x) * Dx**2, x)
  44. assert p == q
  45. p = HolonomicFunction(x * Dx + 1, x)
  46. q = HolonomicFunction(Dx + 1, x)
  47. r = HolonomicFunction((x - 2) + (x**2 - 2) * Dx + (x**2 - x) * Dx**2, x)
  48. assert p + q == r
  49. p = HolonomicFunction(x * Dx + Dx**2 * (x**2 + 2), x)
  50. q = HolonomicFunction(Dx - 3, x)
  51. r = HolonomicFunction((-54 * x**2 - 126 * x - 150) + (-135 * x**3 - 252 * x**2 - 270 * x + 140) * Dx +\
  52. (-27 * x**4 - 24 * x**2 + 14 * x - 150) * Dx**2 + \
  53. (9 * x**4 + 15 * x**3 + 38 * x**2 + 30 * x +40) * Dx**3, x)
  54. assert p + q == r
  55. p = HolonomicFunction(Dx**5 - 1, x)
  56. q = HolonomicFunction(x**3 + Dx, x)
  57. r = HolonomicFunction((-x**18 + 45*x**14 - 525*x**10 + 1575*x**6 - x**3 - 630*x**2) + \
  58. (-x**15 + 30*x**11 - 195*x**7 + 210*x**3 - 1)*Dx + (x**18 - 45*x**14 + 525*x**10 - \
  59. 1575*x**6 + x**3 + 630*x**2)*Dx**5 + (x**15 - 30*x**11 + 195*x**7 - 210*x**3 + \
  60. 1)*Dx**6, x)
  61. assert p+q == r
  62. p = x**2 + 3*x + 8
  63. q = x**3 - 7*x + 5
  64. p = p*Dx - p.diff()
  65. q = q*Dx - q.diff()
  66. r = HolonomicFunction(p, x) + HolonomicFunction(q, x)
  67. s = HolonomicFunction((6*x**2 + 18*x + 14) + (-4*x**3 - 18*x**2 - 62*x + 10)*Dx +\
  68. (x**4 + 6*x**3 + 31*x**2 - 10*x - 71)*Dx**2, x)
  69. assert r == s
  70. def test_HolonomicFunction_multiplication():
  71. x = symbols('x')
  72. R, Dx = DifferentialOperators(ZZ.old_poly_ring(x), 'Dx')
  73. p = HolonomicFunction(Dx+x+x*Dx**2, x)
  74. q = HolonomicFunction(x*Dx+Dx*x+Dx**2, x)
  75. r = HolonomicFunction((8*x**6 + 4*x**4 + 6*x**2 + 3) + (24*x**5 - 4*x**3 + 24*x)*Dx + \
  76. (8*x**6 + 20*x**4 + 12*x**2 + 2)*Dx**2 + (8*x**5 + 4*x**3 + 4*x)*Dx**3 + \
  77. (2*x**4 + x**2)*Dx**4, x)
  78. assert p*q == r
  79. p = HolonomicFunction(Dx**2+1, x)
  80. q = HolonomicFunction(Dx-1, x)
  81. r = HolonomicFunction((2) + (-2)*Dx + (1)*Dx**2, x)
  82. assert p*q == r
  83. p = HolonomicFunction(Dx**2+1+x+Dx, x)
  84. q = HolonomicFunction((Dx*x-1)**2, x)
  85. r = HolonomicFunction((4*x**7 + 11*x**6 + 16*x**5 + 4*x**4 - 6*x**3 - 7*x**2 - 8*x - 2) + \
  86. (8*x**6 + 26*x**5 + 24*x**4 - 3*x**3 - 11*x**2 - 6*x - 2)*Dx + \
  87. (8*x**6 + 18*x**5 + 15*x**4 - 3*x**3 - 6*x**2 - 6*x - 2)*Dx**2 + (8*x**5 + \
  88. 10*x**4 + 6*x**3 - 2*x**2 - 4*x)*Dx**3 + (4*x**5 + 3*x**4 - x**2)*Dx**4, x)
  89. assert p*q == r
  90. p = HolonomicFunction(x*Dx**2-1, x)
  91. q = HolonomicFunction(Dx*x-x, x)
  92. r = HolonomicFunction((x - 3) + (-2*x + 2)*Dx + (x)*Dx**2, x)
  93. assert p*q == r
  94. def test_HolonomicFunction_power():
  95. x = symbols('x')
  96. R, Dx = DifferentialOperators(ZZ.old_poly_ring(x), 'Dx')
  97. p = HolonomicFunction(Dx+x+x*Dx**2, x)
  98. a = HolonomicFunction(Dx, x)
  99. for n in range(10):
  100. assert a == p**n
  101. a *= p
  102. def test_addition_initial_condition():
  103. x = symbols('x')
  104. R, Dx = DifferentialOperators(QQ.old_poly_ring(x), 'Dx')
  105. p = HolonomicFunction(Dx-1, x, 0, [3])
  106. q = HolonomicFunction(Dx**2+1, x, 0, [1, 0])
  107. r = HolonomicFunction(-1 + Dx - Dx**2 + Dx**3, x, 0, [4, 3, 2])
  108. assert p + q == r
  109. p = HolonomicFunction(Dx - x + Dx**2, x, 0, [1, 2])
  110. q = HolonomicFunction(Dx**2 + x, x, 0, [1, 0])
  111. r = HolonomicFunction((-x**4 - x**3/4 - x**2 + Rational(1, 4)) + (x**3 + x**2/4 + x*Rational(3, 4) + 1)*Dx + \
  112. (x*Rational(-3, 2) + Rational(7, 4))*Dx**2 + (x**2 - x*Rational(7, 4) + Rational(1, 4))*Dx**3 + (x**2 + x/4 + S.Half)*Dx**4, x, 0, [2, 2, -2, 2])
  113. assert p + q == r
  114. p = HolonomicFunction(Dx**2 + 4*x*Dx + x**2, x, 0, [3, 4])
  115. q = HolonomicFunction(Dx**2 + 1, x, 0, [1, 1])
  116. r = HolonomicFunction((x**6 + 2*x**4 - 5*x**2 - 6) + (4*x**5 + 36*x**3 - 32*x)*Dx + \
  117. (x**6 + 3*x**4 + 5*x**2 - 9)*Dx**2 + (4*x**5 + 36*x**3 - 32*x)*Dx**3 + (x**4 + \
  118. 10*x**2 - 3)*Dx**4, x, 0, [4, 5, -1, -17])
  119. assert p + q == r
  120. q = HolonomicFunction(Dx**3 + x, x, 2, [3, 0, 1])
  121. p = HolonomicFunction(Dx - 1, x, 2, [1])
  122. r = HolonomicFunction((-x**2 - x + 1) + (x**2 + x)*Dx + (-x - 2)*Dx**3 + \
  123. (x + 1)*Dx**4, x, 2, [4, 1, 2, -5 ])
  124. assert p + q == r
  125. p = expr_to_holonomic(sin(x))
  126. q = expr_to_holonomic(1/x, x0=1)
  127. r = HolonomicFunction((x**2 + 6) + (x**3 + 2*x)*Dx + (x**2 + 6)*Dx**2 + (x**3 + 2*x)*Dx**3, \
  128. x, 1, [sin(1) + 1, -1 + cos(1), -sin(1) + 2])
  129. assert p + q == r
  130. C_1 = symbols('C_1')
  131. p = expr_to_holonomic(sqrt(x))
  132. q = expr_to_holonomic(sqrt(x**2-x))
  133. r = (p + q).to_expr().subs(C_1, -I/2).expand()
  134. assert r == I*sqrt(x)*sqrt(-x + 1) + sqrt(x)
  135. def test_multiplication_initial_condition():
  136. x = symbols('x')
  137. R, Dx = DifferentialOperators(QQ.old_poly_ring(x), 'Dx')
  138. p = HolonomicFunction(Dx**2 + x*Dx - 1, x, 0, [3, 1])
  139. q = HolonomicFunction(Dx**2 + 1, x, 0, [1, 1])
  140. r = HolonomicFunction((x**4 + 14*x**2 + 60) + 4*x*Dx + (x**4 + 9*x**2 + 20)*Dx**2 + \
  141. (2*x**3 + 18*x)*Dx**3 + (x**2 + 10)*Dx**4, x, 0, [3, 4, 2, 3])
  142. assert p * q == r
  143. p = HolonomicFunction(Dx**2 + x, x, 0, [1, 0])
  144. q = HolonomicFunction(Dx**3 - x**2, x, 0, [3, 3, 3])
  145. r = HolonomicFunction((x**8 - 37*x**7/27 - 10*x**6/27 - 164*x**5/9 - 184*x**4/9 + \
  146. 160*x**3/27 + 404*x**2/9 + 8*x + Rational(40, 3)) + (6*x**7 - 128*x**6/9 - 98*x**5/9 - 28*x**4/9 + \
  147. 8*x**3/9 + 28*x**2 + x*Rational(40, 9) - 40)*Dx + (3*x**6 - 82*x**5/9 + 76*x**4/9 + 4*x**3/3 + \
  148. 220*x**2/9 - x*Rational(80, 3))*Dx**2 + (-2*x**6 + 128*x**5/27 - 2*x**4/3 -80*x**2/9 + Rational(200, 9))*Dx**3 + \
  149. (3*x**5 - 64*x**4/9 - 28*x**3/9 + 6*x**2 - x*Rational(20, 9) - Rational(20, 3))*Dx**4 + (-4*x**3 + 64*x**2/9 + \
  150. x*Rational(8, 3))*Dx**5 + (x**4 - 64*x**3/27 - 4*x**2/3 + Rational(20, 9))*Dx**6, x, 0, [3, 3, 3, -3, -12, -24])
  151. assert p * q == r
  152. p = HolonomicFunction(Dx - 1, x, 0, [2])
  153. q = HolonomicFunction(Dx**2 + 1, x, 0, [0, 1])
  154. r = HolonomicFunction(2 -2*Dx + Dx**2, x, 0, [0, 2])
  155. assert p * q == r
  156. q = HolonomicFunction(x*Dx**2 + 1 + 2*Dx, x, 0,[0, 1])
  157. r = HolonomicFunction((x - 1) + (-2*x + 2)*Dx + x*Dx**2, x, 0, [0, 2])
  158. assert p * q == r
  159. p = HolonomicFunction(Dx**2 - 1, x, 0, [1, 3])
  160. q = HolonomicFunction(Dx**3 + 1, x, 0, [1, 2, 1])
  161. r = HolonomicFunction(6*Dx + 3*Dx**2 + 2*Dx**3 - 3*Dx**4 + Dx**6, x, 0, [1, 5, 14, 17, 17, 2])
  162. assert p * q == r
  163. p = expr_to_holonomic(sin(x))
  164. q = expr_to_holonomic(1/x, x0=1)
  165. r = HolonomicFunction(x + 2*Dx + x*Dx**2, x, 1, [sin(1), -sin(1) + cos(1)])
  166. assert p * q == r
  167. p = expr_to_holonomic(sqrt(x))
  168. q = expr_to_holonomic(sqrt(x**2-x))
  169. r = (p * q).to_expr()
  170. assert r == I*x*sqrt(-x + 1)
  171. def test_HolonomicFunction_composition():
  172. x = symbols('x')
  173. R, Dx = DifferentialOperators(ZZ.old_poly_ring(x), 'Dx')
  174. p = HolonomicFunction(Dx-1, x).composition(x**2+x)
  175. r = HolonomicFunction((-2*x - 1) + Dx, x)
  176. assert p == r
  177. p = HolonomicFunction(Dx**2+1, x).composition(x**5+x**2+1)
  178. r = HolonomicFunction((125*x**12 + 150*x**9 + 60*x**6 + 8*x**3) + (-20*x**3 - 2)*Dx + \
  179. (5*x**4 + 2*x)*Dx**2, x)
  180. assert p == r
  181. p = HolonomicFunction(Dx**2*x+x, x).composition(2*x**3+x**2+1)
  182. r = HolonomicFunction((216*x**9 + 324*x**8 + 180*x**7 + 152*x**6 + 112*x**5 + \
  183. 36*x**4 + 4*x**3) + (24*x**4 + 16*x**3 + 3*x**2 - 6*x - 1)*Dx + (6*x**5 + 5*x**4 + \
  184. x**3 + 3*x**2 + x)*Dx**2, x)
  185. assert p == r
  186. p = HolonomicFunction(Dx**2+1, x).composition(1-x**2)
  187. r = HolonomicFunction((4*x**3) - Dx + x*Dx**2, x)
  188. assert p == r
  189. p = HolonomicFunction(Dx**2+1, x).composition(x - 2/(x**2 + 1))
  190. r = HolonomicFunction((x**12 + 6*x**10 + 12*x**9 + 15*x**8 + 48*x**7 + 68*x**6 + \
  191. 72*x**5 + 111*x**4 + 112*x**3 + 54*x**2 + 12*x + 1) + (12*x**8 + 32*x**6 + \
  192. 24*x**4 - 4)*Dx + (x**12 + 6*x**10 + 4*x**9 + 15*x**8 + 16*x**7 + 20*x**6 + 24*x**5+ \
  193. 15*x**4 + 16*x**3 + 6*x**2 + 4*x + 1)*Dx**2, x)
  194. assert p == r
  195. def test_from_hyper():
  196. x = symbols('x')
  197. R, Dx = DifferentialOperators(QQ.old_poly_ring(x), 'Dx')
  198. p = hyper([1, 1], [Rational(3, 2)], x**2/4)
  199. q = HolonomicFunction((4*x) + (5*x**2 - 8)*Dx + (x**3 - 4*x)*Dx**2, x, 1, [2*sqrt(3)*pi/9, -4*sqrt(3)*pi/27 + Rational(4, 3)])
  200. r = from_hyper(p)
  201. assert r == q
  202. p = from_hyper(hyper([1], [Rational(3, 2)], x**2/4))
  203. q = HolonomicFunction(-x + (-x**2/2 + 2)*Dx + x*Dx**2, x)
  204. # x0 = 1
  205. y0 = '[sqrt(pi)*exp(1/4)*erf(1/2), -sqrt(pi)*exp(1/4)*erf(1/2)/2 + 1]'
  206. assert sstr(p.y0) == y0
  207. assert q.annihilator == p.annihilator
  208. def test_from_meijerg():
  209. x = symbols('x')
  210. R, Dx = DifferentialOperators(QQ.old_poly_ring(x), 'Dx')
  211. p = from_meijerg(meijerg(([], [Rational(3, 2)]), ([S.Half], [S.Half, 1]), x))
  212. q = HolonomicFunction(x/2 - Rational(1, 4) + (-x**2 + x/4)*Dx + x**2*Dx**2 + x**3*Dx**3, x, 1, \
  213. [1/sqrt(pi), 1/(2*sqrt(pi)), -1/(4*sqrt(pi))])
  214. assert p == q
  215. p = from_meijerg(meijerg(([], []), ([0], []), x))
  216. q = HolonomicFunction(1 + Dx, x, 0, [1])
  217. assert p == q
  218. p = from_meijerg(meijerg(([1], []), ([S.Half], [0]), x))
  219. q = HolonomicFunction((x + S.Half)*Dx + x*Dx**2, x, 1, [sqrt(pi)*erf(1), exp(-1)])
  220. assert p == q
  221. p = from_meijerg(meijerg(([0], [1]), ([0], []), 2*x**2))
  222. q = HolonomicFunction((3*x**2 - 1)*Dx + x**3*Dx**2, x, 1, [-exp(Rational(-1, 2)) + 1, -exp(Rational(-1, 2))])
  223. assert p == q
  224. def test_to_Sequence():
  225. x = symbols('x')
  226. R, Dx = DifferentialOperators(ZZ.old_poly_ring(x), 'Dx')
  227. n = symbols('n', integer=True)
  228. _, Sn = RecurrenceOperators(ZZ.old_poly_ring(n), 'Sn')
  229. p = HolonomicFunction(x**2*Dx**4 + x + Dx, x).to_sequence()
  230. q = [(HolonomicSequence(1 + (n + 2)*Sn**2 + (n**4 + 6*n**3 + 11*n**2 + 6*n)*Sn**3), 0, 1)]
  231. assert p == q
  232. p = HolonomicFunction(x**2*Dx**4 + x**3 + Dx**2, x).to_sequence()
  233. q = [(HolonomicSequence(1 + (n**4 + 14*n**3 + 72*n**2 + 163*n + 140)*Sn**5), 0, 0)]
  234. assert p == q
  235. p = HolonomicFunction(x**3*Dx**4 + 1 + Dx**2, x).to_sequence()
  236. q = [(HolonomicSequence(1 + (n**4 - 2*n**3 - n**2 + 2*n)*Sn + (n**2 + 3*n + 2)*Sn**2), 0, 0)]
  237. assert p == q
  238. p = HolonomicFunction(3*x**3*Dx**4 + 2*x*Dx + x*Dx**3, x).to_sequence()
  239. q = [(HolonomicSequence(2*n + (3*n**4 - 6*n**3 - 3*n**2 + 6*n)*Sn + (n**3 + 3*n**2 + 2*n)*Sn**2), 0, 1)]
  240. assert p == q
  241. def test_to_Sequence_Initial_Coniditons():
  242. x = symbols('x')
  243. R, Dx = DifferentialOperators(QQ.old_poly_ring(x), 'Dx')
  244. n = symbols('n', integer=True)
  245. _, Sn = RecurrenceOperators(QQ.old_poly_ring(n), 'Sn')
  246. p = HolonomicFunction(Dx - 1, x, 0, [1]).to_sequence()
  247. q = [(HolonomicSequence(-1 + (n + 1)*Sn, 1), 0)]
  248. assert p == q
  249. p = HolonomicFunction(Dx**2 + 1, x, 0, [0, 1]).to_sequence()
  250. q = [(HolonomicSequence(1 + (n**2 + 3*n + 2)*Sn**2, [0, 1]), 0)]
  251. assert p == q
  252. p = HolonomicFunction(Dx**2 + 1 + x**3*Dx, x, 0, [2, 3]).to_sequence()
  253. q = [(HolonomicSequence(n + Sn**2 + (n**2 + 7*n + 12)*Sn**4, [2, 3, -1, Rational(-1, 2), Rational(1, 12)]), 1)]
  254. assert p == q
  255. p = HolonomicFunction(x**3*Dx**5 + 1 + Dx, x).to_sequence()
  256. q = [(HolonomicSequence(1 + (n + 1)*Sn + (n**5 - 5*n**3 + 4*n)*Sn**2), 0, 3)]
  257. assert p == q
  258. C_0, C_1, C_2, C_3 = symbols('C_0, C_1, C_2, C_3')
  259. p = expr_to_holonomic(log(1+x**2))
  260. q = [(HolonomicSequence(n**2 + (n**2 + 2*n)*Sn**2, [0, 0, C_2]), 0, 1)]
  261. assert p.to_sequence() == q
  262. p = p.diff()
  263. q = [(HolonomicSequence((n + 2) + (n + 2)*Sn**2, [C_0, 0]), 1, 0)]
  264. assert p.to_sequence() == q
  265. p = expr_to_holonomic(erf(x) + x).to_sequence()
  266. q = [(HolonomicSequence((2*n**2 - 2*n) + (n**3 + 2*n**2 - n - 2)*Sn**2, [0, 1 + 2/sqrt(pi), 0, C_3]), 0, 2)]
  267. assert p == q
  268. def test_series():
  269. x = symbols('x')
  270. R, Dx = DifferentialOperators(ZZ.old_poly_ring(x), 'Dx')
  271. p = HolonomicFunction(Dx**2 + 2*x*Dx, x, 0, [0, 1]).series(n=10)
  272. q = x - x**3/3 + x**5/10 - x**7/42 + x**9/216 + O(x**10)
  273. assert p == q
  274. p = HolonomicFunction(Dx - 1, x).composition(x**2, 0, [1]) # e^(x**2)
  275. q = HolonomicFunction(Dx**2 + 1, x, 0, [1, 0]) # cos(x)
  276. r = (p * q).series(n=10) # expansion of cos(x) * exp(x**2)
  277. s = 1 + x**2/2 + x**4/24 - 31*x**6/720 - 179*x**8/8064 + O(x**10)
  278. assert r == s
  279. t = HolonomicFunction((1 + x)*Dx**2 + Dx, x, 0, [0, 1]) # log(1 + x)
  280. r = (p * t + q).series(n=10)
  281. s = 1 + x - x**2 + 4*x**3/3 - 17*x**4/24 + 31*x**5/30 - 481*x**6/720 +\
  282. 71*x**7/105 - 20159*x**8/40320 + 379*x**9/840 + O(x**10)
  283. assert r == s
  284. p = HolonomicFunction((6+6*x-3*x**2) - (10*x-3*x**2-3*x**3)*Dx + \
  285. (4-6*x**3+2*x**4)*Dx**2, x, 0, [0, 1]).series(n=7)
  286. q = x + x**3/6 - 3*x**4/16 + x**5/20 - 23*x**6/960 + O(x**7)
  287. assert p == q
  288. p = HolonomicFunction((6+6*x-3*x**2) - (10*x-3*x**2-3*x**3)*Dx + \
  289. (4-6*x**3+2*x**4)*Dx**2, x, 0, [1, 0]).series(n=7)
  290. q = 1 - 3*x**2/4 - x**3/4 - 5*x**4/32 - 3*x**5/40 - 17*x**6/384 + O(x**7)
  291. assert p == q
  292. p = expr_to_holonomic(erf(x) + x).series(n=10)
  293. C_3 = symbols('C_3')
  294. q = (erf(x) + x).series(n=10)
  295. assert p.subs(C_3, -2/(3*sqrt(pi))) == q
  296. assert expr_to_holonomic(sqrt(x**3 + x)).series(n=10) == sqrt(x**3 + x).series(n=10)
  297. assert expr_to_holonomic((2*x - 3*x**2)**Rational(1, 3)).series() == ((2*x - 3*x**2)**Rational(1, 3)).series()
  298. assert expr_to_holonomic(sqrt(x**2-x)).series() == (sqrt(x**2-x)).series()
  299. assert expr_to_holonomic(cos(x)**2/x**2, y0={-2: [1, 0, -1]}).series(n=10) == (cos(x)**2/x**2).series(n=10)
  300. assert expr_to_holonomic(cos(x)**2/x**2, x0=1).series(n=10).together() == (cos(x)**2/x**2).series(n=10, x0=1).together()
  301. assert expr_to_holonomic(cos(x-1)**2/(x-1)**2, x0=1, y0={-2: [1, 0, -1]}).series(n=10) \
  302. == (cos(x-1)**2/(x-1)**2).series(x0=1, n=10)
  303. def test_evalf_euler():
  304. x = symbols('x')
  305. R, Dx = DifferentialOperators(QQ.old_poly_ring(x), 'Dx')
  306. # log(1+x)
  307. p = HolonomicFunction((1 + x)*Dx**2 + Dx, x, 0, [0, 1])
  308. # path taken is a straight line from 0 to 1, on the real axis
  309. r = [0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9, 1]
  310. s = '0.699525841805253' # approx. equal to log(2) i.e. 0.693147180559945
  311. assert sstr(p.evalf(r, method='Euler')[-1]) == s
  312. # path taken is a triangle 0-->1+i-->2
  313. r = [0.1 + 0.1*I]
  314. for i in range(9):
  315. r.append(r[-1]+0.1+0.1*I)
  316. for i in range(10):
  317. r.append(r[-1]+0.1-0.1*I)
  318. # close to the exact solution 1.09861228866811
  319. # imaginary part also close to zero
  320. s = '1.07530466271334 - 0.0251200594793912*I'
  321. assert sstr(p.evalf(r, method='Euler')[-1]) == s
  322. # sin(x)
  323. p = HolonomicFunction(Dx**2 + 1, x, 0, [0, 1])
  324. s = '0.905546532085401 - 6.93889390390723e-18*I'
  325. assert sstr(p.evalf(r, method='Euler')[-1]) == s
  326. # computing sin(pi/2) using this method
  327. # using a linear path from 0 to pi/2
  328. r = [0.1]
  329. for i in range(14):
  330. r.append(r[-1] + 0.1)
  331. r.append(pi/2)
  332. s = '1.08016557252834' # close to 1.0 (exact solution)
  333. assert sstr(p.evalf(r, method='Euler')[-1]) == s
  334. # trying different path, a rectangle (0-->i-->pi/2 + i-->pi/2)
  335. # computing the same value sin(pi/2) using different path
  336. r = [0.1*I]
  337. for i in range(9):
  338. r.append(r[-1]+0.1*I)
  339. for i in range(15):
  340. r.append(r[-1]+0.1)
  341. r.append(pi/2+I)
  342. for i in range(10):
  343. r.append(r[-1]-0.1*I)
  344. # close to 1.0
  345. s = '0.976882381836257 - 1.65557671738537e-16*I'
  346. assert sstr(p.evalf(r, method='Euler')[-1]) == s
  347. # cos(x)
  348. p = HolonomicFunction(Dx**2 + 1, x, 0, [1, 0])
  349. # compute cos(pi) along 0-->pi
  350. r = [0.05]
  351. for i in range(61):
  352. r.append(r[-1]+0.05)
  353. r.append(pi)
  354. # close to -1 (exact answer)
  355. s = '-1.08140824719196'
  356. assert sstr(p.evalf(r, method='Euler')[-1]) == s
  357. # a rectangular path (0 -> i -> 2+i -> 2)
  358. r = [0.1*I]
  359. for i in range(9):
  360. r.append(r[-1]+0.1*I)
  361. for i in range(20):
  362. r.append(r[-1]+0.1)
  363. for i in range(10):
  364. r.append(r[-1]-0.1*I)
  365. p = HolonomicFunction(Dx**2 + 1, x, 0, [1,1]).evalf(r, method='Euler')
  366. s = '0.501421652861245 - 3.88578058618805e-16*I'
  367. assert sstr(p[-1]) == s
  368. def test_evalf_rk4():
  369. x = symbols('x')
  370. R, Dx = DifferentialOperators(QQ.old_poly_ring(x), 'Dx')
  371. # log(1+x)
  372. p = HolonomicFunction((1 + x)*Dx**2 + Dx, x, 0, [0, 1])
  373. # path taken is a straight line from 0 to 1, on the real axis
  374. r = [0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9, 1]
  375. s = '0.693146363174626' # approx. equal to log(2) i.e. 0.693147180559945
  376. assert sstr(p.evalf(r)[-1]) == s
  377. # path taken is a triangle 0-->1+i-->2
  378. r = [0.1 + 0.1*I]
  379. for i in range(9):
  380. r.append(r[-1]+0.1+0.1*I)
  381. for i in range(10):
  382. r.append(r[-1]+0.1-0.1*I)
  383. # close to the exact solution 1.09861228866811
  384. # imaginary part also close to zero
  385. s = '1.098616 + 1.36083e-7*I'
  386. assert sstr(p.evalf(r)[-1].n(7)) == s
  387. # sin(x)
  388. p = HolonomicFunction(Dx**2 + 1, x, 0, [0, 1])
  389. s = '0.90929463522785 + 1.52655665885959e-16*I'
  390. assert sstr(p.evalf(r)[-1]) == s
  391. # computing sin(pi/2) using this method
  392. # using a linear path from 0 to pi/2
  393. r = [0.1]
  394. for i in range(14):
  395. r.append(r[-1] + 0.1)
  396. r.append(pi/2)
  397. s = '0.999999895088917' # close to 1.0 (exact solution)
  398. assert sstr(p.evalf(r)[-1]) == s
  399. # trying different path, a rectangle (0-->i-->pi/2 + i-->pi/2)
  400. # computing the same value sin(pi/2) using different path
  401. r = [0.1*I]
  402. for i in range(9):
  403. r.append(r[-1]+0.1*I)
  404. for i in range(15):
  405. r.append(r[-1]+0.1)
  406. r.append(pi/2+I)
  407. for i in range(10):
  408. r.append(r[-1]-0.1*I)
  409. # close to 1.0
  410. s = '1.00000003415141 + 6.11940487991086e-16*I'
  411. assert sstr(p.evalf(r)[-1]) == s
  412. # cos(x)
  413. p = HolonomicFunction(Dx**2 + 1, x, 0, [1, 0])
  414. # compute cos(pi) along 0-->pi
  415. r = [0.05]
  416. for i in range(61):
  417. r.append(r[-1]+0.05)
  418. r.append(pi)
  419. # close to -1 (exact answer)
  420. s = '-0.999999993238714'
  421. assert sstr(p.evalf(r)[-1]) == s
  422. # a rectangular path (0 -> i -> 2+i -> 2)
  423. r = [0.1*I]
  424. for i in range(9):
  425. r.append(r[-1]+0.1*I)
  426. for i in range(20):
  427. r.append(r[-1]+0.1)
  428. for i in range(10):
  429. r.append(r[-1]-0.1*I)
  430. p = HolonomicFunction(Dx**2 + 1, x, 0, [1,1]).evalf(r)
  431. s = '0.493152791638442 - 1.41553435639707e-15*I'
  432. assert sstr(p[-1]) == s
  433. def test_expr_to_holonomic():
  434. x = symbols('x')
  435. R, Dx = DifferentialOperators(QQ.old_poly_ring(x), 'Dx')
  436. p = expr_to_holonomic((sin(x)/x)**2)
  437. q = HolonomicFunction(8*x + (4*x**2 + 6)*Dx + 6*x*Dx**2 + x**2*Dx**3, x, 0, \
  438. [1, 0, Rational(-2, 3)])
  439. assert p == q
  440. p = expr_to_holonomic(1/(1+x**2)**2)
  441. q = HolonomicFunction(4*x + (x**2 + 1)*Dx, x, 0, [1])
  442. assert p == q
  443. p = expr_to_holonomic(exp(x)*sin(x)+x*log(1+x))
  444. q = HolonomicFunction((2*x**3 + 10*x**2 + 20*x + 18) + (-2*x**4 - 10*x**3 - 20*x**2 \
  445. - 18*x)*Dx + (2*x**5 + 6*x**4 + 7*x**3 + 8*x**2 + 10*x - 4)*Dx**2 + \
  446. (-2*x**5 - 5*x**4 - 2*x**3 + 2*x**2 - x + 4)*Dx**3 + (x**5 + 2*x**4 - x**3 - \
  447. 7*x**2/2 + x + Rational(5, 2))*Dx**4, x, 0, [0, 1, 4, -1])
  448. assert p == q
  449. p = expr_to_holonomic(x*exp(x)+cos(x)+1)
  450. q = HolonomicFunction((-x - 3)*Dx + (x + 2)*Dx**2 + (-x - 3)*Dx**3 + (x + 2)*Dx**4, x, \
  451. 0, [2, 1, 1, 3])
  452. assert p == q
  453. assert (x*exp(x)+cos(x)+1).series(n=10) == p.series(n=10)
  454. p = expr_to_holonomic(log(1 + x)**2 + 1)
  455. q = HolonomicFunction(Dx + (3*x + 3)*Dx**2 + (x**2 + 2*x + 1)*Dx**3, x, 0, [1, 0, 2])
  456. assert p == q
  457. p = expr_to_holonomic(erf(x)**2 + x)
  458. q = HolonomicFunction((8*x**4 - 2*x**2 + 2)*Dx**2 + (6*x**3 - x/2)*Dx**3 + \
  459. (x**2+ Rational(1, 4))*Dx**4, x, 0, [0, 1, 8/pi, 0])
  460. assert p == q
  461. p = expr_to_holonomic(cosh(x)*x)
  462. q = HolonomicFunction((-x**2 + 2) -2*x*Dx + x**2*Dx**2, x, 0, [0, 1])
  463. assert p == q
  464. p = expr_to_holonomic(besselj(2, x))
  465. q = HolonomicFunction((x**2 - 4) + x*Dx + x**2*Dx**2, x, 0, [0, 0])
  466. assert p == q
  467. p = expr_to_holonomic(besselj(0, x) + exp(x))
  468. q = HolonomicFunction((-x**2 - x/2 + S.Half) + (x**2 - x/2 - Rational(3, 2))*Dx + (-x**2 + x/2 + 1)*Dx**2 +\
  469. (x**2 + x/2)*Dx**3, x, 0, [2, 1, S.Half])
  470. assert p == q
  471. p = expr_to_holonomic(sin(x)**2/x)
  472. q = HolonomicFunction(4 + 4*x*Dx + 3*Dx**2 + x*Dx**3, x, 0, [0, 1, 0])
  473. assert p == q
  474. p = expr_to_holonomic(sin(x)**2/x, x0=2)
  475. q = HolonomicFunction((4) + (4*x)*Dx + (3)*Dx**2 + (x)*Dx**3, x, 2, [sin(2)**2/2,
  476. sin(2)*cos(2) - sin(2)**2/4, -3*sin(2)**2/4 + cos(2)**2 - sin(2)*cos(2)])
  477. assert p == q
  478. p = expr_to_holonomic(log(x)/2 - Ci(2*x)/2 + Ci(2)/2)
  479. q = HolonomicFunction(4*Dx + 4*x*Dx**2 + 3*Dx**3 + x*Dx**4, x, 0, \
  480. [-log(2)/2 - EulerGamma/2 + Ci(2)/2, 0, 1, 0])
  481. assert p == q
  482. p = p.to_expr()
  483. q = log(x)/2 - Ci(2*x)/2 + Ci(2)/2
  484. assert p == q
  485. p = expr_to_holonomic(x**S.Half, x0=1)
  486. q = HolonomicFunction(x*Dx - S.Half, x, 1, [1])
  487. assert p == q
  488. p = expr_to_holonomic(sqrt(1 + x**2))
  489. q = HolonomicFunction((-x) + (x**2 + 1)*Dx, x, 0, [1])
  490. assert p == q
  491. assert (expr_to_holonomic(sqrt(x) + sqrt(2*x)).to_expr()-\
  492. (sqrt(x) + sqrt(2*x))).simplify() == 0
  493. assert expr_to_holonomic(3*x+2*sqrt(x)).to_expr() == 3*x+2*sqrt(x)
  494. p = expr_to_holonomic((x**4+x**3+5*x**2+3*x+2)/x**2, lenics=3)
  495. q = HolonomicFunction((-2*x**4 - x**3 + 3*x + 4) + (x**5 + x**4 + 5*x**3 + 3*x**2 + \
  496. 2*x)*Dx, x, 0, {-2: [2, 3, 5]})
  497. assert p == q
  498. p = expr_to_holonomic(1/(x-1)**2, lenics=3, x0=1)
  499. q = HolonomicFunction((2) + (x - 1)*Dx, x, 1, {-2: [1, 0, 0]})
  500. assert p == q
  501. a = symbols("a")
  502. p = expr_to_holonomic(sqrt(a*x), x=x)
  503. assert p.to_expr() == sqrt(a)*sqrt(x)
  504. def test_to_hyper():
  505. x = symbols('x')
  506. R, Dx = DifferentialOperators(QQ.old_poly_ring(x), 'Dx')
  507. p = HolonomicFunction(Dx - 2, x, 0, [3]).to_hyper()
  508. q = 3 * hyper([], [], 2*x)
  509. assert p == q
  510. p = hyperexpand(HolonomicFunction((1 + x) * Dx - 3, x, 0, [2]).to_hyper()).expand()
  511. q = 2*x**3 + 6*x**2 + 6*x + 2
  512. assert p == q
  513. p = HolonomicFunction((1 + x)*Dx**2 + Dx, x, 0, [0, 1]).to_hyper()
  514. q = -x**2*hyper((2, 2, 1), (3, 2), -x)/2 + x
  515. assert p == q
  516. p = HolonomicFunction(2*x*Dx + Dx**2, x, 0, [0, 2/sqrt(pi)]).to_hyper()
  517. q = 2*x*hyper((S.Half,), (Rational(3, 2),), -x**2)/sqrt(pi)
  518. assert p == q
  519. p = hyperexpand(HolonomicFunction(2*x*Dx + Dx**2, x, 0, [1, -2/sqrt(pi)]).to_hyper())
  520. q = erfc(x)
  521. assert p.rewrite(erfc) == q
  522. p = hyperexpand(HolonomicFunction((x**2 - 1) + x*Dx + x**2*Dx**2,
  523. x, 0, [0, S.Half]).to_hyper())
  524. q = besselj(1, x)
  525. assert p == q
  526. p = hyperexpand(HolonomicFunction(x*Dx**2 + Dx + x, x, 0, [1, 0]).to_hyper())
  527. q = besselj(0, x)
  528. assert p == q
  529. def test_to_expr():
  530. x = symbols('x')
  531. R, Dx = DifferentialOperators(ZZ.old_poly_ring(x), 'Dx')
  532. p = HolonomicFunction(Dx - 1, x, 0, [1]).to_expr()
  533. q = exp(x)
  534. assert p == q
  535. p = HolonomicFunction(Dx**2 + 1, x, 0, [1, 0]).to_expr()
  536. q = cos(x)
  537. assert p == q
  538. p = HolonomicFunction(Dx**2 - 1, x, 0, [1, 0]).to_expr()
  539. q = cosh(x)
  540. assert p == q
  541. p = HolonomicFunction(2 + (4*x - 1)*Dx + \
  542. (x**2 - x)*Dx**2, x, 0, [1, 2]).to_expr().expand()
  543. q = 1/(x**2 - 2*x + 1)
  544. assert p == q
  545. p = expr_to_holonomic(sin(x)**2/x).integrate((x, 0, x)).to_expr()
  546. q = (sin(x)**2/x).integrate((x, 0, x))
  547. assert p == q
  548. C_0, C_1, C_2, C_3 = symbols('C_0, C_1, C_2, C_3')
  549. p = expr_to_holonomic(log(1+x**2)).to_expr()
  550. q = C_2*log(x**2 + 1)
  551. assert p == q
  552. p = expr_to_holonomic(log(1+x**2)).diff().to_expr()
  553. q = C_0*x/(x**2 + 1)
  554. assert p == q
  555. p = expr_to_holonomic(erf(x) + x).to_expr()
  556. q = 3*C_3*x - 3*sqrt(pi)*C_3*erf(x)/2 + x + 2*x/sqrt(pi)
  557. assert p == q
  558. p = expr_to_holonomic(sqrt(x), x0=1).to_expr()
  559. assert p == sqrt(x)
  560. assert expr_to_holonomic(sqrt(x)).to_expr() == sqrt(x)
  561. p = expr_to_holonomic(sqrt(1 + x**2)).to_expr()
  562. assert p == sqrt(1+x**2)
  563. p = expr_to_holonomic((2*x**2 + 1)**Rational(2, 3)).to_expr()
  564. assert p == (2*x**2 + 1)**Rational(2, 3)
  565. p = expr_to_holonomic(sqrt(-x**2+2*x)).to_expr()
  566. assert p == sqrt(x)*sqrt(-x + 2)
  567. p = expr_to_holonomic((-2*x**3+7*x)**Rational(2, 3)).to_expr()
  568. q = x**Rational(2, 3)*(-2*x**2 + 7)**Rational(2, 3)
  569. assert p == q
  570. p = from_hyper(hyper((-2, -3), (S.Half, ), x))
  571. s = hyperexpand(hyper((-2, -3), (S.Half, ), x))
  572. D_0 = Symbol('D_0')
  573. C_0 = Symbol('C_0')
  574. assert (p.to_expr().subs({C_0:1, D_0:0}) - s).simplify() == 0
  575. p.y0 = {0: [1], S.Half: [0]}
  576. assert p.to_expr() == s
  577. assert expr_to_holonomic(x**5).to_expr() == x**5
  578. assert expr_to_holonomic(2*x**3-3*x**2).to_expr().expand() == \
  579. 2*x**3-3*x**2
  580. a = symbols("a")
  581. p = (expr_to_holonomic(1.4*x)*expr_to_holonomic(a*x, x)).to_expr()
  582. q = 1.4*a*x**2
  583. assert p == q
  584. p = (expr_to_holonomic(1.4*x)+expr_to_holonomic(a*x, x)).to_expr()
  585. q = x*(a + 1.4)
  586. assert p == q
  587. p = (expr_to_holonomic(1.4*x)+expr_to_holonomic(x)).to_expr()
  588. assert p == 2.4*x
  589. def test_integrate():
  590. x = symbols('x')
  591. R, Dx = DifferentialOperators(ZZ.old_poly_ring(x), 'Dx')
  592. p = expr_to_holonomic(sin(x)**2/x, x0=1).integrate((x, 2, 3))
  593. q = '0.166270406994788'
  594. assert sstr(p) == q
  595. p = expr_to_holonomic(sin(x)).integrate((x, 0, x)).to_expr()
  596. q = 1 - cos(x)
  597. assert p == q
  598. p = expr_to_holonomic(sin(x)).integrate((x, 0, 3))
  599. q = 1 - cos(3)
  600. assert p == q
  601. p = expr_to_holonomic(sin(x)/x, x0=1).integrate((x, 1, 2))
  602. q = '0.659329913368450'
  603. assert sstr(p) == q
  604. p = expr_to_holonomic(sin(x)**2/x, x0=1).integrate((x, 1, 0))
  605. q = '-0.423690480850035'
  606. assert sstr(p) == q
  607. p = expr_to_holonomic(sin(x)/x)
  608. assert p.integrate(x).to_expr() == Si(x)
  609. assert p.integrate((x, 0, 2)) == Si(2)
  610. p = expr_to_holonomic(sin(x)**2/x)
  611. q = p.to_expr()
  612. assert p.integrate(x).to_expr() == q.integrate((x, 0, x))
  613. assert p.integrate((x, 0, 1)) == q.integrate((x, 0, 1))
  614. assert expr_to_holonomic(1/x, x0=1).integrate(x).to_expr() == log(x)
  615. p = expr_to_holonomic((x + 1)**3*exp(-x), x0=-1).integrate(x).to_expr()
  616. q = (-x**3 - 6*x**2 - 15*x + 6*exp(x + 1) - 16)*exp(-x)
  617. assert p == q
  618. p = expr_to_holonomic(cos(x)**2/x**2, y0={-2: [1, 0, -1]}).integrate(x).to_expr()
  619. q = -Si(2*x) - cos(x)**2/x
  620. assert p == q
  621. p = expr_to_holonomic(sqrt(x**2+x)).integrate(x).to_expr()
  622. q = (x**Rational(3, 2)*(2*x**2 + 3*x + 1) - x*sqrt(x + 1)*asinh(sqrt(x)))/(4*x*sqrt(x + 1))
  623. assert p == q
  624. p = expr_to_holonomic(sqrt(x**2+1)).integrate(x).to_expr()
  625. q = (sqrt(x**2+1)).integrate(x)
  626. assert (p-q).simplify() == 0
  627. p = expr_to_holonomic(1/x**2, y0={-2:[1, 0, 0]})
  628. r = expr_to_holonomic(1/x**2, lenics=3)
  629. assert p == r
  630. q = expr_to_holonomic(cos(x)**2)
  631. assert (r*q).integrate(x).to_expr() == -Si(2*x) - cos(x)**2/x
  632. def test_diff():
  633. x, y = symbols('x, y')
  634. R, Dx = DifferentialOperators(ZZ.old_poly_ring(x), 'Dx')
  635. p = HolonomicFunction(x*Dx**2 + 1, x, 0, [0, 1])
  636. assert p.diff().to_expr() == p.to_expr().diff().simplify()
  637. p = HolonomicFunction(Dx**2 - 1, x, 0, [1, 0])
  638. assert p.diff(x, 2).to_expr() == p.to_expr()
  639. p = expr_to_holonomic(Si(x))
  640. assert p.diff().to_expr() == sin(x)/x
  641. assert p.diff(y) == 0
  642. C_0, C_1, C_2, C_3 = symbols('C_0, C_1, C_2, C_3')
  643. q = Si(x)
  644. assert p.diff(x).to_expr() == q.diff()
  645. assert p.diff(x, 2).to_expr().subs(C_0, Rational(-1, 3)).cancel() == q.diff(x, 2).cancel()
  646. assert p.diff(x, 3).series().subs({C_3: Rational(-1, 3), C_0: 0}) == q.diff(x, 3).series()
  647. def test_extended_domain_in_expr_to_holonomic():
  648. x = symbols('x')
  649. p = expr_to_holonomic(1.2*cos(3.1*x))
  650. assert p.to_expr() == 1.2*cos(3.1*x)
  651. assert sstr(p.integrate(x).to_expr()) == '0.387096774193548*sin(3.1*x)'
  652. _, Dx = DifferentialOperators(RR.old_poly_ring(x), 'Dx')
  653. p = expr_to_holonomic(1.1329138213*x)
  654. q = HolonomicFunction((-1.1329138213) + (1.1329138213*x)*Dx, x, 0, {1: [1.1329138213]})
  655. assert p == q
  656. assert p.to_expr() == 1.1329138213*x
  657. assert sstr(p.integrate((x, 1, 2))) == sstr((1.1329138213*x).integrate((x, 1, 2)))
  658. y, z = symbols('y, z')
  659. p = expr_to_holonomic(sin(x*y*z), x=x)
  660. assert p.to_expr() == sin(x*y*z)
  661. assert p.integrate(x).to_expr() == (-cos(x*y*z) + 1)/(y*z)
  662. p = expr_to_holonomic(sin(x*y + z), x=x).integrate(x).to_expr()
  663. q = (cos(z) - cos(x*y + z))/y
  664. assert p == q
  665. a = symbols('a')
  666. p = expr_to_holonomic(a*x, x)
  667. assert p.to_expr() == a*x
  668. assert p.integrate(x).to_expr() == a*x**2/2
  669. D_2, C_1 = symbols("D_2, C_1")
  670. p = expr_to_holonomic(x) + expr_to_holonomic(1.2*cos(x))
  671. p = p.to_expr().subs(D_2, 0)
  672. assert p - x - 1.2*cos(1.0*x) == 0
  673. p = expr_to_holonomic(x) * expr_to_holonomic(1.2*cos(x))
  674. p = p.to_expr().subs(C_1, 0)
  675. assert p - 1.2*x*cos(1.0*x) == 0
  676. def test_to_meijerg():
  677. x = symbols('x')
  678. assert hyperexpand(expr_to_holonomic(sin(x)).to_meijerg()) == sin(x)
  679. assert hyperexpand(expr_to_holonomic(cos(x)).to_meijerg()) == cos(x)
  680. assert hyperexpand(expr_to_holonomic(exp(x)).to_meijerg()) == exp(x)
  681. assert hyperexpand(expr_to_holonomic(log(x)).to_meijerg()).simplify() == log(x)
  682. assert expr_to_holonomic(4*x**2/3 + 7).to_meijerg() == 4*x**2/3 + 7
  683. assert hyperexpand(expr_to_holonomic(besselj(2, x), lenics=3).to_meijerg()) == besselj(2, x)
  684. p = hyper((Rational(-1, 2), -3), (), x)
  685. assert from_hyper(p).to_meijerg() == hyperexpand(p)
  686. p = hyper((S.One, S(3)), (S(2), ), x)
  687. assert (hyperexpand(from_hyper(p).to_meijerg()) - hyperexpand(p)).expand() == 0
  688. p = from_hyper(hyper((-2, -3), (S.Half, ), x))
  689. s = hyperexpand(hyper((-2, -3), (S.Half, ), x))
  690. C_0 = Symbol('C_0')
  691. C_1 = Symbol('C_1')
  692. D_0 = Symbol('D_0')
  693. assert (hyperexpand(p.to_meijerg()).subs({C_0:1, D_0:0}) - s).simplify() == 0
  694. p.y0 = {0: [1], S.Half: [0]}
  695. assert (hyperexpand(p.to_meijerg()) - s).simplify() == 0
  696. p = expr_to_holonomic(besselj(S.Half, x), initcond=False)
  697. assert (p.to_expr() - (D_0*sin(x) + C_0*cos(x) + C_1*sin(x))/sqrt(x)).simplify() == 0
  698. p = expr_to_holonomic(besselj(S.Half, x), y0={Rational(-1, 2): [sqrt(2)/sqrt(pi), sqrt(2)/sqrt(pi)]})
  699. assert (p.to_expr() - besselj(S.Half, x) - besselj(Rational(-1, 2), x)).simplify() == 0
  700. def test_gaussian():
  701. mu, x = symbols("mu x")
  702. sd = symbols("sd", positive=True)
  703. Q = QQ[mu, sd].get_field()
  704. e = sqrt(2)*exp(-(-mu + x)**2/(2*sd**2))/(2*sqrt(pi)*sd)
  705. h1 = expr_to_holonomic(e, x, domain=Q)
  706. _, Dx = DifferentialOperators(Q.old_poly_ring(x), 'Dx')
  707. h2 = HolonomicFunction((-mu/sd**2 + x/sd**2) + (1)*Dx, x)
  708. assert h1 == h2
  709. def test_beta():
  710. a, b, x = symbols("a b x", positive=True)
  711. e = x**(a - 1)*(-x + 1)**(b - 1)/beta(a, b)
  712. Q = QQ[a, b].get_field()
  713. h1 = expr_to_holonomic(e, x, domain=Q)
  714. _, Dx = DifferentialOperators(Q.old_poly_ring(x), 'Dx')
  715. h2 = HolonomicFunction((a + x*(-a - b + 2) - 1) + (x**2 - x)*Dx, x)
  716. assert h1 == h2
  717. def test_gamma():
  718. a, b, x = symbols("a b x", positive=True)
  719. e = b**(-a)*x**(a - 1)*exp(-x/b)/gamma(a)
  720. Q = QQ[a, b].get_field()
  721. h1 = expr_to_holonomic(e, x, domain=Q)
  722. _, Dx = DifferentialOperators(Q.old_poly_ring(x), 'Dx')
  723. h2 = HolonomicFunction((-a + 1 + x/b) + (x)*Dx, x)
  724. assert h1 == h2
  725. def test_symbolic_power():
  726. x, n = symbols("x n")
  727. Q = QQ[n].get_field()
  728. _, Dx = DifferentialOperators(Q.old_poly_ring(x), 'Dx')
  729. h1 = HolonomicFunction((-1) + (x)*Dx, x) ** -n
  730. h2 = HolonomicFunction((n) + (x)*Dx, x)
  731. assert h1 == h2
  732. def test_negative_power():
  733. x = symbols("x")
  734. _, Dx = DifferentialOperators(QQ.old_poly_ring(x), 'Dx')
  735. h1 = HolonomicFunction((-1) + (x)*Dx, x) ** -2
  736. h2 = HolonomicFunction((2) + (x)*Dx, x)
  737. assert h1 == h2
  738. def test_expr_in_power():
  739. x, n = symbols("x n")
  740. Q = QQ[n].get_field()
  741. _, Dx = DifferentialOperators(Q.old_poly_ring(x), 'Dx')
  742. h1 = HolonomicFunction((-1) + (x)*Dx, x) ** (n - 3)
  743. h2 = HolonomicFunction((-n + 3) + (x)*Dx, x)
  744. assert h1 == h2
  745. def test_DifferentialOperatorEqPoly():
  746. x = symbols('x', integer=True)
  747. R, Dx = DifferentialOperators(QQ.old_poly_ring(x), 'Dx')
  748. do = DifferentialOperator([x**2, R.base.zero, R.base.zero], R)
  749. do2 = DifferentialOperator([x**2, 1, x], R)
  750. assert not do == do2
  751. # polynomial comparison issue, see https://github.com/sympy/sympy/pull/15799
  752. # should work once that is solved
  753. # p = do.listofpoly[0]
  754. # assert do == p
  755. p2 = do2.listofpoly[0]
  756. assert not do2 == p2
  757. def test_DifferentialOperatorPow():
  758. x = symbols('x', integer=True)
  759. R, _ = DifferentialOperators(QQ.old_poly_ring(x), 'Dx')
  760. do = DifferentialOperator([x**2, R.base.zero, R.base.zero], R)
  761. a = DifferentialOperator([R.base.one], R)
  762. for n in range(10):
  763. assert a == do**n
  764. a *= do