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.ModuleElementReturn a lazy Laurent series.
INPUT:
coefficient– Python function that computes coefficientsvaluation– integer; approximate valuation of the seriesconstant– eitherNoneor 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
coefficientreturns the value of the coefficient of index \(i\) from input \(s\) and \(i\) where \(s\) is the series itself.Let
valuationbe \(n\). All coefficients of index below \(n\) are zero. IfconstantisNone, then thecoefficientfunction is responsible to compute the values of all coefficients of index \(\ge n\). Ifconstantis a pair \((c,m)\), then thecoefficientfunction 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
functionapplied to each coefficient of this series.INPUT:
function– Python function
Python function
functionreturns 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
precapproximated 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
precEXAMPLES:
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
nof 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–Noneor 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
degreeis notNone, the terms of the series of degree greater thandegreeare truncated first. IfdegreeisNoneand the series is not a polynomial or a Laurent polynomial, aValueErroris 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 >=
dtruncated.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