diff --git a/src/sage/rings/lazy_series.py b/src/sage/rings/lazy_series.py index 043290a333b..9b23aaf2dd0 100644 --- a/src/sage/rings/lazy_series.py +++ b/src/sage/rings/lazy_series.py @@ -1,9 +1,16 @@ # -*- coding: utf-8 -*- -r"""Lazy Series +r""" +Lazy Series -A lazy series is a series whose coefficients are computed on demand. -Therefore, unlike the usual Laurent/power/etc. series in Sage, -lazy series have infinite precision. +Coefficients of lazy series are computed on demand. They have +infinite precision, although equality can only be decided in special +cases. + +AUTHORS: + +- Kwankyu Lee (2019-02-24): initial version +- Tejasvi Chebrolu, Martin Rubey, Travis Scrimshaw (2021-08): + refactored and expanded functionality EXAMPLES: @@ -93,12 +100,6 @@ sage: hinv.valuation() -1 -AUTHORS: - -- Kwankyu Lee (2019-02-24): initial version -- Tejasvi Chebrolu, Martin Rubey, Travis Scrimshaw (2021-08): - refactored and expanded functionality - """ # **************************************************************************** @@ -762,6 +763,9 @@ def define(self, s): raise ValueError("series already defined") self._coeff_stream._target = s._coeff_stream + # an alias for compatibility with padics + set = define + def _repr_(self): r""" Return a string representation of ``self``. diff --git a/src/sage/rings/lazy_series_ring.py b/src/sage/rings/lazy_series_ring.py index a8076af2e74..0545ffbb03f 100644 --- a/src/sage/rings/lazy_series_ring.py +++ b/src/sage/rings/lazy_series_ring.py @@ -1,6 +1,18 @@ r""" Lazy Series Rings +We provide lazy implementations for various `\NN`-graded rings. + +.. csv-table:: + :class: contentstable + :widths: 30, 70 + :delim: | + + :class:`LazyLaurentSeriesRing` | The ring of lazy Laurent series. + :class:`LazyTaylorSeriesRing` | The ring of (possibly multivariate) lazy Taylor series. + :class:`LazySymmetricFunctions` | The ring of (possibly multivariate) lazy symmetric functions. + :class:`LazyDirichletSeriesRing` | The ring of lazy Dirichlet series. + AUTHORS: - Kwankyu Lee (2019-02-24): initial version @@ -34,7 +46,6 @@ from sage.rings.integer_ring import ZZ from sage.rings.polynomial.laurent_polynomial_ring import LaurentPolynomialRing from sage.rings.polynomial.polynomial_ring_constructor import PolynomialRing -from sage.combinat.sf.sf import SymmetricFunctions from sage.rings.lazy_series import (LazyModuleElement, LazyLaurentSeries, LazyTaylorSeries, @@ -430,6 +441,74 @@ def _element_constructor_(self, x=None, valuation=None, degree=None, constant=No raise ValueError(f"unable to convert {x} into {self}") + def unknown(self, valuation=None): + """ + Return an uninitialized series. + + INPUT: + + - ``valuation`` -- integer; a lower bound for the valuation of the series + + Power series can be defined recursively (see + :meth:`sage.rings.lazy_series.LazyModuleElement.define()` for + more examples):: + + EXAMPLES:: + + sage: L. = LazyTaylorSeriesRing(QQ) + sage: s = L.unknown(1) + sage: s.define(z + (s^2+s(z^2))/2) + sage: s + z + z^2 + z^3 + 2*z^4 + 3*z^5 + 6*z^6 + 11*z^7 + O(z^8) + """ + return self(None, valuation=valuation) + + class options(GlobalOptions): + r""" + Set and display the options for Lazy Laurent series. + + If no parameters are set, then the function returns a copy of + the options dictionary. + + The ``options`` to Lazy Laurent series can be accessed as using + :class:`LazyLaurentSeriesRing.options` of :class:`LazyLaurentSeriesRing`. + + @OPTIONS@ + + EXAMPLES:: + + sage: LLS. = LazyLaurentSeriesRing(QQ) + sage: LLS.options.display_length + 7 + sage: f = 1 / (1 + z) + sage: f + 1 - z + z^2 - z^3 + z^4 - z^5 + z^6 + O(z^7) + sage: LLS.options.display_length = 10 + sage: f + 1 - z + z^2 - z^3 + z^4 - z^5 + z^6 - z^7 + z^8 - z^9 + O(z^10) + sage: g = LLS(lambda n: n^2, valuation=-2, degree=5, constant=42) + sage: g + 4*z^-2 + z^-1 + z + 4*z^2 + 9*z^3 + 16*z^4 + 42*z^5 + 42*z^6 + 42*z^7 + O(z^8) + sage: h = 1 / (1 - z) # This is exact + sage: h + 1 + z + z^2 + O(z^3) + sage: LLS.options.constant_length = 1 + sage: g + 4*z^-2 + z^-1 + z + 4*z^2 + 9*z^3 + 16*z^4 + 42*z^5 + O(z^6) + sage: h + 1 + O(z) + sage: LazyLaurentSeriesRing.options._reset() + sage: LazyLaurentSeriesRing.options.display_length + 7 + """ +# NAME = 'LazyLaurentSeriesRing' + module = 'sage.rings.lazy_series_ring' + display_length = dict(default=7, + description='the number of coefficients to display from the valuation', + checker=lambda x: x in ZZ and x > 0) + constant_length = dict(default=3, + description='the number of coefficients to display for nonzero constant series', + checker=lambda x: x in ZZ and x > 0) class LazyLaurentSeriesRing(LazySeriesRing): """ @@ -537,7 +616,8 @@ class LazyLaurentSeriesRing(LazySeriesRing): sage: L(f, valuation=1, degree=4, constant=5) z - z^2 + z^3 + 5*z^4 + 5*z^5 + 5*z^6 + O(z^7) - Power series can be defined recursively (see :meth:`define()` for + Power series can be defined recursively (see + :meth:`sage.rings.lazy_series.LazyModuleElement.define()` for more examples):: sage: L. = LazyLaurentSeriesRing(ZZ) @@ -576,6 +656,7 @@ class LazyLaurentSeriesRing(LazySeriesRing): sage: L. = LazyLaurentSeriesRing(ZZ, sparse=False) sage: L.is_sparse() False + """ Element = LazyLaurentSeries @@ -852,54 +933,6 @@ def zero(self): """ return self.element_class(self, Stream_zero(self._sparse)) - # add options to class - class options(GlobalOptions): - r""" - Set and display the options for Lazy Laurent series. - - If no parameters are set, then the function returns a copy of - the options dictionary. - - The ``options`` to Lazy Laurent series can be accessed as using - :class:`LazyLaurentSeriesRing.options` of :class:`LazyLaurentSeriesRing`. - - @OPTIONS@ - - EXAMPLES:: - - sage: LLS. = LazyLaurentSeriesRing(QQ) - sage: LLS.options.display_length - 7 - sage: f = 1 / (1 + z) - sage: f - 1 - z + z^2 - z^3 + z^4 - z^5 + z^6 + O(z^7) - sage: LLS.options.display_length = 10 - sage: f - 1 - z + z^2 - z^3 + z^4 - z^5 + z^6 - z^7 + z^8 - z^9 + O(z^10) - sage: g = LLS(lambda n: n^2, valuation=-2, degree=5, constant=42) - sage: g - 4*z^-2 + z^-1 + z + 4*z^2 + 9*z^3 + 16*z^4 + 42*z^5 + 42*z^6 + 42*z^7 + O(z^8) - sage: h = 1 / (1 - z) # This is exact - sage: h - 1 + z + z^2 + O(z^3) - sage: LLS.options.constant_length = 1 - sage: g - 4*z^-2 + z^-1 + z + 4*z^2 + 9*z^3 + 16*z^4 + 42*z^5 + O(z^6) - sage: h - 1 + O(z) - sage: LazyLaurentSeriesRing.options._reset() - sage: LazyLaurentSeriesRing.options.display_length - 7 - """ - NAME = 'LazyLaurentSeriesRing' - module = 'sage.rings.lazy_series_ring' - display_length = dict(default=7, - description='the number of coefficients to display from the valuation', - checker=lambda x: x in ZZ and x > 0) - constant_length = dict(default=3, - description='the number of coefficients to display for nonzero constant series', - checker=lambda x: x in ZZ and x > 0) - def series(self, coefficient, valuation, degree=None, constant=None): r""" Return a lazy Laurent series. @@ -1003,9 +1036,9 @@ def _monomial(self, c, n): ###################################################################### -class LazyTaylorSeriesRing(UniqueRepresentation, Parent): +class LazyTaylorSeriesRing(LazySeriesRing): """ - Lazy Taylor series ring. + The ring of (possibly multivariate) lazy Taylor series. INPUT: @@ -1292,7 +1325,7 @@ def _element_constructor_(self, x=None, valuation=None, constant=None, degree=No if valuation < 0: raise ValueError("the valuation of a Taylor series must be positive") if len(self.variable_names()) > 1: - raise ValueError(f"valuation must not be specified for multivariate Taylor series") + raise ValueError("valuation must not be specified for multivariate Taylor series") if len(self.variable_names()) > 1: valuation = 0 @@ -1311,7 +1344,7 @@ def _element_constructor_(self, x=None, valuation=None, constant=None, degree=No constant, degree = constant if constant is not None: if len(self.variable_names()) > 1 and constant: - raise ValueError(f"constant must be zero for multivariate Taylor series") + raise ValueError("constant must be zero for multivariate Taylor series") constant = BR(constant) if x in R: if not x and not constant: @@ -1353,7 +1386,6 @@ def _element_constructor_(self, x=None, valuation=None, constant=None, degree=No if degree is not None: if constant is None: constant = ZZ.zero() - z = R.gen() if len(self.variable_names()) == 1: p = [BR(x(i)) for i in range(valuation, degree)] else: @@ -1422,13 +1454,11 @@ def zero(self): """ return self.element_class(self, Stream_zero(self._sparse)) - options = LazyLaurentSeriesRing.options - ###################################################################### -class LazySymmetricFunctions(UniqueRepresentation, Parent): +class LazySymmetricFunctions(LazySeriesRing): """ - Lazy symmetric functions. + The ring of lazy symmetric functions. INPUT: @@ -1636,7 +1666,6 @@ def _element_constructor_(self, x=None, valuation=None, degree=None, check=True) R = self._laurent_poly_ring - BR = self.base_ring() if x is None: assert degree is None coeff_stream = Stream_uninitialized(self._sparse, valuation) @@ -1741,7 +1770,6 @@ def _an_element_(self): sage: L.an_element() m[] """ - c = self.base_ring()(1) R = self._laurent_poly_ring coeff_stream = Stream_exact([R.one()], self._sparse, order=1, constant=0) return self.element_class(self, coeff_stream) @@ -1776,13 +1804,11 @@ def zero(self): """ return self.element_class(self, Stream_zero(self._sparse)) - options = LazyLaurentSeriesRing.options - ###################################################################### class LazyDirichletSeriesRing(LazySeriesRing): """ - Lazy Dirichlet series ring. + The ring of lazy Dirichlet series. INPUT: @@ -2056,5 +2082,3 @@ def _monomial(self, c, n): except (ValueError, TypeError): return '({})/{}^{}'.format(self.base_ring()(c), n, self.variable_name()) - options = LazyLaurentSeriesRing.options -