Ticket #14507: trac_14507-tropical_semiring-ts.patch

File trac_14507-tropical_semiring-ts.patch, 19.1 KB (added by tscrim, 8 years ago)
  • doc/en/reference/semirings/index.rst

    # HG changeset patch
    # User Travis Scrimshaw <tscrim@ucdavis.edu>
    # Date 1367338691 25200
    # Node ID 0971007b255d3a396007ea762f0ed13f2a96f63c
    # Parent 2abb2d0fb656ab8b94019054baa1dd161fd5bb49
    #14507: Implemented tropical semiring.
    
    diff --git a/doc/en/reference/semirings/index.rst b/doc/en/reference/semirings/index.rst
    a b Standard Semirings 
    55   :maxdepth: 2
    66
    77   sage/rings/semirings/non_negative_integer_semiring
     8   sage/rings/semirings/tropical_semiring
    89
    910.. include:: ../footer.txt
  • module_list.py

    diff --git a/module_list.py b/module_list.py
    a b ext_modules = [ 
    17791779    Extension('sage.rings.polynomial.symmetric_reduction',
    17801780              sources = ['sage/rings/polynomial/symmetric_reduction.pyx']),
    17811781
     1782        ################################
     1783        ##
     1784        ## sage.rings.semirings
     1785        ##
     1786        ################################
     1787
     1788    Extension('sage.rings.semirings.tropical_semiring',
     1789              sources = ['sage/rings/semirings/tropical_semiring.pyx']),
     1790
    17821791    ################################
    17831792    ##
    17841793    ## sage.schemes
  • sage/rings/semirings/all.py

    diff --git a/sage/rings/semirings/all.py b/sage/rings/semirings/all.py
    a b from sage.misc.lazy_import import lazy_i 
    33lazy_import('sage.rings.semirings.non_negative_integer_semiring',
    44            ['NonNegativeIntegerSemiring', 'NN'])
    55
     6from tropical_semiring import TropicalSemiring
     7
  • new file sage/rings/semirings/tropical_semiring.pyx

    diff --git a/sage/rings/semirings/tropical_semiring.pyx b/sage/rings/semirings/tropical_semiring.pyx
    new file mode 100644
    - +  
     1r"""
     2Tropical Semirings
     3
     4AUTHORS:
     5
     6- Travis Scrimshaw (2013-04-28) - Initial version
     7"""
     8#*****************************************************************************
     9#       Copyright (C) 2013 Travis Scrimshaw <tscrim@ucdavis.edu>
     10#
     11#  Distributed under the terms of the GNU General Public License (GPL)
     12#
     13#    This code is distributed in the hope that it will be useful,
     14#    but WITHOUT ANY WARRANTY; without even the implied warranty of
     15#    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
     16#    General Public License for more details.
     17#
     18#  The full text of the GPL is available at:
     19#
     20#                  http://www.gnu.org/licenses/
     21#*****************************************************************************
     22
     23include "../../ext/stdsage.pxi"
     24
     25from sage.misc.cachefunc import cached_method
     26from sage.structure.parent import Parent
     27from sage.structure.unique_representation import UniqueRepresentation
     28from sage.structure.element cimport RingElement, Element, ModuleElement
     29from sage.categories.semirings import Semirings
     30from sage.categories.map cimport Map
     31from sage.sets.family import Family
     32from sage.rings.all import ZZ
     33
     34import operator
     35
     36cdef class TropicalSemiringElement(RingElement):
     37    r"""
     38    An element in the tropical semiring over an ordered additive semigroup
     39    `R`. Either in `R` or `\infty`. The operators `+, \cdot` are defined as
     40    the tropical operators `\oplus, \odot` respectively.
     41    """
     42    cdef ModuleElement _val
     43
     44    cdef TropicalSemiringElement _new(self):
     45        """
     46        Return a new tropical semiring element with parent ``self`.
     47        """
     48        cdef TropicalSemiringElement x
     49        x = PY_NEW(TropicalSemiringElement)
     50        x._parent = self._parent
     51        x._val = self._val
     52        return x
     53
     54    def __init__(self, parent, ModuleElement val=None):
     55        """
     56        Initialize ``self``.
     57
     58        EXAMPLES::
     59
     60            sage: T = TropicalSemiring(QQ)
     61            sage: elt = T(2)
     62            sage: TestSuite(elt).run()
     63        """
     64        RingElement.__init__(self, parent)
     65        self._val = val
     66
     67    def __reduce__(self):
     68        """
     69        Used in pickling tropical semiring elements.
     70
     71        EXAMPLES::
     72
     73            sage: T = TropicalSemiring(QQ)
     74            sage: elt = T(2)
     75            sage: elt.__reduce__()
     76            (<type 'sage.rings.semirings.tropical_semiring.TropicalSemiringElement'>,
     77             (Tropical semiring over Rational Field, 2))
     78        """
     79        return (TropicalSemiringElement, (self.parent(), self._val))
     80
     81    def _repr_(self):
     82        """
     83        Return a string representation of ``self``.
     84
     85        EXAMPLES::
     86
     87            sage: T = TropicalSemiring(QQ)
     88            sage: T(2)
     89            2
     90            sage: T.infinity()
     91            +infinity
     92            sage: T = TropicalSemiring(QQ, False)
     93            sage: T.infinity()
     94            -infinity
     95        """
     96        if self._val is None:
     97            if self.parent()._use_min:
     98                return "+infinity"
     99            return "-infinity"
     100        return repr(self._val)
     101
     102    def _latex_(self):
     103        """
     104        Return a latex representation of ``self``.
     105
     106        EXAMPLES::
     107
     108            sage: T = TropicalSemiring(QQ)
     109            sage: T(2)
     110            2
     111            sage: latex(T.infinity())
     112            \infty
     113            sage: T = TropicalSemiring(QQ, False)
     114            sage: latex(T.infinity())
     115            -\infty
     116        """
     117        if self._val is None:
     118            if self.parent()._use_min:
     119                return "\\infty"
     120            return "-\\infty"
     121        return repr(self._val)
     122
     123    def __hash__(self):
     124        """
     125        Return the hash of ``self``.
     126
     127        EXAMPLES::
     128
     129            sage: T = TropicalSemiring(QQ)
     130            sage: hash(T(2)) == hash(T(2))
     131            True
     132            sage: hash(T.infinity()) == hash(T.infinity())
     133            True
     134        """
     135        return hash(self._val)
     136
     137    # Comparisons
     138
     139    def __richcmp__(left, right, int op):
     140        """
     141        Rich comparisons.
     142
     143        EXAMPLES::
     144
     145            sage: T = TropicalSemiring(QQ)
     146            sage: T(2) == T(2)
     147            True
     148            sage: T.infinity() == T.infinity()
     149            True
     150            sage: T(2) != T(4)
     151            True
     152            sage: T.infinity() != T.infinity()
     153            False
     154            sage: T(2) < T(4)
     155            True
     156            sage: T(2) < T.infinity()
     157            True
     158            sage: T.infinity() < T.infinity()
     159            False
     160            sage: T(2) <= T(4)
     161            True
     162            sage: T.infinity() <= T.infinity()
     163            True
     164            sage: T(2) > T(4)
     165            False
     166            sage: T(2) > T.infinity()
     167            False
     168            sage: T.infinity() > T.infinity()
     169            False
     170            sage: T(2) >= T(4)
     171            False
     172            sage: T.infinity() >= T.infinity()
     173            True
     174        """
     175        return (<RingElement>left)._richcmp(right, op)
     176
     177    cdef int _cmp_c_impl(left, Element right) except -2:
     178        """
     179        Return ``-1`` if ``left`` is less than ``right``, ``0`` if
     180        ``left`` and ``right`` are equal, and ``1`` if ``left`` is
     181        greater than ``right``.
     182
     183        EXAMPLES::
     184
     185            sage: T = TropicalSemiring(QQ)
     186            sage: T(2) == T(2)
     187            True
     188            sage: T(2) != T(4)
     189            True
     190            sage: T(2) < T(4)
     191            True
     192            sage: T(2) > T(4)
     193            False
     194            sage: T.infinity() == T.infinity()
     195            True
     196            sage: T(4) <= T.infinity()
     197            True
     198
     199        Using the `\max` definition::
     200
     201            sage: T = TropicalSemiring(QQ, False)
     202            sage: T(2) == T(2)
     203            True
     204            sage: T(2) != T(4)
     205            True
     206            sage: T(2) < T(4)
     207            True
     208            sage: T(2) > T(4)
     209            False
     210            sage: T.infinity() == T.infinity()
     211            True
     212            sage: T(4) <= T.infinity()
     213            False
     214        """
     215        cdef TropicalSemiringElement self, x
     216        self = left
     217        x = right
     218
     219        if self._val is None:
     220            if x._val is None:
     221                return 0
     222            if self.parent()._use_min:
     223                return 1
     224            return -1
     225
     226        if x._val is None:
     227            if self.parent()._use_min:
     228                return -1
     229            return 1
     230
     231        if self._val < x._val:
     232            return -1
     233        if self._val > x._val:
     234            return 1
     235        return 0
     236
     237    cpdef ModuleElement _add_(left, ModuleElement right):
     238        """
     239        Add ``left`` to ``right``.
     240
     241        EXAMPLES::
     242
     243            sage: T = TropicalSemiring(QQ)
     244            sage: T(2) + T(4)
     245            2
     246            sage: T(2) + T.infinity()
     247            2
     248            sage: T.infinity() + T(2)
     249            2
     250            sage: T = TropicalSemiring(QQ, False)
     251            sage: T(2) + T(4)
     252            4
     253            sage: T(2) + T.infinity()
     254            2
     255            sage: T.infinity() + T(2)
     256            2
     257        """
     258        cdef TropicalSemiringElement self, rhs
     259        self = left
     260        rhs = right
     261        if self._val is None:
     262            return rhs
     263        if rhs._val is None:
     264            return self
     265        cdef TropicalSemiringElement x
     266        x = self._new()
     267        if self.parent()._use_min:
     268            x._val = min(self._val, rhs._val)
     269        else:
     270            x._val = max(self._val, rhs._val)
     271        return x
     272
     273    def __neg__(self):
     274        """
     275        Return the additive inverse, which only exists for `\infty`.
     276
     277        EXAMPLES::
     278
     279            sage: T = TropicalSemiring(QQ)
     280            sage: -T.infinity()
     281            +infinity
     282            sage: -T(2)
     283            Traceback (most recent call last):
     284            ...
     285            ArithmeticError: cannot negate any non-infinite element
     286        """
     287        if self._val is None:
     288            return self
     289        raise ArithmeticError("cannot negate any non-infinite element")
     290
     291    cpdef RingElement _mul_(left, RingElement right):
     292        """
     293        Multiply ``left`` and ``right``.
     294
     295        EXAMPLES::
     296
     297            sage: T = TropicalSemiring(QQ)
     298            sage: T(2) * T(4)
     299            6
     300            sage: T(2) * T.infinity()
     301            +infinity
     302            sage: T(-2) * T(1)
     303            -1
     304        """
     305        cdef TropicalSemiringElement self, rhs
     306        self = left
     307        rhs = right
     308        if self._val is None:
     309            return self
     310        if rhs._val is None:
     311            return rhs
     312        cdef TropicalSemiringElement x
     313        x = self._new()
     314        x._val = self._val + rhs._val
     315        return x
     316
     317    cpdef RingElement _div_(left, RingElement right):
     318        """
     319        Divide ``left`` by ``right``.
     320
     321        EXAMPLES::
     322
     323            sage: T = TropicalSemiring(QQ)
     324            sage: T(2) / T(4)
     325            -2
     326            sage: T.infinity() / T(2)
     327            +infinity
     328        """
     329        cdef TropicalSemiringElement self, rhs
     330        self = left
     331        rhs = right
     332
     333        if rhs._val is None:
     334            raise ZeroDivisionError("Tropical division by infinity")
     335        if self._val is None:
     336            return self
     337        cdef TropicalSemiringElement x
     338        x = self._new()
     339        x._val = self._val - rhs._val
     340        return x
     341
     342    def __invert__(self):
     343        """
     344        Return the multiplicative inverse of ``self``.
     345
     346        EXAMPLES::
     347
     348            sage: T = TropicalSemiring(QQ)
     349            sage: ~T(2)
     350            -2
     351        """
     352        if self.is_one():
     353            return self
     354        if self._val is None:
     355            raise ZeroDivisionError("Tropical division by infinity")
     356        cdef TropicalSemiringElement x
     357        x = self._new()
     358        x._val = -self._val
     359        return x
     360
     361    def __pow__(base, exp, dummy):
     362        """
     363        Return ``self`` to ``exp``.
     364
     365        EXAMPLES::
     366
     367            sage: T = TropicalSemiring(QQ)
     368            sage: elt = T(2)
     369            sage: elt**3
     370            6
     371            sage: elt**-2
     372            -4
     373            sage: elt**(3/7)
     374            6/7
     375        """
     376        cdef TropicalSemiringElement self, x
     377        self = base
     378        x = self._new()
     379        x._val = exp*self._val
     380        return x
     381
     382    def multiplicative_order(self):
     383        """
     384        Return the multiplicative order of ``self``.
     385
     386        EXAMPLES::
     387
     388            sage: T = TropicalSemiring(QQ)
     389            sage: T.one().multiplicative_order()
     390            1
     391            sage: T.zero().multiplicative_order()
     392            +Infinity
     393        """
     394        if self.is_one():
     395            return ZZ.one()
     396        from sage.rings.infinity import infinity
     397        return infinity
     398
     399class TropicalSemiring(Parent, UniqueRepresentation):
     400    r"""
     401    The tropical semiring.
     402
     403    Given an ordered additive semigroup `R`, we define the tropical
     404    semiring `T = R \cup \{+\infty\}` by defining tropical addition
     405    and multiplication as follows:
     406
     407    .. MATH::
     408
     409        a \oplus b = \min(a, b), \quad \quad a \odot b = a + b.
     410
     411    In particular, note that there are no (tropical) additive inverses
     412    (except for `\infty`), and every element in `R` has a (tropical)
     413    multiplicative inverse.
     414
     415    There is an alternative definition where we define `T = R \cup \{-\infty\}`
     416    and alter tropical addition to be defined by
     417
     418    .. MATH::
     419
     420        a \oplus b = \max(a, b).
     421
     422    To use the `\max` definition, set the argument ``use_min = False``.
     423
     424    .. WARNING::
     425
     426        :meth:`zero` and :meth:`one` refer to the tropical additive
     427        and multiplicative identities respectively.
     428
     429    INPUT:
     430
     431    - ``base`` -- The base ordered additive semigroup `R`.
     432    - ``use_min`` -- (Default: ``True``) If ``True``, then the semiring uses
     433      `a \oplus b = \min(a, b)`; otherwise uses `a \oplus b = \max(a, b)`
     434
     435    EXAMPLES::
     436
     437        sage: T = TropicalSemiring(QQ)
     438        sage: elt = T(2); elt
     439        2
     440
     441    Recall that tropical addition is the minimum of two elements::
     442
     443        sage: T(3) + T(5)
     444        3
     445
     446    Tropical multiplication is the addition of two elements::
     447
     448        sage: T(2) * T(3)
     449        5
     450        sage: T(0) * T(-2)
     451        -2
     452
     453    We can also do tropical division and arbitrary tropical exponentiation::
     454
     455        sage: T(2) / T(1)
     456        1
     457        sage: T(2)^(-3/7)
     458        -6/7
     459
     460    Note that "zero" and "one" are the additive and multiplicative
     461    identities of the tropical semiring. In other words,
     462    they are **not** `0 \in R` and `1 \in R` respectively, but instead
     463    the (tropical) additive and multiplicative identities `+\infty` and `0`
     464    respectively::
     465
     466        sage: T.zero() + T(3) == T(3)
     467        True
     468        sage: T.one() * T(3) == T(3)
     469        True
     470    """
     471    def __init__(self, base, use_min=True):
     472        r"""
     473        Initialize ``self``.
     474
     475        TESTS::
     476
     477            sage: T = TropicalSemiring(QQ); T
     478            Tropical semiring over Rational Field
     479            sage: TestSuite(T).run()
     480        """
     481        self._use_min = use_min
     482        self._names = ('x', 'infty')
     483        Parent.__init__(self, base=base, category=Semirings())
     484
     485    def _repr_(self):
     486        r"""
     487        Return a string representation of ``self``.
     488
     489        EXAMPLES::
     490
     491            sage: TropicalSemiring(QQ)
     492            Tropical semiring over Rational Field
     493        """
     494        return "Tropical semiring over %s"%self.base()
     495
     496    def _latex_(self):
     497        r"""
     498        Return a latex representation of ``self``.
     499
     500        EXAMPLES::
     501
     502            sage: latex(TropicalSemiring(QQ))
     503            \Bold{T}\left( \Bold{Q} \right)
     504        """
     505        return "\\Bold{T}\\left( " + self.base()._latex_() + " \\right)"
     506
     507    def _coerce_map_from_(self, S):
     508        """
     509        Canonical coercion of into ``self`` from ``S``.
     510
     511        The only objects that canonically coerce to a tropical semiring are
     512        tropical semirings whose base rings have a coercion.
     513
     514        EXAMPLES::
     515
     516            sage: TR = TropicalSemiring(RR)
     517            sage: T60 = TropicalSemiring(RealField(60))
     518            sage: TR.has_coerce_map_from(T60)
     519            True
     520            sage: TQ = TropicalSemiring(QQ)
     521            sage: TQ.has_coerce_map_from(TropicalSemiring(ZZ))
     522            True
     523            sage: TR.has_coerce_map_from(TR)
     524            True
     525            sage: TQ.has_coerce_map_from(TQ)
     526            True
     527            sage: TR.has_coerce_map_from(TQ)
     528            True
     529            sage: TR.has_coerce_map_from(float)
     530            False
     531            sage: TR.has_coerce_map_from(RR)
     532            False
     533            sage: TR.has_coerce_map_from(QQ)
     534            False
     535            sage: TR.coerce_map_from(T60)(T60(2))
     536            2.00000000000000
     537            sage: TR.coerce(T60(3.4))
     538            3.40000000000000
     539            sage: TR.coerce(T60.infinity())
     540            +infinity
     541            sage: TQ.coerce(TR(3.4))
     542            Traceback (most recent call last):
     543            ...
     544            TypeError: no canonical coercion from Tropical semiring over
     545             Real Field with 53 bits of precision to Tropical semiring over Rational Field
     546        """
     547        if isinstance(S, TropicalSemiring) and self._use_min == S._use_min \
     548                and self.base().has_coerce_map_from(S.base()):
     549            return TropicalToTropical(S, self)
     550
     551    def _element_constructor_(self, val):
     552        """
     553        Construct an element of ``self``.
     554
     555        EXAMPLES::
     556
     557            sage: T = TropicalSemiring(QQ)
     558            sage: T(2)
     559            2
     560        """
     561        if val is not None:
     562            val = self.base()(val)
     563        return self.element_class(self, val)
     564
     565    Element = TropicalSemiringElement
     566
     567    @cached_method
     568    def zero_element(self):
     569        """
     570        Return the (tropical) additive identity element `+\infty`.
     571
     572        EXAMPLES::
     573
     574            sage: T = TropicalSemiring(QQ)
     575            sage: T.zero_element()
     576            +infinity
     577        """
     578        return self.element_class(self, None)
     579
     580    zero = zero_element
     581    infinity = zero_element
     582    additive_identity = zero_element
     583
     584    @cached_method
     585    def one_element(self):
     586        """
     587        Return the (tropical) multiplicative identity element `0`.
     588
     589        EXAMPLES::
     590
     591            sage: T = TropicalSemiring(QQ)
     592            sage: T.one_element()
     593            0
     594        """
     595        return self.element_class(self, self.base().zero_element())
     596
     597    one = one_element
     598    multiplicative_identity = one_element
     599
     600    def gens(self):
     601        """
     602        Return the generators of ``self``.
     603
     604        EXAMPLES::
     605
     606            sage: T = TropicalSemiring(QQ)
     607            sage: T.gens()
     608            (1, +infinity)
     609        """
     610        return (self.element_class(self, self.base().one_element()), self.infinity())
     611
     612cdef class TropicalToTropical(Map):
     613    """
     614    Map from the tropical semiring to itself (possibly with different bases).
     615    Used in coercion.
     616    """
     617    cpdef TropicalSemiringElement _call_(self, x):
     618        """
     619        EXAMPLES::
     620
     621            sage: from sage.rings.semirings.tropical_semiring import TropicalToTropical
     622            sage: TZ = TropicalSemiring(ZZ)
     623            sage: TQ = TropicalSemiring(QQ)
     624            sage: f = TropicalToTropical(TZ, TQ)
     625            sage: a = TZ(2)
     626            sage: f(a)
     627            2
     628            sage: f(TZ.infinity())
     629            +infinity
     630        """
     631        return self._codomain((<TropicalSemiringElement>x)._val)
     632