Hot-keys on this page
r m x p toggle line displays
j k next/prev highlighted chunk
0 (zero) top of page
1 (one) first highlighted chunk
""" 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. """ #***************************************************************************** # Copyright (C) 2008 Mike Hansen <mhansen@gmail.com>, # # Distributed under the terms of the GNU General Public License (GPL) # # This code is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU # General Public License for more details. # # The full text of the GPL is available at: # # http://www.gnu.org/licenses/ #***************************************************************************** from __future__ import absolute_import
from .stream import Stream, Stream_class from .series_order import bounded_decrement, increment, inf, unk from sage.rings.all import Integer from sage.misc.all import prod from functools import partial from sage.misc.misc import repr_lincomb, is_iterator from sage.misc.superseded import deprecated_function_alias
from sage.algebras.algebra import Algebra import sage.structure.parent_base from sage.categories.all import Rings from sage.structure.element import Element, parent, AlgebraElement
class LazyPowerSeriesRing(Algebra): def __init__(self, R, element_class = None, names=None): """ TESTS::
sage: from sage.combinat.species.series import LazyPowerSeriesRing sage: L = LazyPowerSeriesRing(QQ)
Equality testing is undecidable in general, and not much efforts are done at this stage to implement equality when possible. Hence the failing tests below::
sage: TestSuite(L).run() Failure in ... The following tests failed: _test_additive_associativity, _test_associativity, _test_distributivity, _test_elements, _test_one, _test_prod, _test_zero
""" #Make sure R is a ring with unit element raise TypeError("Argument R must be a ring.") except Exception: raise ValueError("R must have a unit element")
#Take care of the names else:
def ngens(self): """ EXAMPLES::
sage: LazyPowerSeriesRing(QQ).ngens() 1 """
def __repr__(self): """ EXAMPLES::
sage: LazyPowerSeriesRing(QQ) Lazy Power Series Ring over Rational Field """
def __eq__(self, x): """ Check whether ``self`` is equal to ``x``.
EXAMPLES::
sage: LQ = LazyPowerSeriesRing(QQ) sage: LZ = LazyPowerSeriesRing(ZZ) sage: LQ == LQ True sage: LZ == LQ False """
def __ne__(self, other): """ Check whether ``self`` is not equal to ``other``.
EXAMPLES::
sage: LQ = LazyPowerSeriesRing(QQ) sage: LZ = LazyPowerSeriesRing(ZZ) sage: LQ != LQ False sage: LZ != LQ True """
def _coerce_impl(self, x): """ EXAMPLES::
sage: L1 = LazyPowerSeriesRing(QQ) sage: L2 = LazyPowerSeriesRing(RR) sage: L2.has_coerce_map_from(L1) True sage: L1.has_coerce_map_from(L2) False
::
sage: a = L1([1]) + L2([1]) sage: a.coefficients(3) [2.00000000000000, 2.00000000000000, 2.00000000000000] """
def __call__(self, x=None, order=unk): """ EXAMPLES::
sage: from sage.combinat.species.stream import Stream sage: L = LazyPowerSeriesRing(QQ) sage: L() Uninitialized lazy power series sage: L(1) 1 sage: L(ZZ).coefficients(10) [0, 1, -1, 2, -2, 3, -3, 4, -4, 5] sage: L(iter(ZZ)).coefficients(10) [0, 1, -1, 2, -2, 3, -3, 4, -4, 5] sage: L(Stream(ZZ)).coefficients(10) [0, 1, -1, 2, -2, 3, -3, 4, -4, 5]
::
sage: a = L([1,2,3]) sage: a.coefficients(3) [1, 2, 3] sage: L(a) is a True sage: L_RR = LazyPowerSeriesRing(RR) sage: b = L_RR(a) sage: b.coefficients(3) [1.00000000000000, 2.00000000000000, 3.00000000000000] sage: L(b) Traceback (most recent call last): ... TypeError: do not know how to coerce ... into self
TESTS::
sage: L(pi) Traceback (most recent call last): ... TypeError: do not know how to coerce pi into self """
aorder_changed=True, is_initialized=False)
raise ValueError
else:
aorder_changed=False, is_initialized=True) x = BR(x) return self.term(x, 0)
def zero(self): """ Returns the zero power series.
EXAMPLES::
sage: L = LazyPowerSeriesRing(QQ) sage: L.zero() 0 """
def identity_element(self): """ Returns the one power series.
EXAMPLES::
sage: L = LazyPowerSeriesRing(QQ) sage: L.identity_element() 1 """
def gen(self, i=0): """ EXAMPLES::
sage: L = LazyPowerSeriesRing(QQ) sage: L.gen().coefficients(5) [0, 1, 0, 0, 0] """
def term(self, 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] """ raise ValueError("n must be non-negative") else:
else:
def _new_initial(self, order, stream): """ Returns a new power series with specified order.
INPUT:
- ``order`` - a non-negative integer
- ``stream`` - a Stream object
EXAMPLES::
sage: from sage.combinat.species.stream import Stream sage: L = LazyPowerSeriesRing(QQ) sage: L._new_initial(0, Stream([1,2,3,0])).coefficients(5) [1, 2, 3, 0, 0] """ aorder_changed=False, is_initialized=True)
def _sum_gen(self, series_list): """ Return a generator for the coefficients of the sum of the lazy power series in series_list.
INPUT:
- ``series_list`` - a list of lazy power series
EXAMPLES::
sage: L = LazyPowerSeriesRing(QQ) sage: series_list = [ L([1]), L([0,1]), L([0,0,1]) ] sage: g = L._sum_gen(series_list) sage: [next(g) for i in range(5)] [1, 2, 3, 3, 3] """
def sum(self, 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] """
#Potentially infinite sum def _sum_generator_gen(self, g): """ EXAMPLES::
sage: L = LazyPowerSeriesRing(QQ) sage: s = L([1]) sage: def f(): ....: while True: ....: yield s sage: g = L._sum_generator_gen(f()) sage: [next(g) for i in range(10)] [1, 2, 3, 4, 5, 6, 7, 8, 9, 10] """
def sum_generator(self, 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] """
#Potentially infinite product def _product_generator_gen(self, g): """ EXAMPLES::
sage: from sage.combinat.species.stream import _integers_from sage: L = LazyPowerSeriesRing(QQ) sage: g = (L([1]+[0]*i+[1]) for i in _integers_from(0)) sage: g2 = L._product_generator_gen(g) sage: [next(g2) for i in range(10)] [1, 1, 2, 4, 7, 12, 20, 33, 53, 84] """
def product_generator(self, 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] """
class LazyPowerSeries(AlgebraElement): def __init__(self, A, stream=None, order=None, aorder=None, aorder_changed=True, is_initialized=False, name=None): """ EXAMPLES::
sage: L = LazyPowerSeriesRing(QQ) sage: f = L() sage: loads(dumps(f)) Uninitialized lazy power series """
def 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 """
def _get_repr_info(self, x): """ EXAMPLES::
sage: L = LazyPowerSeriesRing(QQ) sage: a = L([1,2,3]) sage: a.compute_coefficients(5) sage: a._get_repr_info('x') [('1', 1), ('x', 2), ('x^2', 3)] """
def __repr__(self): """ EXAMPLES::
sage: L = LazyPowerSeriesRing(QQ) sage: s = L(); s._name = 's'; s s
::
sage: L() Uninitialized lazy power series
::
sage: a = L([1,2,3]) sage: a O(1) sage: a.compute_coefficients(2) sage: a 1 + 2*x + 3*x^2 + O(x^3) sage: a.compute_coefficients(4) sage: a 1 + 2*x + 3*x^2 + 3*x^3 + 3*x^4 + 3*x^5 + ...
::
sage: a = L([1,2,3,0]) sage: a.compute_coefficients(5) sage: a 1 + 2*x + 3*x^2 """
else: else: else:
def refine_aorder(self): """ 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 """ #If we already know the order, then we don't have #to worry about the approximate order
#aorder can never be infinity since order would have to #be infinity as well
else: #Try to improve the approximate order
else:
#Try to recognize the zero series #For non-constant series, we cannot do anything
self._reference._copy(self)
def initialize_coefficient_stream(self, 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] """
else:
def compute_coefficients(self, 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 + ... """
def coefficients(self, 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] """
def is_zero(self): """ 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 """
def set_approximate_order(self, 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 """
def _copy(self, x): """ EXAMPLES::
sage: L = LazyPowerSeriesRing(QQ) sage: f = L.term(2, 2) sage: g = L() sage: g._copy(f) sage: g.order 2 sage: g.aorder 2 sage: g.is_initialized True sage: g.coefficients(4) [0, 0, 2, 0] """
def define(self, 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] """
def coefficient(self, 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] """ # The following line must not be written n < self.get_aorder() # because comparison of Integer and OnfinityOrder is not implemented.
def get_aorder(self): """ Returns the approximate order of self.
EXAMPLES::
sage: L = LazyPowerSeriesRing(QQ) sage: a = L.gen() sage: a.get_aorder() 1 """
def get_order(self): """ Returns the order of self.
EXAMPLES::
sage: L = LazyPowerSeriesRing(QQ) sage: a = L.gen() sage: a.get_order() 1 """
def get_stream(self): """ 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] """
def _approximate_order(self, compute_coefficients, new_order, *series):
must_initialize_coefficient_stream = True tchanged = ochanged = False else: raise ValueError
def _new(self, compute_coefficients, order_op, *series, **kwds): aorder_changed=True, is_initialized=False)
def _add_(self, 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] """
add = _add_
def _plus_gen(self, y, ao): """ EXAMPLES::
sage: L = LazyPowerSeriesRing(QQ) sage: gs1 = L([1]) sage: g = gs1._plus_gen(gs1, 0) sage: [next(g) for i in range(5)] [2, 2, 2, 2, 2]
::
sage: g = gs1._plus_gen(gs1, 2) sage: [next(g) for i in range(5)] [0, 0, 2, 2, 2] """
def _mul_(self, 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] """
times = _mul_
def _times_gen(self, y, ao): """ Returns an iterator for the coefficients of self \* y.
EXAMPLES::
sage: L = LazyPowerSeriesRing(QQ) sage: f = L([1,1,0]) sage: g = f._times_gen(f,0) sage: [next(g) for i in range(5)] [1, 2, 1, 0, 0] """
#Handle the zero series yield zero n += 1 continue
def __pow__(self, n): """ EXAMPLES::
sage: L = LazyPowerSeriesRing(QQ) sage: f = L([1,1,0]) # 1+x sage: g = f^3 sage: g.coefficients(4) [1, 3, 3, 1]
::
sage: f^0 1 """ raise ValueError("n must be a nonnegative integer")
def __call__(self, 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 = __call__
def _compose_gen(self, y, ao): """ Returns a iterator for the coefficients of the composition of this power series with the power series y.
EXAMPLES::
sage: L = LazyPowerSeriesRing(QQ) sage: s = L([1]) sage: t = L([0,1]) sage: g = s._compose_gen(t, 0) sage: [next(g) for i in range(10)] [1, 1, 2, 4, 8, 16, 32, 64, 128, 256] """
def tail(self): """ 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] """
def iterator(self, 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: [next(g) for i in range(5)] [2, 3, 4, 5, 6] sage: g = f.iterator(2, initial=[0,0]) sage: [next(g) for i in range(5)] [0, 0, 2, 3, 4] """
compose = __call__
def _power_gen(self): """ Returns a generator for all the powers self^k starting with k = 1.
EXAMPLES::
sage: L = LazyPowerSeriesRing(QQ) sage: f = L([1,1,0]) sage: g = f._power_gen() sage: next(g).coefficients(5) [1, 1, 0, 0, 0] sage: next(g).coefficients(5) [1, 2, 1, 0, 0] sage: next(g).coefficients(5) [1, 3, 3, 1, 0] """
def derivative(self): """ 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] """
def _diff_gen(self, ao): """ Returns an iterator for the coefficients of the derivative of self.
EXAMPLES::
sage: L = LazyPowerSeriesRing(QQ) sage: f = L([1]) sage: g = f._diff_gen(0) sage: [next(g) for i in range(10)] [1, 2, 3, 4, 5, 6, 7, 8, 9, 10] """
########### #Integrals# ########### def integral(self, 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] """ else:
def _integral_zero_gen(self, ao): """ EXAMPLES::
sage: L = LazyPowerSeriesRing(QQ) sage: s = L.gen() sage: g = s._integral_zero_gen(1) sage: [next(g) for i in range(5)] [0, 0, 1/2, 0, 0] """ #Check to see if the stream is finite else:
def _integral_nonzero_gen(self, integration_constant): """ EXAMPLES::
sage: from sage.combinat.species.stream import Stream sage: L = LazyPowerSeriesRing(QQ) sage: f = L._new_initial(2, Stream([0,0,4,5,6,0])).derivative() sage: g = f._integral_nonzero_gen(1) sage: [next(g) for i in range(5)] [1, 0, 4, 5, 6] """
else:
#Check to see if the stream is finite else:
def is_finite(self, 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 """ return True
def exponential(self): """ 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*next(g) 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 """
def __getitem__(self, i): """ Returns the ith coefficient of self.
EXAMPLES::
sage: L = LazyPowerSeriesRing(QQ) sage: f = L([1,2,3,0]) sage: [f[i] for i in range(5)] [1, 2, 3, 0, 0] """
######################### #Min and max restriction# ######################### def restricted(self, 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] """ (max is None and self.get_aorder() >= min)):
lambda ao: builtins.max(ao, min), self)
def _restricted_gen(self, mn, mx, ao): """ EXAMPLES::
sage: L = LazyPowerSeriesRing(QQ) sage: a = L([1]) sage: g = a._restricted_gen(None, None, 2) sage: [next(g) for i in range(10)] [0, 0, 1, 1, 1, 1, 1, 1, 1, 1] sage: g = a._restricted_gen(1, None, 2) sage: [next(g) for i in range(10)] [0, 0, 1, 1, 1, 1, 1, 1, 1, 1] sage: g = a._restricted_gen(3, None, 2) sage: [next(g) for i in range(10)] [0, 0, 0, 1, 1, 1, 1, 1, 1, 1]
::
sage: g = a._restricted_gen(1, 5, 2) sage: [next(g) for i in range(6)] [0, 0, 1, 1, 1, 0] """
else:
############# #Change Ring# ############# def _change_ring_gen(self, R, ao): """ EXAMPLES::
sage: L = LazyPowerSeriesRing(QQ) sage: L2 = LazyPowerSeriesRing(RR) sage: a = L([1]) sage: b = L2(a) sage: b.parent() Lazy Power Series Ring over Real Field with 53 bits of precision sage: b.coefficients(3) [1.00000000000000, 1.00000000000000, 1.00000000000000] """ yield R(0)
#################################
def uninitialized(): """ EXAMPLES::
sage: from sage.combinat.species.series import uninitialized sage: uninitialized() Traceback (most recent call last): ... RuntimeError: we should never be here """ |