Ticket #14279: trac_14279-composition_action.patch

File trac_14279-composition_action.patch, 12.9 KB (added by SimonKing, 9 years ago)

Composition action

  • sage/categories/homset.pyx

    # HG changeset patch
    # User Simon King <simon.king@uni-jena.de>
    # Date 1363598466 -3600
    # Node ID e134bc6c6c082ce2a49c649374ead4bf773ab26d
    # Parent  4e89eea46baee0b08e2ab5fc7888543b4432d242
    #14279: Use an action for multiplication of morphisms.
    
    diff --git a/sage/categories/homset.pyx b/sage/categories/homset.pyx
    a b  
    7070from sage.misc.lazy_attribute import lazy_attribute
    7171from sage.misc.cachefunc import cached_function, cached_method
    7272import types
     73from operator import mul
    7374
    7475###################################
    7576# Use the weak "triple" dictionary
     
    367368    """
    368369    return End(X)(f)
    369370
     371##############################################################
     372##   Implement composisition of morphisms
     373
     374from sage.categories.action cimport Action
     375from sage.categories.map cimport Map
     376cdef class CompositionAction(Action):
     377    cdef Homset H
     378    def __init__(self, Homset G, Homset S):
     379        Action.__init__(self, G, S, 1, mul)
     380        self.H = Hom(S.domain(), G.codomain(), G._hom_category._meet_(S._hom_category))
     381    def _repr_name_(self):
     382        return "composisition action"
     383    cpdef _call_(self, a, b):
     384        return (<Map>a)._composition_(b, self.H)
     385
     386##############################################################
     387
     388
    370389cdef class Homset(Set_generic):
    371390    """
    372391    The class for collections of morphisms in a category.
     
    430449    def __reduce__(self):
    431450        return Hom, (self._domain, self._codomain, self._hom_category)
    432451
     452    cpdef _get_action_(self, S, op, bint self_on_left):
     453        if op != mul:
     454            return None
     455        if isinstance(S, Homset):
     456            if self_on_left:
     457                if self.domain().has_coerce_map_from(S.codomain()):
     458                    return CompositionAction(self, S)
     459            else:
     460                if S.domain().has_coerce_map_from(self.codomain()):
     461                    return CompositionAction(S, self)
     462        return None
     463
    433464    def _repr_(self):
    434465        """
    435466        TESTS::
     
    482513        """
    483514        return self._hom_category
    484515
    485     def _coerce_map_from_(self, S):
     516    cpdef _coerce_map_from_(self, S):
    486517        """
    487518        If ``S`` is a homset, then it coerces into ``self``,
    488519        if ``self``'s domain coerces into ``S``'s domain and
     
    791822
    792823            sage: H = Hom(ZZ^2, ZZ^3)
    793824            sage: H.get_action_c(ZZ, operator.add, ZZ)
     825            doctest:...: DeprecationWarning: Set of Morphisms from Ambient free module of rank 2 over the principal ideal domain Integer Ring to Ambient free module of rank 3 over the principal ideal domain Integer Ring in Category of modules with basis over Integer Ring uses get_action_c, which belongs to the old coercion model
     826            See http://trac.sagemath.org/14279 for details.
    794827        """
     828        from sage.misc.superseded import deprecation
     829        deprecation(14279, "%s uses get_action_c, which belongs to the old coercion model"%self)
    795830        return None
    796831       
    797832    def coerce_map_from_c(self, R):
     
    804839
    805840            sage: H = Hom(ZZ^2, ZZ^3)
    806841            sage: H.coerce_map_from_c(ZZ)
     842            doctest:...: DeprecationWarning: Set of Morphisms from Ambient free module of rank 2 over the principal ideal domain Integer Ring to Ambient free module of rank 3 over the principal ideal domain Integer Ring in Category of modules with basis over Integer Ring uses coerce_map_from_c, which belongs to the old coercion model
     843            See http://trac.sagemath.org/14279 for details.
    807844        """
     845        from sage.misc.superseded import deprecation
     846        deprecation(14279, "%s uses coerce_map_from_c, which belongs to the old coercion model"%self)
    808847        return None
    809848
    810849# Really needed???
    811 class HomsetWithBase(Homset):
     850cdef class HomsetWithBase(Homset):
    812851    def __init__(self, X, Y, category=None, check=True, base=None):
    813852        r"""
    814853        TESTS::
  • sage/categories/map.pxd

    diff --git a/sage/categories/map.pxd b/sage/categories/map.pxd
    a b  
    1717
    1818    cpdef domain(self)
    1919    cpdef codomain(self)
    20    
     20    cdef Map _composition(self, Map right)
     21    cpdef Map _composition_(self, Map right, homset)
     22
    2123    cdef public _repr_type_str
    2224
    2325
  • sage/categories/map.pyx

    diff --git a/sage/categories/map.pyx b/sage/categories/map.pyx
    a b  
    1616#                  http://www.gnu.org/licenses/
    1717#*****************************************************************************
    1818
     19import operator
     20
    1921include "../ext/stdsage.pxi"
     22include "../structure/coerce.pxi"
    2023
    2124import homset
     25from operator import mul
    2226from sage.structure.parent cimport Set_PythonType
     27from sage.structure.element cimport CoercionModel
     28from sage.categories.action cimport Action
    2329
    24 # copied from sage.structure.parent
    25 cdef inline parent_c(x):
    26     if PY_TYPE_CHECK(x, Element):
    27         return (<Element>x)._parent
    28     else:
    29         try:
    30             return x.parent()
    31         except AttributeError:
    32             return <object>PY_TYPE(x)
     30cdef CoercionModel coercion_model = None
     31
     32## copied from sage.structure.parent
     33#cdef inline parent_c(x):
     34#    if PY_TYPE_CHECK(x, Element):
     35#        return (<Element>x)._parent
     36#    else:
     37#        try:
     38#            return x.parent()
     39#        except AttributeError:
     40#            return <object>PY_TYPE(x)
    3341
    3442def unpickle_map(_class, parent, _dict, _slots):
    3543    """
     
    646654                      From: Multivariate Polynomial Ring in a, b over Rational Field
    647655                      To:   Rational Field
    648656        """
     657        global coercion_model
     658        if coercion_model is None:
     659            from sage.structure.element import get_coercion_model
     660            coercion_model = get_coercion_model()
     661        # In the coercion model, if both arguments are in the same
     662        # parent, __mul__ is called (which is bad here, because of recursion...)
     663        cdef Action action = coercion_model.get_action(parent_c(self), parent_c(right), mul, self, right)
     664        if action is not None:
     665            return action._call_(self,right)
     666        return coercion_model.bin_op(self, right, mul)
    649667        if not isinstance(right, Map):
    650668            return super(Map,self).__mul__(right)
    651669            #raise TypeError, "right (=%s) must be a map to multiply it by %s"%(right, self)
    652670        if right.codomain() != self.domain():
    653671            raise TypeError, "self (=%s) domain must equal right (=%s) codomain"%(self, right)
    654         return self._composition(right)
     672        return (<Map>self)._composition(right)
    655673
    656674    # The following is needed, since Map only inherits from ModuleElement,
    657675    # and ModuleElement.__imul__ complains if both arguments come from the same parent.
    658676    __imul__ = __mul__
    659677
    660     def _composition(self, right):
     678    cdef Map _composition(self, Map right):
    661679        """
    662680        Composition of maps, which generically returns a :class:`CompositeMap`.
    663681       
     
    680698            sage: Z = QQ
    681699            sage: phi_xy = SetMorphism(Hom(X, Y, Rings()), lambda p: p[0])
    682700            sage: phi_yz = SetMorphism(Hom(Y, Z, CommutativeAdditiveMonoids()), lambda y: QQ(y)/2)
    683             sage: phi_yz._composition(phi_xy)
     701            sage: phi_yz*phi_xy   # indirect doctest
    684702            Composite map:
    685703              From: Univariate Polynomial Ring in x over Integer Ring
    686704              To:   Rational Field
     
    699717        return self._composition_(right, H)
    700718
    701719    # The following is needed for the _test_prod test of endomorphism rings
    702     _mul_ = _composition
     720    def _mul_(self, Map right):
     721        return self._composition(right)
    703722
    704     def _composition_(self, right, homset):
     723    cpdef Map _composition_(self, Map right, homset):
    705724        """
    706725        INPUT:
    707726       
     
    774793            sage: f_R*f_S
    775794            Traceback (most recent call last):
    776795            ...
    777             TypeError: self (=Ring endomorphism of Multivariate Polynomial Ring in x, y over Rational Field
    778               Defn: x |--> x + y
    779                     y |--> x - y) domain must equal right (=Ring endomorphism of Multivariate Polynomial Ring in a, b over Rational Field
    780               Defn: a |--> a + b
    781                     b |--> a - b) codomain
     796            TypeError: unsupported operand parent(s) for '*': 'Set of Homomorphisms from Multivariate Polynomial Ring in x, y over Rational Field to Multivariate Polynomial Ring in x, y over Rational Field' and 'Set of Homomorphisms from Multivariate Polynomial Ring in a, b over Rational Field to Multivariate Polynomial Ring in a, b over Rational Field'
     797
    782798        """
    783799        return FormalCompositeMap(homset, right, self)
    784800
     
    819835            right = right.extend_codomain(self.domain())
    820836        return self._composition(right)
    821837
    822     def post_compose(self, left):
     838    def post_compose(self, Map left):
    823839        """
    824840        INPUT:
    825841
     
    15531569                raise NotImplementedError, "Not enough information to deduce surjectivity."
    15541570        else:
    15551571            return False
    1556        
     1572
  • sage/modular/abvar/homspace.py

    diff --git a/sage/modular/abvar/homspace.py b/sage/modular/abvar/homspace.py
    a b  
    182182import sage.rings.integer_ring
    183183import sage.rings.all
    184184
    185 from sage.rings.ring import Ring
    186185from sage.categories.category import Category
    187186from sage.categories.rings import Rings
    188187from sage.matrix.matrix_space import MatrixSpace
     
    681680# NOTE/WARNING/TODO:  Below in the __init__, etc. we do *not* check
    682681# that the input gens are give something that spans a sub*ring*, as apposed
    683682# to just a subgroup.
    684 class EndomorphismSubring(Homspace, Ring):
     683#
     684# NOTE: This class used to inherit from sage.rings.ring.Ring.
     685# But unfortunately, Python tends to confuse c(p)def methods for
     686# classes inheriting from two extension classes (here: sage.rings.ring.Ring
     687# and sage.categories.homset.Homset). Therefore, we implement the
     688# ring properties of EndomorphismSubring via the category framework.
     689class EndomorphismSubring(Homspace):
    685690
    686691    def __init__(self, A, gens=None):
    687692        """
     
    728733        # category for its endomorphism sets
    729734        # We need to initialise it as a ring first
    730735        homset_cat = A.category()
    731         cat = Category.join([homset_cat.hom_category(),Rings()])
    732         Ring.__init__(self, A.base_ring())
    733736        Homspace.__init__(self, A, A, cat=homset_cat)
    734737        self._refine_category_(Rings())
    735738        if gens is None:
  • sage/modular/hecke/morphism.py

    diff --git a/sage/modular/hecke/morphism.py b/sage/modular/hecke/morphism.py
    a b  
    8484        sage: F * G
    8585        Traceback (most recent call last):
    8686        ...
    87         TypeError: self (=Hecke module morphism defined by the matrix
    88         [1 2]
    89         Domain: Modular Forms space of dimension 1 for Modular Group SL(2,Z) ...
    90         Codomain: Modular Forms space of dimension 2 for Modular Group SL(2,Z) ...) domain must equal right (=Hecke module morphism defined by the matrix
    91         [1 2 3]
    92         [4 5 6]
    93         Domain: Modular Forms space of dimension 2 for Modular Group SL(2,Z) ...
    94         Codomain: Modular Forms space of dimension 3 for Modular Group SL(2,Z) ...) codomain
     87        TypeError: unsupported operand parent(s) for '*':
     88        'Set of Morphisms from Modular Forms space of dimension 1 for Modular Group SL(2,Z) of weight 4 over Rational Field to Modular Forms space of dimension 2 for Modular Group SL(2,Z) of weight 16 over Rational Field in Category of Hecke modules over Rational Field'
     89        and
     90        'Set of Morphisms from Modular Forms space of dimension 2 for Modular Group SL(2,Z) of weight 16 over Rational Field to Modular Forms space of dimension 3 for Modular Group SL(2,Z) of weight 28 over Rational Field in Category of Hecke modules over Rational Field'
    9591
    9692    """
    9793    def __init__(self, parent, A, name=''):
  • sage/rings/morphism.pxd

    diff --git a/sage/rings/morphism.pxd b/sage/rings/morphism.pxd
    a b  
    22
    33from sage.structure.element cimport Element
    44from sage.categories.morphism cimport Morphism
     5from sage.categories.map cimport Map
    56from sage.rings.ring cimport Ring
    67from sage.structure.category_object cimport CategoryObject
    78
  • sage/rings/morphism.pyx

    diff --git a/sage/rings/morphism.pyx b/sage/rings/morphism.pyx
    a b  
    683683            pass
    684684        return Morphism._extra_slots(self, _slots)
    685685
    686     def _composition_(self, right, homset):
     686    cpdef Map _composition_(self, Map right, homset):
    687687        """
    688688        If ``homset`` is a homset of rings and ``right`` is a
    689689        ring homomorphism given by the images of generators,
     
    759759                    return homset(self*right.abs_hom())
    760760                except ValueError:
    761761                    pass
    762         return sage.categories.map.Map._composition_(self, right, homset)
     762        return RingMap._composition_(self, right, homset)
    763763
    764764    def is_injective(self):
    765765        """