Power Series Methods - Power Series Rings and Laurent Series Rings

Skip to content
Back to top
View this page
Edit this page

# Power Series Methods

The class `PowerSeries_poly` provides additional methods for univariate power series.

class sage.rings.power_series_poly.BaseRingFloorDivAction

  Bases: `Action`

  The floor division action of the base ring on a formal power series.

class sage.rings.power_series_poly.PowerSeries_poly

  Bases: `PowerSeries`

  EXAMPLES:

  Sage

      sage: R.<q> = PowerSeriesRing(CC); R                                        # needs sage.rings.real_mpfr
      Power Series Ring in q over Complex Field with 53 bits of precision
      sage: loads(q.dumps()) == q                                                 # needs sage.rings.real_mpfr
      True

      sage: R.<t> = QQ[[]]
      sage: f = 3 - t^3 + O(t^5)
      sage: a = f^3; a
      27 - 27*t^3 + O(t^5)
      sage: b = f^-3; b
      1/27 + 1/27*t^3 + O(t^5)
      sage: a*b
      1 + O(t^5)

  Python

      >>> from sage.all import *
      >>> R = PowerSeriesRing(CC, names=('q',)); (q,) = R._first_ngens(1); R                                        # needs sage.rings.real_mpfr
      Power Series Ring in q over Complex Field with 53 bits of precision
      >>> loads(q.dumps()) == q                                                 # needs sage.rings.real_mpfr
      True

      >>> R = QQ[['t']]; (t,) = R._first_ngens(1)
      >>> f = Integer(3) - t**Integer(3) + O(t**Integer(5))
      >>> a = f**Integer(3); a
      27 - 27*t^3 + O(t^5)
      >>> b = f**-Integer(3); b
      1/27 + 1/27*t^3 + O(t^5)
      >>> a*b
      1 + O(t^5)

  Check that Issue #22216 is fixed:

  Sage

      sage: R.<T> = PowerSeriesRing(QQ)
      sage: R(pari('1 + O(T)'))                                                   # needs sage.libs.pari
      1 + O(T)
      sage: R(pari('1/T + O(T)'))                                                 # needs sage.libs.pari
      Traceback (most recent call last):
      ...
      ValueError: series has negative valuation

  [Python]

      >>> from sage.all import *
      >>> R = PowerSeriesRing(QQ, names=('T',)); (T,) = R._first_ngens(1)
      >>> R(pari('1 + O(T)'))                                                   # needs sage.libs.pari
      1 + O(T)
      >>> R(pari('1/T + O(T)'))                                                 # needs sage.libs.pari
      Traceback (most recent call last):
      ...
      ValueError: series has negative valuation

  degree()

    Return the degree of the underlying polynomial of `self`.

    That is, if `self` is of the form \(f(x) + O(x^n)\), we return the degree of \(f(x)\). Note that if \(f(x)\) is \(0\), we return \(-1\), just as with polynomials.

    EXAMPLES:

    Sage

        sage: R.<t> = ZZ[[]]
        sage: (5 + t^3 + O(t^4)).degree()
        3
        sage: (5 + O(t^4)).degree()
        0
        sage: O(t^4).degree()
        -1

    Python

        >>> from sage.all import *
        >>> R = ZZ[['t']]; (t,) = R._first_ngens(1)
        >>> (Integer(5) + t**Integer(3) + O(t**Integer(4))).degree()
        3
        >>> (Integer(5) + O(t**Integer(4))).degree()
        0
        >>> O(t**Integer(4)).degree()
        -1

  dict(copy=True)

    alias of `monomial_coefficients()`.

  integral(var=None)

    Return the integral of this power series.

    By default, the integration variable is the variable of the power series.

    Otherwise, the integration variable is the optional parameter `var`.

    Note

    The integral is always chosen so the constant term is 0.

    EXAMPLES:

    Sage

        sage: k.<w> = QQ[[]]
        sage: (1+17*w+15*w^3+O(w^5)).integral()
        w + 17/2*w^2 + 15/4*w^4 + O(w^6)
        sage: (w^3 + 4*w^4 + O(w^7)).integral()
        1/4*w^4 + 4/5*w^5 + O(w^8)
        sage: (3*w^2).integral()
        w^3

    Python

        >>> from sage.all import *
        >>> k = QQ[['w']]; (w,) = k._first_ngens(1)
        >>> (Integer(1)+Integer(17)*w+Integer(15)*w**Integer(3)+O(w**Integer(5))).integral()
        w + 17/2*w^2 + 15/4*w^4 + O(w^6)
        >>> (w**Integer(3) + Integer(4)*w**Integer(4) + O(w**Integer(7))).integral()
        1/4*w^4 + 4/5*w^5 + O(w^8)
        >>> (Integer(3)*w**Integer(2)).integral()
        w^3

  list()

    Return the list of known coefficients for `self`.

    This is just the list of coefficients of the underlying polynomial, so in particular, need not have length equal to `self.prec()`.

    EXAMPLES:

    Sage

        sage: R.<t> = ZZ[[]]
        sage: f = 1 - 5*t^3 + t^5 + O(t^7)
        sage: f.list()
        [1, 0, 0, -5, 0, 1]

    Python

        >>> from sage.all import *
        >>> R = ZZ[['t']]; (t,) = R._first_ngens(1)
        >>> f = Integer(1) - Integer(5)*t**Integer(3) + t**Integer(5) + O(t**Integer(7))
        >>> f.list()
        [1, 0, 0, -5, 0, 1]

  monomial_coefficients(copy=True)

    Return a dictionary of coefficients for `self`.

    This is simply a dict for the underlying polynomial, so need not have keys corresponding to every number smaller than `self.prec()`.

    EXAMPLES:

    Sage

        sage: R.<t> = ZZ[[]]
        sage: f = 1 + t^10 + O(t^12)
        sage: f.monomial_coefficients()
        {0: 1, 10: 1}

    Python

        >>> from sage.all import *
        >>> R = ZZ[['t']]; (t,) = R._first_ngens(1)
        >>> f = Integer(1) + t**Integer(10) + O(t**Integer(12))
        >>> f.monomial_coefficients()
        {0: 1, 10: 1}

    `dict` is an alias:

    Sage

        sage: f.dict()
        {0: 1, 10: 1}

    [Python]

        >>> from sage.all import *
        >>> f.dict()
        {0: 1, 10: 1}

  pade(m, n)

    Return the Padé approximant of `self` of index \((m, n)\).

    The Padé approximant of index \((m, n)\) of a formal power series \(f\) is the quotient \(Q/P\) of two polynomials \(Q\) and \(P\) such that \(\deg(Q)\leq m\), \(\deg(P)\leq n\) and

    \[f(z) - Q(z)/P(z) = O(z^{m+n+1}).\]

    The formal power series \(f\) must be known up to order \(n + m\).

    See Wikipedia article Padé_approximant

    INPUT:

    - `m`, `n` – integers, describing the degrees of the polynomials

    OUTPUT: a ratio of two polynomials

    ALGORITHM:

    This method uses the formula as a quotient of two determinants.

    See also

    - `sage.matrix.berlekamp_massey`,

    - `sage.rings.polynomial.polynomial_zmod_flint.Polynomial_zmod_flint.rational_reconstruction()`

    EXAMPLES:

    Sage

        sage: z = PowerSeriesRing(QQ, 'z').gen()
        sage: exp(z).pade(4, 0)
        1/24*z^4 + 1/6*z^3 + 1/2*z^2 + z + 1
        sage: exp(z).pade(1, 1)
        (-z - 2)/(z - 2)
        sage: exp(z).pade(3, 3)
        (-z^3 - 12*z^2 - 60*z - 120)/(z^3 - 12*z^2 + 60*z - 120)
        sage: log(1-z).pade(4, 4)
        (25/6*z^4 - 130/3*z^3 + 105*z^2 - 70*z)/(z^4 - 20*z^3 + 90*z^2
        - 140*z + 70)
        sage: sqrt(1+z).pade(3, 2)
        (1/6*z^3 + 3*z^2 + 8*z + 16/3)/(z^2 + 16/3*z + 16/3)
        sage: exp(2*z).pade(3, 3)
        (-z^3 - 6*z^2 - 15*z - 15)/(z^3 - 6*z^2 + 15*z - 15)

    Python

        >>> from sage.all import *
        >>> z = PowerSeriesRing(QQ, 'z').gen()
        >>> exp(z).pade(Integer(4), Integer(0))
        1/24*z^4 + 1/6*z^3 + 1/2*z^2 + z + 1
        >>> exp(z).pade(Integer(1), Integer(1))
        (-z - 2)/(z - 2)
        >>> exp(z).pade(Integer(3), Integer(3))
        (-z^3 - 12*z^2 - 60*z - 120)/(z^3 - 12*z^2 + 60*z - 120)
        >>> log(Integer(1)-z).pade(Integer(4), Integer(4))
        (25/6*z^4 - 130/3*z^3 + 105*z^2 - 70*z)/(z^4 - 20*z^3 + 90*z^2
        - 140*z + 70)
        >>> sqrt(Integer(1)+z).pade(Integer(3), Integer(2))
        (1/6*z^3 + 3*z^2 + 8*z + 16/3)/(z^2 + 16/3*z + 16/3)
        >>> exp(Integer(2)*z).pade(Integer(3), Integer(3))
        (-z^3 - 6*z^2 - 15*z - 15)/(z^3 - 6*z^2 + 15*z - 15)

  polynomial()

    Return the underlying polynomial of `self`.

    EXAMPLES:

    Sage

        sage: R.<t> = GF(7)[[]]
        sage: f = 3 - t^3 + O(t^5)
        sage: f.polynomial()
        6*t^3 + 3

    Python

        >>> from sage.all import *
        >>> R = GF(Integer(7))[['t']]; (t,) = R._first_ngens(1)
        >>> f = Integer(3) - t**Integer(3) + O(t**Integer(5))
        >>> f.polynomial()
        6*t^3 + 3

  reverse(precision=None)

    Return the reverse of \(f\), i.e., the series \(g\) such that \(g(f(x)) = x\).

    Given an optional argument `precision`, return the reverse with given precision (note that the reverse can have precision at most `f.prec()`). If \(f\) has infinite precision, and the argument `precision` is not given, then the precision of the reverse defaults to the default precision of `f.parent()`.

    Note that this is only possible if the valuation of `self` is exactly 1.

    ALGORITHM:

    We first attempt to pass the computation to pari; if this fails, we use Lagrange inversion. Using `sage: set_verbose(1)` will print a message if passing to pari fails.

    If the base ring has positive characteristic, then we attempt to lift to a characteristic zero ring and perform the reverse there. If this fails, an error is raised.

    EXAMPLES:

    Sage

        sage: R.<x> = PowerSeriesRing(QQ)
        sage: f = 2*x + 3*x^2 - x^4 + O(x^5)
        sage: g = f.reverse()
        sage: g
        1/2*x - 3/8*x^2 + 9/16*x^3 - 131/128*x^4 + O(x^5)
        sage: f(g)
        x + O(x^5)
        sage: g(f)
        x + O(x^5)

        sage: A.<t> = PowerSeriesRing(ZZ)
        sage: a = t - t^2 - 2*t^4 + t^5 + O(t^6)
        sage: b = a.reverse(); b
        t + t^2 + 2*t^3 + 7*t^4 + 25*t^5 + O(t^6)
        sage: a(b)
        t + O(t^6)
        sage: b(a)
        t + O(t^6)

        sage: B.<b,c> = PolynomialRing(ZZ)
        sage: A.<t> = PowerSeriesRing(B)
        sage: f = t + b*t^2 + c*t^3 + O(t^4)
        sage: g = f.reverse(); g
        t - b*t^2 + (2*b^2 - c)*t^3 + O(t^4)
        sage: f(g)
        t + O(t^4)
        sage: g(f)
        t + O(t^4)

        sage: A.<t> = PowerSeriesRing(ZZ)
        sage: B.<s> = A[[]]
        sage: f = (1 - 3*t + 4*t^3 + O(t^4))*s + (2 + t + t^2 + O(t^3))*s^2 + O(s^3)
        sage: from sage.misc.verbose import set_verbose
        sage: set_verbose(1)
        sage: g = f.reverse(); g
        verbose 1 (<module>) passing to pari failed; trying Lagrange inversion
        (1 + 3*t + 9*t^2 + 23*t^3 + O(t^4))*s + (-2 - 19*t - 118*t^2 + O(t^3))*s^2 + O(s^3)
        sage: set_verbose(0)
        sage: f(g) == g(f) == s
        True

    Python

        >>> from sage.all import *
        >>> R = PowerSeriesRing(QQ, names=('x',)); (x,) = R._first_ngens(1)
        >>> f = Integer(2)*x + Integer(3)*x**Integer(2) - x**Integer(4) + O(x**Integer(5))
        >>> g = f.reverse()
        >>> g
        1/2*x - 3/8*x^2 + 9/16*x^3 - 131/128*x^4 + O(x^5)
        >>> f(g)
        x + O(x^5)
        >>> g(f)
        x + O(x^5)

        >>> A = PowerSeriesRing(ZZ, names=('t',)); (t,) = A._first_ngens(1)
        >>> a = t - t**Integer(2) - Integer(2)*t**Integer(4) + t**Integer(5) + O(t**Integer(6))
        >>> b = a.reverse(); b
        t + t^2 + 2*t^3 + 7*t^4 + 25*t^5 + O(t^6)
        >>> a(b)
        t + O(t^6)
        >>> b(a)
        t + O(t^6)

        >>> B = PolynomialRing(ZZ, names=('b', 'c',)); (b, c,) = B._first_ngens(2)
        >>> A = PowerSeriesRing(B, names=('t',)); (t,) = A._first_ngens(1)
        >>> f = t + b*t**Integer(2) + c*t**Integer(3) + O(t**Integer(4))
        >>> g = f.reverse(); g
        t - b*t^2 + (2*b^2 - c)*t^3 + O(t^4)
        >>> f(g)
        t + O(t^4)
        >>> g(f)
        t + O(t^4)

        >>> A = PowerSeriesRing(ZZ, names=('t',)); (t,) = A._first_ngens(1)
        >>> B = A[['s']]; (s,) = B._first_ngens(1)
        >>> f = (Integer(1) - Integer(3)*t + Integer(4)*t**Integer(3) + O(t**Integer(4)))*s + (Integer(2) + t + t**Integer(2) + O(t**Integer(3)))*s**Integer(2) + O(s**Integer(3))
        >>> from sage.misc.verbose import set_verbose
        >>> set_verbose(Integer(1))
        >>> g = f.reverse(); g
        verbose 1 (<module>) passing to pari failed; trying Lagrange inversion
        (1 + 3*t + 9*t^2 + 23*t^3 + O(t^4))*s + (-2 - 19*t - 118*t^2 + O(t^3))*s^2 + O(s^3)
        >>> set_verbose(Integer(0))
        >>> f(g) == g(f) == s
        True

    If the leading coefficient is not a unit, we pass to its fraction field if possible:

    Sage

        sage: A.<t> = PowerSeriesRing(ZZ)
        sage: a = 2*t - 4*t^2 + t^4 - t^5 + O(t^6)
        sage: a.reverse()
        1/2*t + 1/2*t^2 + t^3 + 79/32*t^4 + 437/64*t^5 + O(t^6)

        sage: B.<b> = PolynomialRing(ZZ)
        sage: A.<t> = PowerSeriesRing(B)
        sage: f = 2*b*t + b*t^2 + 3*b^2*t^3 + O(t^4)
        sage: g = f.reverse(); g
        1/(2*b)*t - 1/(8*b^2)*t^2 + ((-3*b + 1)/(16*b^3))*t^3 + O(t^4)
        sage: f(g)
        t + O(t^4)
        sage: g(f)
        t + O(t^4)

    [Python]

        >>> from sage.all import *
        >>> A = PowerSeriesRing(ZZ, names=('t',)); (t,) = A._first_ngens(1)
        >>> a = Integer(2)*t - Integer(4)*t**Integer(2) + t**Integer(4) - t**Integer(5) + O(t**Integer(6))
        >>> a.reverse()
        1/2*t + 1/2*t^2 + t^3 + 79/32*t^4 + 437/64*t^5 + O(t^6)

        >>> B = PolynomialRing(ZZ, names=('b',)); (b,) = B._first_ngens(1)
        >>> A = PowerSeriesRing(B, names=('t',)); (t,) = A._first_ngens(1)
        >>> f = Integer(2)*b*t + b*t**Integer(2) + Integer(3)*b**Integer(2)*t**Integer(3) + O(t**Integer(4))
        >>> g = f.reverse(); g
        1/(2*b)*t - 1/(8*b^2)*t^2 + ((-3*b + 1)/(16*b^3))*t^3 + O(t^4)
        >>> f(g)
        t + O(t^4)
        >>> g(f)
        t + O(t^4)

    We can handle some base rings of positive characteristic:

    Sage

        sage: A8.<t> = PowerSeriesRing(Zmod(8))
        sage: a = t - 15*t^2 - 2*t^4 + t^5 + O(t^6)
        sage: b = a.reverse(); b
        t + 7*t^2 + 2*t^3 + 5*t^4 + t^5 + O(t^6)
        sage: a(b)
        t + O(t^6)
        sage: b(a)
        t + O(t^6)

    Python

        >>> from sage.all import *
        >>> A8 = PowerSeriesRing(Zmod(Integer(8)), names=('t',)); (t,) = A8._first_ngens(1)
        >>> a = t - Integer(15)*t**Integer(2) - Integer(2)*t**Integer(4) + t**Integer(5) + O(t**Integer(6))
        >>> b = a.reverse(); b
        t + 7*t^2 + 2*t^3 + 5*t^4 + t^5 + O(t^6)
        >>> a(b)
        t + O(t^6)
        >>> b(a)
        t + O(t^6)

    The optional argument `precision` sets the precision of the output:

    Sage

        sage: R.<x> = PowerSeriesRing(QQ)
        sage: f = 2*x + 3*x^2 - 7*x^3 + x^4 + O(x^5)
        sage: g = f.reverse(precision=3); g
        1/2*x - 3/8*x^2 + O(x^3)
        sage: f(g)
        x + O(x^3)
        sage: g(f)
        x + O(x^3)

    [Python]

        >>> from sage.all import *
        >>> R = PowerSeriesRing(QQ, names=('x',)); (x,) = R._first_ngens(1)
        >>> f = Integer(2)*x + Integer(3)*x**Integer(2) - Integer(7)*x**Integer(3) + x**Integer(4) + O(x**Integer(5))
        >>> g = f.reverse(precision=Integer(3)); g
        1/2*x - 3/8*x^2 + O(x^3)
        >>> f(g)
        x + O(x^3)
        >>> g(f)
        x + O(x^3)

    If the input series has infinite precision, the precision of the output is automatically set to the default precision of the parent ring:

    Sage

        sage: R.<x> = PowerSeriesRing(QQ, default_prec=20)
        sage: (x - x^2).reverse() # get some Catalan numbers
        x + x^2 + 2*x^3 + 5*x^4 + 14*x^5 + 42*x^6 + 132*x^7 + 429*x^8 + 1430*x^9
         + 4862*x^10 + 16796*x^11 + 58786*x^12 + 208012*x^13 + 742900*x^14
         + 2674440*x^15 + 9694845*x^16 + 35357670*x^17 + 129644790*x^18
         + 477638700*x^19 + O(x^20)
        sage: (x - x^2).reverse(precision=3)
        x + x^2 + O(x^3)

    Python

        >>> from sage.all import *
        >>> R = PowerSeriesRing(QQ, default_prec=Integer(20), names=('x',)); (x,) = R._first_ngens(1)
        >>> (x - x**Integer(2)).reverse() # get some Catalan numbers
        x + x^2 + 2*x^3 + 5*x^4 + 14*x^5 + 42*x^6 + 132*x^7 + 429*x^8 + 1430*x^9
         + 4862*x^10 + 16796*x^11 + 58786*x^12 + 208012*x^13 + 742900*x^14
         + 2674440*x^15 + 9694845*x^16 + 35357670*x^17 + 129644790*x^18
         + 477638700*x^19 + O(x^20)
        >>> (x - x**Integer(2)).reverse(precision=Integer(3))
        x + x^2 + O(x^3)

  truncate(prec='infinity')

    The polynomial obtained from power series by truncation at precision `prec`.

    EXAMPLES:

    Sage

        sage: R.<I> = GF(2)[[]]
        sage: f = 1/(1+I+O(I^8)); f
        1 + I + I^2 + I^3 + I^4 + I^5 + I^6 + I^7 + O(I^8)
        sage: f.truncate(5)
        I^4 + I^3 + I^2 + I + 1

    Python

        >>> from sage.all import *
        >>> R = GF(Integer(2))[['I']]; (I,) = R._first_ngens(1)
        >>> f = Integer(1)/(Integer(1)+I+O(I**Integer(8))); f
        1 + I + I^2 + I^3 + I^4 + I^5 + I^6 + I^7 + O(I^8)
        >>> f.truncate(Integer(5))
        I^4 + I^3 + I^2 + I + 1

  truncate_powerseries(prec)

    Given input `prec` = \(n\), returns the power series of degree \(< n\) which is equivalent to `self` modulo \(x^n\).

    EXAMPLES:

    Sage

        sage: R.<I> = GF(2)[[]]
        sage: f = 1/(1+I+O(I^8)); f
        1 + I + I^2 + I^3 + I^4 + I^5 + I^6 + I^7 + O(I^8)
        sage: f.truncate_powerseries(5)
        1 + I + I^2 + I^3 + I^4 + O(I^5)

    Python

        >>> from sage.all import *
        >>> R = GF(Integer(2))[['I']]; (I,) = R._first_ngens(1)
        >>> f = Integer(1)/(Integer(1)+I+O(I**Integer(8))); f
        1 + I + I^2 + I^3 + I^4 + I^5 + I^6 + I^7 + O(I^8)
        >>> f.truncate_powerseries(Integer(5))
        1 + I + I^2 + I^3 + I^4 + O(I^5)

  valuation()

    Return the valuation of `self`.

    EXAMPLES:

    Sage

        sage: R.<t> = QQ[[]]
        sage: (5 - t^8 + O(t^11)).valuation()
        0
        sage: (-t^8 + O(t^11)).valuation()
        8
        sage: O(t^7).valuation()
        7
        sage: R(0).valuation()
        +Infinity

    Python

        >>> from sage.all import *
        >>> R = QQ[['t']]; (t,) = R._first_ngens(1)
        >>> (Integer(5) - t**Integer(8) + O(t**Integer(11))).valuation()
        0
        >>> (-t**Integer(8) + O(t**Integer(11))).valuation()
        8
        >>> O(t**Integer(7)).valuation()
        7
        >>> R(Integer(0)).valuation()
        +Infinity

sage.rings.power_series_poly.make_powerseries_poly_v0(parent, f, prec, is_gen)

  Return the power series specified by `f`, `prec`, and `is_gen`.

  This function exists for the purposes of pickling. Do not delete this function – if you change the internal representation, instead make a new function and make sure that both kinds of objects correctly unpickle as the new type.

  EXAMPLES:

  Sage

      sage: R.<t> = QQ[[]]
      sage: sage.rings.power_series_poly.make_powerseries_poly_v0(R, t, infinity, True)
      t

  Python

      >>> from sage.all import *
      >>> R = QQ[['t']]; (t,) = R._first_ngens(1)
      >>> sage.rings.power_series_poly.make_powerseries_poly_v0(R, t, infinity, True)
      t