Lazy Laurent Series¶
A lazy Laurent series is a Laurent series whose coefficients are computed as demanded or needed. Unlike the usual Laurent series in Sage, lazy Laurent series do not have precisions because a lazy Laurent series knows (can be computed, lazily) all its coefficients.
EXAMPLES:
Generating functions are Laurent series over the integer ring:
sage: L.<z> = LazyLaurentSeriesRing(ZZ)
This defines the generating function of Fibonacci sequence:
sage: def coeff(s, i):
....: if i in [0, 1]:
....: return 1
....: else:
....: return s.coefficient(i - 1) + s.coefficient(i - 2)
sage: f = L.series(coeff, valuation=0); f
1 + z + 2*z^2 + 3*z^3 + 5*z^4 + 8*z^5 + 13*z^6 + ...
The 100th element of Fibonacci sequence can be obtained from the generating function:
sage: f.coefficient(100)
573147844013817084101
Coefficients are computed and cached only when necessary:
sage: f._cache[100]
573147844013817084101
sage: f._cache[101]
Traceback (most recent call last):
...
KeyError: 101
You can do arithmetic with lazy power series:
sage: f
1 + z + 2*z^2 + 3*z^3 + 5*z^4 + 8*z^5 + 13*z^6 + ...
sage: f^-1
1 - z - z^2 + ...
sage: f + f^-1
2 + z^2 + 3*z^3 + 5*z^4 + 8*z^5 + 13*z^6 + ...
sage: g = (f + f^-1)*(f - f^-1); g
4*z + 6*z^2 + 8*z^3 + 19*z^4 + 38*z^5 + 71*z^6 + ...
You may need to change the base ring:
sage: h = g.change_ring(QQ)
sage: h.parent()
Lazy Laurent Series Ring in z over Rational Field
sage: h
4*z + 6*z^2 + 8*z^3 + 19*z^4 + 38*z^5 + 71*z^6 + ...
sage: h^-1
1/4*z^-1 - 3/8 + 1/16*z - 17/32*z^2 + 5/64*z^3 - 29/128*z^4 + 165/256*z^5 + ...
sage: _.valuation()
-1
AUTHORS:
Kwankyu Lee (2019-02-24): initial version
- class sage.rings.lazy_laurent_series.LazyLaurentSeries(parent, coefficient=None, valuation=0, constant=None)¶
Bases:
sage.structure.element.ModuleElement
Return a lazy Laurent series.
INPUT:
coefficient
– Python function that computes coefficientsvaluation
– integer; approximate valuation of the seriesconstant
– eitherNone
or pair of an element of the base ring and an integer
Let the coefficient of index i mean the coefficient of the term of the series with exponent i.
Python function
coefficient
returns the value of the coefficient of index i from input s and i where s is the series itself.Let
valuation
be n. All coefficients of index below n are zero. Ifconstant
isNone
, then thecoefficient
function is responsible to compute the values of all coefficients of index ≥n. Ifconstant
is a pair (c,m), then thecoefficient
function is responsible to compute the values of all coefficients of index ≥n and <m and all the coefficients of index ≥m is the constant c.EXAMPLES:
sage: L = LazyLaurentSeriesRing(ZZ, 'z') sage: L.series(lambda s, i: i, valuation=-3, constant=(-1,3)) -3*z^-3 - 2*z^-2 - z^-1 + z + 2*z^2 - z^3 - z^4 - z^5 + ...
sage: def coeff(s, i): ....: if i in [0, 1]: ....: return 1 ....: else: ....: return s.coefficient(i - 1) + s.coefficient(i - 2) sage: f = L.series(coeff, valuation=0); f 1 + z + 2*z^2 + 3*z^3 + 5*z^4 + 8*z^5 + 13*z^6 + ... sage: f.coefficient(100) 573147844013817084101
Lazy Laurent series is picklable:
sage: z = L.gen() sage: f = 1/(1 - z - z^2) sage: f 1 + z + 2*z^2 + 3*z^3 + 5*z^4 + 8*z^5 + 13*z^6 + ... sage: g = loads(dumps(f)) sage: g 1 + z + 2*z^2 + 3*z^3 + 5*z^4 + 8*z^5 + 13*z^6 + ... sage: g == f True
- apply_to_coefficients(function)¶
Return the series with
function
applied to each coefficient of this series.INPUT:
function
– Python function
Python function
function
returns a new coefficient for input coefficient.EXAMPLES:
sage: L.<z> = LazyLaurentSeriesRing(ZZ) sage: s = z/(1 - 2*z) sage: t = s.apply_to_coefficients(lambda c: c + 1) sage: s z + 2*z^2 + 4*z^3 + 8*z^4 + 16*z^5 + 32*z^6 + 64*z^7 + ... sage: t 2*z + 3*z^2 + 5*z^3 + 9*z^4 + 17*z^5 + 33*z^6 + 65*z^7 + ...
- approximate_series(prec, name=None)¶
Return the Laurent series with absolute precision
prec
approximated from this series.INPUT:
prec
– an integername
– name of the variable; if it isNone
, the name of the variable of the series is used
OUTPUT: a Laurent series with absolute precision
prec
EXAMPLES:
sage: L = LazyLaurentSeriesRing(ZZ, 'z') sage: z = L.gen() sage: f = (z - 2*z^3)^5/(1 - 2*z) sage: f z^5 + 2*z^6 - 6*z^7 - 12*z^8 + 16*z^9 + 32*z^10 - 16*z^11 + ... sage: g = f.approximate_series(10) sage: g z^5 + 2*z^6 - 6*z^7 - 12*z^8 + 16*z^9 + O(z^10) sage: g.parent() Power Series Ring in z over Integer Ring
sage: h = (f^-1).approximate_series(3) sage: h z^-5 - 2*z^-4 + 10*z^-3 - 20*z^-2 + 60*z^-1 - 120 + 280*z - 560*z^2 + O(z^3) sage: h.parent() Laurent Series Ring in z over Integer Ring
- change_ring(ring)¶
Return this series with coefficients converted to elements of
ring
.INPUT:
ring
– a ring
EXAMPLES:
sage: L.<z> = LazyLaurentSeriesRing(ZZ) sage: s = 2 + z sage: t = s.change_ring(QQ) sage: t^-1 1/2 - 1/4*z + 1/8*z^2 - 1/16*z^3 + 1/32*z^4 - 1/64*z^5 + 1/128*z^6 + ...
- coefficient(n)¶
Return the coefficient of the term with exponent
n
of the series.INPUT:
n
– integer
EXAMPLES:
sage: L = LazyLaurentSeriesRing(ZZ, 'z') sage: def g(s, i): ....: if i == 0: ....: return 1 ....: else: ....: return sum(s.coefficient(j)*s.coefficient(i - 1 -j) for j in [0..i-1]) sage: e = L.series(g, valuation=0) sage: e.coefficient(10) 16796 sage: e 1 + z + 2*z^2 + 5*z^3 + 14*z^4 + 42*z^5 + 132*z^6 + ...
- polynomial(degree=None, name=None)¶
Return the polynomial or Laurent polynomial if the series is actually so.
INPUT:
degree
–None
or an integername
– name of the variable; if it isNone
, the name of the variable of the series is used
OUTPUT: a Laurent polynomial if the valuation of the series is negative or a polynomial otherwise.
If
degree
is notNone
, the terms of the series of degree greater thandegree
are truncated first. Ifdegree
isNone
and the series is not a polynomial or a Laurent polynomial, aValueError
is raised.EXAMPLES:
sage: L = LazyLaurentSeriesRing(ZZ, 'z') sage: f = L.series([1,0,0,2,0,0,0,3], 5); f z^5 + 2*z^8 + 3*z^12 sage: f.polynomial() 3*z^12 + 2*z^8 + z^5
sage: g = L.series([1,0,0,2,0,0,0,3], -5); g z^-5 + 2*z^-2 + 3*z^2 sage: g.polynomial() z^-5 + 2*z^-2 + 3*z^2
sage: z = L.gen() sage: f = (1 + z)/(z^3 - z^5) sage: f z^-3 + z^-2 + z^-1 + 1 + z + z^2 + z^3 + ... sage: f.polynomial(5) z^-3 + z^-2 + z^-1 + 1 + z + z^2 + z^3 + z^4 + z^5 sage: f.polynomial(0) z^-3 + z^-2 + z^-1 + 1 sage: f.polynomial(-5) 0
- prec()¶
Return the precision of the series, which is infinity.
EXAMPLES:
sage: L.<z> = LazyLaurentSeriesRing(ZZ) sage: f = 1/(1 - z) sage: f.prec() +Infinity
- truncate(d)¶
Return this series with its terms of degree >=
d
truncated.INPUT:
d
– integer
EXAMPLES:
sage: L.<z> = LazyLaurentSeriesRing(ZZ) sage: alpha = 1/(1-z) sage: alpha 1 + z + z^2 + z^3 + z^4 + z^5 + z^6 + ... sage: beta = alpha.truncate(5) sage: beta 1 + z + z^2 + z^3 + z^4 sage: alpha - beta z^5 + z^6 + z^7 + z^8 + z^9 + z^10 + z^11 + ...
- valuation()¶
Return the valuation of the series.
This method determines the valuation of the series by looking for a nonzero coefficient. Hence if the series happens to be zero, then it may run forever.
EXAMPLES:
sage: L.<z> = LazyLaurentSeriesRing(ZZ) sage: s = 1/(1 - z) - 1/(1 - 2*z) sage: s.valuation() 1 sage: t = z - z sage: t.valuation() +Infinity