Ticket #3738: 3738-7-maps.patch

File 3738-7-maps.patch, 56.1 KB (added by robertwb, 11 years ago)
  • sage/categories/homset.py

    # HG changeset patch
    # User Robert Bradshaw <robertwb@math.washington.edu>
    # Date 1217391411 25200
    # Node ID e16fe6aeb45f07894dfa57bfc6ac3dd04979296a
    # Parent  8a86866fba288ef218e88aa494b4b3129b01045b
    Use Maps rather than just Morphims in coercion model.
    
    It is abuse of notation to call many of the maps here (especially conversion
    maps) morphisms.
    
    diff -r 8a86866fba28 -r e16fe6aeb45f sage/categories/homset.py
    a b class Homset(Set_generic): 
    281281              From: SymmetricGroup(5)
    282282              To:   SymmetricGroup(6)
    283283            sage: H(phi)
    284             Composite morphism:
     284            Composite map:
    285285              From: SymmetricGroup(4)
    286286              To:   SymmetricGroup(7)
    287               Defn:   Composite morphism:
     287              Defn:   Composite map:
    288288                      From: SymmetricGroup(4)
    289289                      To:   SymmetricGroup(6)
    290290                      Defn:   Call morphism:
  • new file sage/categories/map.pxd

    diff -r 8a86866fba28 -r e16fe6aeb45f sage/categories/map.pxd
    - +  
     1from sage.structure.parent cimport Parent
     2from sage.structure.element cimport Element
     3
     4cdef class Map(Element):
     5    cdef Parent _domain
     6    cdef Parent _codomain
     7
     8    cdef public int _coerce_cost # a rough measure of the cost of using this morphism in the coercion system.
     9                          # 10 by default, 100 if a DefaultCoercionMorphism, 10000 if inexact.
     10
     11    cdef _update_slots(self, _dict)
     12    cdef _extra_slots(self, _dict)
     13
     14    # these methods require x is an element of domain, and returns an element with parent codomain
     15    cpdef Element _call_(self, x)
     16    cpdef Element _call_with_args(self, x, args=*, kwds=*)
     17
     18    cpdef domain(self)
     19    cpdef codomain(self)
     20
     21
     22cdef class Section(Map):
     23    cdef Map _inverse
     24
     25cdef class FormalCompositeMap(Map):
     26    cdef Map __first
     27    cdef Map __second
     28
  • new file sage/categories/map.pyx

    diff -r 8a86866fba28 -r e16fe6aeb45f sage/categories/map.pyx
    - +  
     1#*****************************************************************************
     2#       Copyright (C) 2008 Robert Bradshaw <robertwb@math.washington.edu>
     3#
     4#  Distributed under the terms of the GNU General Public License (GPL)
     5#
     6#    This code is distributed in the hope that it will be useful,
     7#    but WITHOUT ANY WARRANTY; without even the implied warranty of
     8#    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
     9#    General Public License for more details.
     10#
     11#  The full text of the GPL is available at:
     12#
     13#                  http://www.gnu.org/licenses/
     14#*****************************************************************************
     15
     16include "../ext/stdsage.pxi"
     17
     18import homset
     19
     20from sage.structure.element import generic_power
     21
     22def unpickle_map(_class, parent, _dict, _slots):
     23    # should we use slots?
     24    # from element.pyx
     25    cdef Map mor = _class.__new__(_class)
     26    mor._set_parent(parent)
     27    mor._update_slots(_slots)
     28    if HAS_DICTIONARY(mor):
     29        mor.__dict__ = _dict
     30    return mor
     31
     32def is_Map(x):
     33    return isinstance(x, Map)
     34
     35cdef class Map(Element):
     36    def __init__(self, parent, codomain=None):
     37        if codomain is not None:
     38            parent = homset.Hom(parent, codomain)
     39        elif not isinstance(parent, homset.Homset):
     40            raise TypeError, "parent (=%s) must be a Homspace"%parent
     41        Element.__init__(self, parent)
     42        self._domain = parent.domain()
     43        self._codomain = parent.codomain()
     44        if self._domain.is_exact() and self._codomain.is_exact():
     45            self._coerce_cost = 10 # default value.
     46        else:
     47            self._coerce_cost = 10000 # inexact morphisms are bad.
     48
     49    cdef _update_slots(self, _slots):
     50        self._domain = _slots['_domain']
     51        self._codomain = _slots['_codomain']
     52
     53    def _test_update_slots(self, _slots):
     54        self._update_slots(_slots)
     55   
     56    cdef _extra_slots(self, _slots):
     57        _slots['_domain'] = self._domain
     58        _slots['_codomain'] = self._codomain
     59        return _slots
     60
     61    def _test_extra_slots(self, _slots):
     62        return self._extra_slots(_slots)
     63       
     64    def __reduce__(self):
     65        if HAS_DICTIONARY(self):
     66            _dict = self.__dict__
     67        else:
     68            _dict = {}
     69        return unpickle_map, (self.__class__, self._parent, _dict, self._extra_slots({}))
     70   
     71    def _repr_type(self):
     72        return "Generic"
     73
     74    def _repr_defn(self):
     75        return ""
     76
     77    def _repr_(self):
     78        s = "%s map:"%self._repr_type()
     79        s += "\n  From: %s"%self.domain()
     80        s += "\n  To:   %s"%self.codomain()
     81        d = self._repr_defn()
     82        if d != '':
     83            s += "\n  Defn: %s"%('\n        '.join(self._repr_defn().split('\n')))
     84        return s
     85       
     86    cpdef domain(self):
     87        return self._domain
     88       
     89    cpdef codomain(self):
     90        return self._codomain
     91       
     92    def __call__(self, x, *args, **kwds):
     93        """
     94        Apply this map to x.
     95
     96        INPUT:
     97            x -- an element coercible to self; also objects like
     98                 ideals are supported in some cases
     99
     100        OUTPUT:
     101            an element (or ideal, etc.)
     102
     103        EXAMPLES:
     104            sage: R.<x,y> = QQ[]; phi=R.hom([y,x])
     105            sage: phi(y)
     106            x
     107
     108        We take the image of an ideal:
     109            sage: I = ideal(x,y); I
     110            Ideal (x, y) of Multivariate Polynomial Ring in x, y over Rational Field
     111            sage: phi(I)
     112            Ideal (y, x) of Multivariate Polynomial Ring in x, y over Rational Field
     113        """
     114        if len(args) == 0 and len(kwds) == 0:       
     115            if not PY_TYPE_CHECK(x, Element):
     116                return self._call_(x)
     117            elif (<Element>x)._parent is not self._domain:
     118                try:
     119                    x = self._domain(x)
     120                except TypeError:
     121                    try:
     122                        return self.pushforward(x)
     123                    except (TypeError, NotImplementedError):
     124                        raise TypeError, "%s must be coercible into %s"%(x, self._domain)
     125            return self._call_(x)
     126        else:
     127            if PY_TYPE_CHECK(x, Element):
     128                if (<Element>x)._parent is not self._domain:
     129                    x = self._domain(x)
     130            return self._call_with_args(x, args, kwds)
     131
     132    cpdef Element _call_(self, x):
     133        raise NotImplementedError, type(self)
     134
     135    cpdef Element _call_with_args(self, x, args=(), kwds={}):
     136        if len(args) == 0 and len(kwds) == 0:
     137            return self(x)
     138        else:
     139            raise NotImplementedError, "_call_with_args not overridden to accept arguments for %s" % type(self)
     140
     141    def __mul__(self, right):
     142        r"""
     143        The multiplication * operator is operator composition.
     144
     145        INPUT:
     146            self -- Map
     147            right -- Map
     148
     149        OUTPUT:
     150            The map $x \mapsto self(right(x))$.
     151        """
     152        if not isinstance(right, Map):
     153            raise TypeError, "right (=%s) must be a map to multiply it by %s"%(right, self)
     154        if right.codomain() != self.domain():
     155            raise TypeError, "self (=%s) domain must equal right (=%s) codomain"%(self, right)
     156        H = homset.Hom(right.domain(), self.codomain(), self.parent().category())
     157        return self._composition_(right, H)
     158
     159    def _composition_(self, right, homset):
     160        return FormalCompositeMap(homset, right, self)
     161       
     162    def pre_compose(self, right):
     163        if self.domain() is not right.codomain():
     164            right = right.extend_codomain(self.domain())
     165        H = homset.Hom(right.domain(), self.codomain(), self.parent().category())
     166        return self._composition_(right, H)
     167       
     168    def post_compose(self, left):
     169        H = homset.Hom(self.domain(), left.codomain(), self.parent().category())
     170        return left._composition_(self, H)
     171       
     172    def extend_domain(self, new_domain):
     173        r"""
     174        INPUT:
     175            self          -- a member of Hom(Y, Z)
     176            new_codomain  -- an object X such that there is a cannonical
     177                             coercion $\phi$ in Hom(X, Y)
     178                             
     179        OUTPUT:
     180            An element of Hom(X, Z) obtained by composing self with the $\phi$.
     181            If no cannonical $\phi$ exists, a TypeError is raised.
     182       
     183        EXAMPLES:
     184            sage: mor = CDF.coerce_map_from(RDF)
     185            sage: mor.extend_domain(QQ)
     186            Composite map:
     187              From: Rational Field
     188              To:   Complex Double Field
     189              Defn:   Native morphism:
     190                      From: Rational Field
     191                      To:   Real Double Field
     192                    then
     193                      Native morphism:
     194                      From: Real Double Field
     195                      To:   Complex Double Field
     196            sage: mor.extend_domain(ZZ['x'])
     197            Traceback (most recent call last):
     198            ...
     199            TypeError: No coercion from Univariate Polynomial Ring in x over Integer Ring to Real Double Field
     200        """
     201        cdef Map connecting = self.domain().coerce_map_from(new_domain)
     202        if connecting is None:
     203            raise TypeError, "No coercion from %s to %s" % (new_domain, self.domain())
     204        elif connecting.codomain() is not self.domain():
     205            raise RuntimeError, "BUG: coerce_map_from should always return a map to self (%s)" % self.domain()
     206        else:
     207            return self.pre_compose(connecting)
     208       
     209    def extend_codomain(self, new_codomain):
     210        r"""
     211        INPUT:
     212            self          -- a member of Hom(X, Y)
     213            new_codomain  -- an object Z such that there is a cannonical
     214                             coercion $\phi$ in Hom(Y, Z)
     215                             
     216        OUTPUT:
     217            An element of Hom(X, Z) obtained by composing self with the $\phi$.
     218            If no cannonical $\phi$ exists, a TypeError is raised.
     219       
     220        EXAMPLES:
     221            sage: mor = QQ.coerce_map_from(ZZ)
     222            sage: mor.extend_codomain(RDF)
     223            Composite map:
     224              From: Integer Ring
     225              To:   Real Double Field
     226              Defn:   Natural morphism:
     227                      From: Integer Ring
     228                      To:   Rational Field
     229                    then
     230                      Native morphism:
     231                      From: Rational Field
     232                      To:   Real Double Field
     233            sage: mor.extend_codomain(GF(7))
     234            Traceback (most recent call last):
     235            ...
     236            TypeError: No coercion from Rational Field to Finite Field of size 7
     237        """
     238        cdef Map connecting = new_codomain.coerce_map_from(self.codomain())
     239        if connecting is None:
     240            raise TypeError, "No coercion from %s to %s" % (self.codomain(), new_codomain)
     241        elif connecting.domain() is not self.codomain():
     242            raise RuntimeError, "BUG: coerce_map_from should always return a map from its input (%s)" % new_codomain
     243        else:
     244            return self.post_compose(connecting)
     245           
     246    def is_injective(self):
     247        raise NotImplementedError, type(self)
     248
     249    def is_surjective(self):
     250        raise NotImplementedError, type(self)
     251
     252    def __pow__(self, n, dummy):
     253        if not self._domain is not self._codomain:
     254            raise TypeError, "self must be an endomorphism."
     255        # todo -- what about the case n=0 -- need to specify the identity map somehow.
     256        return generic_power(self, n)
     257       
     258    def section(self):
     259        return None
     260
     261cdef class Section(Map):
     262    def __init__(self, map):
     263        from sage.categories.homset import Hom
     264        from sage.categories.category_types import SetsWithPartialMaps
     265        Map.__init__(self, Hom(map.codomain(), map.domain(), SetsWithPartialMaps()))
     266        self._inverse = map
     267
     268    def _repr_type(self):
     269        return "Section"
     270
     271cdef class FormalCompositeMap(Map):
     272    def __init__(self, parent, first, second):
     273        Map.__init__(self, parent)
     274        self.__first = first
     275        self.__second = second
     276        self._coerce_cost = (<Map>first)._coerce_cost + (<Map>second)._coerce_cost
     277
     278    cdef _update_slots(self, _slots):
     279        self.__first = _slots['__first']
     280        self.__second = _slots['__second']
     281        Map._update_slots(self, _slots)
     282       
     283    cdef _extra_slots(self, _slots):
     284        _slots['__first'] = self.__first
     285        _slots['__second'] = self.__second
     286        return Map._extra_slots(self, _slots)
     287
     288    cpdef Element _call_(self, x):
     289        return self.__second._call_(self.__first._call_(x))
     290
     291    cpdef Element _call_with_args(self, x, args=(), kwds={}):
     292        return self.__second._call_with_args(self.__first._call_(x), args, kwds)
     293   
     294    def _repr_type(self):
     295        return "Composite"
     296
     297    def _repr_defn(self):
     298        return "  %s\nthen\n  %s"%(self.__first, self.__second)
     299
     300    def first(self):
     301        """
     302        The first map in the formal composition, where the
     303        composition is x|--> second(first(x)).
     304       
     305        """
     306        return self.__first
     307       
     308    def second(self):
     309        """
     310        The second map in the formal composition, where the
     311        composition is x|--> second(first(x)).
     312        """
     313        return self.__second
     314       
     315    def is_injective(self):
     316        if self.__first.is_injective():
     317            if self.__second.is_injective():
     318                return True
     319            elif self.__first.is_surjective():
     320                return False
     321            else:
     322                raise NotImplementedError, "Not enough information to deduce injectivity."
     323        else:
     324            return False
     325       
     326    def is_surjective(self):
     327        if self.__second.is_surjective():
     328            if self.__first.is_surjective():
     329                return True
     330            elif self.__second.is_injective():
     331                return False
     332            else:
     333                raise NotImplementedError, "Not enough information to deduce surjectivity."
     334        else:
     335            return False
     336       
  • sage/categories/morphism.pxd

    diff -r 8a86866fba28 -r e16fe6aeb45f sage/categories/morphism.pxd
    a b from sage.structure.element cimport Elem 
     1from sage.structure.parent cimport Parent
    12from sage.structure.element cimport Element
    2 from sage.structure.parent cimport Parent
     3from map cimport Map
    34
    4 cdef class Morphism(Element):
    5     cdef Parent _domain
    6     cdef Parent _codomain
    7 
    8     cdef public int _coerce_cost # a rough measure of the cost of using this morphism in the coercion system.
    9                           # 10 by default, 100 if a DefaultCoercionMorphism, 10000 if inexact.
    10 
    11 # TODO: remove this requirement when we better understand pickling   
    12 #    cdef __dict__
    13 
    14     cdef _update_slots(self, _dict)
    15     cdef _extra_slots(self, _dict)
    16    
    17     # these methods assume x is an element of domain, and returns an element with parent codomain
    18     cpdef Element _call_(self, x)
    19     cpdef Element _call_with_args(self, x, args=*, kwds=*)
    20 
    21     cpdef domain(self)
    22 
    23     cpdef codomain(self)
    24 
    25 cdef class Section(Morphism):
    26     cdef Morphism _morphism
    27 
    28 cdef class FormalCoercionMorphism(Morphism):
    29     pass
    30 
    31 cdef class FormalCompositeMorphism(Morphism):
    32     cdef Morphism __first
    33     cdef Morphism __second
     5cdef class Morphism(Map):
    346    pass
    357
    368cdef class SetMorphism(Morphism):
  • sage/categories/morphism.pyx

    diff -r 8a86866fba28 -r e16fe6aeb45f sage/categories/morphism.pyx
    a b import homset 
    2828
    2929include "../ext/stdsage.pxi"
    3030from sage.structure.element cimport Element
    31 from sage.structure.element import generic_power
    3231
    3332def make_morphism(_class, parent, _dict, _slots):
    3433    # from element.pyx
    def is_Morphism(x): 
    4241def is_Morphism(x):
    4342    return isinstance(x, Morphism)
    4443
    45 cdef class Morphism(Element):
    46     def __init__(Morphism self, parent):
    47         if not isinstance(parent, homset.Homset):
    48             raise TypeError, "parent (=%s) must be a Homspace"%parent
    49         Element.__init__(self, parent)
    50         self._domain = parent.domain()
    51         self._codomain = parent.codomain()
    52         if self._domain.is_exact() and self._codomain.is_exact():
    53             self._coerce_cost = 10 # default value.
    54         else:
    55             self._coerce_cost = 10000 # inexact morphisms are bad.
     44cdef class Morphism(Map):
    5645       
    57     cdef _update_slots(self, _slots):
    58         self._domain = _slots['_domain']
    59         self._codomain = _slots['_codomain']
    60 
    61     def _test_update_slots(self, _slots):
    62         self._update_slots(_slots)
    63    
    64     cdef _extra_slots(self, _slots):
    65         _slots['_domain'] = self._domain
    66         _slots['_codomain'] = self._codomain
    67         return _slots
    68 
    69     def _test_extra_slots(self, _slots):
    70         return self._extra_slots(_slots)
    71        
    72     def __reduce__(self):
    73         if HAS_DICTIONARY(self):
    74             _dict = self.__dict__
    75         else:
    76             _dict = {}
    77         return make_morphism, (self.__class__, self._parent, _dict, self._extra_slots({}))
    78    
    79     def _repr_type(self):
    80         return "Generic"
    81 
    82     def _repr_defn(self):
    83         return ""
    84 
    8546    def _repr_(self):
    8647        if self.is_endomorphism():
    8748            s = "%s endomorphism of %s"%(self._repr_type(), self.domain())
    cdef class Morphism(Element): 
    9354        if d != '':
    9455            s += "\n  Defn: %s"%('\n        '.join(self._repr_defn().split('\n')))
    9556        return s
    96        
    97     cpdef domain(self):
    98         return self._domain
    99        
    100     cpdef codomain(self):
    101         return self._codomain
    10257
    10358    def category(self):
    10459        return self.parent().category()
    cdef class Morphism(Element): 
    10863
    10964    def __invert__(self):  # notation in python is (~f) for the inverse of f.
    11065        raise NotImplementedError
    111                        
    112     def __call__(self, x, *args, **kwds):
    113         """
    114         Apply this morphism to x.
    115 
    116         INPUT:
    117             x -- an element coercible to self; also objects like
    118                  ideals are supported in some cases
    119 
    120         OUTPUT:
    121             an element (or ideal, etc.)
    122 
    123         EXAMPLES:
    124             sage: R.<x,y> = QQ[]; phi=R.hom([y,x])
    125             sage: phi(y)
    126             x
    127 
    128         We take the image of an ideal:
    129             sage: I = ideal(x,y); I
    130             Ideal (x, y) of Multivariate Polynomial Ring in x, y over Rational Field
    131             sage: phi(I)
    132             Ideal (y, x) of Multivariate Polynomial Ring in x, y over Rational Field
    133         """
    134         if len(args) == 0 and len(kwds) == 0:       
    135             if not PY_TYPE_CHECK(x, Element):
    136                 return self._call_(x)
    137             elif (<Element>x)._parent is not self._domain:
    138                 try:
    139                     x = self._domain(x)
    140                 except TypeError:
    141                     try:
    142                         return self.pushforward(x)
    143                     except (TypeError, NotImplementedError):
    144                         raise TypeError, "%s must be coercible into %s"%(x, self._domain)
    145             return self._call_(x)
    146         else:
    147             if PY_TYPE_CHECK(x, Element):
    148                 if (<Element>x)._parent is not self._domain:
    149                     x = self._domain(x)
    150             return self._call_with_args(x, args, kwds)
    151 
    152     cpdef Element _call_(self, x):
    153         raise NotImplementedError, type(self)
    154 
    155     cpdef Element _call_with_args(self, x, args=(), kwds={}):
    156         if len(args) == 0 and len(kwds) == 0:
    157             return self(x)
    158         else:
    159             raise NotImplementedError, "_call_with_args not overridden to accept arguments for %s" % type(self)
    16066
    16167    def pushforward(self, I):
    16268        raise NotImplementedError
    163 
    164     def __mul__(self, right):
    165         r"""
    166         The multiplication * operator is operator composition.
    167 
    168         INPUT:
    169             self -- Morphism
    170             right -- Morphism
    171 
    172         OUTPUT:
    173             The morphism $x \mapsto self(right(x))$.
    174         """
    175         if not isinstance(right, Morphism):
    176             raise TypeError, "right (=%s) must be a morphism to multiply it by %s"%(right, self)
    177         if right.codomain() != self.domain():
    178             raise TypeError, "self (=%s) domain must equal right (=%s) codomain"%(self, right)
    179         H = homset.Hom(right.domain(), self.codomain(), self.parent().category())
    180         return self._composition_(right, H)
    181 
    182     def _composition_(self, right, homset):
    183         return FormalCompositeMorphism(homset, right, self)
    184        
    185     def pre_compose(self, right):
    186         if self.domain() is not right.codomain():
    187             right = right.extend_codomain(self.domain())
    188         H = homset.Hom(right.domain(), self.codomain(), self.parent().category())
    189         return self._composition_(right, H)
    190        
    191     def post_compose(self, left):
    192         H = homset.Hom(self.domain(), left.codomain(), self.parent().category())
    193         return left._composition_(self, H)
    194        
    195     def extend_domain(self, new_domain):
    196         r"""
    197         INPUT:
    198             self          -- a member of Hom(Y, Z)
    199             new_codomain  -- an object X such that there is a cannonical
    200                              coercion $\phi$ in Hom(X, Y)
    201                              
    202         OUTPUT:
    203             An element of Hom(X, Z) obtained by composing self with the $\phi$.
    204             If no cannonical $\phi$ exists, a TypeError is raised.
    205        
    206         EXAMPLES:
    207             sage: mor = CDF.coerce_map_from(RDF)
    208             sage: mor.extend_domain(QQ)
    209             Composite morphism:
    210               From: Rational Field
    211               To:   Complex Double Field
    212               Defn:   Native morphism:
    213                       From: Rational Field
    214                       To:   Real Double Field
    215                     then
    216                       Native morphism:
    217                       From: Real Double Field
    218                       To:   Complex Double Field
    219             sage: mor.extend_domain(ZZ['x'])
    220             Traceback (most recent call last):
    221             ...
    222             TypeError: No coercion from Univariate Polynomial Ring in x over Integer Ring to Real Double Field
    223         """
    224         cdef Morphism connecting = self.domain().coerce_map_from(new_domain)
    225         if connecting is None:
    226             raise TypeError, "No coercion from %s to %s" % (new_domain, self.domain())
    227         elif connecting.codomain() is not self.domain():
    228             raise RuntimeError, "BUG: coerce_map_from should always return a map to self (%s)" % self.domain()
    229         else:
    230             return self.pre_compose(connecting)
    231        
    232     def extend_codomain(self, new_codomain):
    233         r"""
    234         INPUT:
    235             self          -- a member of Hom(X, Y)
    236             new_codomain  -- an object Z such that there is a cannonical
    237                              coercion $\phi$ in Hom(Y, Z)
    238                              
    239         OUTPUT:
    240             An element of Hom(X, Z) obtained by composing self with the $\phi$.
    241             If no cannonical $\phi$ exists, a TypeError is raised.
    242        
    243         EXAMPLES:
    244             sage: mor = QQ.coerce_map_from(ZZ)
    245             sage: mor.extend_codomain(RDF)
    246             Composite morphism:
    247               From: Integer Ring
    248               To:   Real Double Field
    249               Defn:   Natural morphism:
    250                       From: Integer Ring
    251                       To:   Rational Field
    252                     then
    253                       Native morphism:
    254                       From: Rational Field
    255                       To:   Real Double Field
    256             sage: mor.extend_codomain(GF(7))
    257             Traceback (most recent call last):
    258             ...
    259             TypeError: No coercion from Rational Field to Finite Field of size 7
    260         """
    261         cdef Morphism connecting = new_codomain.coerce_map_from(self.codomain())
    262         if connecting is None:
    263             raise TypeError, "No coercion from %s to %s" % (self.codomain(), new_codomain)
    264         elif connecting.domain() is not self.codomain():
    265             raise RuntimeError, "BUG: coerce_map_from should always return a map from its input (%s)" % new_codomain
    266         else:
    267             return self.post_compose(connecting)
    268            
    269     def is_injective(self):
    270         raise NotImplementedError, type(self)
    271 
    272     def is_surjective(self):
    273         raise NotImplementedError, type(self)
    274 
    275     def __pow__(self, n, dummy):
    276         if not self.is_endomorphism():
    277             raise TypeError, "self must be an endomorphism."
    278         # todo -- what about the case n=0 -- need to specify the identity map somehow.
    279         return generic_power(self, n)
    280        
    281     def section(self):
    282         return None
    283 
    284 cdef class Section(Morphism):
    285     def __init__(self, morphism):
    286         from sage.categories.homset import Hom
    287         from sage.categories.category_types import SetsWithPartialMaps
    288         Morphism.__init__(self, Hom(morphism.codomain(), morphism.domain(), SetsWithPartialMaps()))
    289         self._morphism = morphism
    290 
    291     def _repr_type(self):
    292         return "Section"
    29369
    29470cdef class FormalCoercionMorphism(Morphism):
    29571    def __init__(self, parent):
    cdef class IdentityMorphism(Morphism): 
    350126    def __invert__(self):
    351127        return self
    352128           
    353 
    354 cdef class FormalCompositeMorphism(Morphism):
    355     def __init__(self, parent, first, second):
    356         Morphism.__init__(self, parent)
    357         self.__first = first
    358         self.__second = second
    359         self._coerce_cost = (<Morphism>first)._coerce_cost + (<Morphism>second)._coerce_cost
    360 
    361     cdef _update_slots(self, _slots):
    362         self.__first = _slots['__first']
    363         self.__second = _slots['__second']
    364         Morphism._update_slots(self, _slots)
    365        
    366     cdef _extra_slots(self, _slots):
    367         _slots['__first'] = self.__first
    368         _slots['__second'] = self.__second
    369         return Morphism._extra_slots(self, _slots)
    370 
    371     cpdef Element _call_(self, x):
    372         return self.__second._call_(self.__first._call_(x))
    373 
    374     cpdef Element _call_with_args(self, x, args=(), kwds={}):
    375         return self.__second._call_with_args(self.__first._call_(x), args, kwds)
    376    
    377     def _repr_type(self):
    378         return "Composite"
    379 
    380     def _repr_defn(self):
    381         return "  %s\nthen\n  %s"%(self.__first, self.__second)
    382 
    383     def first(self):
    384         """
    385         The first morphism in the formal composition, where the
    386         composition is x|--> second(first(x)).
    387        
    388         """
    389         return self.__first
    390        
    391     def second(self):
    392         """
    393         The second morphism in the formal composition, where the
    394         composition is x|--> second(first(x)).
    395         """
    396         return self.__second
    397        
    398     def is_injective(self):
    399         if self.__first.is_injective():
    400             if self.__second.is_injective():
    401                 return True
    402             elif self.__first.is_surjective():
    403                 return False
    404             else:
    405                 raise NotImplementedError, "Not enough information to deduce injectivity."
    406         else:
    407             return False
    408        
    409     def is_surjective(self):
    410         if self.__second.is_surjective():
    411             if self.__first.is_surjective():
    412                 return True
    413             elif self.__second.is_injective():
    414                 return False
    415             else:
    416                 raise NotImplementedError, "Not enough information to deduce surjectivity."
    417         else:
    418             return False
    419        
    420129cdef class SetMorphism(Morphism):
    421130    def __init__(self, parent, function):
    422131        """
  • sage/rings/morphism.pyx

    diff -r 8a86866fba28 -r e16fe6aeb45f sage/rings/morphism.pyx
    a b We next compose the inclusion with reduc 
    146146      To:   Finite Field of size 2
    147147    sage: f = i * pi
    148148    sage: f
    149     Composite morphism:
     149    Composite map:
    150150      From: Integer Ring
    151151      To:   Finite Field in a of size 2^2
    152152      Defn:   Ring Coercion morphism:
  • sage/rings/polynomial/laurent_polynomial_ring.py

    diff -r 8a86866fba28 -r e16fe6aeb45f sage/rings/polynomial/laurent_polynomial_ring.py
    a b class LaurentPolynomialRing_generic(Comm 
    461461        EXAMPLES:
    462462            sage: L.<x,y> = LaurentPolynomialRing(QQ)
    463463            sage: L.coerce_map_from(QQ)
    464             Composite morphism:
     464            Composite map:
    465465              From: Rational Field
    466466              To:   Multivariate Laurent Polynomial Ring in x, y over Rational Field
    467467              Defn:   Call morphism:
  • sage/structure/coerce.pxd

    diff -r 8a86866fba28 -r e16fe6aeb45f sage/structure/coerce.pxd
    a b from element cimport Element, RingElemen 
    33
    44from parent cimport Parent
    55from sage.categories.action cimport Action
    6 from sage.categories.morphism cimport Morphism
    76
    87from coerce_dict cimport TripleDict, TripleDictIter
    98
  • sage/structure/coerce.pyx

    diff -r 8a86866fba28 -r e16fe6aeb45f sage/structure/coerce.pyx
    a b import operator 
    7676import operator
    7777
    7878from sage_object cimport SageObject
     79from sage.categories.map cimport Map
    7980import sage.categories.morphism
    8081from sage.categories.morphism import IdentityMorphism
    8182from sage.categories.action import InverseAction, PrecomposedAction
    cdef class CoercionModel_cache_maps(Coer 
    186187        """
    187188        # This MUST be a mapping of tuples, where each
    188189        # tuple contains at least two elements that are either
    189         # None or of type Morphism.
     190        # None or of type Map.
    190191        self._coercion_maps = TripleDict(lookup_dict_size, threshold=lookup_dict_threshold)
    191192        # This MUST be a mapping to actions.
    192193        self._action_maps = TripleDict(lookup_dict_size, threshold=lookup_dict_threshold)
    cdef class CoercionModel_cache_maps(Coer 
    305306        """
    306307        Returns the list of exceptions that were caught in the course of
    307308        executing the last binary operation. Useful for diagnosis when
    308         user-defined morphisms or actions raise exceptions that are caught in
     309        user-defined maps or actions raise exceptions that are caught in
    309310        the course of coercion detection.
    310311       
    311312        If all went well, this should be the empty list. If things aren't
    cdef class CoercionModel_cache_maps(Coer 
    632633        if coercions is not None:
    633634            x_map, y_map = coercions
    634635            if x_map is not None:
    635                 x_elt = (<Morphism>x_map)._call_(x)
     636                x_elt = (<Map>x_map)._call_(x)
    636637            else:
    637638                x_elt = x
    638639            if y_map is not None:
    639                 y_elt = (<Morphism>y_map)._call_(y)
     640                y_elt = (<Map>y_map)._call_(y)
    640641            else:
    641642                y_elt = y
    642643            if x_elt is None:
    643                 raise RuntimeError, "BUG in morphism, returned None %s %s %s" % (x, type(x_map), x_map)
     644                raise RuntimeError, "BUG in map, returned None %s %s %s" % (x, type(x_map), x_map)
    644645            elif y_elt is None:
    645                 raise RuntimeError, "BUG in morphism, returned None %s %s %s" % (y, type(y_map), y_map)
     646                raise RuntimeError, "BUG in map, returned None %s %s %s" % (y, type(y_map), y_map)
    646647            if x_elt._parent is y_elt._parent:
    647648                # We must verify this as otherwise we are prone to
    648649                # getting into an infinite loop in c, and the above
    649                 # morphisms may be written by (imperfect) users.
     650                # maps may be written by (imperfect) users.
    650651                return x_elt,y_elt
    651652            elif x_elt._parent == y_elt._parent:
    652653                # TODO: Non-uniqueness of parents strikes again!
    cdef class CoercionModel_cache_maps(Coer 
    750751            else:
    751752                if homs is not None:
    752753                    x_map, y_map = homs
    753                     if x_map is not None and not isinstance(x_map, Morphism):
    754                         raise RuntimeError, "BUG in coercion model: coerce_map_from must return Morphism"
    755                     if y_map is not None and not isinstance(y_map, Morphism):
    756                         raise RuntimeError, "BUG in coercion model: coerce_map_from must return Morphism"
     754                    if x_map is not None and not isinstance(x_map, Map):
     755                        raise RuntimeError, "BUG in coercion model: coerce_map_from must return a Map"
     756                    if y_map is not None and not isinstance(y_map, Map):
     757                        raise RuntimeError, "BUG in coercion model: coerce_map_from must return a Map"
    757758            swap = None if homs is None else (homs[1], homs[0])
    758759            self._coercion_maps.set(R, S, None, homs)
    759760            self._coercion_maps.set(S, R, None, swap)
    cdef class CoercionModel_cache_maps(Coer 
    781782        """
    782783        if homs is None:
    783784            return None
    784         cdef Morphism x_map, y_map
     785        cdef Map x_map, y_map
    785786        R_map, S_map = homs
    786787        if PY_TYPE_CHECK(R, type):
    787788            R = Set_PythonType(R)
    cdef class CoercionModel_cache_maps(Coer 
    11191120            Both x (='f(a)') and y (='g(b)') are supposed to have identical parents but they don't.
    11201121            In fact, x has parent '<type 'str'>'
    11211122            whereas y has parent '<type 'str'>'
    1122             Original elements 'a' (parent <type 'str'>) and 'b' (parent <type 'str'>) and morphisms
     1123            Original elements 'a' (parent <type 'str'>) and 'b' (parent <type 'str'>) and maps
    11231124            <type 'str'> 'f'
    11241125            <type 'str'> 'g'
    11251126        """
    Both x (=%r) and y (=%r) are supposed to 
    11271128Both x (=%r) and y (=%r) are supposed to have identical parents but they don't.
    11281129In fact, x has parent '%s'
    11291130whereas y has parent '%s'
    1130 Original elements %r (parent %s) and %r (parent %s) and morphisms
     1131Original elements %r (parent %s) and %r (parent %s) and maps
    11311132%s %r
    11321133%s %r"""%( x_elt, y_elt, parent_c(x_elt), parent_c(y_elt),
    11331134            x, parent_c(x), y, parent_c(y),
  • sage/structure/coerce_maps.pxd

    diff -r 8a86866fba28 -r e16fe6aeb45f sage/structure/coerce_maps.pxd
    a b from sage.categories.action cimport Acti 
    11from sage.categories.action cimport Action
    2 from sage.categories.morphism cimport Morphism
     2from sage.categories.map cimport Map
    33
    4 cdef class DefaultConvertMorphism(Morphism):
     4cdef class DefaultConvertMap(Map):
    55    cdef public bint _force_use
    66    cdef public bint _is_coercion
    77
    8 cdef class DefaultConvertMorphism_unique(DefaultConvertMorphism):
     8cdef class DefaultConvertMap_unique(DefaultConvertMap):
    99    pass
    1010
    11 cdef class NamedConvertMorphism(Morphism):
     11cdef class NamedConvertMap(Map):
    1212    cdef readonly method_name
    1313    cdef public bint _force_use
    1414
    15 cdef class TryMorphism(Morphism):
    16     cdef Morphism _morphism_p
    17     cdef Morphism _morphism_b
     15cdef class TryMap(Map):
     16    cdef Map _map_p
     17    cdef Map _map_b
    1818    cdef _error_types
  • sage/structure/coerce_maps.pyx

    diff -r 8a86866fba28 -r e16fe6aeb45f sage/structure/coerce_maps.pyx
    a b import re 
    33import re
    44import types
    55
    6 import sage.categories.homset as homset
    76from parent import Set_PythonType
     7from sage.structure.parent cimport Parent
    88from sage.structure.element cimport Element
    9 from sage.structure.parent cimport Parent
    109
    1110cdef object BuiltinMethodType = type(repr)
    1211
    cdef bint print_warnings = 0 
    1413cdef bint print_warnings = 0
    1514
    1615
    17 cdef class DefaultConvertMorphism(Morphism):
     16cdef class DefaultConvertMap(Map):
    1817    """
    19     This morphism simply differs action to the codomain's element_constructor method,
     18    This morphism simply calls the codomain's element_constructor method,
    2019    passing in the codomain as the first argument.
    2120    """
    2221    def __init__(self, domain, codomain, force_use=False):
    2322        if not PY_TYPE_CHECK(domain, Parent):
    2423            domain = Set_PythonType(domain)
    25         Morphism.__init__(self, homset.Hom(domain, codomain))
     24        Map.__init__(self, domain, codomain)
    2625        self._coerce_cost = 100
    2726        self._force_use = force_use
    2827        if self._codomain._element_constructor is None:
    cdef class DefaultConvertMorphism(Morphi 
    5857    def _repr_type(self):
    5958        return "Conversion"
    6059
    61 cdef class DefaultConvertMorphism_unique(DefaultConvertMorphism):
     60cdef class DefaultConvertMap_unique(DefaultConvertMap):
    6261    """
    6362    This morphism simply differs action to the codomain's element_constructor method,
    6463    WITHOUT passing in the codomain as the first argument.
    cdef class DefaultConvertMorphism_unique 
    9897    def _repr_type(self):
    9998        return "Coercion" if self._is_coercion else "Conversion"
    10099
    101 cdef class NamedConvertMorphism(Morphism):
     100cdef class NamedConvertMap(Map):
    102101    """
    103102    This is used for creating a elements via the _xxx_ methods.
    104103   
    cdef class NamedConvertMorphism(Morphism 
    109108    def __init__(self, domain, codomain, method_name, force_use=False):
    110109        if PY_TYPE_CHECK(domain, type):
    111110            domain = Set_PythonType(domain)
    112         Morphism.__init__(self, homset.Hom(domain, codomain))
     111        Map.__init__(self, domain, codomain)
    113112        self._coerce_cost = 400
    114113        self._force_use = force_use
    115114        self.method_name = method_name
    cdef class NamedConvertMorphism(Morphism 
    123122                print type(self._codomain), self._codomain
    124123                print self.method_name
    125124            raise TypeError, "Cannot coerce %s to %s"%(x, self._codomain)
    126         cdef Morphism m
     125        cdef Map m
    127126        cdef Element e = method(self._codomain)
    128127        if e is None:
    129128            raise RuntimeError, "BUG in coercion model: %s method of %s returned None" % (self.method_name, type(x))
    cdef class NamedConvertMorphism(Morphism 
    137136    def _repr_type(self):
    138137        return "Conversion via %s" % self.method_name
    139138   
    140 cdef class CallableConvertMorphism(Morphism):
     139cdef class CallableConvertMap(Map):
    141140    cdef bint _parent_as_first_arg
    142141    cdef _func
    143142   
    144143    def __init__(self, domain, codomain, func, parent_as_first_arg=None):
    145144        """
    146         This lets one easily create morphims from any callable object.
     145        This lets one easily create maps from any callable object.
    147146       
    148         This is especially useful to create morphisms from bound methods.
     147        This is especially useful to create maps from bound methods.
    149148       
    150149        EXAMPLES:
    151             sage: from sage.structure.coerce_maps import CallableConvertMorphism
     150            sage: from sage.structure.coerce_maps import CallableConvertMap
    152151            sage: def foo(P, x): return x/2
    153             sage: f = CallableConvertMorphism(ZZ, QQ, foo)
     152            sage: f = CallableConvertMap(ZZ, QQ, foo)
    154153            sage: f(3)
    155154            3/2
    156155            sage: f
    157             Conversion via foo morphism:
     156            Conversion via foo map:
    158157              From: Integer Ring
    159158              To:   Rational Field
    160159           
    161160        Create a homomorphism from $\R$ to $\R^+$ viewed as additave groups.
    162             sage: f = CallableConvertMorphism(RR, RR, exp, parent_as_first_arg=False)
     161            sage: f = CallableConvertMap(RR, RR, exp, parent_as_first_arg=False)
    163162            sage: f(0)
    164163            1.00000000000000
    165164            sage: f(1)
    cdef class CallableConvertMorphism(Morph 
    169168        """
    170169        if PY_TYPE_CHECK(domain, type):
    171170            domain = Set_PythonType(domain)
    172         Morphism.__init__(self, homset.Hom(domain, codomain))
     171        Map.__init__(self, domain, codomain)
    173172        self._coerce_cost = 100
    174173        self._func = func
    175174        if parent_as_first_arg is None:
    cdef class CallableConvertMorphism(Morph 
    188187        checking (the return value must be an element with the correct parent).
    189188               
    190189        TESTS:
    191             sage: from sage.structure.coerce_maps import CallableConvertMorphism
     190            sage: from sage.structure.coerce_maps import CallableConvertMap
    192191            sage: def foo(P, x): return x
    193             sage: f = CallableConvertMorphism(ZZ, ZZ, foo)
     192            sage: f = CallableConvertMap(ZZ, ZZ, foo)
    194193            sage: f(0)
    195194            0
    196             sage: f = CallableConvertMorphism(ZZ, QQ, foo)
     195            sage: f = CallableConvertMap(ZZ, QQ, foo)
    197196            sage: f(0)
    198197            Traceback (most recent call last):
    199198            ...
    cdef class CallableConvertMorphism(Morph 
    220219        except AttributeError:
    221220            return "Conversion via %s" % self._func
    222221   
    223 cdef class ListMorphism(Morphism):
     222cdef class ListMorphism(Map):
    224223
    225     cdef Morphism _real_morphism
     224    cdef Map _real_morphism
    226225
    227     def __init__(self, domain, Morphism real_morphism):
     226    def __init__(self, domain, Map real_morphism):
    228227        if not PY_TYPE_CHECK(domain, Parent):
    229228            domain = Set_PythonType(domain)
    230         Morphism.__init__(self, homset.Hom(domain, real_morphism.codomain()))
     229        Map.__init__(self, domain, real_morphism.codomain())
    231230        self._coerce_cost = real_morphism._coerce_cost + 3
    232231        self._real_morphism = real_morphism
    233232
    cdef class ListMorphism(Morphism): 
    248247    def _repr_type(self):
    249248        return "List"
    250249
    251 cdef class TryMorphism(Morphism):
     250cdef class TryMap(Map):
    252251    def __init__(self, morphism_preferred, morphism_backup, error_types=None):
    253252        if morphism_preferred.parent() is not morphism_backup.parent():
    254253            raise TypeError, "incorrectly matching parent"
    255         Morphism.__init__(self, morphism_preferred.parent())
    256         self._morphism_p = <Morphism?>morphism_preferred
    257         self._morphism_b = <Morphism?>morphism_backup
     254        Map.__init__(self, morphism_preferred.parent())
     255        self._map_p = morphism_preferred
     256        self._map_b = morphism_backup
    258257        if error_types is None:
    259258            self._error_types = (ValueError, TypeError, AttributeError)
    260259        else:
    cdef class TryMorphism(Morphism): 
    262261
    263262    cpdef Element _call_(self, x):
    264263        try:
    265             return self._morphism_p._call_(x)
     264            return self._map_p._call_(x)
    266265        except self._error_types:
    267             return self._morphism_b._call_(x)
     266            return self._map_b._call_(x)
    268267
    269268    cpdef Element _call_with_args(self, x, args=(), kwds={}):
    270269        try:
    271             return self._morphism_p._call_with_args(x, args, kwds)
     270            return self._map_p._call_with_args(x, args, kwds)
    272271        except self._error_types:
    273             return self._morphism_b._call_with_args(x, args, kwds)
     272            return self._map_b._call_with_args(x, args, kwds)
  • sage/structure/parent.pyx

    diff -r 8a86866fba28 -r e16fe6aeb45f sage/structure/parent.pyx
    a b This came up in some subtle bug once. 
    1515"""
    1616cimport element
    1717cimport sage.categories.morphism as morphism
     18cimport sage.categories.map as map
    1819
    1920cdef int bad_parent_warnings = 0
    2021cdef int unique_parent_warnings = 0
    cdef class Parent(category_object.Catego 
    224225            return x
    225226        if self._coerce_from_hash is None: # this is because parent.__init__() does not always get called
    226227            self.init_coerce()
    227         cdef morphism.Morphism mor = <morphism.Morphism>self.convert_map_from(R)
     228        cdef map.Map mor = <map.Map>self.convert_map_from(R)
    228229        if mor is not None:
    229230            try:
    230231                if no_extra_args:
    cdef class Parent(category_object.Catego 
    300301                    _record_exception()
    301302            raise TypeError, "no cannonical coercion from %s to %s" % (parent_c(x), self)
    302303        else:
    303             return (<morphism.Morphism>mor)._call_(x)
     304            return (<map.Map>mor)._call_(x)
    304305   
    305306    def list(self):
    306307        """
    cdef class Parent(category_object.Catego 
    434435            coerce_list  -- a list of coercion Morphisms to self and
    435436                            parents with cannonical coercions to self
    436437            action_list  -- a list of actions on and by self
    437             convert_list -- a list of conversion Morphisms to self and
     438            convert_list -- a list of conversion Maps to self and
    438439                            parents with conversions to self
    439440            embedding    -- a single Morphism from self
    440441            convert_method_name -- a name to look for that other elements
    cdef class Parent(category_object.Catego 
    455456        self._initial_action_list = action_list
    456457        self._initial_convert_list = convert_list
    457458       
    458         from sage.categories.morphism import Morphism
    459 
    460459        self._convert_method_name = convert_method_name
    461460        if init_no_parent is not None:
    462461            self._element_init_pass_parent = not init_no_parent
    463462       
    464463        for mor in coerce_list:
    465             if PY_TYPE_CHECK(mor, Morphism):
     464            if PY_TYPE_CHECK(mor, map.Map):
    466465                if mor.codomain() is not self:
    467                     raise ValueError, "Morphism's codomain must be self (%s) is not (%s)" % (self, mor.codomain())
     466                    raise ValueError, "Map's codomain must be self (%s) is not (%s)" % (self, mor.codomain())
    468467                self._coerce_from_list.append(mor)
    469468                self._coerce_from_hash[mor.domain()] = mor
    470469            elif PY_TYPE_CHECK(mor, Parent) or PY_TYPE_CHECK(mor, type):
    cdef class Parent(category_object.Catego 
    473472                self._coerce_from_list.append(mor)
    474473                self._coerce_from_hash[P] = mor
    475474            else:
    476                 raise TypeError, "entries in the coerce_list must be parents or morphisms (got %s)" % type(mor)
     475                raise TypeError, "entries in the coerce_list must be parents or maps (got %s)" % type(mor)
    477476               
    478477        from sage.categories.action import Action
    479478        for action in action_list:
    cdef class Parent(category_object.Catego 
    490489                raise TypeError, "entries in the action_list must be actions"
    491490               
    492491        for mor in convert_list:
    493             if isinstance(mor, Morphism):
     492            if isinstance(mor, map.Map):
    494493                if mor.codomain() is not self:
    495                     raise ValueError, "Morphism's codomain must be self"
     494                    raise ValueError, "Map's codomain must be self"
    496495                self._convert_from_list.append(mor)
    497496                self._convert_from_hash[mor.domain()] = mor
    498497            elif PY_TYPE_CHECK(mor, Parent) or PY_TYPE_CHECK(mor, type):
    cdef class Parent(category_object.Catego 
    500499                self._convert_from_list.append(mor)
    501500                self._convert_from_hash[mor.domain()] = mor
    502501            else:
    503                 raise TypeError, "entries in the convert_list must be parents or morphisms"
     502                raise TypeError, "entries in the convert_list must be parents or maps"
    504503               
    505         if isinstance(embedding, Morphism):
     504        if isinstance(embedding, map.Map):
    506505            if embedding.domain() is not self:
    507                 raise ValueError, "Morphism's domain must be self"
     506                raise ValueError, "embedding's domain must be self"
    508507            self._embedding = embedding
    509508        elif isinstance(embedding, Parent):
    510509            self._embedding = embedding._generic_convert_map(self)
    511510        elif embedding is not None:
    512             raise TypeError, "embedding must be a parent or morphism"
     511            raise TypeError, "embedding must be a parent or map"
    513512           
    514513    def get_embedding(self):
    515514        return self._embedding
    cdef class Parent(category_object.Catego 
    528527            else:
    529528                element_constructor = None
    530529            if element_constructor is not None and hasattr(element_constructor, self._convert_method_name):
    531                 return coerce_maps.NamedConvertMorphism(S, self, self._convert_method_name)
     530                return coerce_maps.NamedConvertMap(S, self, self._convert_method_name)
    532531           
    533532        if self._element_init_pass_parent:
    534             return coerce_maps.DefaultConvertMorphism(S, self)
     533            return coerce_maps.DefaultConvertMap(S, self)
    535534        else:
    536             return coerce_maps.DefaultConvertMorphism_unique(S, self)
     535            return coerce_maps.DefaultConvertMap_unique(S, self)
    537536
    538537    cpdef bint has_coerce_map_from(self, S) except -2:
    539538        """
    cdef class Parent(category_object.Catego 
    570569        return self.coerce_map_from(S) is not None
    571570       
    572571    cpdef coerce_map_from(self, S):
    573         cdef morphism.Morphism mor
     572        cdef map.Map mor
    574573        if S is self:
    575574            from sage.categories.homset import Hom
    576575            return Hom(self, self).identity()
    cdef class Parent(category_object.Catego 
    620619       
    621620            1. If S has an embedding into T, look for T -> self and return composition
    622621            2. If self._coerce_map_from_(S) is NOT exactly one of
    623                     - DefaultConvertMorphism
    624                     - DefaultConvertMorphism_unique
    625                     - NamedConvertMorphism
    626                 return this morphism
    627             3. Traverse the coercion lists looking for the "best" morphism
     622                    - DefaultConvertMap
     623                    - DefaultConvertMap_unique
     624                    - NamedConvertMap
     625                return this map
     626            3. Traverse the coercion lists looking for the "best" map
    628627               (including the one found at 2).
    629628        """
    630629        best_mor = None
    cdef class Parent(category_object.Catego 
    635634            if connecting is not None:
    636635                return (<Parent>S)._embedding.post_compose(connecting)
    637636       
    638         cdef morphism.Morphism mor = self._coerce_map_from_(S)
     637        cdef map.Map mor = self._coerce_map_from_(S)
    639638        if mor is not None:
    640             from sage.categories.morphism import Morphism
    641             from coerce_maps import DefaultConvertMorphism, DefaultConvertMorphism_unique, NamedConvertMorphism
    642             if not PY_TYPE_CHECK(mor, Morphism):
    643                 raise TypeError, "_coerce_map_from_ must return None or an explicit Morphism"
    644             elif (PY_TYPE_CHECK_EXACT(mor, DefaultConvertMorphism) or
    645                   PY_TYPE_CHECK_EXACT(mor, DefaultConvertMorphism_unique) or
    646                   PY_TYPE_CHECK_EXACT(mor, NamedConvertMorphism)) and not mor._force_use:
     639            from sage.categories.map import Map
     640            from coerce_maps import DefaultConvertMap, DefaultConvertMap_unique, NamedConvertMap
     641            if not PY_TYPE_CHECK(mor, Map):
     642                raise TypeError, "_coerce_map_from_ must return None or an explicit Map"
     643            elif (PY_TYPE_CHECK_EXACT(mor, DefaultConvertMap) or
     644                  PY_TYPE_CHECK_EXACT(mor, DefaultConvertMap_unique) or
     645                  PY_TYPE_CHECK_EXACT(mor, NamedConvertMap)) and not mor._force_use:
    647646                # If there is something better in the list, try to return that instead
    648647                # This is so, for example, has_coerce_map_from can return True but still
    649648                # take advantage of the _populate_coercion_lists_ data.
    650649                best_mor = mor
    651650            else:
    652651                return mor
    653         import sage.categories.morphism
    654         from sage.categories.morphism import Morphism
     652        from sage.categories.map import Map
    655653        from sage.categories.homset import Hom
    656654
    657655        cdef int num_paths = 1 # this is the number of paths we find before settling on the best (the one with lowest coerce_cost).
    658656                               # setting this to 1 will make it return the first path found.
    659657        cdef int mor_found = 0
    660658        cdef Parent R
    661         # Recurse.  Note that if S is the domain of one of the morphisms in self._coerce_from_list,
    662         # we will have stuck the morphism into _coerce_map_hash and thus returned it already.
     659        # Recurse.  Note that if S is the domain of one of the maps in self._coerce_from_list,
     660        # we will have stuck the map into _coerce_map_hash and thus returned it already.
    663661        for mor in self._coerce_from_list:
    664662            if mor._domain is S:
    665663                if best_mor is None or mor._coerce_cost < best_mor._coerce_cost:
    cdef class Parent(category_object.Catego 
    694692            return mor
    695693           
    696694    cdef discover_convert_map_from(self, S):
    697         cdef morphism.Morphism mor = self.coerce_map_from(S)
     695        cdef map.Map mor = self.coerce_map_from(S)
    698696        if mor is not None:
    699697            return mor
    700698
    cdef class Parent(category_object.Catego 
    759757        # G acts on S, G -> G', R -> S => G' acts on R (?)
    760758        # NO! ZZ[x,y] acts on Matrices(ZZ[x]) but ZZ[y] does not.
    761759        # What may be true is that if the action's desination is S, then this can be allowed.
    762         import sage.categories.morphism
    763760        from sage.categories.action import Action, PrecomposedAction
    764         from sage.categories.morphism import Morphism
    765761        from sage.categories.homset import Hom
    766762        from coerce_actions import LeftModuleAction, RightModuleAction
    767763        cdef Parent R
  • sage/structure/parent_old.pyx

    diff -r 8a86866fba28 -r e16fe6aeb45f sage/structure/parent_old.pyx
    a b cdef class Parent(parent.Parent): 
    158158        else:
    159159            mor = self.coerce_map_from_c_impl(S)
    160160        import sage.categories.morphism
     161        import sage.categories.map
    161162        if mor is True:
    162163            mor = sage.categories.morphism.CallMorphism(S, self)
    163164        elif mor is False:
    164165            mor = None
    165         elif mor is not None and not isinstance(mor, sage.categories.morphism.Morphism):
    166             raise TypeError, "coerce_map_from_impl must return a boolean, None, or an explicit Morphism"
     166        elif mor is not None and not isinstance(mor, sage.categories.map.Map):
     167            raise TypeError, "coerce_map_from_impl must return a boolean, None, or an explicit Map"
    167168        if mor is not None:
    168169            self._coerce_from_hash[S] = mor # TODO: if this is None, could it be non-None in the future?
    169170        return mor
    cdef class Parent(parent.Parent): 
    173174           
    174175    cdef coerce_map_from_c_impl(self, S):
    175176        import sage.categories.morphism
    176         from sage.categories.morphism import Morphism
     177        from sage.categories.map import Map
    177178        from sage.categories.homset import Hom
    178179        cdef parent.Parent R
    179180        for mor in self._coerce_from_list:
    180             if PY_TYPE_CHECK(mor, Morphism):
     181            if PY_TYPE_CHECK(mor, Map):
    181182                R = mor.domain()
    182183            else:
    183184                R = mor
    cdef class Parent(parent.Parent): 
    226227           
    227228    cdef get_action_c_impl(self, S, op, bint self_on_left):
    228229        # G acts on S, G -> G', R -> S => G' acts on R (?)
    229         import sage.categories.morphism
    230230        from sage.categories.action import Action, PrecomposedAction
    231         from sage.categories.morphism import Morphism
    232231        from sage.categories.homset import Hom
    233232        from coerce_actions import LeftModuleAction, RightModuleAction
    234233        cdef parent.Parent R
  • setup.py

    diff -r 8a86866fba28 -r e16fe6aeb45f setup.py
    a b ext_modules = [ \ 
    521521    Extension('sage.structure.element',
    522522              sources = ['sage/structure/element.pyx']), \
    523523
     524    Extension('sage.categories.map',
     525              sources = ['sage/categories/map.pyx']), \
     526             
    524527    Extension('sage.categories.morphism',
    525528              sources = ['sage/categories/morphism.pyx']), \
    526529