### Navigation

- index
- modules |
- next |
- previous |
- Combinatorics »
- Combinatorial Species »

# Lazy Power Series

This file provides an implementation of lazy univariate power series, which uses the stream class for its internal data structure. The lazy power series keep track of their approximate order as much as possible without forcing the computation of any additional coefficients. This is required for recursively defined power series.

This code is based on the work of Ralf Hemmecke and Martin Rubey’s Aldor-Combinat, which can be found at http://www.risc.uni-linz.ac.at/people/hemmecke/aldor/combinat/index.html. In particular, the relevant section for this file can be found at http://www.risc.uni-linz.ac.at/people/hemmecke/AldorCombinat/combinatse9.html.

class `sage.combinat.species.series.``LazyPowerSeries`(A, stream=None, order=None, aorder=None, aorder_changed=True, is_initialized=False, name=None)

  Bases: `sage.structure.element.AlgebraElement`

  EXAMPLES:

      sage: L = LazyPowerSeriesRing(QQ)
      sage: f = L()
      sage: loads(dumps(f))
      Uninitialized lazy power series

  `add`(y)

    EXAMPLES: Test Plus 1

        sage: from sage.combinat.species.series import *
        sage: from sage.combinat.species.stream import Stream
        sage: L = LazyPowerSeriesRing(QQ)
        sage: gs0 = L([0])
        sage: gs1 = L([1])
        sage: sum1 = gs0 + gs1
        sage: sum2 = gs1 + gs1
        sage: sum3 = gs1 + gs0
        sage: [gs0.coefficient(i) for i in range(11)]
        [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
        sage: [gs1.coefficient(i) for i in range(11)]
        [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1]
        sage: [sum1.coefficient(i) for i in range(11)]
        [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1]
        sage: [sum2.coefficient(i) for i in range(11)]
        [2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2]
        sage: [sum3.coefficient(i) for i in range(11)]
        [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1]

    Test Plus 2

        sage: gs1 = L([1,2,4,8,0])
        sage: gs2 = L([-1, 0,-1,-9,22,0])
        sage: sum = gs1 + gs2
        sage: sum2 = gs2 + gs1
        sage: [ sum.coefficient(i) for i in range(5) ]
        [0,  2, 3, -1, 22]
        sage: [ sum.coefficient(i) for i in range(5, 11) ]
        [0, 0, 0, 0, 0, 0]
        sage: [ sum2.coefficient(i) for i in range(5) ]
        [0,  2, 3, -1, 22]
        sage: [ sum2.coefficient(i) for i in range(5, 11) ]
        [0, 0, 0, 0, 0, 0]

  `coefficient`(n)

    Returns the coefficient of xn in self.

    EXAMPLES:

        sage: L = LazyPowerSeriesRing(QQ)
        sage: f = L(ZZ)
        sage: [f.coefficient(i) for i in range(5)]
        [0, 1, -1, 2, -2]

  `coefficients`(n)

    Returns the first n coefficients of self.

    EXAMPLES:

        sage: L = LazyPowerSeriesRing(QQ)
        sage: f = L([1,2,3,0])
        sage: f.coefficients(5)
        [1, 2, 3, 0, 0]

  `compose`(y)

    Returns the composition of this power series and the power series y.

    EXAMPLES:

        sage: L = LazyPowerSeriesRing(QQ)
        sage: s = L([1])
        sage: t = L([0,0,1])
        sage: u = s(t)
        sage: u.coefficients(11)
        [1, 0, 1, 1, 2, 3, 5, 8, 13, 21, 34]

    Test Compose 2

        sage: s = L([1])
        sage: t = L([0,0,1,0])
        sage: u = s(t)
        sage: u.aorder
        0
        sage: u.order
        Unknown series order
        sage: u.coefficients(10)
        [1, 0, 1, 0, 1, 0, 1, 0, 1, 0]
        sage: u.aorder
        0
        sage: u.order
        0

    Test Compose 3 s = 1/(1-x), t = x/(1-x) s(t) = (1-x)/(1-2x)

        sage: s = L([1])
        sage: t = L([0,1])
        sage: u = s(t)
        sage: u.coefficients(14)
        [1, 1, 2, 4, 8, 16, 32, 64, 128, 256, 512, 1024, 2048, 4096]

  `composition`(y)

    Returns the composition of this power series and the power series y.

    EXAMPLES:

        sage: L = LazyPowerSeriesRing(QQ)
        sage: s = L([1])
        sage: t = L([0,0,1])
        sage: u = s(t)
        sage: u.coefficients(11)
        [1, 0, 1, 1, 2, 3, 5, 8, 13, 21, 34]

    Test Compose 2

        sage: s = L([1])
        sage: t = L([0,0,1,0])
        sage: u = s(t)
        sage: u.aorder
        0
        sage: u.order
        Unknown series order
        sage: u.coefficients(10)
        [1, 0, 1, 0, 1, 0, 1, 0, 1, 0]
        sage: u.aorder
        0
        sage: u.order
        0

    Test Compose 3 s = 1/(1-x), t = x/(1-x) s(t) = (1-x)/(1-2x)

        sage: s = L([1])
        sage: t = L([0,1])
        sage: u = s(t)
        sage: u.coefficients(14)
        [1, 1, 2, 4, 8, 16, 32, 64, 128, 256, 512, 1024, 2048, 4096]

  `compute_aorder`(*args, **kwargs)

    The default compute_aorder does nothing.

    EXAMPLES:

        sage: L = LazyPowerSeriesRing(QQ)
        sage: a = L(1)
        sage: a.compute_aorder() is None
        True

  `compute_coefficients`(i)

    Computes all the coefficients of self up to i.

    EXAMPLES:

        sage: L = LazyPowerSeriesRing(QQ)
        sage: a = L([1,2,3])
        sage: a.compute_coefficients(5)
        sage: a
        1 + 2*x + 3*x^2 + 3*x^3 + 3*x^4 + 3*x^5 + ...

  `define`(x)

    EXAMPLES: Test Recursive 0

        sage: L = LazyPowerSeriesRing(QQ)
        sage: one = L(1)
        sage: monom = L.gen()
        sage: s = L()
        sage: s._name = 's'
        sage: s.define(one+monom*s)
        sage: s.aorder
        0
        sage: s.order
        Unknown series order
        sage: [s.coefficient(i) for i in range(6)]
        [1, 1, 1, 1, 1, 1]

    Test Recursive 1

        sage: s = L()
        sage: s._name = 's'
        sage: s.define(one+monom*s*s)
        sage: s.aorder
        0
        sage: s.order
        Unknown series order
        sage: [s.coefficient(i) for i in range(6)]
        [1, 1, 2, 5, 14, 42]

    Test Recursive 1b

        sage: s = L()
        sage: s._name = 's'
        sage: s.define(monom + s*s)
        sage: s.aorder
        1
        sage: s.order
        Unknown series order
        sage: [s.coefficient(i) for i in range(7)]
        [0, 1, 1, 2, 5, 14, 42]

    Test Recursive 2

        sage: s = L()
        sage: s._name = 's'
        sage: t = L()
        sage: t._name = 't'
        sage: s.define(one+monom*t*t*t)
        sage: t.define(one+monom*s*s)
        sage: [s.coefficient(i) for i in range(9)]
        [1, 1, 3, 9, 34, 132, 546, 2327, 10191]
        sage: [t.coefficient(i) for i in range(9)]
        [1, 1, 2, 7, 24, 95, 386, 1641, 7150]

    Test Recursive 2b

        sage: s = L()
        sage: s._name = 's'
        sage: t = L()
        sage: t._name = 't'
        sage: s.define(monom + t*t*t)
        sage: t.define(monom + s*s)
        sage: [s.coefficient(i) for i in range(9)]
        [0, 1, 0, 1, 3, 3, 7, 30, 63]
        sage: [t.coefficient(i) for i in range(9)]
        [0, 1, 1, 0, 2, 6, 7, 20, 75]

    Test Recursive 3

        sage: s = L()
        sage: s._name = 's'
        sage: s.define(one+monom*s*s*s)
        sage: [s.coefficient(i) for i in range(10)]
        [1, 1, 3, 12, 55, 273, 1428, 7752, 43263, 246675]

  `derivative`()

    EXAMPLES:

        sage: from sage.combinat.species.stream import Stream
        sage: L = LazyPowerSeriesRing(QQ)
        sage: one = L(1)
        sage: monom = L.gen()
        sage: s = L([1])
        sage: u = s.derivative()
        sage: u.coefficients(10)
        [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]

        sage: s = L()
        sage: s._name = 's'
        sage: s.define(one+monom*s*s)
        sage: u = s.derivative()
        sage: u.coefficients(5) #[1*1, 2*2, 3*5, 4*14, 5*42]
        [1, 4, 15, 56, 210]

        sage: s = L([1])
        sage: t = L([0,1])
        sage: u = s(t).derivative()
        sage: v = (s.derivative().compose(t))*t.derivative()
        sage: u.coefficients(11)
        [1, 4, 12, 32, 80, 192, 448, 1024, 2304, 5120, 11264]
        sage: v.coefficients(11)
        [1, 4, 12, 32, 80, 192, 448, 1024, 2304, 5120, 11264]

        sage: s = L(); s._name='s'
        sage: t = L(); t._name='t'
        sage: s.define(monom+t*t*t)
        sage: t.define(monom+s*s)
        sage: u = (s*t).derivative()
        sage: v = s.derivative()*t + s*t.derivative()
        sage: u.coefficients(10)
        [0, 2, 3, 4, 30, 72, 133, 552, 1791, 4260]
        sage: v.coefficients(10)
        [0, 2, 3, 4, 30, 72, 133, 552, 1791, 4260]
        sage: u.coefficients(10) == v.coefficients(10)
        True

        sage: f = L._new_initial(2, Stream([0,0,4,5,6,0]))
        sage: d = f.derivative()
        sage: d.get_aorder()
        1
        sage: d.coefficients(5)
        [0, 8, 15, 24, 0]

  `exponential`()

    TESTS:

        sage: def inv_factorial():
        ...       q = 1
        ...       yield 0
        ...       yield q
        ...       n = 2
        ...       while True:
        ...           q = q / n
        ...           yield q
        ...           n += 1
        sage: L = LazyPowerSeriesRing(QQ)
        sage: f = L(inv_factorial()) #e^(x)-1
        sage: u = f.exponential()
        sage: g = inv_factorial()
        sage: z1 = [1,1,2,5,15,52,203,877,4140,21147,115975]
        sage: l1 = [z*g.next() for z in z1]
        sage: l1 = [1] + l1[1:]
        sage: u.coefficients(11)
        [1, 1, 1, 5/6, 5/8, 13/30, 203/720, 877/5040, 23/224, 1007/17280, 4639/145152]
        sage: l1 == u.coefficients(11)
        True

  `get_aorder`()

    Returns the approximate order of self.

    EXAMPLES:

        sage: L = LazyPowerSeriesRing(QQ)
        sage: a = L.gen()
        sage: a.get_aorder()
        1

  `get_order`()

    Returns the order of self.

    EXAMPLES:

        sage: L = LazyPowerSeriesRing(QQ)
        sage: a = L.gen()
        sage: a.get_order()
        1

  `get_stream`()

    Returns self’s underlying Stream object.

    EXAMPLES:

        sage: L = LazyPowerSeriesRing(QQ)
        sage: a = L.gen()
        sage: s = a.get_stream()
        sage: [s[i] for i in range(5)]
        [0, 1, 0, 0, 0]

  `initialize_coefficient_stream`(compute_coefficients)

    Initializes the coefficient stream.

    INPUT: compute_coefficients

    TESTS:

        sage: from sage.combinat.species.series_order import inf, unk
        sage: L = LazyPowerSeriesRing(QQ)
        sage: f = L()
        sage: compute_coefficients = lambda ao: iter(ZZ)
        sage: f.order = inf
        sage: f.aorder = inf
        sage: f.initialize_coefficient_stream(compute_coefficients)
        sage: f.coefficients(5)
        [0, 0, 0, 0, 0]

        sage: f = L()
        sage: compute_coefficients = lambda ao: iter(ZZ)
        sage: f.order = 1
        sage: f.aorder = 1
        sage: f.initialize_coefficient_stream(compute_coefficients)
        sage: f.coefficients(5)
        [0, 1, -1, 2, -2]

  `integral`(integration_constant=0)

    EXAMPLES:

        sage: L = LazyPowerSeriesRing(QQ)
        sage: zero = L(0)
        sage: s = zero
        sage: t = s.integral()
        sage: t.is_zero()
        True

        sage: s = zero
        sage: t = s.integral(1)
        sage: t.coefficients(6)
        [1, 0, 0, 0, 0, 0]
        sage: t._stream.is_constant()
        True

        sage: s = L.term(1, 0)
        sage: t = s.integral()
        sage: t.coefficients(6)
        [0, 1, 0, 0, 0, 0]
        sage: t._stream.is_constant()
        True

        sage: s = L.term(1,0)
        sage: t = s.integral(1)
        sage: t.coefficients(6)
        [1, 1, 0, 0, 0, 0]
        sage: t._stream.is_constant()
        True

        sage: s = L.term(1, 4)
        sage: t = s.integral()
        sage: t.coefficients(10)
        [0, 0, 0, 0, 0, 1/5, 0, 0, 0, 0]

        sage: s = L.term(1,4)
        sage: t = s.integral(1)
        sage: t.coefficients(10)
        [1, 0, 0, 0, 0, 1/5, 0, 0, 0, 0]

    TESTS:

        sage: from sage.combinat.species.stream import Stream
        sage: f = L._new_initial(2, Stream([0,0,4,5,6,0]))
        sage: i = f.derivative().integral()
        sage: i.get_aorder()
        2
        sage: i.coefficients(5)
        [0, 0, 4, 5, 6]
        sage: i = f.derivative().integral(1)
        sage: i.get_aorder()
        0
        sage: i.coefficients(5)
        [1, 0, 4, 5, 6]

  `is_finite`(n=None)

    EXAMPLES:

        sage: L = LazyPowerSeriesRing(QQ)
        sage: a = L([0,0,1,0,0]); a
        O(1)
        sage: a.is_finite()
        False
        sage: c = a[4]
        sage: a.is_finite()
        False
        sage: a.is_finite(4)
        False
        sage: c = a[5]
        sage: a.is_finite()
        True
        sage: a.is_finite(4)
        True

  `is_zero`()

    Returns True if and only if self is zero.

    EXAMPLES:

        sage: L = LazyPowerSeriesRing(QQ)
        sage: s = L([0,2,3,0])
        sage: s.is_zero()
        False

        sage: s = L(0)
        sage: s.is_zero()
        True

        sage: s = L([0])
        sage: s.is_zero()
        False
        sage: s.coefficient(0)
        0
        sage: s.coefficient(1)
        0
        sage: s.is_zero()
        True

  `iterator`(n=0, initial=None)

    Returns an iterator for the coefficients of self starting at n.

    EXAMPLES:

        sage: from sage.combinat.species.stream import Stream
        sage: L = LazyPowerSeriesRing(QQ)
        sage: f = L(range(10))
        sage: g = f.iterator(2)
        sage: [g.next() for i in range(5)]
        [2, 3, 4, 5, 6]
        sage: g = f.iterator(2, initial=[0,0])
        sage: [g.next() for i in range(5)]
        [0, 0, 2, 3, 4]

  `refine_aorder`()

    Refines the approximate order of self as much as possible without computing any coefficients.

    EXAMPLES:

        sage: L = LazyPowerSeriesRing(QQ)
        sage: a = L([0,0,0,0,1])
        sage: a.aorder
        0
        sage: a.coefficient(2)
        0
        sage: a.aorder
        0
        sage: a.refine_aorder()
        sage: a.aorder
        3

        sage: a = L([0,0])
        sage: a.aorder
        0
        sage: a.coefficient(5)
        0
        sage: a.refine_aorder()
        sage: a.aorder
        Infinite series order

        sage: a = L([0,0,1,0,0,0])
        sage: a[4]
        0
        sage: a.refine_aorder()
        sage: a.aorder
        2

  `restricted`(min=None, max=None)

    Returns the power series restricted to the coefficients starting at min and going up to, but not including max. If min is not specified, then it is assumed to be zero. If max is not specified, then it is assumed to be infinity.

    EXAMPLES:

        sage: L = LazyPowerSeriesRing(QQ)
        sage: a = L([1])
        sage: a.restricted().coefficients(10)
        [1, 1, 1, 1, 1, 1, 1, 1, 1, 1]
        sage: a.restricted(min=2).coefficients(10)
        [0, 0, 1, 1, 1, 1, 1, 1, 1, 1]
        sage: a.restricted(max=5).coefficients(10)
        [1, 1, 1, 1, 1, 0, 0, 0, 0, 0]
        sage: a.restricted(min=2, max=6).coefficients(10)
        [0, 0, 1, 1, 1, 1, 0, 0, 0, 0]

  `set_approximate_order`(new_order)

    Sets the approximate order of self and returns True if the approximate order has changed otherwise it will return False.

    EXAMPLES:

        sage: L = LazyPowerSeriesRing(QQ)
        sage: f = L([0,0,0,3,2,1,0])
        sage: f.get_aorder()
        0
        sage: f.set_approximate_order(3)
        True
        sage: f.set_approximate_order(3)
        False

  `tail`()

    Returns the power series whose coefficients obtained by subtracting the constant term from this series and then dividing by x.

    EXAMPLES:

        sage: from sage.combinat.species.stream import Stream
        sage: L = LazyPowerSeriesRing(QQ)
        sage: f = L(range(20))
        sage: g = f.tail()
        sage: g.coefficients(10)
        [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]

  `times`(y)

    EXAMPLES:

        sage: L = LazyPowerSeriesRing(QQ)
        sage: gs0 = L(0)
        sage: gs1 = L([1])

        sage: prod0 = gs0 * gs1
        sage: [prod0.coefficient(i) for i in range(11)]
        [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]

        sage: prod1 = gs1 * gs0
        sage: [prod1.coefficient(i) for i in range(11)]
        [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]

        sage: prod2 = gs1 * gs1
        sage: [prod2.coefficient(i) for i in range(11)]
        [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11]

        sage: gs1 = L([1,2,4,8,0])
        sage: gs2 = L([-1, 0,-1,-9,22,0])

        sage: prod1 = gs1 * gs2
        sage: [prod1.coefficient(i) for i in range(11)]
        [-1, -2, -5, -19, 0, 0, 16, 176, 0, 0, 0]

        sage: prod2 = gs2 * gs1
        sage: [prod2.coefficient(i) for i in range(11)]
        [-1, -2, -5, -19, 0, 0, 16, 176, 0, 0, 0]

class `sage.combinat.species.series.``LazyPowerSeriesRing`(R, element_class=None, names=None)

  Bases: `sage.rings.ring.Algebra`

  TESTS:

      sage: from sage.combinat.species.series import LazyPowerSeriesRing
      sage: L = LazyPowerSeriesRing(QQ)
      sage: loads(dumps(L))
      Lazy Power Series Ring over Rational Field

  `gen`(i=0)

    EXAMPLES:

        sage: L = LazyPowerSeriesRing(QQ)
        sage: L.gen().coefficients(5)
        [0, 1, 0, 0, 0]

  `identity_element`()

    Returns the one power series.

    EXAMPLES:

        sage: L = LazyPowerSeriesRing(QQ)
        sage: L.identity_element()
        1

  `ngens`()

    EXAMPLES:

        sage: LazyPowerSeriesRing(QQ).ngens()
        1

  `product_generator`(g)

    EXAMPLES:

        sage: L = LazyPowerSeriesRing(QQ)
        sage: s1 = L([1,1,0])
        sage: s2 = L([1,0,1,0])
        sage: s3 = L([1,0,0,1,0])
        sage: s4 = L([1,0,0,0,1,0])
        sage: s5 = L([1,0,0,0,0,1,0])
        sage: s6 = L([1,0,0,0,0,0,1,0])
        sage: s = [s1, s2, s3, s4, s5, s6]
        sage: def g():
        ...       for a in s:
        ...           yield a
        sage: p = L.product_generator(g())
        sage: p.coefficients(26)
        [1, 1, 1, 2, 2, 3, 4, 4, 4, 5, 5, 5, 5, 4, 4, 4, 3, 2, 2, 1, 1, 1, 0, 0, 0, 0]

        sage: def m(n):
        ...       yield 1
        ...       while True:
        ...           for i in range(n-1):
        ...               yield 0
        ...           yield 1
        ...
        sage: def s(n):
        ...       q = 1/n
        ...       yield 0
        ...       while True:
        ...           for i in range(n-1):
        ...               yield 0
        ...           yield q
        ...

        sage: def lhs_gen():
        ...       n = 1
        ...       while True:
        ...           yield L(m(n))
        ...           n += 1
        ...

        sage: def rhs_gen():
        ...       n = 1
        ...       while True:
        ...           yield L(s(n))
        ...           n += 1
        ...
        sage: lhs = L.product_generator(lhs_gen())
        sage: rhs = L.sum_generator(rhs_gen()).exponential()
        sage: lhs.coefficients(10)
        [1, 1, 2, 3, 5, 7, 11, 15, 22, 30]
        sage: rhs.coefficients(10)
        [1, 1, 2, 3, 5, 7, 11, 15, 22, 30]

  `sum`(a)

    EXAMPLES:

        sage: L = LazyPowerSeriesRing(QQ)
        sage: l = [L(ZZ)]*3
        sage: L.sum(l).coefficients(10)
        [0, 3, -3, 6, -6, 9, -9, 12, -12, 15]

  `sum_generator`(g)

    EXAMPLES:

        sage: L = LazyPowerSeriesRing(QQ)
        sage: g = [L([1])]*6 + [L(0)]
        sage: t = L.sum_generator(g)
        sage: t.coefficients(10)
        [1, 2, 3, 4, 5, 6, 6, 6, 6, 6]

        sage: s = L([1])
        sage: def g():
        ...       while True:
        ...           yield s
        sage: t = L.sum_generator(g())
        sage: t.coefficients(9)
        [1, 2, 3, 4, 5, 6, 7, 8, 9]

  `term`(r, n)

    EXAMPLES:

        sage: L = LazyPowerSeriesRing(QQ)
        sage: L.term(0,0)
        0
        sage: L.term(3,2).coefficients(5)
        [0, 0, 3, 0, 0]

  `zero_element`()

    Returns the zero power series.

    EXAMPLES:

        sage: L = LazyPowerSeriesRing(QQ)
        sage: L.zero_element()
        0

`sage.combinat.species.series.``uninitialized`()

  EXAMPLES:

      sage: from sage.combinat.species.series import uninitialized
      sage: uninitialized()
      Traceback (most recent call last):
      ...
      RuntimeError: we should never be here

### Navigation

- index
- modules |
- next |
- previous |
- Combinatorics »
- Combinatorial Species »