Ticket #14279: trac_14279-new_coercion_for_homsets.patch

File trac_14279-new_coercion_for_homsets.patch, 120.9 KB (added by SimonKing, 9 years ago)

Main patch, needs better documentation of the changes

  • sage/categories/action.pyx

    # HG changeset patch
    # User Simon King <simon.king@uni-jena.de>
    # Date 1363367073 -3600
    # Node ID 4e89eea46baee0b08e2ab5fc7888543b4432d242
    # Parent  a0ca4ca2e910564a8da9e9548f256c1d96abed2c
    #14279: New coercion model for homsets and morphisms
    
    diff --git a/sage/categories/action.pyx b/sage/categories/action.pyx
    a b  
    337337        return "Action of %s on %s under %s."%(self._g,
    338338                                               self._action.underlying_set(), self._action)
    339339       
    340     def __mul__(left, right):
     340    def _mul_(left, right):
    341341        cdef ActionEndomorphism left_c, right_c
    342342        if PY_TYPE_CHECK(left, ActionEndomorphism) and PY_TYPE_CHECK(right, ActionEndomorphism):
    343343            left_c = left
  • sage/categories/homset.pyx

    diff --git a/sage/categories/homset.pyx b/sage/categories/homset.pyx
    a b  
    238238                raise ValueError, "%s of type %s is not a unique parent"%(Y,type(Y))
    239239
    240240    orig_category = category
    241     cat_X = X.category()
    242     cat_Y = Y.category()
     241    # Note: During unpickling, it may happen that
     242    # in order to unpickle X one needs a hom (coercion map)
     243    # with codomain X, which needs a Hom with codomain X,
     244    # and then we are here, needing X.category(). But during
     245    # unpickling, if X.category() depends on, say, X.base_ring(),
     246    # which may be None at this point!
     247    # Hence, for unpickling, we trust that the given category is correct.
     248    try:
     249        cat_X = X.category()
     250    except StandardError:
     251        cat_X = category
     252    try:
     253        cat_Y = Y.category()
     254    except StandardError:
     255        cat_Y = category
    243256    if category is None:
    244257        category = cat_X._meet_(cat_Y)
    245258    elif isinstance(category, Category):
     
    414427       
    415428        Parent.__init__(self, base = base, category = category.hom_category())
    416429
     430    def __reduce__(self):
     431        return Hom, (self._domain, self._codomain, self._hom_category)
     432
    417433    def _repr_(self):
    418434        """
    419435        TESTS::
     
    453469        """
    454470        return True
    455471
    456     cpdef _generic_convert_map(self, S):
    457         """
    458         Return a generic map from a given homset to ``self``.
    459 
    460         INPUT:
    461 
    462         - ``S`` -- a homset
    463 
    464         OUTPUT:
    465 
    466         A map (by default: a Call morphism) from ``S`` to ``self``.
    467        
    468         EXAMPLES::
    469 
    470             sage: H = Hom(ZZ,QQ['t'], CommutativeAdditiveGroups())
    471             sage: P.<t> = ZZ[]
    472             sage: f = P.hom([2*t])
    473             sage: H._generic_convert_map(f.parent())
    474             Call morphism:
    475               From: Set of Homomorphisms from Univariate Polynomial Ring in t over Integer Ring to Univariate Polynomial Ring in t over Integer Ring
    476               To:   Set of Morphisms from Integer Ring to Univariate Polynomial Ring in t over Rational Field in Category of commutative additive groups
    477             sage: H._generic_convert_map(f.parent())(f)
    478             Composite map:
    479               From: Integer Ring
    480               To:   Univariate Polynomial Ring in t over Rational Field
    481               Defn:   Composite map:
    482                       From: Integer Ring
    483                       To:   Univariate Polynomial Ring in t over Integer Ring
    484                       Defn:   Polynomial base injection morphism:
    485                               From: Integer Ring
    486                               To:   Univariate Polynomial Ring in t over Integer Ring
    487                             then
    488                               Ring endomorphism of Univariate Polynomial Ring in t over Integer Ring
    489                               Defn: t |--> 2*t
    490                     then
    491                       Conversion map:
    492                       From: Univariate Polynomial Ring in t over Integer Ring
    493                       To:   Univariate Polynomial Ring in t over Rational Field
    494        
    495         """
    496         if self._element_constructor is None:
    497             from sage.categories.morphism import CallMorphism
    498             from sage.categories.homset import Hom
    499             return CallMorphism(Hom(S, self))
    500         else:
    501             return Parent._generic_convert_map(self, S)
    502 
    503472    def homset_category(self):
    504473        """
    505474        Return the category that this is a Hom in, i.e., this is typically
     
    513482        """
    514483        return self._hom_category
    515484
    516     def __call__(self, x=None, y=None, check=True, on_basis=None):
     485    def _coerce_map_from_(self, S):
     486        """
     487        If ``S`` is a homset, then it coerces into ``self``,
     488        if ``self``'s domain coerces into ``S``'s domain and
     489        ``S``'s codomain coerces into ``self``'s codomain.
     490
     491        EXAMPLES::
     492
     493            sage: U = ZZ^3
     494            sage: V = GF(7)^3
     495            sage: W = GF(7)['x']^3
     496            sage: H = Hom(U,W)
     497            sage: S = Hom(V,V)
     498            sage: H.has_coerce_map_from(S)  # indirect doctest
     499            True
     500
     501        """
     502        if isinstance(S, Homset):
     503            return S.domain().has_coerce_map_from(self.domain()) and self.codomain().has_coerce_map_from(S.codomain())
     504
     505    def _element_constructor_(self, x=None, y=None, check=True, on_basis=None):
    517506        """
    518507        Construct a morphism in this homset from ``x`` if possible.
    519508       
  • sage/categories/map.pxd

    diff --git a/sage/categories/map.pxd b/sage/categories/map.pxd
    a b  
    1 from sage.structure.parent cimport Parent
    2 from sage.structure.element cimport Element
     1from sage.structure.category_object cimport CategoryObject
     2from sage.structure.element cimport ModuleElement, Element
    33
    4 cdef class Map(Element):
    5     cdef Parent _domain
    6     cdef Parent _codomain
     4cdef class Map(ModuleElement):
     5    cdef CategoryObject _domain
     6    cdef CategoryObject _codomain
    77
    88    cdef public int _coerce_cost # a rough measure of the cost of using this morphism in the coercion system.
    99                          # 10 by default, 100 if a DefaultCoercionMorphism, 10000 if inexact.
  • sage/categories/map.pyx

    diff --git a/sage/categories/map.pyx b/sage/categories/map.pyx
    a b  
    6666    """
    6767    return isinstance(x, Map)
    6868
    69 cdef class Map(Element):
     69cdef class Map(ModuleElement):
    7070    """
    7171    Basic class for all maps.
    7272
     
    128128        Element.__init__(self, parent)
    129129        self._domain = parent.domain()
    130130        self._codomain = parent.codomain()
    131         if self._domain.is_exact() and self._codomain.is_exact():
    132             self._coerce_cost = 10 # default value.
    133         else:
    134             self._coerce_cost = 10000 # inexact morphisms are bad.
     131        try:
     132            if self._domain.is_exact() and self._codomain.is_exact():
     133                self._coerce_cost = 10 # default value.
     134            else:
     135                self._coerce_cost = 10000 # inexact morphisms are bad.
     136        except AttributeError:
     137            # Objects that aren't parents are still worse...
     138            self._coerce_cost = 20000
    135139
    136140    cdef _update_slots(self, _slots):
    137141        """
     
    643647                      To:   Rational Field
    644648        """
    645649        if not isinstance(right, Map):
    646             raise TypeError, "right (=%s) must be a map to multiply it by %s"%(right, self)
     650            return super(Map,self).__mul__(right)
     651            #raise TypeError, "right (=%s) must be a map to multiply it by %s"%(right, self)
    647652        if right.codomain() != self.domain():
    648653            raise TypeError, "self (=%s) domain must equal right (=%s) codomain"%(self, right)
    649654        return self._composition(right)
    650655
     656    # The following is needed, since Map only inherits from ModuleElement,
     657    # and ModuleElement.__imul__ complains if both arguments come from the same parent.
     658    __imul__ = __mul__
     659
    651660    def _composition(self, right):
    652661        """
    653662        Composition of maps, which generically returns a :class:`CompositeMap`.
     
    689698        H = homset.Hom(right.domain(), self.codomain(), category)
    690699        return self._composition_(right, H)
    691700
     701    # The following is needed for the _test_prod test of endomorphism rings
     702    _mul_ = _composition
     703
    692704    def _composition_(self, right, homset):
    693705        """
    694706        INPUT:
  • sage/categories/modules_with_basis.py

    diff --git a/sage/categories/modules_with_basis.py b/sage/categories/modules_with_basis.py
    a b  
    913913            Abstract class for hom sets
    914914            """
    915915
    916             def __call__(self, on_basis = None, *args, **options):
     916            def _element_constructor_(self, x = None, on_basis = None, *args, **options):
    917917                """
    918918                Construct an element of this homset
    919919
    920920                INPUT:
    921921
    922                  - on_basis (optional) -- a function from the indices
    923                    of the basis of the domain of ``self`` to the
    924                    codomain of ``self``
     922                - x -- a dummy attribute, that is needed since the default call method
     923                  of :class:`~sage.structure.parent.Parent` uses it.
     924                - on_basis (optional) -- a function from the indices
     925                  of the basis of the domain of ``self`` to the
     926                  codomain of ``self``
     927
     928                NOTE:
     929
     930                If ``on_basis`` is not None, then ``x`` will be ignored. Otherwise,
     931                the value of ``on_basis`` will be obtained from ``x``
    925932
    926933                EXAMPLES::
    927934
     
    955962                This is achieved internaly by using
    956963                :meth:`ModulesWithBasis.ParentMethods.module_morphism`, which see.
    957964                """
     965                if on_basis is None:
     966                    on_basis = x
    958967                if on_basis is not None:
    959968                    args = (self.domain().module_morphism(on_basis, codomain = self.codomain()),) + args
    960                 h = Homset.__call__(self, *args, **options)
     969                h = Homset._element_constructor_(self, *args, **options)
    961970                if on_basis is not None:
    962971                    h._on_basis = on_basis
    963972                return h
    964973
     974            def _an_element_(self):
     975                zero = self.codomain().zero()
     976                return self(on_basis = lambda i: zero)
     977
    965978            # Temporary hack
    966             __call_on_basis__ = __call__
     979            __call_on_basis__ = _element_constructor_
    967980
    968981            @lazy_attribute
    969982            def element_class_set_morphism(self):
     
    984997                    sage: Y = CombinatorialFreeModule(QQ, [1,2,3,4]); Y.rename("Y")
    985998                    sage: H = Hom(X, Y)
    986999                    sage: H.element_class_set_morphism
    987                     <class 'sage.categories.morphism.SetMorphism_with_category'>
     1000                    <class 'sage.categories.morphism.ModulesWithBasis.HomCategory.parent_class.element_class_set_morphism'>
    9881001                    sage: H.element_class_set_morphism.mro()
    989                     [<class 'sage.categories.morphism.SetMorphism_with_category'>,
     1002                    [<class 'sage.categories.morphism.ModulesWithBasis.HomCategory.parent_class.element_class_set_morphism'>,
    9901003                     <type 'sage.categories.morphism.SetMorphism'>,
    9911004                     <type 'sage.categories.morphism.Morphism'>,
    9921005                     <type 'sage.categories.map.Map'>,
     1006                     <type 'sage.structure.element.ModuleElement'>,
    9931007                     <type 'sage.structure.element.Element'>,
    9941008                     <type 'sage.structure.sage_object.SageObject'>,
    9951009                     <class 'sage.categories.modules_with_basis.ModulesWithBasis.HomCategory.element_class'>,
     
    10031017                    sage: H.element_class_set_morphism
    10041018                    <type 'sage.categories.morphism.SetMorphism'>
    10051019                """
    1006                 return self.__make_element_class__(SetMorphism, inherit = True)
     1020                return self.__make_element_class__(SetMorphism, name="%s.element_class_set_morphism"%self.__class__.__name__, inherit = True)
    10071021
    10081022        class ElementMethods:
    10091023            """
  • sage/categories/morphism.pyx

    diff --git a/sage/categories/morphism.pyx b/sage/categories/morphism.pyx
    a b  
    214214        else:
    215215            return self._codomain._element_constructor(x, *args, **kwds)
    216216
    217     def __mul__(left, right):
    218         if not isinstance(right, Morphism):
    219             raise TypeError, "right (=%s) must be a morphism to multiply it by %s"%(right, left)
    220         if not isinstance(left, Morphism):
    221             raise TypeError, "left (=%s) must be a morphism to multiply it by %s"%(left, right)
    222         if right.codomain() != left.domain():
    223             raise TypeError, "self (=%s) domain must equal right (=%s) codomain"%(left, right)
     217    def _composition_(left, right):
    224218        if isinstance(left, IdentityMorphism):
    225219            return right
    226220        else:
    227221            return left
    228        
     222
    229223    def __pow__(self, n, dummy):
    230224        return self
    231        
     225
    232226    def __invert__(self):
    233227        return self
    234            
     228
    235229cdef class SetMorphism(Morphism):
    236230    def __init__(self, parent, function):
    237231        """
  • sage/combinat/sf/sf.py

    diff --git a/sage/combinat/sf/sf.py b/sage/combinat/sf/sf.py
    a b  
    11031103            basis1 = getattr(self, basis1_name)()
    11041104            basis2 = getattr(self, basis2_name)()
    11051105            on_basis = SymmetricaConversionOnBasis(t = conversion_functions[basis1_name,basis2_name], domain = basis1, codomain = basis2)
    1106             iso(basis1._module_morphism(on_basis, codomain = basis2))
     1106            iso(basis1._module_morphism(on_basis = on_basis, codomain = basis2))
    11071107
    11081108        # Todo: fill in with other conversion functions on the classical bases
    11091109
  • sage/groups/group_homset.py

    diff --git a/sage/groups/group_homset.py b/sage/groups/group_homset.py
    a b  
    3535    def _repr_(self):
    3636        return "Set of Homomorphisms from %s to %s"%(self.domain(), self.codomain())
    3737
    38     def __call__(self, im_gens, check=True):
     38    def _element_constructor_(self, im_gens, check=True):
    3939        """
    4040        EXAMPLES:
    4141
    4242        """
    4343        try:
    44             return morphism.GroupHomomorphism_im_gens(self, im_gens, check=check)
     44            return self.__make_element_class(morphism.GroupHomomorphism_im_gens)(self, im_gens, check=check)
    4545        except (NotImplementedError, ValueError), err:
    4646            raise TypeError, "images (=%s) do not define a valid homomorphism"%im_gens
    4747
  • sage/groups/matrix_gps/homset.py

    diff --git a/sage/groups/matrix_gps/homset.py b/sage/groups/matrix_gps/homset.py
    a b  
    6868         [[[1, 2], [4, 1]], [[1, 1], [0, 1]]]
    6969
    7070    """
     71    Element = matrix_group_morphism.MatrixGroupMorphism_im_gens
    7172    def __init__(self, G, H):
    7273        r"""
    7374        See ``MatrixGroupHomset`` for full documentation.
     
    8586        """
    8687        HomsetWithBase.__init__(self, G, H, GROUPS, G.base_ring())
    8788       
    88     def __call__(self, im_gens, check=True):
     89    def _element_constructor_(self, im_gens, check=True):
    8990        """
    9091        Return the homomorphism defined by images of generators.
    9192
     
    110111
    111112        """
    112113        try:
    113             return matrix_group_morphism.MatrixGroupMorphism_im_gens(self,
    114                                                             im_gens, check=check)
     114            return self.element_class(self, im_gens, check=check)
    115115        except (NotImplementedError, ValueError), err:
    116116            raise TypeError, "images (=%s) do not define a valid homomorphism"%im_gens
    117117
  • sage/homology/cell_complex.py

    diff --git a/sage/homology/cell_complex.py b/sage/homology/cell_complex.py
    a b  
    3333    just make sure it gets documented.
    3434"""
    3535
    36 from sage.structure.sage_object import SageObject
     36from sage.structure.category_object import CategoryObject
    3737from sage.rings.integer_ring import ZZ
    3838from sage.rings.rational_field import QQ
    3939
    40 class GenericCellComplex(SageObject):
     40class GenericCellComplex(CategoryObject):
    4141    r"""
    4242    Class of abstract cell complexes.
    4343   
  • sage/homology/chain_complex.py

    diff --git a/sage/homology/chain_complex.py b/sage/homology/chain_complex.py
    a b  
    3333parameter used in defining the chain complex.
    3434"""
    3535
    36 from sage.structure.sage_object import SageObject
     36from sage.structure.parent import Parent
    3737from sage.rings.integer_ring import ZZ
    3838from sage.rings.rational_field import QQ
    3939from sage.modules.free_module import FreeModule, VectorSpace
     
    258258    else:
    259259        return str(latex(FreeModule(R, m)))
    260260
    261 class ChainComplex(SageObject):
     261class ChainComplex(Parent):
    262262    r"""
    263263    Define a chain complex.
    264264   
     
    470470        # here ends the initialization/error-checking of the data
    471471        self._grading_group = grading_group
    472472        self._degree = deg
     473        Parent.__init__(self, base = base_ring)
    473474        self._base_ring = base_ring
    474475        self._diff = new_data
    475476        # self._ranks: dictionary for caching the ranks of the
  • sage/homology/chain_complex_homspace.py

    diff --git a/sage/homology/chain_complex_homspace.py b/sage/homology/chain_complex_homspace.py
    a b  
    124124        Set of Morphisms from Chain complex with at most 5 nonzero terms over Integer Ring to Chain complex with at most 5 nonzero terms over Integer Ring in Category of chain complexes over Integer Ring
    125125
    126126    """
    127     def __call__(self, f):
     127    Element = chain_complex_morphism.ChainComplexMorphism
     128    def _element_constructor_(self, f):
    128129        """
    129130        `f` is a dictionary of matrices in the basis of the chain complex.
    130131
     
    142143            True
    143144
    144145        """
    145         return chain_complex_morphism.ChainComplexMorphism(f, self.domain(), self.codomain())
     146        if isinstance(f, chain_complex_morphism.ChainComplexMorphism):
     147            f = f._matrix_dictionary
     148        return self.element_class(self, f)
  • sage/homology/chain_complex_morphism.py

    diff --git a/sage/homology/chain_complex_morphism.py b/sage/homology/chain_complex_morphism.py
    a b  
    1414
    1515EXAMPLES::
    1616
    17     from sage.matrix.constructor import zero_matrix
     17    sage: from sage.matrix.constructor import zero_matrix
    1818    sage: S = simplicial_complexes.Sphere(1)
    1919    sage: S
    2020    Simplicial complex with vertex set (0, 1, 2) and facets {(1, 2), (0, 2), (0, 1)}
     
    2828    sage: x = G(f)
    2929    sage: x
    3030    Chain complex morphism from Chain complex with at most 2 nonzero terms over Integer Ring to Chain complex with at most 2 nonzero terms over Integer Ring
     31    sage: type(x)
     32    <class 'sage.homology.chain_complex_morphism.ChainComplexHomspace_with_category.element_class'>
    3133    sage: x._matrix_dictionary
    3234    {0: [0 0 0]
    3335    [0 0 0]
     
    5355#
    5456#*****************************************************************************
    5557
     58import sage
    5659import sage.matrix.all as matrix
    57 from sage.structure.sage_object import SageObject
     60from sage.categories.morphism import Morphism
     61from sage.categories.homset import Hom
    5862from sage.rings.integer_ring import ZZ
     63import sage
    5964
    6065def is_ChainComplexMorphism(x):
    6166    """
     
    7984    """
    8085    return isinstance(x,ChainComplexMorphism)
    8186
    82 class ChainComplexMorphism(SageObject):
     87class ChainComplexMorphism(Morphism):
    8388    """
    8489    An element of this class is a morphism of chain complexes.
    8590    """
    86     def __init__(self,matrices,C,D):
     91    def __init__(self, H, matrices):
    8792        """
    8893        Create a morphism from a dictionary of matrices.
    8994
     95        INPUT:
     96
     97        - ``H`` -- A chain complex homset
     98        - ``matrices`` -- a dictionary of matrices
     99
    90100        EXAMPLES::
    91101
    92102            from sage.matrix.constructor import zero_matrix
     
    118128            sage: g.associated_chain_complex_morphism()
    119129            Chain complex morphism from Chain complex with at most 2 nonzero terms over Integer Ring to Chain complex with at most 1 nonzero terms over Integer Ring
    120130        """
     131        if not isinstance(H, sage.homology.chain_complex_homspace.ChainComplexHomspace):
     132            raise TypeError, "parent of a chain complex morphism must be a chain complex homspace"
     133        C = H.domain()
     134        D = H.codomain()
     135        Morphism.__init__(self, H)
    121136        if C._grading_group != ZZ:
    122137            raise NotImplementedError, "Chain complex morphisms are not implemented over gradings other than ZZ."
    123138        d = C._degree
     
    193208        f = dict()
    194209        for i in self._matrix_dictionary.keys():
    195210            f[i] = -self._matrix_dictionary[i]
    196         return ChainComplexMorphism(f,self._domain,self._codomain)
     211        return self.parent()(f)
    197212
    198     def __add__(self,x):
     213    def _add_(self,x):
    199214        """
    200215        Returns ``self + x``.
    201216
     
    223238            [0 0 0 2]}
    224239
    225240        """
    226         if not isinstance(x,ChainComplexMorphism) or self._codomain != x._codomain or self._domain != x._domain or self._matrix_dictionary.keys() != x._matrix_dictionary.keys():
    227             raise TypeError, "Unsupported operation."
     241#        if not isinstance(x,ChainComplexMorphism) or self._codomain != x._codomain or self._domain != x._domain or self._matrix_dictionary.keys() != x._matrix_dictionary.keys():
     242#            raise TypeError, "Unsupported operation."
    228243        f = dict()
    229244        for i in self._matrix_dictionary.keys():
    230245            f[i] = self._matrix_dictionary[i] + x._matrix_dictionary[i]
    231         return ChainComplexMorphism(f,self._domain,self._codomain)
     246        return self.parent()(f)
    232247
    233     def __mul__(self,x):
     248    def _mul_(self,x, H):
    234249        """
    235250        Returns ``self * x`` if ``self`` and ``x`` are composable morphisms
    236251        or if ``x`` is an element of the base ring.
     
    283298            f = dict()
    284299            for i in self._matrix_dictionary.keys():
    285300                f[i] = self._matrix_dictionary[i] * y
    286             return ChainComplexMorphism(f,self._domain,self._codomain)
     301            return self.parent()(f)
    287302        f = dict()
    288303        for i in self._matrix_dictionary.keys():
    289304            f[i] = x._matrix_dictionary[i]*self._matrix_dictionary[i]
    290         return ChainComplexMorphism(f,self._domain,x._codomain)
     305        return Hom(self._domain, x._codomain)(f)
    291306
    292     def __rmul__(self,x):
     307    def _composition_(self, x, homset):
     308        if not isinstance(x, ChainComplexMorphism):
     309            return super(ChainComplexMorphism,self)._composition_(x, homset)
     310        f = dict()
     311        for i in self._matrix_dictionary.keys():
     312            f[i] = x._matrix_dictionary[i]*self._matrix_dictionary[i]
     313        return homset(f)
     314
     315    def _rmul_(self,x):
    293316        """
    294317        Returns ``x * self`` if ``x`` is an element of the base ring.
    295318
     
    311334        f = dict()
    312335        for i in self._matrix_dictionary.keys():
    313336            f[i] = y * self._matrix_dictionary[i]
    314         return ChainComplexMorphism(f,self._domain,self._codomain)
     337        return self.parent()(f)
    315338
    316     def __sub__(self,x):
     339    def _sub_(self,x):
    317340        """
    318341        Returns ``self - x``.
    319342
  • sage/homology/simplicial_complex_homset.py

    diff --git a/sage/homology/simplicial_complex_homset.py b/sage/homology/simplicial_complex_homset.py
    a b  
    7474    """
    7575    return isinstance(x, SimplicialComplexHomset)
    7676
    77 class SimplicialComplexHomset(sage.categories.homset.Homset):
    78     def __call__(self, f):
     77class SimplicialComplexHomset(sage.categories.homset.HomsetWithBase):
     78    Element = simplicial_complex_morphism.SimplicialComplexMorphism
     79    def _element_constructor_(self, f):
    7980        """
    8081        INPUT:
    8182
     
    9293            sage: x
    9394            Simplicial complex morphism {0: 0, 1: 1, 2: 2, 3: 2, 4: 2} from Simplicial complex with vertex set (0, 1, 2, 3, 4) and 5 facets to Simplicial complex with vertex set (0, 1, 2, 3) and facets {(0, 2, 3), (0, 1, 2), (1, 2, 3), (0, 1, 3)}
    9495        """
    95         return simplicial_complex_morphism.SimplicialComplexMorphism(f,self.domain(),self.codomain())
     96        return self.element_class(self, f)
    9697
    9798    def diagonal_morphism(self,rename_vertices=True):
    9899        r"""
     
    127128            else:
    128129                for i in self._domain.vertices().set():
    129130                    f[i] = (i,i)
    130             return simplicial_complex_morphism.SimplicialComplexMorphism(f, self._domain,X)
     131            return self.element_class(self, f)
    131132        else:
    132133            raise TypeError, "Diagonal morphism is only defined for Hom(X,XxX)."
    133134       
     
    154155            f = dict()
    155156            for i in self._domain.vertices().set():
    156157                f[i]=i
    157             return simplicial_complex_morphism.SimplicialComplexMorphism(f,self._domain,self._codomain)
     158            return self.element_class(self, f)
    158159        else:
    159160            raise TypeError("Identity map is only defined for endomorphism sets.")
    160161
     
    182183        f = dict()
    183184        for x in X_vertices:
    184185            f[x]=i
    185         return simplicial_complex_morphism.SimplicialComplexMorphism(f,self._domain,self._codomain)
     186        return self.element_class(self, f)
  • sage/homology/simplicial_complex_morphism.py

    diff --git a/sage/homology/simplicial_complex_morphism.py b/sage/homology/simplicial_complex_morphism.py
    a b  
    2727    sage: f = {0:0,1:1,2:2,3:1,4:3,5:3}
    2828    sage: H = Hom(S,T)
    2929    sage: x = H(f)
     30    sage: type(x)
     31    <class 'sage.homology.simplicial_complex_morphism.SimplicialComplexHomset_with_category.element_class'>
    3032    sage: x.image()
    3133    Simplicial complex with vertex set (0, 1, 2, 3) and facets {(1, 3), (0, 2)}
    3234    sage: x.is_surjective()
     
    9395
    9496import sage.homology.simplicial_complex as simplicial_complex
    9597import sage.matrix.all as matrix
    96 from sage.structure.sage_object import SageObject
     98from sage.categories.morphism import Morphism
     99from sage.categories.homset import Hom
    97100from sage.rings.integer_ring import ZZ
    98101from sage.homology.chain_complex_morphism import ChainComplexMorphism
    99102from sage.combinat.permutation import Permutation
    100103from sage.algebras.steenrod.steenrod_algebra_misc import convert_perm
     104import sage
    101105
    102106def is_SimplicialComplexMorphism(x):
    103107    """
     
    116120    """
    117121    return isinstance(x,SimplicialComplexMorphism)
    118122
    119 class SimplicialComplexMorphism(SageObject):
     123class SimplicialComplexMorphism(Morphism):
    120124    """
    121125    An element of this class is a morphism of simplicial complexes.
    122126    """
    123     def __init__(self,f,X,Y):
     127    def __init__(self, H, f):
    124128        """
    125         Input is a dictionary ``f``, the domain ``X``, and the codomain ``Y``.
     129        Input is homset ``H`` (domain `X` and codomain `Y`) and a dictionary ``f``.
    126130
    127131        One can define the dictionary on the vertices of `X`.
    128132
     
    143147            sage: x.image() == y.image()
    144148            False
    145149        """
     150        if not isinstance(H, sage.homology.simplicial_complex_homset.SimplicialComplexHomset):
     151            raise TypeError("The parent of a simplicial complex morphism must be a simplicial complex homset")
     152        Morphism.__init__(self, H)
     153        X = H.domain()
     154        Y = H.codomain()
    146155        if not isinstance(X,simplicial_complex.SimplicialComplex) or not isinstance(Y,simplicial_complex.SimplicialComplex):
    147             raise ValueError("X and Y must be SimplicialComplexes.")
     156            raise ValueError("Domain and codomain must be SimplicialComplexes.")
    148157        if not set(f.keys()) == X._vertex_set.set():
    149             raise ValueError("f must be a dictionary from the vertex set of X to single values in the vertex set of Y.")
     158            raise ValueError("f must be a dictionary from the vertex set of the domain to single values in the vertex set of the codomain.")
    150159        dim = X.dimension()
    151160        Y_faces = Y.faces()
    152161        for k in range(dim+1):
     
    157166                    fi.append(f[j])
    158167                v = simplicial_complex.Simplex(set(fi))
    159168            if not v in Y_faces[v.dimension()]:
    160                 raise ValueError("f must be a dictionary from the vertices of X to the vertices of Y.")
     169                raise ValueError("f must be a dictionary from the vertices of the domain to the vertices of the codomain.")
    161170        self._vertex_dictionary = f
    162171        self._domain = X
    163172        self._codomain = Y
     
    275284            sage: a = x.associated_chain_complex_morphism()
    276285            sage: a
    277286            Chain complex morphism from Chain complex with at most 2 nonzero terms over Integer Ring to Chain complex with at most 3 nonzero terms over Integer Ring
     287            sage: type(a)
     288            <class 'sage.homology.chain_complex_morphism.ChainComplexHomspace_with_category.element_class'>
    278289            sage: a._matrix_dictionary
    279290            {0: [0 0 0]
    280291            [0 1 0]
     
    357368                matrices[dim] = m
    358369            else:
    359370                matrices[dim] = m.transpose()
     371        AugD = self._domain.chain_complex(base_ring=base_ring,augmented=augmented,cochain=cochain)
     372        AugC = self._codomain.chain_complex(base_ring=base_ring,augmented=augmented,cochain=cochain)
    360373        if not cochain:
    361             return ChainComplexMorphism(matrices,\
    362                     self._domain.chain_complex(base_ring=base_ring,augmented=augmented,cochain=cochain),\
    363                     self._codomain.chain_complex(base_ring=base_ring,augmented=augmented,cochain=cochain))
     374            return Hom(AugD, AugC)(matrices)
    364375        else:
    365             return ChainComplexMorphism(matrices,\
    366                     self._codomain.chain_complex(base_ring=base_ring,augmented=augmented,cochain=cochain),\
    367                     self._domain.chain_complex(base_ring=base_ring,augmented=augmented,cochain=cochain))
     376            return Hom(AugC, AugD)(matrices)
    368377       
    369378    def image(self):
    370379        """
     
    576585                    else:
    577586                        v.append((i,j))
    578587                        f[(i,j)] = self._vertex_dictionary[i]
    579         return SimplicialComplexMorphism(f, X.generated_subcomplex(v), self._codomain)
     588        return Hom(X.generated_subcomplex(v, is_mutable=False), self._codomain)(f)
  • sage/modular/abvar/abvar.py

    diff --git a/sage/modular/abvar/abvar.py b/sage/modular/abvar/abvar.py
    a b  
    254254            sage: A.base_extend(GF(7))
    255255            Abelian variety J0(37) over Finite Field of size 7 of dimension 2
    256256        """
    257         N = self.__newform_level if hasattr(self, '__newform_level') else None
     257        N = getattr(self, '__newform_level', None)
    258258        return ModularAbelianVariety(self.groups(), self.lattice(), K, newform_level=N)
    259259
    260260    def __contains__(self, x):
     
    291291        nLambda = self.ambient_variety().lattice().scale(n)
    292292        return n*v in self.lattice() + nLambda
    293293
     294    def __hash__(self):
     295        """
     296        Return the hash of self.lattice().
     297
     298        TESTS::
     299
     300            sage: D = {J0(37)[0]:0, J0(37)[1]:1}
     301            sage: D[J0(37)[1]]         # indirect doctest
     302            1
     303
     304        The hash is obtained from the data used for comparison.
     305        This implicitly includes the :meth:`label`. Hence, we have::
     306
     307            sage: J = J0(11); phi = J.degeneracy_map(33, 1) + J.degeneracy_map(33,3)
     308            sage: B = phi.image(); B
     309            Abelian subvariety of dimension 1 of J0(33)
     310            sage: C = J.degeneracy_map(33,3).image(); C
     311            Abelian subvariety of dimension 1 of J0(33)
     312            sage: B == C
     313            False
     314            sage: D = {B:0, C:1}
     315            sage: D[B]
     316            0
     317            sage: D[C]
     318            1
     319
     320        """
     321        return hash(self.lattice())
     322
    294323    def __cmp__(self, other):
    295324        """
    296325        Compare two modular abelian varieties.
     
    29222951            else:
    29232952                # Decompose each ambient modular symbols factor.
    29242953                #X = [ModularAbelianVariety_modsym(ModularSymbols(G,sign=0).cuspidal_submodule()) for G in self.groups()]
    2925                 from abvar_ambient_jacobian import ModAbVar_ambient_jacobian_class
    2926                 X = [ModAbVar_ambient_jacobian_class(G) for G in self.groups()]
     2954                from abvar_ambient_jacobian import ModAbVar_ambient_jacobian
     2955                X = [ModAbVar_ambient_jacobian(G) for G in self.groups()]
    29272956                E = [A.decomposition(simple=simple, bound=bound) for A in X]
    29282957                i = 0
    29292958                n = 2*self.dimension()
  • sage/modular/abvar/abvar_ambient_jacobian.py

    diff --git a/sage/modular/abvar/abvar_ambient_jacobian.py b/sage/modular/abvar/abvar_ambient_jacobian.py
    a b  
    1111
    1212import weakref
    1313from sage.structure.sequence import Sequence
     14from sage.structure.unique_representation import CachedRepresentation
    1415
    1516from abvar             import (ModularAbelianVariety_modsym_abstract, ModularAbelianVariety,
    1617                               simple_factorization_of_modsym_space, modsym_lattices,
     
    2122import morphism
    2223
    2324
    24 _cache = {}
    25 
    26 def ModAbVar_ambient_jacobian(group):
     25class ModAbVar_ambient_jacobian(CachedRepresentation, ModularAbelianVariety_modsym_abstract):
    2726    """
    28     Return the ambient Jacobian attached to a given congruence
    29     subgroup.
     27    An ambient Jacobian modular abelian variety attached to a
     28    congruence subgroup.
    3029   
    31     The result is cached using a weakref. This function is called
    32     internally by modular abelian variety constructors.
     30    This uses :class:`~sage.structure.unique_representation.CachedRepresentation`
     31    to have a weak cache on the result.
    3332   
    3433    INPUT:
    35    
    36    
     34
    3735    -  ``group`` - a congruence subgroup.
    38    
    39    
     36
     37
    4038    OUTPUT: a modular abelian variety attached
    41    
     39
    4240    EXAMPLES::
    43    
     41
    4442        sage: import sage.modular.abvar.abvar_ambient_jacobian as abvar_ambient_jacobian
    4543        sage: A = abvar_ambient_jacobian.ModAbVar_ambient_jacobian(Gamma0(11))
    4644        sage: A
     
    4846        sage: B = abvar_ambient_jacobian.ModAbVar_ambient_jacobian(Gamma0(11))
    4947        sage: A is B
    5048        True
    51    
    52     You can get access to and/or clear the cache as follows::
    53    
    54         sage: abvar_ambient_jacobian._cache = {}
     49
     50    If you really want to create non-unique parents, you can do so as follows::
     51
     52        sage: abvar_ambient_jacobian.ModAbVar_ambient_jacobian._clear_cache_()
    5553        sage: B = abvar_ambient_jacobian.ModAbVar_ambient_jacobian(Gamma0(11))
    5654        sage: A is B
    5755        False
    58     """
    59     try:
    60         X = _cache[group]()
    61         if not X is None:
    62             return X
    63     except KeyError:
    64         pass
    65     X = ModAbVar_ambient_jacobian_class(group)
    66     _cache[group] = weakref.ref(X)
    67     return X
    6856
    69 class ModAbVar_ambient_jacobian_class(ModularAbelianVariety_modsym_abstract):
    70     """
    71     An ambient Jacobian modular abelian variety attached to a
    72     congruence subgroup.
    7357    """
    7458    def __init__(self, group):
    7559        """
    7660        Create an ambient Jacobian modular abelian variety.
    77        
     61
    7862        EXAMPLES::
    7963       
    8064            sage: A = J0(37); A
    8165            Abelian variety J0(37) of dimension 2
    8266            sage: type(A)
    83             <class 'sage.modular.abvar.abvar_ambient_jacobian.ModAbVar_ambient_jacobian_class_with_category'>
     67            <class 'sage.modular.abvar.abvar_ambient_jacobian.ModAbVar_ambient_jacobian_with_category'>
    8468            sage: A.group()
    8569            Congruence Subgroup Gamma0(37)
    8670        """
     
    123107            sage: A
    124108            J_0(11)
    125109       
    126         We now clear the cache to get rid of our renamed
    127         `J_0(11)`.
    128        
    129         ::
    130        
    131             sage: import sage.modular.abvar.abvar_ambient_jacobian as abvar_ambient_jacobian
    132             sage: abvar_ambient_jacobian._cache = {}
     110        Since a weak cache is used, we do not need to clear the cache in order
     111        to prevent side-effects on other tests.
     112
    133113        """
    134114        return 'Abelian variety %s of dimension %s%s'%(self._ambient_repr(), self.dimension(),
    135115                                    '' if self.base_field() == QQ else ' over %s'%self.base_field())
     
    389369        D = Sequence(D, immutable=True, cr=True, universe=self.category())
    390370        self.__decomposition[simple] = D
    391371        return D
    392            
    393        
    394372
    395    
     373# For unpickling old data:
     374ModAbVar_ambient_jacobian_class = ModAbVar_ambient_jacobian
  • sage/modular/abvar/homspace.py

    diff --git a/sage/modular/abvar/homspace.py b/sage/modular/abvar/homspace.py
    a b  
    195195    """
    196196    A space of homomorphisms between two modular abelian varieties.
    197197    """
     198    Element = morphism.Morphism
    198199    def __init__(self, domain, codomain, cat):
    199200        """
    200201        Create a homspace.
     
    225226        self._matrix_space = MatrixSpace(ZZ,2*domain.dimension(), 2*codomain.dimension())
    226227        self._gens = None
    227228        HomsetWithBase.__init__(self, domain, codomain, cat)
    228        
    229     def __call__(self, M):
     229
     230    def _element_constructor_(self, M):
    230231        r"""
    231232        Create a homomorphism in this space from M. M can be any of the
    232233        following:
     
    297298            M = self.matrix_space()(M)
    298299        else:
    299300            raise TypeError, "can only coerce in matrices or morphisms"
    300         return morphism.Morphism(self, M)
     301        return self.element_class(self, M)
    301302       
    302303    def _coerce_impl(self, x):
    303304        """
     
    432433        self.calculate_generators()
    433434        if i > self.ngens():
    434435            raise ValueError, "self only has %s generators"%self.ngens()
    435         return morphism.Morphism(self, self._gens[i])
     436        return self.element_class(self, self._gens[i])
    436437
    437438    def ngens(self):
    438439        """
     
    708709            Join of Category of hom sets in Category of sets and Category of rings
    709710            sage: E.homset_category()
    710711            Category of modular abelian varieties over Rational Field
    711             sage: TestSuite(E).run(skip=["_test_elements"])
     712            sage: TestSuite(E).run()
    712713
    713714        TESTS:
    714715
     
    753754        else:
    754755            return "Subring of endomorphism ring of %s" % self._A
    755756
     757    def _coerce_map_from_(self, S):
     758        """
     759        In addition to the coercions of homsets, the base ring
     760        coerces into self.
     761
     762        EXAMPLES::
     763
     764            sage: t2 = J0(33).hecke_operator(2)
     765            sage: t2.parent().has_coerce_map_from(ZZ)
     766            True
     767            sage: t2 + 2        # indirect doctest
     768            Abelian variety endomorphism of Abelian variety J0(33) of dimension 3
     769        """
     770        if self.base().has_coerce_map_from(S):
     771            return True
     772        return super(EndomorphismSubring, self)._coerce_map_from_(S)
     773
    756774    def abelian_variety(self):
    757775        """
    758776        Return the abelian variety that this endomorphism ring is attached
  • sage/modular/abvar/morphism.py

    diff --git a/sage/modular/abvar/morphism.py b/sage/modular/abvar/morphism.py
    a b  
    5555        sage: from sage.modular.abvar.morphism import Morphism
    5656        sage: isinstance(t, Morphism)
    5757        True
     58
    5859    """
    59 
    6060    def _repr_(self):
    6161        r"""
    6262        Return string representation of this morphism.
     
    108108        try:
    109109            iM, denom = M._invert_iml()
    110110        except AttributeError:
    111             iM = M.matrix_over_field().invert()
     111            iM = M.matrix_over_field().inverse()
    112112            iM, denom = iM._clear_denom()
    113113        return Morphism(self.parent().reversed(), iM)
    114114       
     
    655655        ims = sum([ (L(b)*self.matrix()).list() for b in B], [])
    656656        MS = matrix_space.MatrixSpace(self.base_ring(), len(B), self.codomain().rank())
    657657        H = sub.Hom(self.codomain(), self.category_for())
    658         return H(MS(ims))
     658        return H.element_class(H,MS(ims))
    659659
    660660class DegeneracyMap(Morphism):
    661661    def __init__(self, parent, A, t):
  • sage/modular/hecke/hecke_operator.py

    diff --git a/sage/modular/hecke/hecke_operator.py b/sage/modular/hecke/hecke_operator.py
    a b  
    144144                name = "T_%s"%self.index()
    145145            else:
    146146                name = ""
    147             self.__hecke_module_morphism = morphism.HeckeModuleMorphism_matrix(H, T, name)
     147            self.__hecke_module_morphism = H.element_class(H, T,name)#morphism.HeckeModuleMorphism_matrix(H, T, name)
    148148            return self.__hecke_module_morphism
    149149
    150150    def _add_(self, other):
  • sage/modular/hecke/homspace.py

    diff --git a/sage/modular/hecke/homspace.py b/sage/modular/hecke/homspace.py
    a b  
    4040    A space of homomorphisms between two objects in the category of Hecke
    4141    modules over a given base ring.
    4242    """
     43    Element = morphism.HeckeModuleMorphism_matrix
    4344    def __init__(self, X, Y, category = None):
    4445        r"""
    4546        Create the space of homomorphisms between X and Y, which must have the
     
    5960        """
    6061        if not module.is_HeckeModule(X) or not module.is_HeckeModule(Y):
    6162            raise TypeError, "X and Y must be Hecke modules"
    62         if X.base_ring() != Y.base_ring():
    63             raise TypeError, "X and Y must have the same base ring"
     63        Xbase = X.base_ring()
     64        Ybase = Y.base_ring()
     65        if Xbase is not None and Ybase is not None:
     66            # this may happen during unpickling of X or Y,
     67            # and we trust that the pickle is sane.
     68            if Xbase != Ybase:
     69                raise TypeError, "X and Y must have the same base ring"
    6470        if category is None:
    6571            category = X.category()
    6672        sage.categories.homset.HomsetWithBase.__init__(self, X, Y, category = category)
    6773
    68     def __call__(self, A, name=''):
     74    def _element_constructor_(self, A, name=''):
    6975        r"""
    7076        Create an element of this space from A, which should be an element of a
    7177        Hecke algebra, a Hecke module morphism, or a matrix.
     
    108114                raise TypeError, "unable to coerce A to self"
    109115        except AttributeError:
    110116            pass
    111         return morphism.HeckeModuleMorphism_matrix(self, A, name)
    112 
    113 
     117        return self.element_class(self, A, name)
  • 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: Incompatible composition of morphisms: domain of left morphism must be codomain of right.
     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
     95
    8896    """
    8997    def __init__(self, parent, A, name=''):
    9098        """
  • sage/modular/modsym/ambient.py

    diff --git a/sage/modular/modsym/ambient.py b/sage/modular/modsym/ambient.py
    a b  
    12971297            Domain: Modular Symbols space of dimension 7 for Gamma_0(20) of weight ...
    12981298            Codomain: Space of Boundary Modular Symbols for Congruence Subgroup Gamma0(20) ...
    12991299            sage: type(ModularSymbols(20,2).boundary_map())
    1300             <class 'sage.modular.hecke.morphism.HeckeModuleMorphism_matrix'>
     1300            <class 'sage.modular.hecke.morphism.HeckeModules.HomCategory.parent_class.element_class'>
    13011301        """
    13021302        try:
    13031303            return self.__boundary_map
  • sage/modules/fg_pid/fgp_module.py

    diff --git a/sage/modules/fg_pid/fgp_module.py b/sage/modules/fg_pid/fgp_module.py
    a b  
    13641364        EXAMPLE::
    13651365
    13661366            sage: class SillyModule(sage.modules.fg_pid.fgp_module.FGP_Module_class):
     1367            ...       @cached_method
    13671368            ...       def gens(self):
    13681369            ...           return tuple(flatten([[x,x] for x in self.smith_form_gens()]))
    13691370            sage: A = SillyModule(ZZ**1, span([[3]], ZZ))
  • sage/modules/fg_pid/fgp_morphism.py

    diff --git a/sage/modules/fg_pid/fgp_morphism.py b/sage/modules/fg_pid/fgp_morphism.py
    a b  
    2121####################################################################################
    2222
    2323from sage.categories.all import Morphism, is_Morphism
     24from sage.misc.cachefunc import cached_method
    2425import fgp_module
    2526
    2627
     
    130131            self.domain().base_ring(), self.domain().invariants(), self.codomain().invariants(),
    131132            list(self.im_gens()))
    132133
     134    @cached_method
    133135    def im_gens(self):
    134136        """
    135137        Return tuple of the images of the generators of the domain
     
    144146            sage: phi.im_gens() is phi.im_gens()
    145147            True
    146148        """
    147         try: return self.__im_gens
    148         except AttributeError: pass
    149         self.__im_gens = tuple([self(x) for x in self.domain().gens()])
    150         return self.__im_gens
     149        try:
     150            bla = self.domain().gens()
     151        except NameError:
     152            error = "%s\n%s\n%s\n%s"%( self.domain(),
     153                                       type(self.domain()),
     154                                       self.domain().gens.__module__,
     155                                       self.domain().smith_form_gens()
     156                                       )
     157            raise NameError(error)
     158        return tuple(self(x) for x in self.domain().gens())
    151159
    152160    def __cmp__(self, right):
    153161        """
     
    452460        assert self(y) == x, "bug in phi.lift()"
    453461        return y
    454462
     463
     464################################################
     465## The homsets corresponding to FGP_Morphism
     466
    455467from sage.categories.homset import Homset
     468from sage.structure.coerce_dict import TripleDict
     469_cache = TripleDict(53, weak_values=True)
    456470
    457 import weakref
    458 _fgp_homset = weakref.WeakValueDictionary()
    459 def FGP_Homset(X, Y):
     471def FGP_Homset(X,Y):
     472    try:
     473        return _cache[X,Y,None]
     474    except KeyError:
     475        H = FGP_Homset_class(X,Y)
     476        _cache[X,Y,None] = H
     477        return H
     478
     479class FGP_Homset_class(Homset):
    460480    """
    461481    EXAMPLES::
    462482
     
    467487        True
    468488        sage: type(Q.Hom(Q))
    469489        <class 'sage.modules.fg_pid.fgp_morphism.FGP_Homset_class_with_category'>
    470     """
    471     key = (X,Y)
    472     try: return _fgp_homset[key]
    473     except KeyError: pass
    474     H = FGP_Homset_class(X, Y)
    475     # Caching breaks tests in fgp_module.
    476     # _fgp_homset[key] = H
    477     return H
    478        
    479    
    480 class FGP_Homset_class(Homset):
     490    """   
     491    Element = FGP_Morphism
    481492    def __init__(self, X, Y):
    482493        """
    483494        EXAMPLES::
     
    490501        self._populate_coercion_lists_(element_constructor = FGP_Morphism,
    491502                                       coerce_list = [])
    492503
     504    def __reduce__(self):
     505        return FGP_Homset, (self.domain(), self.codomain())
     506
    493507    def _coerce_map_from_(self, S):
    494508        """
    495509        EXAMPLES::
    496510
    497511            sage: V = span([[1/2,1,1],[3/2,2,1],[0,0,1]],ZZ); W = V.span([2*V.0+4*V.1, 9*V.0+12*V.1, 4*V.2]); Q = V/W
    498512            sage: phi = Q.hom([Q.0,Q.0 + 2*Q.1]);  psi = loads(dumps(phi))
     513            sage: phi.parent() is psi.parent()
     514            False
     515            sage: phi.parent() == psi.parent()
     516            True
    499517            sage: phi.parent()._coerce_map_from_(psi.parent())
    500518            True
    501519            sage: phi.parent()._coerce_map_from_(Q.Hom(ZZ^3))
     
    510528            return R == S or bool(R._coerce_map_from_(S))
    511529        return False
    512530
    513     def __call__(self, x):
     531    def _element_constructor_(self, x):
    514532        """
    515533        Convert x into an fgp morphism.
    516534
     
    521539            sage: H(3)
    522540            Morphism from module over Integer Ring with invariants (4, 16) to module with invariants (4, 16) that sends the generators to [(3, 0), (0, 3)]
    523541        """
    524         return FGP_Morphism(self, x)
     542        return self.element_class(self, x)
    525543
  • sage/modules/free_module_homspace.py

    diff --git a/sage/modules/free_module_homspace.py b/sage/modules/free_module_homspace.py
    a b  
    120120    return isinstance(x, FreeModuleHomspace)
    121121
    122122class FreeModuleHomspace(sage.categories.homset.HomsetWithBase):
    123     def __call__(self, A, check=True):
     123    Element = free_module_morphism.FreeModuleMorphism
     124    def _coerce_map_from_(self, S):
     125        """
     126        If ``S`` coerces into the matrix space associated with ``self``,
     127        then it coerces into self.
     128
     129        EXAMPLES::
     130
     131            sage: H = Hom(GF(7)^3,GF(7)^3)
     132            sage: H.has_coerce_map_from(ZZ)
     133            True
     134            sage: H.an_element() + 1
     135            Vector space morphism represented by the matrix:
     136            [3 0 0]
     137            [0 3 0]
     138            [0 0 3]
     139            Domain: Vector space of dimension 3 over Finite Field of size 7
     140            Codomain: Vector space of dimension 3 over Finite Field of size 7
     141
     142        """
     143        return self.matrix_space().has_coerce_map_from(S) or super(FreeModuleHomspace, self)._coerce_map_from_(S)
     144
     145    def _element_constructor_(self, A, check=True):
    124146        r"""
    125147        INPUT:
    126148
     
    152174            sage: phi(V.0) == V.1
    153175            True
    154176
     177        ::
     178
     179            sage: U = ZZ^3
     180            sage: V = GF(7)^3
     181            sage: W = GF(7)['x']^3
     182            sage: H = Hom(U,W)
     183            sage: S = Hom(V,V)
     184            sage: S.an_element()
     185            Vector space morphism represented by the matrix:
     186            [2 0 0]
     187            [0 2 0]
     188            [0 0 2]
     189            Domain: Vector space of dimension 3 over Finite Field of size 7
     190            Codomain: Vector space of dimension 3 over Finite Field of size 7
     191            sage: H(S.an_element())
     192            Free module morphism defined by the matrix
     193            [2 0 0]
     194            [0 2 0]
     195            [0 0 2]
     196            Domain: Ambient free module of rank 3 over the principal ideal domain Integer Ring
     197            Codomain: Ambient free module of rank 3 over the principal ideal domain Univariate Polynomial Ring in x over Finite Field of size 7
     198
    155199        The following tests against a bug that was fixed in trac
    156200        ticket #9944. The method ``zero()`` calls this hom space with
    157201        a function, not with a matrix, and that case had previously
     
    187231                except TypeError, msg:
    188232                    # Let us hope that FreeModuleMorphism knows to handle that case
    189233                    pass
    190         return free_module_morphism.FreeModuleMorphism(self, A)
     234        return self.element_class(self, A)
    191235
    192236    @cached_method
    193237    def zero(self):
     
    222266        """
    223267        return self(lambda x: self.codomain().zero())
    224268
    225     def _matrix_space(self):
     269    @cached_method
     270    def matrix_space(self):
    226271        """
    227         Return underlying matrix space that contains the matrices that define
     272        Return the underlying matrix space that contains the matrices that define
    228273        the homomorphisms in this free module homspace.
    229274       
    230275        OUTPUT:
     
    234279        EXAMPLES::
    235280       
    236281            sage: H = Hom(QQ^3, QQ^2)
    237             sage: H._matrix_space()
     282            sage: H.matrix_space()
    238283            Full MatrixSpace of 3 by 2 dense matrices over Rational Field
    239284        """
    240         try:
    241             return self.__matrix_space
    242         except AttributeError:
    243             R = self.domain().base_ring()
    244             M = matrix.MatrixSpace(R, self.domain().rank(), self.codomain().rank())
    245             self.__matrix_space = M
    246             return M
     285        return matrix.MatrixSpace(self.base(), self.domain().rank(), self.codomain().rank())
    247286       
    248287    def basis(self):
    249288        """
     
    270309        try:
    271310            return self.__basis
    272311        except AttributeError:
    273             M = self._matrix_space()
     312            M = self.matrix_space()
    274313            B = M.basis()
    275314            self.__basis = tuple([self(x) for x in B])
    276315            return self.__basis
  • sage/modules/free_module_morphism.py

    diff --git a/sage/modules/free_module_morphism.py b/sage/modules/free_module_morphism.py
    a b  
    7373            sage: V = ZZ^3; W = span([[1,2,3],[-1,2,8]], ZZ)
    7474            sage: phi = V.hom(matrix(ZZ,3,[1..9]))
    7575            sage: type(phi)
    76             <class 'sage.modules.free_module_morphism.FreeModuleMorphism'>
     76            <class 'sage.modules.free_module_morphism.FreeModuleHomspace_with_category.element_class'>
     77            sage: isinstance(phi, sage.modules.free_module_morphism.FreeModuleMorphism)
     78            True
    7779        """
    7880        if not free_module_homspace.is_FreeModuleHomspace(parent):
    7981            raise TypeError, "parent (=%s) must be a free module hom space"%parent
    8082        if isinstance(A, matrix_morphism.MatrixMorphism):
    8183            A = A.matrix()
    82         A = parent._matrix_space()(A)
     84        A = parent.matrix_space()(A)
    8385        matrix_morphism.MatrixMorphism.__init__(self, parent, A)
    8486
    85     def __call__(self, x):
     87    def pushforward(self, x):
    8688        """
    8789        Evaluate this matrix morphism at x, which is either an element
    8890        that can be coerced into the domain or a submodule of the domain.
     
    139141        if free_module.is_FreeModule(x):
    140142            V = self.domain().submodule(x)
    141143            return self.restrict_domain(V).image()
    142         return matrix_morphism.MatrixMorphism.__call__(self, x)
    143        
     144        else:
     145            return self._call_(self.domain()(x))
     146
    144147    def _repr_(self):
    145148        r"""
    146149        Return string representation of this morphism of free modules.
     
    569572            raise TypeError, "not an endomorphism"
    570573
    571574    minpoly = minimal_polynomial
    572    
    573  No newline at end of file
     575   
  • sage/modules/matrix_morphism.py

    diff --git a/sage/modules/matrix_morphism.py b/sage/modules/matrix_morphism.py
    a b  
    109109        """
    110110        return cmp(self.matrix(), other.matrix())
    111111               
    112     def __call__(self, x):
     112    def _call_(self, x):
    113113        """
    114         Evaluate this matrix morphism at an element that can be coerced
    115         into the domain.
     114        Evaluate this matrix morphism at an element of the domain.
    116115       
    117116        EXAMPLES::
    118117       
     
    128127            [4 5]
    129128            Domain: Vector space of dimension 3 over Rational Field
    130129            Codomain: Vector space of dimension 2 over Rational Field
    131             sage: phi(V.0)
     130            sage: phi(V.0)         # indirect doctest
    132131            (0, 1)
    133132            sage: phi([1,2,3])
    134133            (16, 22)
    135134            sage: phi(5)
    136135            Traceback (most recent call last):
    137136            ...
    138             TypeError: 5 must be coercible into Vector space of dimension 3 over Rational Field
     137            TypeError: 5 fails to convert into the map's domain Vector space of dimension 3 over Rational Field, but a `pushforward` method is not properly implemented
    139138            sage: phi([1,1])
    140139            Traceback (most recent call last):
    141140            ...
    142             TypeError: [1, 1] must be coercible into Vector space of dimension 3 over Rational Field
     141            TypeError: [1, 1] fails to convert into the map's domain Vector space of dimension 3 over Rational Field, but a `pushforward` method is not properly implemented
    143142        """
    144         try:
    145             if not hasattr(x, 'parent') or x.parent() != self.domain():
    146                 x = self.domain()(x)
    147         except TypeError:
    148             raise TypeError, "%s must be coercible into %s"%(x,self.domain())
    149143        if self.domain().is_ambient():
    150144            x = x.element()
    151145        else:
     
    156150            return C(v)
    157151        return C(C.linear_combination_of_basis(v), check=False)
    158152
    159     def _call_(self, x):
    160         """
    161         Alternative for compatibility with sage.categories.map.FormalCompositeMap._call_
    162         """
    163         return self.__call__(x)
    164 
    165153    def __invert__(self):
    166154        """
    167155        Invert this matrix morphism.
     
    189177        except ZeroDivisionError:
    190178            raise ZeroDivisionError, "matrix morphism not invertible"
    191179        try:
    192             return self.parent().reversed()(B)
     180            RH = self.parent().reversed()
     181            return RH.element_class(RH, B)
    193182        except TypeError:
    194183            raise ZeroDivisionError, "matrix morphism not invertible"
    195184
     
    335324            [0 4]...
    336325        """
    337326        R = self.base_ring()
    338         return self.parent()(R(left) * self.matrix())
     327        H = self.parent()
     328        return H.element_class(H, R(left) * self.matrix())
    339329
    340     def __mul__(self, right):
     330    def _composition_(self, right, homset):
    341331        """
    342332        Composition of morphisms, denoted by \*.
    343333       
     
    390380            [ 92 113 134 155]
    391381            Domain: Vector space of dimension 3 over Rational Field
    392382            Codomain: Vector space of dimension 4 over Rational Field
    393             sage: phi*psi
    394             Traceback (most recent call last):
    395             ...
    396             TypeError: Incompatible composition of morphisms: domain of left morphism must be codomain of right.
    397383            sage: phi.matrix()*psi.matrix()
    398384            [ 20  23  26  29]
    399385            [ 56  68  80  92]
    400386            [ 92 113 134 155]
    401387
     388        ::
     389
     390            sage: phi*psi
     391            Traceback (most recent call last):
     392            ...
     393            TypeError: self (=Vector space morphism represented by the matrix:
     394            [0 1 2]
     395            [3 4 5]
     396            [6 7 8]
     397            Domain: Vector space of dimension 3 over Rational Field
     398            Codomain: Vector space of dimension 3 over Rational Field) domain must equal right (=Vector space morphism represented by the matrix:
     399            [ 0  1  2  3]
     400            [ 4  5  6  7]
     401            [ 8  9 10 11]
     402            Domain: Vector space of dimension 3 over Rational Field
     403            Codomain: Vector space of dimension 4 over Rational Field) codomain
     404
    402405        Composite maps can be formed with matrix morphisms::
    403406
    404407            sage: K.<a> = NumberField(x^2 + 23)
     
    421424        """
    422425        if not isinstance(right, MatrixMorphism):
    423426            if isinstance(right, (sage.categories.morphism.Morphism, sage.categories.map.Map)):
    424                 return sage.categories.map.Map.__mul__(self, right)
     427                return sage.categories.map.Map._composition_(self, right, homset)
    425428            R = self.base_ring()
    426             return self.parent()(self.matrix() * R(right))
    427         if self.domain() != right.codomain():
    428             raise TypeError, "Incompatible composition of morphisms: domain of left morphism must be codomain of right."
    429         M = right.matrix() * self.matrix()
    430         return right.domain().Hom(self.codomain())(M)
     429            return homset.element_class(homset, R(right) * self.matrix())
     430#        if self.domain() != right.codomain():
     431#            raise TypeError, "Incompatible composition of morphisms: domain of left morphism must be codomain of right."
     432        return homset(right.matrix() * self.matrix())
    431433
    432     def __add__(self, right):
     434    def _add_(self, right):
    433435        """
    434436        Sum of morphisms, denoted by +.
    435437       
     
    463465            sage: phi + psi
    464466            Traceback (most recent call last):
    465467            ...
    466             ValueError: a matrix from
    467             Full MatrixSpace of 3 by 3 dense matrices over Integer Ring
    468             cannot be converted to a matrix in
    469             Full MatrixSpace of 2 by 2 dense matrices over Integer Ring!
     468            TypeError: unsupported operand parent(s) for '+': 'Set of Morphisms from Ambient free module of rank 2 over the principal ideal domain Integer Ring to Ambient free module of rank 2 over the principal ideal domain Integer Ring in Category of modules with basis over Integer Ring' and 'Set of Morphisms from Ambient free module of rank 3 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'
     469
    470470        """
    471471        # TODO: move over to any coercion model!
    472472        if not isinstance(right, MatrixMorphism):
    473473            R = self.base_ring()
    474             return self.parent()(self.matrix() + R(right))
     474            H = self.parent()
     475            return H.element_class(H, self.matrix() + R(right))
    475476        if not right.parent() == self.parent():
    476             right = self.parent()(right)
     477            H = self.parent()
     478            right = H.element_class(H, right.matrix())
    477479        M = self.matrix() + right.matrix()
    478480        return self.domain().Hom(right.codomain())(M)
    479481       
     
    487489            [-1 -1]
    488490            [ 0 -2]...
    489491        """
    490         return self.parent()(-self.matrix())
     492        H = self.parent()
     493        return H.element_class(H, -self.matrix())
    491494       
    492495    def __sub__(self, other):
    493496        """
     
    500503            [0 0]...
    501504        """
    502505        # TODO: move over to any coercion model!
     506        H = self.parent()
    503507        if not isinstance(other, MatrixMorphism):
    504508            R = self.base_ring()
    505             return self.parent()(self.matrix() - R(other))
     509            return H.element_class(H, self.matrix() - R(other))
    506510        if not other.parent() == self.parent():
    507             other = self.parent()(other)
    508         return self.parent()(self.matrix() - other.matrix())
     511            other = H.element_class(H, other.matrix())
     512        return H.element_class(H, self.matrix() - other.matrix())
    509513                             
    510514    def base_ring(self):
    511515        """
     
    10291033            V = sub.free_module()
    10301034        A = self.matrix().restrict_domain(V)
    10311035        H = sub.Hom(self.codomain())
    1032         return H(A)
     1036        return H.element_class(H, A)
    10331037
    10341038    def restrict_codomain(self, sub):
    10351039        """
     
    11001104            V = C.coordinate_module(sub)
    11011105        else:
    11021106            V = sub.free_module()
    1103         return H(self.matrix().restrict_codomain(V))
     1107        return H.element_class(H, self.matrix().restrict_codomain(V))
    11041108
    11051109
    11061110    def restrict(self, sub):
     
    11581162            V = sub.free_module()
    11591163        A = self.matrix().restrict(V)
    11601164        H = sage.categories.homset.End(sub, self.domain().category())
    1161         return H(A)
     1165        return H.element_class(H, A)
    11621166
    11631167
    11641168class MatrixMorphism(MatrixMorphism_abstract):
  • sage/modules/vector_space_homspace.py

    diff --git a/sage/modules/vector_space_homspace.py b/sage/modules/vector_space_homspace.py
    a b  
    194194import sage.matrix.all as matrix
    195195import sage.modules.free_module_homspace
    196196import vector_space_morphism
     197from sage.misc.cachefunc import cached_method
    197198
    198199# This module initially overrides just the minimum functionality necessary
    199200# from  sage.modules.free_module_homspace.FreeModuleHomSpace.
     
    242243    return isinstance(x, VectorSpaceHomspace)
    243244
    244245class VectorSpaceHomspace(sage.modules.free_module_homspace.FreeModuleHomspace):
     246    Element = vector_space_morphism.VectorSpaceMorphism
    245247
    246     def __call__(self, A, check=True):
     248    def _element_constructor_(self, A, check=True):
    247249        r"""
    248250        INPUT:
    249251
     
    254256            which acts on a vector placed to the left of the matrix
    255257          - a list or tuple containing images of the domain's basis vectors
    256258          - a function from the domain to the codomain
     259          - an element coercible into the base ring, interpreted as multiplication map
    257260        - ``check`` (default: True) - ``True`` or ``False``, required for
    258261          compatibility with calls from
    259262          :meth:`sage.structure.parent_gens.ParentWithGens.hom`.
     
    274277            [1 1 0]
    275278            [1 0 2]
    276279
    277         Coercing a matrix::
     280        Converting a matrix::
    278281
    279282            sage: A = matrix(QQ, [[0, 1], [1, 0]])
    280283            sage: rho = H(A)          # indirect doctest
     
    291294            [1 1 0]
    292295            [1 0 2]
    293296
    294         Coercing a list of images::
     297        Converting a list of images::
    295298
    296299            sage: phi = H([V.1, V.0])
    297300            sage: phi(V.1) == V.0
     
    311314            [1 1 0]
    312315            [1 0 2]
    313316
    314         Coercing a lambda function::
     317        Converting a lambda function::
    315318
    316319            sage: f = lambda x: vector(QQ, [x[0], (1/2)*x[2], 2*x[1]])
    317320            sage: zeta = H(f)
     
    328331            [1 1 0]
    329332            [1 0 2]
    330333
     334        Converting a base ring element::
     335
     336            sage: H(3)
     337            Vector space morphism represented by the matrix:
     338            [3 0]
     339            [0 3]
     340            Domain: Vector space of degree 3 and dimension 2 over Rational Field
     341            User basis matrix:
     342            [1 1 0]
     343            [1 0 2]
     344            Codomain: Vector space of degree 3 and dimension 2 over Rational Field
     345            User basis matrix:
     346            [1 1 0]
     347            [1 0 2]
     348
    331349        See other examples in the module-level documentation.
    332350       
    333351        TESTS::
     
    355373                msg = 'function cannot be applied properly to some basis element because\n' + e.args[0]
    356374                raise ValueError(msg)
    357375            try:
    358                 A = matrix.matrix(D.dimension(), C.dimension(), [C.coordinates(C(a)) for a in images])
     376                A = self.matrix_space()([C.coordinates(C(a)) for a in images])
    359377            except (ArithmeticError, TypeError), e:
    360378                msg = 'some image of the function is not in the codomain, because\n' + e.args[0]
    361379                raise ArithmeticError(msg)
     
    365383                raise ValueError(msg.format(len(D.basis()), len(A)))
    366384            try:
    367385                v = [C(a) for a in A]
    368                 A = matrix.matrix(D.dimension(), C.dimension(), [C.coordinates(a) for a in v])
     386                A = self.matrix_space()([C.coordinates(a) for a in v])
    369387            except (ArithmeticError, TypeError), e:
    370388                msg = 'some proposed image is not in the codomain, because\n' + e.args[0]
    371389                raise ArithmeticError(msg)
     390        elif A in self.base():
     391            A = self.matrix_space()(A)
    372392        else:
    373393            msg = 'vector space homspace can only coerce matrices, vector space morphisms, functions or lists, not {0}'
    374394            raise TypeError(msg.format(A))
    375         return vector_space_morphism.VectorSpaceMorphism(self, A)
     395        return self.element_class(self, A)
    376396
    377397    def _repr_(self):
    378398        r"""
  • sage/modules/vector_space_morphism.py

    diff --git a/sage/modules/vector_space_morphism.py b/sage/modules/vector_space_morphism.py
    a b  
    836836            sage: V = QQ^3; W = V.subspace_with_basis([[1,2,3], [-1,2,5/3], [0,1,-1]])
    837837            sage: phi = V.hom(matrix(QQ, 3, range(9)), codomain=W) # indirect doctest
    838838            sage: type(phi)
    839             <class 'sage.modules.vector_space_morphism.VectorSpaceMorphism'>
     839            <class 'sage.modules.vector_space_morphism.VectorSpaceHomspace_with_category.element_class'>
    840840
    841841        A matrix may be coerced into a vector space homspace to
    842842        create a vector space morphism.  ::
     
    846846            sage: A = matrix(QQ, 3, 2, range(6))
    847847            sage: rho = H(A)  # indirect doctest
    848848            sage: type(rho)
    849             <class 'sage.modules.vector_space_morphism.VectorSpaceMorphism'>
     849            <class 'sage.modules.vector_space_morphism.VectorSpaceHomspace_with_category.element_class'>
    850850        """
    851851        if not vector_space_homspace.is_VectorSpaceHomspace(homspace):
    852852            raise TypeError, 'homspace must be a vector space hom space, not {0}'.format(homspace)
     
    862862        if homspace.codomain().dimension() != A.ncols():
    863863            raise TypeError('codomain dimension is incompatible with matrix size')
    864864
    865         A = homspace._matrix_space()(A)
     865        A = homspace.matrix_space()(A)
    866866        free_module_morphism.FreeModuleMorphism.__init__(self, homspace, A)
    867867
    868868    def is_invertible(self):
  • sage/rings/finite_rings/homset.py

    diff --git a/sage/rings/finite_rings/homset.py b/sage/rings/finite_rings/homset.py
    a b  
    4040from sage.rings.integer import Integer
    4141from sage.structure.sequence import Sequence
    4242
     43class FiniteFieldHomomorphism_im_gens(RingHomomorphism_im_gens):
     44    pass
     45
    4346class FiniteFieldHomset(RingHomset_generic):
    4447    """
    4548    Set of homomorphisms with domain a given finite field.
    4649    """
    47     def __call__(self, im_gens, check=True):
     50    Element = FiniteFieldHomomorphism_im_gens
     51    def _element_constructor_(self, im_gens, check=True):
    4852        """
    4953        Construct the homomorphism defined by ``im_gens``.
    5054
     
    8387        if isinstance(im_gens, FiniteFieldHomomorphism_im_gens):
    8488            return self._coerce_impl(im_gens)
    8589        try:
    86             return FiniteFieldHomomorphism_im_gens(self, im_gens, check=check)
     90            return self.element_class(self, im_gens, check=check)
    8791        except (NotImplementedError, ValueError), err:
    8892            try:
    8993                return self._coerce_impl(im_gens)
     
    115119        if x.parent() is self:
    116120            return x
    117121        if x.parent() == self:
    118             return FiniteFieldHomomorphism_im_gens(self, x.im_gens())
     122            return self.element_class(self, x.im_gens())
    119123        raise TypeError
    120124
    121125    def _repr_(self):
     
    264268        """
    265269        return self.list().index(item)
    266270
    267 class FiniteFieldHomomorphism_im_gens(RingHomomorphism_im_gens):
    268     pass
    269 
    270271from sage.structure.sage_object import register_unpickle_override
    271272register_unpickle_override('sage.rings.finite_field_morphism', 'FiniteFieldHomset', FiniteFieldHomset)
    272273register_unpickle_override('sage.rings.finite_field_morphism', 'FiniteFieldHomomorphism_im_gens', FiniteFieldHomomorphism_im_gens)
  • sage/rings/finite_rings/integer_mod_ring.py

    diff --git a/sage/rings/finite_rings/integer_mod_ring.py b/sage/rings/finite_rings/integer_mod_ring.py
    a b  
    145145        if order == 0:
    146146            return integer_ring.IntegerRing()
    147147        else:
    148             return IntegerModRing_generic(order,category=category)
     148            out = IntegerModRing_generic(order,category=category)
     149            out._IntegerModRing_generic__orig_category = category
     150            return out
    149151   
    150152Zmod = Integers = IntegerModRing = IntegerModFactory("IntegerModRing")
    151153
     
    173175   
    174176from sage.categories.commutative_rings import CommutativeRings
    175177from sage.categories.finite_enumerated_sets import FiniteEnumeratedSets
    176 from sage.categories.category import JoinCategory
    177 default_category = JoinCategory((CommutativeRings(), FiniteEnumeratedSets()))
     178from sage.categories.monoids import Monoids
     179from sage.categories.semigroups import Semigroups
     180from sage.categories.commutative_rings import CommutativeRings
     181from sage.categories.finite_enumerated_sets import FiniteEnumeratedSets
     182from sage.categories.category import Category
     183default_category = Category.join([CommutativeRings(), Monoids().Subquotients(), Semigroups().Quotients(), FiniteEnumeratedSets()])
    178184ZZ = integer_ring.IntegerRing()
    179185
    180186class IntegerModRing_generic(quotient_ring.QuotientRing_generic):
     
    238244        We have seen above that an integer mod ring is, by default, not
    239245        initialised as an object in the category of fields. However, one
    240246        can force it to be. Moreover, testing containment in the category
    241         of fields my re-initialise the category of the integer mod ring::
     247        of fields may re-initialise the category of the integer mod ring::
    242248
    243249            sage: F19 = IntegerModRing(19, category = Fields())
    244250            sage: F19.category().is_subcategory(Fields())
     
    312318        self.__factored_order = None
    313319        self.__factored_unit_order = None
    314320        if category is None:
    315             from sage.categories.commutative_rings import CommutativeRings
    316             from sage.categories.finite_enumerated_sets import FiniteEnumeratedSets
    317             from sage.categories.category import Category
    318             category = Category.join([CommutativeRings(), FiniteEnumeratedSets()])
    319 #            category = default_category
     321            category = default_category
    320322        # If the category is given then we trust that is it right.
    321323        # Give the generator a 'name' to make quotients work.  The
    322324        # name 'x' is used because it's also used for the ring of
     
    337339        self._zero_element = integer_mod.IntegerMod(self, 0)
    338340        self._one_element = integer_mod.IntegerMod(self, 1)
    339341
     342    def __reduce__(self):
     343        return IntegerModRing, (self.__order, self.__orig_category)
     344
    340345    def _macaulay2_init_(self):
    341346        """
    342347        EXAMPLES::
  • sage/rings/homset.py

    diff --git a/sage/rings/homset.py b/sage/rings/homset.py
    a b  
    1111#*****************************************************************************
    1212
    1313from sage.categories.homset import HomsetWithBase
     14from sage.structure.coerce_maps import CallableConvertMap
    1415from sage.categories.rings import Rings
    1516_Rings = Rings()
    1617
     
    8788        """
    8889        return "Set of Homomorphisms from %s to %s"%(self.domain(), self.codomain())
    8990
    90     def has_coerce_map_from(self, x):
     91    def _coerce_map_from_(self, x):
    9192        """
    9293        The default for coercion maps between ring homomorphism spaces is
    9394        very restrictive (until more implementation work is done).
     
    9899
    99100            sage: H = Hom(ZZ, QQ)
    100101            sage: H2 = Hom(QQ, ZZ)
    101             sage: H.has_coerce_map_from(H2)
     102            sage: H.has_coerce_map_from(H2)    # indirect doctest
    102103            False
    103104        """
    104         return (x.domain() == self.domain() and x.codomain() == self.codomain())
     105        try:
     106            return (x.domain() == self.domain() and x.codomain() == self.codomain())
     107        except AttributeError:
     108            return False
    105109
    106110    def _coerce_impl(self, x):
    107111        """
     
    154158        except StandardError:
    155159            raise TypeError
    156160
    157     def __call__(self, im_gens, check=True):
     161    def _element_constructor_(self, im_gens, check=True):
    158162        """
    159163        Create a homomorphism.
    160164
     
    238242        sage: phi == loads(dumps(phi))
    239243        True
    240244    """
    241     def __call__(self, im_gens, check=True):
     245    def _element_constructor_(self, im_gens, check=True):
    242246        """
    243247        Create a homomorphism.
    244248
  • sage/rings/laurent_series_ring.py

    diff --git a/sage/rings/laurent_series_ring.py b/sage/rings/laurent_series_ring.py
    a b  
    411411        if c: return c
    412412        return 0
    413413
    414 
    415414    def _is_valid_homomorphism_(self, codomain, im_gens):
    416415        """
    417416        EXAMPLES::
  • sage/rings/number_field/maps.py

    diff --git a/sage/rings/number_field/maps.py b/sage/rings/number_field/maps.py
    a b  
    113113        sage: type(fr), type(to)
    114114        (<class 'sage.rings.number_field.maps.MapVectorSpaceToNumberField'>,
    115115         <class 'sage.rings.number_field.maps.MapNumberFieldToVectorSpace'>)
    116 
    117116        sage: fr.is_injective(), fr.is_surjective()
    118117        (True, True)
    119118
     
    484483          To:   Number Field in b0 with defining polynomial x^2 + a0 over its base field
    485484          Defn: a |--> b0
    486485        sage: type(fr), type(to)
    487         (<class 'sage.rings.number_field.morphism.RelativeNumberFieldHomomorphism_from_abs'>,
    488          <class 'sage.rings.number_field.morphism.NumberFieldHomomorphism_im_gens'>)
     486        (<class 'sage.rings.number_field.morphism.RelativeNumberFieldHomset_with_category.element_class'>,
     487         <class 'sage.rings.number_field.morphism.NumberFieldHomset_with_category.element_class'>)
     488
     489        sage: isinstance(fr, sage.rings.number_field.morphism.RelativeNumberFieldHomomorphism_from_abs)
     490        True
     491        sage: isinstance(to, sage.rings.number_field.morphism.NumberFieldHomomorphism_im_gens)
     492        True
    489493
    490494        sage: M.<c> = L.absolute_field(); M
    491495        Number Field in c with defining polynomial x^6 + 4*x^2 + 200
  • sage/rings/number_field/morphism.py

    diff --git a/sage/rings/number_field/morphism.py b/sage/rings/number_field/morphism.py
    a b  
    1111from sage.rings.finite_rings.integer_mod_ring import Zmod
    1212from sage.structure.sequence import Sequence
    1313
     14class NumberFieldHomomorphism_im_gens(RingHomomorphism_im_gens):
     15    def __invert__(self):
     16        r"""
     17
     18        Return the inverse of an isomorphism of absolute number fields
     19
     20        EXAMPLES::
     21
     22            sage: K.<a> = NumberField(x^2 + 5)
     23            sage: tau1, tau2 = K.automorphisms(); tau1, tau2
     24            (Ring endomorphism of Number Field in a with defining polynomial x^2 + 5
     25              Defn: a |--> a,
     26             Ring endomorphism of Number Field in a with defining polynomial x^2 + 5
     27              Defn: a |--> -a)
     28            sage: ~tau1
     29            Ring endomorphism of Number Field in a with defining polynomial x^2 + 5
     30             Defn: a |--> a
     31            sage: ~tau2
     32            Ring endomorphism of Number Field in a with defining polynomial x^2 + 5
     33             Defn: a |--> -a
     34
     35            sage: L.<z> = CyclotomicField(5)
     36            sage: tau1, tau2, tau3, tau4 = L.automorphisms()
     37            sage: (tau1, ~tau1)
     38            (Ring endomorphism of Cyclotomic Field of order 5 and degree 4
     39              Defn: z |--> z,
     40             Ring endomorphism of Cyclotomic Field of order 5 and degree 4
     41              Defn: z |--> z)
     42            sage: (tau2, ~tau2)
     43            (Ring endomorphism of Cyclotomic Field of order 5 and degree 4
     44              Defn: z |--> z^2,
     45             Ring endomorphism of Cyclotomic Field of order 5 and degree 4
     46              Defn: z |--> z^3)
     47            sage: (tau4, ~tau4)
     48            (Ring endomorphism of Cyclotomic Field of order 5 and degree 4
     49              Defn: z |--> z^3,
     50             Ring endomorphism of Cyclotomic Field of order 5 and degree 4
     51              Defn: z |--> z^2)
     52
     53             sage: M.<w> = NumberField(x^4 - 5*x + 5)
     54             sage: phi = M.hom([z - z^2]); phi
     55             Ring morphism:
     56               From: Number Field in w with defining polynomial x^4 - 5*x + 5
     57               To:   Cyclotomic Field of order 5 and degree 4
     58               Defn: w |--> -z^2 + z
     59             sage: phi^-1
     60             Ring morphism:
     61               From: Cyclotomic Field of order 5 and degree 4
     62               To:   Number Field in w with defining polynomial x^4 - 5*x + 5
     63               Defn: z |--> 3/11*w^3 + 4/11*w^2 + 9/11*w - 14/11
     64             
     65        """
     66        K = self.domain()
     67        L = self.codomain()
     68        if K.degree() != L.degree():
     69            raise TypeError, "Can only invert isomorphisms"
     70        V, V_into_K, _ = K.vector_space()
     71        _, _, L_into_W = L.vector_space()
     72        linear_inverse = ~V.hom(map(L_into_W*self*V_into_K, V.basis()))
     73        return L.hom(map(V_into_K*linear_inverse*L_into_W, [L.gen()]))
     74
     75    def preimage(self, y):
     76        r"""
     77        Computes a preimage of `y` in the domain, provided one exists.
     78        Raises a ValueError if `y` has no preimage.
     79       
     80        INPUT:
     81               
     82        - `y` -- an element of the codomain of self.
     83
     84        OUTPUT:
     85
     86        Returns the preimage of `y` in the domain, if one exists.
     87        Raises a ValueError if `y` has no preimage.
     88
     89        EXAMPLES::
     90
     91            sage: K.<a> = NumberField(x^2 - 7)
     92            sage: L.<b> = NumberField(x^4 - 7)
     93            sage: f = K.embeddings(L)[0]
     94            sage: f.preimage(3*b^2 - 12/7)
     95            3*a - 12/7
     96            sage: f.preimage(b)
     97            Traceback (most recent call last):
     98            ...
     99            ValueError: Element 'b' is not in the image of this homomorphism.
     100       
     101        ::
     102           
     103            sage: F.<b> = QuadraticField(23)
     104            sage: G.<a> = F.extension(x^3+5)
     105            sage: f = F.embeddings(G)[0]
     106            sage: f.preimage(a^3+2*b+3)
     107            2*b - 2
     108           
     109        """
     110   
     111        # Throughout this method I am using the convention that self is a homomorphism from the number field K to the number field L
     112        # Therefore, I use the names K and L in place of domain and codomain
     113
     114        # try to get the cached transformation matrix and vector space isomorphisms if they exist
     115        try:
     116            M,LtoV,VtoK = self._transformation_data
     117        except StandardError:
     118            # get the identifications of K and L with vector spaces over Q
     119            V,VtoL,LtoV = self.codomain().absolute_vector_space()
     120            V,VtoK,KtoV = self.domain().absolute_vector_space()
     121            # construct the transformation matrix from K to L by making the columns be the image of the basis of V_K in V_L using the homomorphism
     122            from sage.matrix.constructor import matrix
     123            from sage.rings.all import QQ
     124            M = matrix(QQ, [LtoV(self(VtoK(e))) for e in V.basis()]).transpose()
     125            self._transformation_data = (M,LtoV,VtoK)
     126
     127        # get the coordinate vector of y, solve the linear system, pass to domain
     128        yvec = LtoV(y)                  # pass from a point in L to its vector space representation
     129        try:
     130            xvec = M.solve_right(yvec)      # solve the linear system, throws an exception if there is no solution
     131        except ValueError:
     132            raise ValueError, "Element '%s' is not in the image of this homomorphism."%y
     133        return VtoK(xvec)               # pass from the vector space representation of K back to a point in K
     134
    14135class NumberFieldHomset(RingHomset_generic):
    15136    """
    16137    Set of homomorphisms with domain a given number field.
     
    19140
    20141        sage: H = Hom(QuadraticField(-1, 'a'), QuadraticField(-1, 'b'))
    21142        sage: TestSuite(H).run()
    22           Failure in _test_category:
    23         ...
    24         The following tests failed: _test_elements
     143
    25144    """
    26 
    27     def __call__(self, im_gens, check=True):
     145    Element = NumberFieldHomomorphism_im_gens
     146    def _element_constructor_(self, im_gens, check=True):
    28147        """
    29148        Create the homomorphism sending the generators to ``im_gens``.
    30149
     
    41160        if isinstance(im_gens, NumberFieldHomomorphism_im_gens):
    42161            return self._coerce_impl(im_gens)
    43162        try:
    44             return NumberFieldHomomorphism_im_gens(self, im_gens, check=check)
     163            return self.element_class(self, im_gens, check=check)
    45164        except (NotImplementedError, ValueError), err:
    46165            try:
    47166                return self._coerce_impl(im_gens)
     
    66185        if x.parent() is self:
    67186            return x
    68187        if x.parent() == self:
    69             return NumberFieldHomomorphism_im_gens(self, x.im_gens())
     188            return self.element_class(self, x.im_gens())
    70189        raise TypeError
    71190
    72191    def _an_element_(self):
     
    195314              Defn: zeta37 |--> zeta37^4
    196315        """
    197316        return self.list()[n]
    198        
    199 
    200 class NumberFieldHomomorphism_im_gens(RingHomomorphism_im_gens):
    201     def __invert__(self):
    202         r"""
    203 
    204         Return the inverse of an isomorphism of absolute number fields
    205 
    206         EXAMPLES::
    207 
    208             sage: K.<a> = NumberField(x^2 + 5)
    209             sage: tau1, tau2 = K.automorphisms(); tau1, tau2
    210             (Ring endomorphism of Number Field in a with defining polynomial x^2 + 5
    211               Defn: a |--> a,
    212              Ring endomorphism of Number Field in a with defining polynomial x^2 + 5
    213               Defn: a |--> -a)
    214             sage: ~tau1
    215             Ring endomorphism of Number Field in a with defining polynomial x^2 + 5
    216              Defn: a |--> a
    217             sage: ~tau2
    218             Ring endomorphism of Number Field in a with defining polynomial x^2 + 5
    219              Defn: a |--> -a
    220 
    221             sage: L.<z> = CyclotomicField(5)
    222             sage: tau1, tau2, tau3, tau4 = L.automorphisms()
    223             sage: (tau1, ~tau1)
    224             (Ring endomorphism of Cyclotomic Field of order 5 and degree 4
    225               Defn: z |--> z,
    226              Ring endomorphism of Cyclotomic Field of order 5 and degree 4
    227               Defn: z |--> z)
    228             sage: (tau2, ~tau2)
    229             (Ring endomorphism of Cyclotomic Field of order 5 and degree 4
    230               Defn: z |--> z^2,
    231              Ring endomorphism of Cyclotomic Field of order 5 and degree 4
    232               Defn: z |--> z^3)
    233             sage: (tau4, ~tau4)
    234             (Ring endomorphism of Cyclotomic Field of order 5 and degree 4
    235               Defn: z |--> z^3,
    236              Ring endomorphism of Cyclotomic Field of order 5 and degree 4
    237               Defn: z |--> z^2)
    238 
    239              sage: M.<w> = NumberField(x^4 - 5*x + 5)
    240              sage: phi = M.hom([z - z^2]); phi
    241              Ring morphism:
    242                From: Number Field in w with defining polynomial x^4 - 5*x + 5
    243                To:   Cyclotomic Field of order 5 and degree 4
    244                Defn: w |--> -z^2 + z
    245              sage: phi^-1
    246              Ring morphism:
    247                From: Cyclotomic Field of order 5 and degree 4
    248                To:   Number Field in w with defining polynomial x^4 - 5*x + 5
    249                Defn: z |--> 3/11*w^3 + 4/11*w^2 + 9/11*w - 14/11
    250              
    251         """
    252         K = self.domain()
    253         L = self.codomain()
    254         if K.degree() != L.degree():
    255             raise TypeError, "Can only invert isomorphisms"
    256         V, V_into_K, _ = K.vector_space()
    257         _, _, L_into_W = L.vector_space()
    258         linear_inverse = ~V.hom(map(L_into_W*self*V_into_K, V.basis()))
    259         return L.hom(map(V_into_K*linear_inverse*L_into_W, [L.gen()]))
    260 
    261     def preimage(self, y):
    262         r"""
    263         Computes a preimage of `y` in the domain, provided one exists.
    264         Raises a ValueError if `y` has no preimage.
    265        
    266         INPUT:
    267                
    268         - `y` -- an element of the codomain of self.
    269 
    270         OUTPUT:
    271 
    272         Returns the preimage of `y` in the domain, if one exists.
    273         Raises a ValueError if `y` has no preimage.
    274 
    275         EXAMPLES::
    276 
    277             sage: K.<a> = NumberField(x^2 - 7)
    278             sage: L.<b> = NumberField(x^4 - 7)
    279             sage: f = K.embeddings(L)[0]
    280             sage: f.preimage(3*b^2 - 12/7)
    281             3*a - 12/7
    282             sage: f.preimage(b)
    283             Traceback (most recent call last):
    284             ...
    285             ValueError: Element 'b' is not in the image of this homomorphism.
    286        
    287         ::
    288            
    289             sage: F.<b> = QuadraticField(23)
    290             sage: G.<a> = F.extension(x^3+5)
    291             sage: f = F.embeddings(G)[0]
    292             sage: f.preimage(a^3+2*b+3)
    293             2*b - 2
    294            
    295         """
    296    
    297         # Throughout this method I am using the convention that self is a homomorphism from the number field K to the number field L
    298         # Therefore, I use the names K and L in place of domain and codomain
    299 
    300         # try to get the cached transformation matrix and vector space isomorphisms if they exist
    301         try:
    302             M,LtoV,VtoK = self._transformation_data
    303         except StandardError:
    304             # get the identifications of K and L with vector spaces over Q
    305             V,VtoL,LtoV = self.codomain().absolute_vector_space()
    306             V,VtoK,KtoV = self.domain().absolute_vector_space()
    307             # construct the transformation matrix from K to L by making the columns be the image of the basis of V_K in V_L using the homomorphism
    308             from sage.matrix.constructor import matrix
    309             from sage.rings.all import QQ
    310             M = matrix(QQ, [LtoV(self(VtoK(e))) for e in V.basis()]).transpose()
    311             self._transformation_data = (M,LtoV,VtoK)
    312 
    313         # get the coordinate vector of y, solve the linear system, pass to domain
    314         yvec = LtoV(y)                  # pass from a point in L to its vector space representation
    315         try:
    316             xvec = M.solve_right(yvec)      # solve the linear system, throws an exception if there is no solution
    317         except ValueError:
    318             raise ValueError, "Element '%s' is not in the image of this homomorphism."%y
    319         return VtoK(xvec)               # pass from the vector space representation of K back to a point in K
    320 
    321 class RelativeNumberFieldHomset(NumberFieldHomset):
    322     """
    323     Set of homomorphisms with domain a given relative number field.
    324 
    325     EXAMPLES:
    326 
    327     We construct a homomorphism from a relative field by giving
    328     the image of a generator::
    329 
    330         sage: L.<cuberoot2, zeta3> = CyclotomicField(3).extension(x^3 - 2)
    331         sage: phi = L.hom([cuberoot2 * zeta3]); phi
    332         Relative number field endomorphism of Number Field in cuberoot2 with defining polynomial x^3 - 2 over its base field
    333           Defn: cuberoot2 |--> zeta3*cuberoot2
    334                 zeta3 |--> zeta3
    335         sage: phi(cuberoot2 + zeta3)
    336         zeta3*cuberoot2 + zeta3
    337 
    338     In fact, this phi is a generator for the Kummer Galois group of this
    339     cyclic extension::
    340 
    341         sage: phi(phi(cuberoot2 + zeta3))
    342         (-zeta3 - 1)*cuberoot2 + zeta3
    343         sage: phi(phi(phi(cuberoot2 + zeta3)))
    344         cuberoot2 + zeta3
    345     """
    346     def __call__(self, im_gen, base_hom=None, check=True):
    347         r"""
    348         Create a homomorphism in this homset from the given data, which can be:
    349 
    350         - A homomorphism from this number field.
    351         - A homomorphism from the absolute number field corresponding to this
    352           relative number field.
    353         - An element (specifying the image of the generator) of a ring into
    354           which the base ring coerces.
    355         - A pair consisting of an element of a ring R and a homomorphism from
    356           the base ring to R.
    357 
    358         EXAMPLES::
    359 
    360             sage: K.<a> = NumberField(x^2 + 1)
    361             sage: L.<b> = K.extension(x^4 - 2)
    362             sage: E = End(L)
    363             sage: E(E[0]) # indirect doctest
    364             Relative number field endomorphism of Number Field in b with defining polynomial x^4 - 2 over its base field
    365               Defn: b |--> b
    366                     a |--> a
    367             sage: E(L.absolute_field('c').hom(b+a, L)) # indirect doctest
    368             Relative number field endomorphism of Number Field in b with defining polynomial x^4 - 2 over its base field
    369               Defn: b |--> b
    370                     a |--> -a
    371             sage: E(-b*a) # indirect doctest
    372             Relative number field endomorphism of Number Field in b with defining polynomial x^4 - 2 over its base field
    373               Defn: b |--> -a*b
    374                     a |--> a
    375             sage: E(-a*b, K.hom([-a])) # indirect doctest
    376             Relative number field endomorphism of Number Field in b with defining polynomial x^4 - 2 over its base field
    377               Defn: b |--> -a*b
    378                     a |--> -a
    379         """
    380 
    381         if isinstance(im_gen, NumberFieldHomomorphism_im_gens):
    382             # Then it must be a homomorphism from the corresponding
    383             # absolute number field
    384             abs_hom = im_gen
    385             K = abs_hom.domain()
    386             if K != self.domain().absolute_field(K.variable_name()):
    387                 raise TypeError, "domain of morphism must be absolute field of domain."
    388             from_K, to_K = K.structure()
    389             if abs_hom.domain() != K:
    390                 raise ValueError, "domain of absolute homomorphism must be absolute field of domain."
    391             if abs_hom.codomain() != self.codomain():
    392                 raise ValueError, "codomain of absolute homomorphism must be codomain of this homset."
    393             return RelativeNumberFieldHomomorphism_from_abs(self, abs_hom)
    394         if isinstance(im_gen, RelativeNumberFieldHomomorphism_from_abs):
    395             return self._coerce_impl(im_gen)
    396         if base_hom is None:
    397             base_hom = self.default_base_hom()
    398         if isinstance(im_gen, (list, tuple)) and len(im_gen) == 1:
    399             im_gen = im_gen[0]
    400         if check:
    401             im_gen = self.codomain()(im_gen)
    402         return self._from_im(im_gen, base_hom)
    403 
    404     def _coerce_impl(self, x):
    405         r"""
    406         Canonically coerce ``x`` into this homset. This will only work if ``x``
    407         is already in the homset.
    408 
    409         EXAMPLE::
    410 
    411             sage: L.<a, b> = NumberField([x^3 - x + 1, x^2 + 23])
    412             sage: E = End(L)
    413             sage: E.coerce(loads(dumps(E[0])))  # indirect doctest
    414             Relative number field endomorphism of Number Field in a with defining polynomial x^3 - x + 1 over its base field
    415               Defn: a |--> a
    416                     b |--> b
    417         """
    418         if not isinstance(x, RelativeNumberFieldHomomorphism_from_abs):
    419             raise TypeError
    420         if x.parent() is self:
    421             return x
    422         if x.parent() == self:
    423             return RelativeNumberFieldHomomorphism_from_abs(self, x.abs_hom())
    424         raise TypeError
    425 
    426     def _from_im(self, im_gen, base_hom):
    427         """
    428         Return the homomorphism that acts on the base as given and
    429         sends the generator of the domain to im_gen.
    430 
    431         EXAMPLE::
    432 
    433             sage: K.<a> = NumberField(x^2 + 23)
    434             sage: L.<b> = K.extension(x^3 - x + 1)
    435             sage: End(L)._from_im( -3/23*a*b^2 + (-9/46*a - 1/2)*b + 2/23*a, K.hom([-a], K))
    436             Relative number field endomorphism of Number Field in b with defining polynomial x^3 - x + 1 over its base field
    437               Defn: b |--> -3/23*a*b^2 + (-9/46*a - 1/2)*b + 2/23*a
    438                     a |--> -a
    439         """
    440         K = self.domain().absolute_field('a')
    441         from_K, to_K = K.structure()
    442         a = from_K(K.gen())
    443         # We just have to figure out where a goes to
    444         # under the morphism defined by im_gen and base_hom.
    445         L = self.codomain()
    446         R = L['x']
    447         f = R([base_hom(x) for x in a.list()])
    448         b = f(im_gen)
    449         abs_hom = K.hom([b])
    450         return RelativeNumberFieldHomomorphism_from_abs(self, abs_hom)
    451 
    452     def default_base_hom(self):
    453         r"""
    454         Pick an embedding of the base field of self into the codomain of this
    455         homset. This is done in an essentially arbitrary way.
    456 
    457         EXAMPLES::
    458 
    459             sage: L.<a, b> = NumberField([x^3 - x + 1, x^2 + 23])
    460             sage: M.<c> = NumberField(x^4 + 80*x^2 + 36)
    461             sage: Hom(L, M).default_base_hom()
    462             Ring morphism:
    463               From: Number Field in b with defining polynomial x^2 + 23
    464               To:   Number Field in c with defining polynomial x^4 + 80*x^2 + 36
    465               Defn: b |--> 1/12*c^3 + 43/6*c
    466         """
    467         try:
    468             return self.__default_base_hom
    469         except AttributeError:
    470             pass
    471         v = self.domain().base_field().embeddings(self.codomain())
    472         if len(v) == 0:
    473             raise ValueError, "no way to map base field to codomain."
    474         self.__default_base_hom = v[0]
    475         return v[0]
    476        
    477     def list(self):
    478         """
    479         Return a list of all the elements of self.
    480 
    481         EXAMPLES::
    482 
    483             sage: K.<a, b> = NumberField( [x^2 + x + 1, x^3 + 2] )
    484             sage: G = End(K); G
    485             Automorphism group of Number Field in a with defining polynomial x^2 + x + 1 over its base field
    486             sage: v = G.list(); v
    487             [
    488             Relative number field endomorphism of Number Field in a with defining polynomial x^2 + x + 1 over its base field
    489               Defn: a |--> a
    490                     b |--> b,
    491             ...
    492             Relative number field endomorphism of Number Field in a with defining polynomial x^2 + x + 1 over its base field
    493               Defn: a |--> a
    494                     b |--> -b*a - b
    495             ]
    496         """
    497         try:
    498             return self.__list
    499         except AttributeError:
    500             pass
    501         D = self.domain()
    502         C = self.codomain()
    503         K = D.absolute_field('a')
    504         v = K.Hom(C).list()
    505         w = [self(phi) for phi in v]
    506         w = Sequence(w, immutable=True, cr=w!=[], universe=self)           
    507         self.__list = w
    508         return w
    509 
    510317
    511318class RelativeNumberFieldHomomorphism_from_abs(RingHomomorphism):
    512319    r"""
     
    526333              Defn: a |--> (-b - 1)*a
    527334                    b |--> b
    528335            sage: type(f)
    529             <class 'sage.rings.number_field.morphism.RelativeNumberFieldHomomorphism_from_abs'>
     336            <class 'sage.rings.number_field.morphism.RelativeNumberFieldHomset_with_category.element_class'>
     337            sage: isinstance(f, sage.rings.number_field.morphism.RelativeNumberFieldHomomorphism_from_abs)
     338            True
    530339        """
    531340        RingHomomorphism.__init__(self, parent)
    532341        self.__abs_hom = abs_hom
     
    624433            sage: K.hom(a*b, K)(17 + 3*a + 2*b) # indirect doctest
    625434            3*b*a + 2*b + 17
    626435        """
    627         return self.__abs_hom(self.__to_K(x))
     436        return self.__abs_hom(self.__to_K(x))       
    628437
     438class RelativeNumberFieldHomset(NumberFieldHomset):
     439    """
     440    Set of homomorphisms with domain a given relative number field.
     441
     442    EXAMPLES:
     443
     444    We construct a homomorphism from a relative field by giving
     445    the image of a generator::
     446
     447        sage: L.<cuberoot2, zeta3> = CyclotomicField(3).extension(x^3 - 2)
     448        sage: phi = L.hom([cuberoot2 * zeta3]); phi
     449        Relative number field endomorphism of Number Field in cuberoot2 with defining polynomial x^3 - 2 over its base field
     450          Defn: cuberoot2 |--> zeta3*cuberoot2
     451                zeta3 |--> zeta3
     452        sage: phi(cuberoot2 + zeta3)
     453        zeta3*cuberoot2 + zeta3
     454
     455    In fact, this phi is a generator for the Kummer Galois group of this
     456    cyclic extension::
     457
     458        sage: phi(phi(cuberoot2 + zeta3))
     459        (-zeta3 - 1)*cuberoot2 + zeta3
     460        sage: phi(phi(phi(cuberoot2 + zeta3)))
     461        cuberoot2 + zeta3
     462    """
     463    Element = RelativeNumberFieldHomomorphism_from_abs
     464    def _element_constructor_(self, im_gen, base_hom=None, check=True):
     465        r"""
     466        Create a homomorphism in this homset from the given data, which can be:
     467
     468        - A homomorphism from this number field.
     469        - A homomorphism from the absolute number field corresponding to this
     470          relative number field.
     471        - An element (specifying the image of the generator) of a ring into
     472          which the base ring coerces.
     473        - A pair consisting of an element of a ring R and a homomorphism from
     474          the base ring to R.
     475
     476        EXAMPLES::
     477
     478            sage: K.<a> = NumberField(x^2 + 1)
     479            sage: L.<b> = K.extension(x^4 - 2)
     480            sage: E = End(L)
     481            sage: E(E[0]) # indirect doctest
     482            Relative number field endomorphism of Number Field in b with defining polynomial x^4 - 2 over its base field
     483              Defn: b |--> b
     484                    a |--> a
     485            sage: E(L.absolute_field('c').hom(b+a, L)) # indirect doctest
     486            Relative number field endomorphism of Number Field in b with defining polynomial x^4 - 2 over its base field
     487              Defn: b |--> b
     488                    a |--> -a
     489            sage: E(-b*a) # indirect doctest
     490            Relative number field endomorphism of Number Field in b with defining polynomial x^4 - 2 over its base field
     491              Defn: b |--> -a*b
     492                    a |--> a
     493            sage: E(-a*b, K.hom([-a])) # indirect doctest
     494            Relative number field endomorphism of Number Field in b with defining polynomial x^4 - 2 over its base field
     495              Defn: b |--> -a*b
     496                    a |--> -a
     497        """
     498
     499        if isinstance(im_gen, NumberFieldHomomorphism_im_gens):
     500            # Then it must be a homomorphism from the corresponding
     501            # absolute number field
     502            abs_hom = im_gen
     503            K = abs_hom.domain()
     504            if K != self.domain().absolute_field(K.variable_name()):
     505                raise TypeError, "domain of morphism must be absolute field of domain."
     506            from_K, to_K = K.structure()
     507            if abs_hom.domain() != K:
     508                raise ValueError, "domain of absolute homomorphism must be absolute field of domain."
     509            if abs_hom.codomain() != self.codomain():
     510                raise ValueError, "codomain of absolute homomorphism must be codomain of this homset."
     511            return self.element_class(self, abs_hom)
     512        if isinstance(im_gen, RelativeNumberFieldHomomorphism_from_abs):
     513            return self._coerce_impl(im_gen)
     514        if base_hom is None:
     515            base_hom = self.default_base_hom()
     516        if isinstance(im_gen, (list, tuple)) and len(im_gen) == 1:
     517            im_gen = im_gen[0]
     518        if check:
     519            im_gen = self.codomain()(im_gen)
     520        return self._from_im(im_gen, base_hom)
     521
     522    def _coerce_impl(self, x):
     523        r"""
     524        Canonically coerce ``x`` into this homset. This will only work if ``x``
     525        is already in the homset.
     526
     527        EXAMPLE::
     528
     529            sage: L.<a, b> = NumberField([x^3 - x + 1, x^2 + 23])
     530            sage: E = End(L)
     531            sage: E.coerce(loads(dumps(E[0])))  # indirect doctest
     532            Relative number field endomorphism of Number Field in a with defining polynomial x^3 - x + 1 over its base field
     533              Defn: a |--> a
     534                    b |--> b
     535        """
     536        if not isinstance(x, RelativeNumberFieldHomomorphism_from_abs):
     537            raise TypeError
     538        if x.parent() is self:
     539            return x
     540        if x.parent() == self:
     541            return self.element_class(self, x.abs_hom())
     542        raise TypeError
     543
     544    def _from_im(self, im_gen, base_hom):
     545        """
     546        Return the homomorphism that acts on the base as given and
     547        sends the generator of the domain to im_gen.
     548
     549        EXAMPLE::
     550
     551            sage: K.<a> = NumberField(x^2 + 23)
     552            sage: L.<b> = K.extension(x^3 - x + 1)
     553            sage: End(L)._from_im( -3/23*a*b^2 + (-9/46*a - 1/2)*b + 2/23*a, K.hom([-a], K))
     554            Relative number field endomorphism of Number Field in b with defining polynomial x^3 - x + 1 over its base field
     555              Defn: b |--> -3/23*a*b^2 + (-9/46*a - 1/2)*b + 2/23*a
     556                    a |--> -a
     557        """
     558        K = self.domain().absolute_field('a')
     559        from_K, to_K = K.structure()
     560        a = from_K(K.gen())
     561        # We just have to figure out where a goes to
     562        # under the morphism defined by im_gen and base_hom.
     563        L = self.codomain()
     564        R = L['x']
     565        f = R([base_hom(x) for x in a.list()])
     566        b = f(im_gen)
     567        abs_hom = K.hom([b])
     568        return self.element_class(self, abs_hom)
     569
     570    def default_base_hom(self):
     571        r"""
     572        Pick an embedding of the base field of self into the codomain of this
     573        homset. This is done in an essentially arbitrary way.
     574
     575        EXAMPLES::
     576
     577            sage: L.<a, b> = NumberField([x^3 - x + 1, x^2 + 23])
     578            sage: M.<c> = NumberField(x^4 + 80*x^2 + 36)
     579            sage: Hom(L, M).default_base_hom()
     580            Ring morphism:
     581              From: Number Field in b with defining polynomial x^2 + 23
     582              To:   Number Field in c with defining polynomial x^4 + 80*x^2 + 36
     583              Defn: b |--> 1/12*c^3 + 43/6*c
     584        """
     585        try:
     586            return self.__default_base_hom
     587        except AttributeError:
     588            pass
     589        v = self.domain().base_field().embeddings(self.codomain())
     590        if len(v) == 0:
     591            raise ValueError, "no way to map base field to codomain."
     592        self.__default_base_hom = v[0]
     593        return v[0]
     594       
     595    def list(self):
     596        """
     597        Return a list of all the elements of self.
     598
     599        EXAMPLES::
     600
     601            sage: K.<a, b> = NumberField( [x^2 + x + 1, x^3 + 2] )
     602            sage: G = End(K); G
     603            Automorphism group of Number Field in a with defining polynomial x^2 + x + 1 over its base field
     604            sage: v = G.list(); v
     605            [
     606            Relative number field endomorphism of Number Field in a with defining polynomial x^2 + x + 1 over its base field
     607              Defn: a |--> a
     608                    b |--> b,
     609            ...
     610            Relative number field endomorphism of Number Field in a with defining polynomial x^2 + x + 1 over its base field
     611              Defn: a |--> a
     612                    b |--> -b*a - b
     613            ]
     614        """
     615        try:
     616            return self.__list
     617        except AttributeError:
     618            pass
     619        D = self.domain()
     620        C = self.codomain()
     621        K = D.absolute_field('a')
     622        v = K.Hom(C).list()
     623        w = [self(phi) for phi in v]
     624        w = Sequence(w, immutable=True, cr=w!=[], universe=self)           
     625        self.__list = w
     626        return w
     627
     628class CyclotomicFieldHomomorphism_im_gens(NumberFieldHomomorphism_im_gens):
     629    pass
    629630
    630631class CyclotomicFieldHomset(NumberFieldHomset):
    631632    """
     
    636637        sage: End(CyclotomicField(16))
    637638        Automorphism group of Cyclotomic Field of order 16 and degree 8
    638639    """
    639     def __call__(self, im_gens, check=True):
     640    Element = CyclotomicFieldHomomorphism_im_gens
     641    def _element_constructor_(self, im_gens, check=True):
    640642        """
    641643        Create an element of this homset.
    642644
     
    658660        if isinstance(im_gens, CyclotomicFieldHomomorphism_im_gens):
    659661            return self._coerce_impl(im_gens)
    660662        try:
    661             return CyclotomicFieldHomomorphism_im_gens(self, im_gens, check=check)
     663            return self.element_class(self, im_gens, check=check)
    662664        except (NotImplementedError, ValueError), err:
    663665            try:
    664666                return self._coerce_impl(im_gens)
     
    685687        if x.parent() is self:
    686688            return x
    687689        if x.parent() == self:
    688             return CyclotomicFieldHomomorphism_im_gens(self, x.im_gens())
     690            return self.element_class(self, x.im_gens())
    689691        raise TypeError
    690692
    691693    def list(self):
     
    732734        v = Sequence(v, immutable=True, cr=v!=[])           
    733735        self.__list = v
    734736        return v
    735 
    736 class CyclotomicFieldHomomorphism_im_gens(NumberFieldHomomorphism_im_gens):
    737     pass
  • sage/rings/quotient_ring.py

    diff --git a/sage/rings/quotient_ring.py b/sage/rings/quotient_ring.py
    a b  
    438438                    category = check_default_category(_RingsQuotients,category)
    439439            ring.Ring.__init__(self, R.base_ring(), names=names, category=category)
    440440        # self._populate_coercion_lists_([R]) # we don't want to do this, since subclasses will often implement improved coercion maps.
    441        
     441
     442    def __reduce__(self):
     443        F, R = self.construction()
     444        return F, (R,)
     445
    442446    def construction(self):
    443447        """
    444448        EXAMPLES::
  • sage/rings/ring.pyx

    diff --git a/sage/rings/ring.pyx b/sage/rings/ring.pyx
    a b  
    20252025    # x's category, so that calling x in Fields() will be faster next time.
    20262026    try:
    20272027        result = isinstance(x, Field) or x.is_field()
    2028     except AttributeError:
     2028    except (AttributeError, NotImplementedError):
    20292029        result = False
    20302030    if result:
    20312031        x._refine_category_(_Fields)
  • sage/schemes/generic/homset.py

    diff --git a/sage/schemes/generic/homset.py b/sage/schemes/generic/homset.py
    a b  
    8484        sage: A3 = AffineSpace(QQ,3)
    8585        sage: Hom = A3.Hom(A2)
    8686       
    87     The Hom-sets are unique::
     87    Here is a tricky point concerning uniqueness of the Hom-sets. The Hom-sets
     88    are only identical if domains/codomains are identical. If
     89    domains/codomains are isomorphic but not identical, then the same holds
     90    for the homsets. Since :func:`~sage.schemes.generic.affine_space.AffineSpace`
     91    is not cached, we thus obtain::
    8892   
    8993        sage: Hom is copy(Hom)
    9094        True
    9195        sage: Hom is A3.Hom(A2)
    9296        True
    93         sage: loads(Hom.dumps()) is Hom
     97        sage: loads(dumps(Hom.domain())) is Hom.domain()
     98        False
     99        sage: loads(dumps(Hom.domain())) == Hom.domain()
    94100        True
    95 
    96     Here is a tricky point. The Hom-sets are not identical if
    97     domains/codomains are isomorphic but not identiacal::
    98 
    99         sage: A3_iso = AffineSpace(QQ,3)
    100         sage: [ A3_iso is A3, A3_iso == A3 ]
    101         [False, True]
    102         sage: Hom_iso = A3_iso.Hom(A2)
    103         sage: Hom_iso is Hom
     101        sage: loads(dumps(Hom)) is Hom
    104102        False
    105         sage: Hom_iso == Hom
     103        sage: loads(dumps(Hom)) == Hom
    106104        True
     105        sage: cmp(loads(dumps(Hom)), Hom)
     106        0
    107107
    108108    TESTS::
    109109
     
    112112        sage: Hom.base_ring()
    113113        Integer Ring
    114114    """
    115    
     115
    116116    def create_key_and_extra_args(self, X, Y, category=None, base=ZZ,
    117117                                  check=True):
    118118        """
     
    245245    """
    246246    Element = SchemeMorphism
    247247
    248     def __call__(self, *args, **kwds):
    249         r"""
    250         Make Hom-sets callable.
    251 
    252         See the ``_call_()`` method of the derived class. All
    253         arguments are handed through.
    254 
    255         EXAMPLES::
    256 
    257             sage: A2 = AffineSpace(QQ,2)
    258             sage: A2(4,5)
    259             (4, 5)
    260         """
    261         # Homset (base of HomsetWithBase) overrides __call__ @#$
    262         from sage.structure.parent import Set_generic
    263         return Set_generic.__call__(self, *args, **kwds)
     248    def __reduce__(self):
     249        return SchemeHomset, (self.domain(), self.codomain())
    264250
    265251    def _repr_(self):
    266252        r"""
     
    543529        Set of rational points of Spectrum of Rational Field
    544530    """
    545531
    546     def _element_constructor_(self, *args, **kwds):
    547         """
    548         The element contstructor.
    549 
    550         EXAMPLES::
    551 
    552             sage: X = Spec(QQ)
    553             sage: ring_hom = QQ.hom((1,), QQ);  ring_hom
    554             Ring endomorphism of Rational Field
    555               Defn: 1 |--> 1
    556             sage: Hom = X.Hom(X)
    557             sage: Hom(ring_hom)
    558             Affine Scheme endomorphism of Spectrum of Rational Field
    559               Defn: Ring endomorphism of Rational Field
    560                       Defn: 1 |--> 1
    561 
    562         TESTS::
    563 
    564             sage: Hom._element_constructor_(ring_hom)
    565             Affine Scheme endomorphism of Spectrum of Rational Field
    566               Defn: Ring endomorphism of Rational Field
    567                       Defn: 1 |--> 1
    568         """
    569         return SchemeHomset_generic._element_constructor_(self, *args, **kwds)
     532#    def _element_constructor_(self, *args, **kwds):
     533#        """
     534#        The element contstructor.
     535#
     536#        EXAMPLES::
     537#
     538#            sage: X = Spec(QQ)
     539#            sage: ring_hom = QQ.hom((1,), QQ);  ring_hom
     540#            Ring endomorphism of Rational Field
     541#              Defn: 1 |--> 1
     542#            sage: Hom = X.Hom(X)
     543#            sage: Hom(ring_hom)
     544#            Affine Scheme endomorphism of Spectrum of Rational Field
     545#              Defn: Ring endomorphism of Rational Field
     546#                      Defn: 1 |--> 1
     547#
     548#        TESTS::
     549#
     550#            sage: Hom._element_constructor_(ring_hom)
     551#            Affine Scheme endomorphism of Spectrum of Rational Field
     552#              Defn: Ring endomorphism of Rational Field
     553#                      Defn: 1 |--> 1
     554#        """
     555#        return SchemeHomset_generic._element_constructor_(self, *args, **kwds)
    570556       
    571557    def _repr_(self):
    572558        """
  • sage/schemes/hyperelliptic_curves/jacobian_homset.py

    diff --git a/sage/schemes/hyperelliptic_curves/jacobian_homset.py b/sage/schemes/hyperelliptic_curves/jacobian_homset.py
    a b  
    5454from jacobian_morphism import JacobianMorphism_divisor_class_field
    5555
    5656class JacobianHomset_divisor_classes(SchemeHomset_points):
     57    Element = JacobianMorphism_divisor_class_field
    5758    def __init__(self, Y, X, **kwds):
    5859        R = X.base_ring()
    5960        S = Y.coordinate_ring()
     
    6667            P2 = PolynomialRing(P1,name=y)
    6768        self._printing_ring = P2
    6869       
    69     def __call__(self, P):
     70    def _element_constructor_(self, P):
    7071        r"""
    7172        Returns a rational point P in the abstract Homset J(K), given:
    7273       
     
    116117        """
    117118        if isinstance(P,(int,long,Integer)) and P == 0:
    118119            R = PolynomialRing(self.value_ring(), 'x')
    119             return JacobianMorphism_divisor_class_field(self, (R(1),R(0)))
     120            return self.element_class(self, (R(1),R(0)))
    120121        elif isinstance(P,(list,tuple)):
    121122            if len(P) == 1 and P[0] == 0:
    122123                R = PolynomialRing(self.value_ring(), 'x')
    123                 return JacobianMorphism_divisor_class_field(self, (R(1),R(0)))
     124                return self.element_class(self, (R(1),R(0)))
    124125            elif len(P) == 2:
    125126                P1 = P[0]
    126127                P2 = P[1]
     
    128129                    R = PolynomialRing(self.value_ring(), 'x')
    129130                    P1 = R(P1)
    130131                    P2 = R(P2)
    131                     return JacobianMorphism_divisor_class_field(self, tuple([P1,P2]))
     132                    return self.element_class(self, tuple([P1,P2]))
    132133                if is_Integer(P1) and is_Polynomial(P2):
    133134                    R = PolynomialRing(self.value_ring(), 'x')
    134135                    P1 = R(P1)
    135                     return JacobianMorphism_divisor_class_field(self, tuple([P1,P2]))
     136                    return self.element_class(self, tuple([P1,P2]))
    136137                if is_Integer(P2) and is_Polynomial(P1):
    137138                    R = PolynomialRing(self.value_ring(), 'x')
    138139                    P2 = R(P2)
    139                     return JacobianMorphism_divisor_class_field(self, tuple([P1,P2]))
     140                    return self.element_class(self, tuple([P1,P2]))
    140141                if is_Polynomial(P1) and is_Polynomial(P2):
    141                     return JacobianMorphism_divisor_class_field(self, tuple(P))
     142                    return self.element_class(self, tuple(P))
    142143                if is_SchemeMorphism(P1) and is_SchemeMorphism(P2):
    143144                    return self(P1) - self(P2)
    144145            raise TypeError, "Argument P (= %s) must have length 2."%P
    145         elif isinstance(P,JacobianMorphism_divisor_class_field) and self == P.parent():
    146             return P
     146        elif isinstance(P,JacobianMorphism_divisor_class_field):
     147            if self is P.parent():
     148                return P
     149            if self.has_coerce_map_from(P.parent()):
     150                R = PolynomialRing(self.value_ring(), 'x')
     151                return self((R(P[0]), R(P[1])))
    147152        elif is_SchemeMorphism(P):
    148153            x0 = P[0]; y0 = P[1]
    149154            R, x = PolynomialRing(self.value_ring(), 'x').objgen()
    150             return self((x-x0,R(y0)))
     155            return self((x-x0,R(y0)))    # used to be self((x-x0,R(y0))), but this seems wrong (S.K.)
    151156        raise TypeError, "Argument P (= %s) does not determine a divisor class"%P
    152157
    153158    def _cmp_(self,other):
  • sage/schemes/hyperelliptic_curves/jacobian_morphism.py

    diff --git a/sage/schemes/hyperelliptic_curves/jacobian_morphism.py b/sage/schemes/hyperelliptic_curves/jacobian_morphism.py
    a b  
    373373            Finite Field of size 37 defined by
    374374            y^2 = x^5 + 12*x^4 + 13*x^3 + 15*x^2 + 33*x
    375375            sage: type(P1)
    376             <class 'sage.schemes.hyperelliptic_curves.jacobian_morphism.JacobianMorphism_divisor_class_field'>
     376            <class 'sage.schemes.hyperelliptic_curves.jacobian_morphism.JacobianHomset_divisor_classes_with_category.element_class'>
     377            sage: isinstance(P1, sage.schemes.hyperelliptic_curves.jacobian_morphism.JacobianMorphism_divisor_class_field)
     378            True
    377379        """
    378380        SchemeMorphism.__init__(self, parent)
    379381        if check:
  • sage/schemes/toric/homset.py

    diff --git a/sage/schemes/toric/homset.py b/sage/schemes/toric/homset.py
    a b  
    8181from sage.schemes.generic.homset import (SchemeHomset_generic,
    8282                                         SchemeHomset_points)
    8383
     84from sage.schemes.toric.morphism import SchemeMorphism_polynomial_toric_variety, SchemeMorphism_fan_toric_variety
     85from sage.misc.lazy_attribute import lazy_attribute
    8486
    8587class SchemeHomset_toric_variety(SchemeHomset_generic):
    8688    """
     
    104106          Defn: Defined by sending Rational polyhedral fan in 2-d lattice N
    105107                to Rational polyhedral fan in 1-d lattice N.
    106108    """
    107 
    108109    def __init__(self, X, Y, category=None, check=True, base=ZZ):
    109110        """
    110111        The Python constructor.
     
    138139        SchemeHomset_generic.__init__(self, X, Y, category=category, check=check, base=base)
    139140        self.register_conversion(MatrixSpace(ZZ, X.fan().dim(), Y.fan().dim()))
    140141
     142    @lazy_attribute
     143    def element_class_polynomial(self):
     144        return self.__make_element_class__(SchemeMorphism_polynomial_toric_variety, name="%s.element_class_polynomial"%self.__class__.__name__)
     145
     146    @lazy_attribute
     147    def element_class_fan(self):
     148        return self.__make_element_class__(SchemeMorphism_fan_toric_variety, name="%s.element_class_fan"%self.__class__.__name__)
     149
    141150    def _element_constructor_(self, x, check=True):
    142151        """
    143152        Construct a scheme morphism.
     
    163172            sage: dP8.<t,x0,x1,x2> = toric_varieties.dP8()
    164173            sage: P2.<y0,y1,y2> = toric_varieties.P2()
    165174            sage: hom_set = dP8.Hom(P2)
     175            sage: TestSuite(hom_set).run(skip=["_test_an_element", "_test_elements", "_test_elements_eq", "_test_some_elements"])
    166176
    167177            sage: fm = FanMorphism(identity_matrix(2), dP8.fan(), P2.fan())
    168178            sage: hom_set(fm)     # calls hom_set._element_constructor_()
     
    211221              Defn: Defined on coordinates by sending [t : x0 : x1 : x2] to
    212222                    [x0 : x1 : x2]
    213223        """
    214         from sage.schemes.toric.morphism import SchemeMorphism_polynomial_toric_variety
    215224        if isinstance(x, (list, tuple)):
    216             return SchemeMorphism_polynomial_toric_variety(self, x, check=check)
     225            return self.element_class_polynomial(self, x, check=check)
    217226       
    218227        if is_RingHomomorphism(x):
    219228            assert x.domain() is self.codomain().coordinate_ring()
    220229            assert x.codomain() is self.domain().coordinate_ring()
    221             return SchemeMorphism_polynomial_toric_variety(self, x.im_gens(), check=check)
     230            return self.element_class_polynomial(self, x.im_gens(), check=check)
    222231
    223232        from sage.schemes.toric.morphism import SchemeMorphism_fan_toric_variety
    224233        if isinstance(x, FanMorphism):
    225             return SchemeMorphism_fan_toric_variety(self, x, check=check)
     234            return self.element_class_fan(self, x, check=check)
    226235
    227236        if is_Matrix(x):
    228237            fm = FanMorphism(x, self.domain().fan(), self.codomain().fan())
    229             return SchemeMorphism_fan_toric_variety(self, fm, check=check)
     238            return self.element_class_fan(self, fm, check=check)
    230239       
    231240        raise TypeError, "x must be a fan morphism or a list/tuple of polynomials"
    232241
  • sage/schemes/toric/morphism.py

    diff --git a/sage/schemes/toric/morphism.py b/sage/schemes/toric/morphism.py
    a b  
    379379          Defn: Defined by sending Rational polyhedral fan in 2-d lattice N
    380380                to Rational polyhedral fan in 2-d lattice N.
    381381        sage: type(f)
    382         <class 'sage.schemes.toric.morphism.SchemeMorphism_fan_toric_variety'>
     382        <class 'sage.schemes.toric.morphism.SchemeHomset_toric_variety_with_category.element_class_fan'>
    383383
    384384    Slightly more explicit construction::
    385385
  • sage/structure/parent.pyx

    diff --git a/sage/structure/parent.pyx b/sage/structure/parent.pyx
    a b  
    15821582        self._element_init_pass_parent = guess_pass_parent(self, element_constructor)
    15831583       
    15841584        if not PY_TYPE_CHECK(coerce_list, list):
    1585             raise ValueError("%s_populate_coercion_lists_: coerce_list is type %s, must be list" % (type(coerce_list), type(self)))
     1585            raise ValueError("%s._populate_coercion_lists_: coerce_list is type %s, must be list" % (type(self), type(coerce_list)))
    15861586        if not PY_TYPE_CHECK(action_list, list):
    1587             raise ValueError("%s_populate_coercion_lists_: action_list is type %s, must be list" % (type(action_list), type(self)))
     1587            raise ValueError("%s._populate_coercion_lists_: action_list is type %s, must be list" % (type(self), type(action_list)))
    15881588        if not PY_TYPE_CHECK(convert_list, list):
    1589             raise ValueError("%s_populate_coercion_lists_: convert_list is type %s, must be list" % (type(convert_list), type(self)))
     1589            raise ValueError("%s._populate_coercion_lists_: convert_list is type %s, must be list" % (type(self), type(convert_list)))
    15901590
    15911591        self._initial_coerce_list = copy(coerce_list)
    15921592        self._initial_action_list = copy(action_list)
     
    23282328            return mor
    23292329
    23302330        if PY_TYPE_CHECK(S, Parent):
    2331             mor = S.coerce_map_from(self)
     2331            try:
     2332                mor = S.coerce_map_from(self)
     2333            except NotImplementedError:
     2334                pass
    23322335            if mor is not None:
    23332336                mor = mor.section()
    23342337                if mor is not None:
     
    23412344                return user_provided_mor
    23422345            elif callable(user_provided_mor):
    23432346                from coerce_maps import CallableConvertMap
    2344                 return CallableConvertMap(user_provided_mor)
     2347                return CallableConvertMap(S, self, user_provided_mor)
    23452348            else:
    23462349                raise TypeError("_convert_map_from_ must return a map or callable (called on %s, got %s)" % (type(self), type(user_provided_mor)))
    23472350