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 \(\ge n\). Ifconstant
is a pair \((c,m)\), then thecoefficient
function is responsible to compute the values of all coefficients of index \(\ge n\) and \(< m\) and all the coefficients of index \(\ge 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