Ticket #14814: trac_14814-review-2-dg.patch

File trac_14814-review-2-dg.patch, 19.7 KB (added by darij, 8 years ago)

another review patch, atop of the previous one

  • sage/rings/multi_power_series_ring.py

    # HG changeset patch
    # User darij grinberg <darijgrinberg@gmail.com>
    # Date 1384330716 28800
    # Node ID 30cbf3f732b0f3b87b525c61993c43b13e8175b6
    # Parent  0c6554481464056d480e56ed0731d642c6be82e8
    trac #14814: review patch
    
    diff --git a/sage/rings/multi_power_series_ring.py b/sage/rings/multi_power_series_ring.py
    a b  
    11r"""
    2 Multivariate Power Series Rings
     2Multivariate Power Series Rings.
    33
    4 Construct a multivariate power series ring over a given (commutative) base ring.
     4Construct a multivariate power series ring (in finitely many variables)
     5over a given (commutative) base ring.
    56
    67EXAMPLES:
    78
    Coercion from symbolic ring:: 
    172173    Multivariate Power Series Ring in x, y over Finite Field of size 11
    173174    sage: f.parent() == S
    174175    True
    175    
     176
     177The implementation of the multivariate power series ring uses a combination
     178of multivariate polynomials and univariate power series. Namely, in order
     179to construct the multivariate power series ring `R[[x_1, x_2, \cdots, x_n]]`,
     180we consider the univariate power series ring `S[[T]]` over the multivariate
     181polynomial ring `S := R[x_1, x_2, \cdots, x_n]`, and in it we take the
     182subring formed by all power series whose `i`-th coefficient has degree `i`
     183for all `i \geq 0`. This subring is isomorphic to
     184`R[[x_1, x_2, \cdots, x_n]]`. This is how `R[[x_1, x_2, \cdots, x_n]]` is
     185implemented in this class. The ring `S` is called the foreground polynomial
     186ring, and the ring `S[[T]]` is called the background univariate power
     187series ring.
    176188
    177189AUTHORS:
    178190
    class MPowerSeriesRing_generic(PowerSeri 
    969981            sage: T.O(10)
    970982            0 + O(a, b)^10           
    971983        """
    972         return self(0).O(prec)
     984        return self.zero().O(prec)
    973985
    974986    def O(self,prec):
    975987        """
  • sage/rings/multi_power_series_ring_element.py

    diff --git a/sage/rings/multi_power_series_ring_element.py b/sage/rings/multi_power_series_ring_element.py
    a b  
    11r"""
    2 Multivariate Power Series
     2Multivariate Power Series.
    33
    4 Construct and manipulate multivariate power series over a given commutative
    5 ring. Multivariate power series are implemented with total-degree precision.
     4Construct and manipulate multivariate power series (in finitely many
     5variables) over a given commutative ring. Multivariate power series
     6are implemented with total-degree precision.
    67
    78EXAMPLES:
    89
    Calling:: 
    5960    s*t + t^2 + s*t^2 + t^3 + 3*s*t^3 + 3*t^4 + O(s, t)^5
    6061    sage: f(t^2,s^2)
    6162    s^2*t^2 + t^4 + s^2*t^4 + t^6 + 3*s^2*t^6 + 3*t^8 + O(s, t)^10
    62    
     63
    6364Substitution is defined only for elements of positive valuation, unless `f`
    6465has infinite precision::
    6566
    has infinite precision:: 
    7677    t^2 + s^2*t^2 + 2*t^4 + O(s, t)^5
    7778
    78790 has valuation ``+Infinity``::
    79    
     80
    8081    sage: f(t^2,0)
    8182    t^4 + t^6 + 3*t^8 + O(s, t)^10
    8283    sage: f(t^2,s^2+s)
    Substitution of power series with finite 
    9495    sage: t(0,f) == s(f,0)
    9596    True
    9697
    97 Subs works as expected::
     98The ``subs`` syntax works as expected::
    9899
    99100    sage: r0 = -t^2 - s*t^3 - 2*t^6 + s^7 + s^5*t^2 + R.O(10)
    100101    sage: r1 = s^4 - s*t^4 + s^6*t - 4*s^2*t^5 - 6*s^3*t^5 + R.O(10)
    Construct ring homomorphisms from one po 
    120121    sage: phi(a+b+3*a*b^2 + A.O(5))
    121122    x + 2*y + 12*x*y^2 + O(x, y)^5
    122123
    123 
    124 Inversion::
     124Multiplicative inversion of power series::
    125125
    126126    sage: h = 1 + s + t + s*t + s^2*t^2 + 3*s^4 + 3*s^3*t + R.O(5);
    127127    sage: k = h^-1; k
    Inversion:: 
    142142    sage: h*f
    143143    1 + O(s, t)^101
    144144
    145 
    146 
    147145AUTHORS:
    148146
    149147- Niles Johnson (07/2010): initial code
    from sage.rings.infinity import infinity 
    171169
    172170def is_MPowerSeries(f):
    173171    """
    174     Return ``True`` if input is a multivariate power series.
     172    Return ``True`` if ``f`` is a multivariate power series.
    175173
    176174    TESTS::
    177175
    def is_MPowerSeries(f): 
    187185        False
    188186        sage: is_PowerSeries(1 - v + v^2 +O(v^3))
    189187        True
    190 
    191         """
     188    """
    192189
    193190    return isinstance(f, MPowerSeries)
    194191
    class MPowerSeries(PowerSeries): 
    793790
    794791    def trailing_monomial(self):
    795792        """
    796         Return the trailing monomial of ``self``
     793        Return the trailing monomial of ``self``.
    797794
    798795        This is defined here as the lowest term of the underlying polynomial.
    799796
    800         EXAMPLE::
     797        EXAMPLES::
    801798
    802799            sage: R.<a,b,c> = PowerSeriesRing(ZZ)
    803800            sage: f = 1 + a + b - a*b + R.O(3)
    class MPowerSeries(PowerSeries): 
    815812        """
    816813        return self.polynomial().lt()
    817814
    818     def quo_rem(self, other):
     815    def quo_rem(self, other, precision=None):
    819816        r"""
    820         Quotient and remainder for increasing power division
     817        Return the pair of quotient and remainder for the increasing power
     818        division of ``self`` by ``other``.
    821819
    822         INPUT: ``other`` - an element of the same power series ring as ``self``
     820        If `a` and `b` are two elements of a power series ring
     821        `R[[x_1, x_2, \cdots, x_n]]` such that the trailing term of
     822        `b` is invertible in `R`, then the pair of quotient and
     823        remainder for the increasing power division of `a` by `b` is
     824        the unique pair `(u, v) \in R[[x_1, x_2, \cdots, x_n]] \times
     825        R[x_1, x_2, \cdots, x_n]` such that `a = bu + v` and such that
     826        no monomial appearing in `v` divides the trailing monomial
     827        (:meth:`trailing_monomial`) of `b`. Note that this depends on
     828        the order of the variables.
    823829
    824         EXAMPLE::
     830        This method returns both quotient and remainder as power series,
     831        even though in mathematics, the remainder for the increasing
     832        power division of two power series is a polynomial. This is
     833        because Sage's power series come with a precision, and that
     834        precision is not always sufficient to determine the remainder
     835        completely. Disregarding this issue, the :meth:`polynomial`
     836        method can be used to recast the remainder as an actual
     837        polynomial.
     838
     839        INPUT:
     840
     841        - ``other`` -- an element of the same power series ring as
     842          ``self`` such that the trailing term of ``other`` is
     843          invertible in ``self`` (this is automatically satisfied
     844          if the base ring is a field, unless ``other`` is zero)
     845
     846        - ``precision`` -- (default: the default precision of the
     847          parent of ``self``) nonnegative integer, determining the
     848          precision to be cast on the resulting quotient and
     849          remainder if both ``self`` and ``other`` have infinite
     850          precision (ignored otherwise); note that the resulting
     851          precision might be lower than this integer
     852
     853        EXAMPLES::
    825854
    826855            sage: R.<a,b,c> = PowerSeriesRing(ZZ)
    827856            sage: f = 1 + a + b - a*b + R.O(3)
    class MPowerSeries(PowerSeries): 
    846875            sage: a*f == q*(b*g)+r
    847876            True
    848877
     878        Trying to divide two polynomials, we run into the issue that
     879        there is no natural setting for the precision of the quotient
     880        and remainder (and if we wouldn't set a precision, the
     881        algorithm would never terminate). Here, default precision
     882        comes to our help::
     883
     884            sage: (1+a^3).quo_rem(a+a^2)
     885            (a^2 - a^3 + a^4 - a^5 + a^6 - a^7 + a^8 - a^9 + a^10 + O(a, b, c)^11, 1 + O(a, b, c)^12)
     886
     887            sage: (1+a^3+a*b).quo_rem(b+c)
     888            (a + O(a, b, c)^11, 1 - a*c + a^3 + O(a, b, c)^12)
     889            sage: (1+a^3+a*b).quo_rem(b+c, precision=17)
     890            (a + O(a, b, c)^16, 1 - a*c + a^3 + O(a, b, c)^17)
     891
     892            sage: (a^2+b^2+c^2).quo_rem(a+b+c)
     893            (a - b - c + O(a, b, c)^11, 2*b^2 + 2*b*c + 2*c^2 + O(a, b, c)^12)
     894
     895            sage: (a^2+b^2+c^2).quo_rem(1/(1+a+b+c))
     896            (a^2 + b^2 + c^2 + a^3 + a^2*b + a^2*c + a*b^2 + a*c^2 + b^3 + b^2*c + b*c^2 + c^3 + O(a, b, c)^14,
     897             0)
     898
     899            sage: (a^2+b^2+c^2).quo_rem(a/(1+a+b+c))
     900            (a + a^2 + a*b + a*c + O(a, b, c)^13, b^2 + c^2)
     901
     902            sage: (1+a+a^15).quo_rem(a^2)
     903            (0 + O(a, b, c)^10, 1 + a + O(a, b, c)^12)
     904            sage: (1+a+a^15).quo_rem(a^2, precision=15)
     905            (0 + O(a, b, c)^13, 1 + a + O(a, b, c)^15)
     906            sage: (1+a+a^15).quo_rem(a^2, precision=16)
     907            (a^13 + O(a, b, c)^14, 1 + a + O(a, b, c)^16)
     908
     909        Illustrating the dependency on the ordering of variables::
     910
     911            sage: (1+a+b).quo_rem(b+c)
     912            (1 + O(a, b, c)^11, 1 + a - c + O(a, b, c)^12)
     913            sage: (1+b+c).quo_rem(c+a)
     914            (0 + O(a, b, c)^11, 1 + b + c + O(a, b, c)^12)
     915            sage: (1+c+a).quo_rem(a+b)
     916            (1 + O(a, b, c)^11, 1 - b + c + O(a, b, c)^12)
     917
    849918        TESTS::
    850919
    851920            sage: (f).quo_rem(R.zero())
    class MPowerSeries(PowerSeries): 
    857926            Traceback (most recent call last):
    858927            ...
    859928            ZeroDivisionError
     929
     930        Coercion is applied on ``other``::
     931
     932            sage: (a+b).quo_rem(1)
     933            (a + b + O(a, b, c)^12, 0 + O(a, b, c)^12)
     934
     935            sage: R.<a,b,c> = PowerSeriesRing(QQ)
     936            sage: R(3).quo_rem(2)
     937            (3/2 + O(a, b, c)^12, 0 + O(a, b, c)^12)
    860938        """
    861         if other.parent() is not self.parent():
    862             raise ValueError("Do not know how to divide by a element of %s" % (other.parent()))
     939        parent = self.parent()
     940        if other.parent() is not parent:
     941            other = self.parent(other)
    863942        other_tt = other.trailing_monomial()
    864943        if not other_tt:
    865944            raise ZeroDivisionError()
    866         rem = self.parent().zero().add_bigoh(self.prec())
    867         quo = self.parent().zero().add_bigoh(self.prec()-other.valuation())
     945        self_prec = self.prec()
     946        if self_prec == infinity and other.prec() == infinity:
     947            if precision is None:
     948                precision = parent.default_prec()
     949            self = self.add_bigoh(precision)
     950            self_prec = self.prec()
     951        rem = parent.zero().add_bigoh(self_prec)
     952        quo = parent.zero().add_bigoh(self_prec-other.valuation())
    868953        while self:
     954            # Loop invariants:
     955            # ``(the original value of self) - self == quo * other + rem``
     956            # and
     957            # ``(quo * other).prec() <= self.prec().
     958            # (``other`` doesn't change throughout the loop.)
     959            # The loop terminates because:
     960            # (1) every step increases ``self_tt``;
     961            # (2) either ``self`` has finite precision, or ``self`` is a
     962            #     polynomial and ``other`` has infinite precision (in
     963            #     which case either ``self`` will run out of nonzero
     964            #     coefficients after sufficiently many iterations of the
     965            #     if-case, or ``self``'s precision gets reduced to finite
     966            #     in one iteration of the else-case).
     967            # These show that at the end we have
     968            # ``(the original value of self) == quo * other + rem``
     969            # up to the minimum of the precision of either side of this
     970            # equality and the precision of self.
    869971            self_tt = self.trailing_monomial()
    870             assert self_tt
     972            #assert self_tt
    871973            if not other_tt.divides(self_tt):
    872974                self -= self_tt
    873975                rem += self_tt
    class MPowerSeries(PowerSeries): 
    882984        r"""
    883985        Division in the ring of power series.
    884986
    885         EXAMPLE::
     987        EXAMPLES::
    886988
    887989            sage: R.<a,b,c> = PowerSeriesRing(ZZ)
    888990            sage: f = 1 + a + b - a*b + R.O(3)
    class MPowerSeries(PowerSeries): 
    893995            sage: g == ~f
    894996            True
    895997
    896         When possible, division by non unit also works::
     998        When possible, division by non-units also works::
    897999
    8981000            sage: a/(a*f)
    8991001            1 - a - b + a^2 + 3*a*b + b^2 + O(a, b, c)^3
    class MPowerSeries(PowerSeries): 
    9091011            ...
    9101012            ValueError: not divisible
    9111013
    912         An example where one looses precision::
     1014        An example where one loses precision::
    9131015
    9141016            sage: ((1+a)*f - f) / a*f
    9151017            1 + 2*a + 2*b + O(a, b, c)^2
    class MPowerSeries(PowerSeries): 
    9221024            True
    9231025        """
    9241026        if denom_r.is_unit(): # faster if denom_r is a unit
    925             return self*~denom_r
     1027            return self.parent(self._bg_value * denom_r._bg_value.__invert__())
    9261028        quo, rem = self.quo_rem(denom_r)
    9271029        if rem:
    9281030            raise ValueError("not divisible")
    class MPowerSeries(PowerSeries): 
    10151117
    10161118    def polynomial(self):
    10171119        """
    1018         Return underlying polynomial of ``self`` as an element of underlying
    1019         multivariate polynomial ring.
     1120        Return the underlying polynomial of ``self`` as an element of
     1121        the underlying multivariate polynomial ring (the "foreground
     1122        polynomial ring").
    10201123
    10211124        EXAMPLES::
    1022        
     1125
    10231126            sage: M = PowerSeriesRing(QQ,4,'t'); M
    10241127            Multivariate Power Series Ring in t0, t1, t2, t3 over Rational
    10251128            Field
    class MPowerSeries(PowerSeries): 
    10291132            sage: f
    10301133            1/2*t0^3*t1^3*t2^2 + 2/3*t0*t2^6*t3 - t0^3*t1^3*t3^3
    10311134            - 1/4*t0*t1*t2^7 + O(t0, t1, t2, t3)^10
    1032            
     1135
    10331136            sage: f.polynomial()
    10341137            1/2*t0^3*t1^3*t2^2 + 2/3*t0*t2^6*t3 - t0^3*t1^3*t3^3
    10351138            - 1/4*t0*t1*t2^7
    1036            
     1139
    10371140            sage: f.polynomial().parent()
    10381141            Multivariate Polynomial Ring in t0, t1, t2, t3 over Rational Field
    10391142           
    1040         Contrast with truncate::
    1041        
     1143        Contrast with :meth:`truncate`::
     1144
    10421145            sage: f.truncate()
    10431146            1/2*t0^3*t1^3*t2^2 + 2/3*t0*t2^6*t3 - t0^3*t1^3*t3^3 - 1/4*t0*t1*t2^7
    10441147            sage: f.truncate().parent()
    class MPowerSeries(PowerSeries): 
    11641267
    11651268        .. MATH::
    11661269
    1167             \sum a_{m_0, \ldots, m_k} x_0^{n m_0} \cdots x_n^{n m_k}.
     1270            \sum a_{m_0, \ldots, m_k} x_0^{n m_0} \cdots x_k^{n m_k}.
    11681271
    11691272        The total-degree precision of the output is ``n`` times the precision
    11701273        of ``self``.
    class MPowerSeries(PowerSeries): 
    12001303
    12011304    def add_bigoh(self, prec):
    12021305        """
    1203         Return a multivariate power series of total precision
    1204         obtained by truncating self at precision ``prec``.  This
    1205         is the same as :meth:`O`.
     1306        Return a multivariate power series of precision ``prec``
     1307        obtained by truncating ``self`` at precision ``prec``.
     1308
     1309        This is the same as :meth:`O`.
    12061310
    12071311        EXAMPLES::
    12081312
    class MPowerSeries(PowerSeries): 
    12231327
    12241328    def O(self, prec):
    12251329        """
    1226         Return a multivariate power series of total precision obtained
    1227         by truncating ``self`` at precision ``prec``. This is the same
    1228         as :meth:`add_bigoh`.
     1330        Return a multivariate power series of precision ``prec``
     1331        obtained by truncating ``self`` at precision ``prec``.
     1332
     1333        This is the same as :meth:`add_bigoh`.
    12291334
    12301335        EXAMPLES::
    12311336
    class MPowerSeries(PowerSeries): 
    12761381        return self.parent((self.O(prec))._value())
    12771382
    12781383    def valuation(self):
    1279         """
    1280         Return valuation of ``self``.
     1384        r"""
     1385        Return the valuation of ``self``.
     1386
     1387        The valuation of a power series `f` is the highest nonnegative
     1388        integer `k` less or equal to the precision of `f` and such
     1389        that the coefficient of `f` before each term of degree `< k` is
     1390        zero. (If such an integer does not exist, then the valuation is
     1391        the precision of `f` itself.)
    12811392
    12821393        EXAMPLES::
    12831394
    class MPowerSeries(PowerSeries): 
    12901401            sage: g = 1 + a + a^3
    12911402            sage: g.valuation()
    12921403            0
     1404            sage: R.zero().valuation()
     1405            +Infinity
    12931406        """
    12941407        try:
    12951408            return self._bg_value.valuation()
    class MPowerSeries(PowerSeries): 
    13071420        """
    13081421        Return ``True`` if ``self`` is nilpotent. This occurs if
    13091422
    1310         - ``self`` has finite precision and positive valuation
    1311         - ``self`` is constant and nilpotent in base ring
     1423        - ``self`` has finite precision and positive valuation, or
     1424        - ``self`` is constant and nilpotent in base ring.
    13121425
    1313         otherwise, return ``False``.
     1426        Otherwise, return ``False``.
     1427
     1428        .. WARNING::
     1429
     1430            This is so far just a sufficient condition, so don't trust
     1431            a ``False`` output to be legit!
     1432
     1433        .. TODO::
     1434
     1435            What should we do about this method? Is nilpotency of a
     1436            power series even decidable (assuming a nilpotency oracle
     1437            in the base ring)? And I am not sure that returning
     1438            ``True`` just because the series has finite precision and
     1439            zero constant term is a good idea.
    13141440
    13151441        EXAMPLES::
    13161442
    class MPowerSeries(PowerSeries): 
    13681494        coefficient is a unit.
    13691495
    13701496        EXAMPLES::
    1371        
     1497
    13721498            sage: R.<a,b> = PowerSeriesRing(ZZ); R
    13731499            Multivariate Power Series Ring in a, b over Integer Ring
    13741500            sage: f = 2 + a^2 + a*b + a^3 + R.O(9)
    class MPowerSeries(PowerSeries): 
    14651591        The formal integral of this multivariate power series, with respect to
    14661592        variables supplied in ``args``.
    14671593
     1594        The variable sequence ``args`` can contain both variables and
     1595        counts; for the syntax, see
     1596        :meth:`~sage.misc.derivative.derivative_parse`.
     1597
    14681598        EXAMPLES::
    14691599
    14701600            sage: T.<a,b> = PowerSeriesRing(QQ,2)
    class MPowerSeries(PowerSeries): 
    14851615
    14861616        .. warning:: Coefficient division.
    14871617
    1488             If the base ring is not a field (e.g. `ZZ`), or if it has a non
    1489             zero characteristic, (e.g. `ZZ/3ZZ`), integration is not always
    1490             possible, while staying with the same base ring. In the first
    1491             case, Sage will report that it has not been able to coerce some
    1492             coefficient to the base ring::
     1618            If the base ring is not a field (e.g. `ZZ`), or if it has a
     1619            non-zero characteristic, (e.g. `ZZ/3ZZ`), integration is not
     1620            always possible while staying with the same base ring. In the
     1621            first case, Sage will report that it has not been able to
     1622            coerce some coefficient to the base ring::
    14931623
    14941624                sage: T.<a,b> = PowerSeriesRing(ZZ,2)
    14951625                sage: f = a + T.O(5)
    class MPowerSeries(PowerSeries): 
    15031633                sage: f.change_ring(QQ).integral(a)
    15041634                1/2*a^2 + O(a, b)^6
    15051635
    1506             However, a correct result is returned if the denominator cancels::
     1636            However, a correct result is returned even without base change
     1637            if the denominator cancels::
    15071638
    15081639                sage: f = 2*b + T.O(5)
    15091640                sage: f.integral(b)
    15101641                b^2 + O(a, b)^6
    15111642
    1512             In non zero characteristic, Sage will report that a zero division
     1643            In non-zero characteristic, Sage will report that a zero division
    15131644            occurred ::
    15141645
    15151646                sage: T.<a,b> = PowerSeriesRing(Zmod(3),2)
    class MPowerSeries(PowerSeries): 
    15281659
    15291660    def _integral(self, xx):
    15301661        """
    1531         Formal integral for multivariate power series
     1662        Formal integral for multivariate power series.
    15321663
    1533         INPUT: ``xx`` a generator of the power series ring
     1664        INPUT: ``xx`` - a generator of the power series ring (the
     1665        one with respect to which to integrate)
    15341666
    15351667        EXAMPLES::
    15361668
    class MPowerSeries(PowerSeries): 
    15431675
    15441676        TESTS:
    15451677
    1546         We try to recognise variables even if they are not recognized as
     1678        We try to recognize variables even if they are not recognized as
    15471679        genrators of the rings::
    15481680
    15491681            sage: T.<a,b> = PowerSeriesRing(QQ,2)