approximants.py 3.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104
  1. from sympy.core.singleton import S
  2. from sympy.core.symbol import Symbol
  3. from sympy.utilities import public
  4. @public
  5. def approximants(l, X=Symbol('x'), simplify=False):
  6. """
  7. Return a generator for consecutive Pade approximants for a series.
  8. It can also be used for computing the rational generating function of a
  9. series when possible, since the last approximant returned by the generator
  10. will be the generating function (if any).
  11. Explanation
  12. ===========
  13. The input list can contain more complex expressions than integer or rational
  14. numbers; symbols may also be involved in the computation. An example below
  15. show how to compute the generating function of the whole Pascal triangle.
  16. The generator can be asked to apply the sympy.simplify function on each
  17. generated term, which will make the computation slower; however it may be
  18. useful when symbols are involved in the expressions.
  19. Examples
  20. ========
  21. >>> from sympy.series import approximants
  22. >>> from sympy import lucas, fibonacci, symbols, binomial
  23. >>> g = [lucas(k) for k in range(16)]
  24. >>> [e for e in approximants(g)]
  25. [2, -4/(x - 2), (5*x - 2)/(3*x - 1), (x - 2)/(x**2 + x - 1)]
  26. >>> h = [fibonacci(k) for k in range(16)]
  27. >>> [e for e in approximants(h)]
  28. [x, -x/(x - 1), (x**2 - x)/(2*x - 1), -x/(x**2 + x - 1)]
  29. >>> x, t = symbols("x,t")
  30. >>> p=[sum(binomial(k,i)*x**i for i in range(k+1)) for k in range(16)]
  31. >>> y = approximants(p, t)
  32. >>> for k in range(3): print(next(y))
  33. 1
  34. (x + 1)/((-x - 1)*(t*(x + 1) + (x + 1)/(-x - 1)))
  35. nan
  36. >>> y = approximants(p, t, simplify=True)
  37. >>> for k in range(3): print(next(y))
  38. 1
  39. -1/(t*(x + 1) - 1)
  40. nan
  41. See Also
  42. ========
  43. See function sympy.concrete.guess.guess_generating_function_rational and
  44. function mpmath.pade
  45. """
  46. p1, q1 = [S.One], [S.Zero]
  47. p2, q2 = [S.Zero], [S.One]
  48. while len(l):
  49. b = 0
  50. while l[b]==0:
  51. b += 1
  52. if b == len(l):
  53. return
  54. m = [S.One/l[b]]
  55. for k in range(b+1, len(l)):
  56. s = 0
  57. for j in range(b, k):
  58. s -= l[j+1] * m[b-j-1]
  59. m.append(s/l[b])
  60. l = m
  61. a, l[0] = l[0], 0
  62. p = [0] * max(len(p2), b+len(p1))
  63. q = [0] * max(len(q2), b+len(q1))
  64. for k in range(len(p2)):
  65. p[k] = a*p2[k]
  66. for k in range(b, b+len(p1)):
  67. p[k] += p1[k-b]
  68. for k in range(len(q2)):
  69. q[k] = a*q2[k]
  70. for k in range(b, b+len(q1)):
  71. q[k] += q1[k-b]
  72. while p[-1]==0: p.pop()
  73. while q[-1]==0: q.pop()
  74. p1, p2 = p2, p
  75. q1, q2 = q2, q
  76. # yield result
  77. from sympy.polys.polytools import lcm
  78. from sympy.simplify import simplify as simp
  79. from sympy.simplify.radsimp import denom
  80. c = 1
  81. for x in p:
  82. c = lcm(c, denom(x))
  83. for x in q:
  84. c = lcm(c, denom(x))
  85. out = ( sum(c*e*X**k for k, e in enumerate(p))
  86. / sum(c*e*X**k for k, e in enumerate(q)) )
  87. if simplify:
  88. yield(simp(out))
  89. else:
  90. yield out
  91. return