_pade.py 1.8 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667
  1. from numpy import zeros, asarray, eye, poly1d, hstack, r_
  2. from scipy import linalg
  3. __all__ = ["pade"]
  4. def pade(an, m, n=None):
  5. """
  6. Return Pade approximation to a polynomial as the ratio of two polynomials.
  7. Parameters
  8. ----------
  9. an : (N,) array_like
  10. Taylor series coefficients.
  11. m : int
  12. The order of the returned approximating polynomial `q`.
  13. n : int, optional
  14. The order of the returned approximating polynomial `p`. By default,
  15. the order is ``len(an)-1-m``.
  16. Returns
  17. -------
  18. p, q : Polynomial class
  19. The Pade approximation of the polynomial defined by `an` is
  20. ``p(x)/q(x)``.
  21. Examples
  22. --------
  23. >>> import numpy as np
  24. >>> from scipy.interpolate import pade
  25. >>> e_exp = [1.0, 1.0, 1.0/2.0, 1.0/6.0, 1.0/24.0, 1.0/120.0]
  26. >>> p, q = pade(e_exp, 2)
  27. >>> e_exp.reverse()
  28. >>> e_poly = np.poly1d(e_exp)
  29. Compare ``e_poly(x)`` and the Pade approximation ``p(x)/q(x)``
  30. >>> e_poly(1)
  31. 2.7166666666666668
  32. >>> p(1)/q(1)
  33. 2.7179487179487181
  34. """
  35. an = asarray(an)
  36. if n is None:
  37. n = len(an) - 1 - m
  38. if n < 0:
  39. raise ValueError("Order of q <m> must be smaller than len(an)-1.")
  40. if n < 0:
  41. raise ValueError("Order of p <n> must be greater than 0.")
  42. N = m + n
  43. if N > len(an)-1:
  44. raise ValueError("Order of q+p <m+n> must be smaller than len(an).")
  45. an = an[:N+1]
  46. Akj = eye(N+1, n+1, dtype=an.dtype)
  47. Bkj = zeros((N+1, m), dtype=an.dtype)
  48. for row in range(1, m+1):
  49. Bkj[row,:row] = -(an[:row])[::-1]
  50. for row in range(m+1, N+1):
  51. Bkj[row,:] = -(an[row-m:row])[::-1]
  52. C = hstack((Akj, Bkj))
  53. pq = linalg.solve(C, an)
  54. p = pq[:n+1]
  55. q = r_[1.0, pq[n+1:]]
  56. return poly1d(p[::-1]), poly1d(q[::-1])