source: sage/categories/homset.py @ 1894:720897da8f7f

Revision 1894:720897da8f7f, 8.4 KB checked in by William Stein <wstein@…>, 7 years ago (diff)

Comparison, coercion for free module homomorphisms; reduce for parents.

Line 
1"""
2Homsets
3
4AUTHORS:
5    -- David Kohel and William Stein
6    -- David Joyner (2005-12-17): added examples
7    -- William Stein (2006-01-14): Changed from Homspace to Homset.
8"""
9
10#*****************************************************************************
11#  Copyright (C) 2005 David Kohel <kohel@maths.usyd.edu>, William Stein <wstein@gmail.com>
12#
13#  Distributed under the terms of the GNU General Public License (GPL)
14#
15#    This code is distributed in the hope that it will be useful,
16#    but WITHOUT ANY WARRANTY; without even the implied warranty
17#    of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
18#
19#  See the GNU General Public License for more details; the full text
20#  is available at:
21#
22#                  http://www.gnu.org/licenses/
23#*****************************************************************************
24
25import weakref
26
27import category
28import morphism
29from sage.sets.set import Set_generic
30from sage.structure.parent_base import ParentWithBase
31
32_cache = {}
33def Hom(X, Y, cat=None):
34    """
35    Create the space of homomorphisms from X to Y in the category cat.
36
37    INPUT:
38        X -- anything
39        Y -- anything
40        cat -- (optional) category in which the morphisms must be
41
42    OUTPUT:
43        a homset in cat
44
45    EXAMPLES:
46        sage: V = VectorSpace(QQ,3)
47        sage: Hom(V, V)
48        Set of Morphisms from Vector space of dimension 3 over Rational
49        Field to Vector space of dimension 3 over Rational Field in
50        Category of vector spaces over Rational Field
51        sage: G = SymmetricGroup(3)
52        sage: Hom(G, G)
53        Set of Morphisms from SymmetricGroup(3) to SymmetricGroup(3) in Category of groups
54        sage: Hom(ZZ, QQ, Sets())
55        Set of Morphisms from Integer Ring to Rational Field in Category of sets
56    """
57    global _cache
58    key = (X,Y,cat)
59    if _cache.has_key(key):
60        H = _cache[key]()
61        if H: return H
62
63    if cat is None or (cat is X.category() and cat is Y.category()):
64        try:
65            H = X._Hom_(Y)
66        except AttributeError:
67            pass
68
69    cat_X = X.category()
70    cat_Y = Y.category()
71    if cat is None:
72        if cat_X.is_subcategory(cat_Y):
73            cat = cat_Y
74        elif cat_Y.is_subcategory(cat_X):
75            if not (cat is None) and not (cat_X is cat_Y):
76                raise ValueError, "No unambiguous category found for Hom from %s to %s."%(X,Y)
77            cat = cat_X
78        else:
79            raise TypeError, "No suitable category found for Hom from %s to %s."%(X,Y)
80       
81    elif isinstance(cat, category.Category):
82        if not isinstance(cat, category.Category):
83            raise TypeError, "Argument cat (= %s) must be a category."%cat
84        if not cat_X.is_subcategory(cat) \
85               or not cat_Y.is_subcategory(cat):
86            raise TypeError, \
87                  "Argument cat (= %s) is incompatible with %s and %s."%(cat, X, Y)
88    else:
89        raise TypeError, "Argument cat (= %s) must be a category."%cat
90   
91
92    # coercing would be incredibly annoying, since the domain and codomain
93    # are totally different objects
94    #X = cat(X); Y = cat(Y)
95
96    # construct H
97    if cat._is_subclass(category.HeckeModules):
98
99        from sage.modular.hecke.homspace import HeckeModuleHomspace
100        H = HeckeModuleHomspace(X, Y)
101       
102    elif cat._is_subclass(category.FreeModules):
103
104        from sage.modules.free_module_homspace import FreeModuleHomspace
105        H = FreeModuleHomspace(X, Y, cat)
106
107    elif cat._is_subclass(category.Rings):
108
109        from sage.rings.homset import RingHomset
110        H = RingHomset(X, Y)
111
112    elif cat._is_subclass(category.Schemes) or cat._is_subclass(category.Schemes_over_base):
113
114        from sage.schemes.generic.homset import SchemeHomset
115        H = SchemeHomset(X, Y)
116       
117    else:  # default
118        if isinstance(X, ParentWithBase):
119            H = HomsetWithBase(X, Y, cat)
120        else:
121            H = Homset(X, Y, cat)
122           
123    ##_cache[key] = weakref.ref(H)
124    _cache[(X, Y, cat)] = weakref.ref(H)
125   
126    return H
127
128def hom(X, Y, f):
129    """
130    Return Hom(X,Y)(f), where f is data that defines an element of Hom(X,Y).
131
132    EXAMPLES:
133        sage: R, x = PolynomialRing(QQ,'x').objgen()
134        sage: phi = hom(R, QQ, [2])
135        sage: phi(x^2 + 3)
136        7
137    """
138    return Hom(X,Y)(f)
139
140def End(X, cat=None):
141    r"""
142    Create the set of endomorphisms of X in the category cat.
143
144    INPUT:
145        X -- anything
146        cat -- (optional) category in which to coerce X
147
148    OUTPUT:
149        a set of endomorphisms in cat
150       
151    EXAMPLES:
152        sage: V = VectorSpace(QQ, 3)
153        sage: End(V)
154        Set of Morphisms from Vector space of dimension 3 over Rational
155        Field to Vector space of dimension 3 over Rational Field in
156        Category of vector spaces over Rational Field
157
158        sage: G = SymmetricGroup(3)
159        sage: S = End(G); S
160        Set of Morphisms from SymmetricGroup(3) to SymmetricGroup(3) in Category of groups
161        sage: is_Endset(S)
162        True
163        sage: S.domain()
164        Symmetric group of order 3! as a permutation group
165
166    Homsets are \emph{not} objects in their category.  They are
167    currently sets.
168        sage: S.category()
169        Category of sets
170        sage: S.domain().category()
171        Category of groups
172    """
173    return Hom(X,X, cat)
174
175def end(X, f):
176    """
177    Return End(X)(f), where f is data that defines an element of End(X).
178
179    EXAMPLES:
180        sage: R, x = PolynomialRing(QQ,'x').objgen()
181        sage: phi = end(R, [x + 1])
182        sage: phi
183        Ring endomorphism of Univariate Polynomial Ring in x over Rational Field
184          Defn: x |--> x + 1
185        sage: phi(x^2 + 5)
186        x^2 + 2*x + 6
187    """
188    return End(X)(f)
189
190class Homset(Set_generic):
191    """
192    The class for collections of morphisms in a category.
193
194    EXAMPLES:
195        sage: H = Hom(QQ^2, QQ^3)
196        sage: loads(H.dumps()) == H
197        True
198        sage: E = End(AffineSpace(2, names='x,y'))
199        sage: loads(E.dumps()) == E
200        True
201    """
202    def __init__(self, X, Y, cat=None, check=True):
203        self.__domain = X
204        self.__codomain = Y
205        if cat is None:
206            cat = X.category()
207        self.__category = cat
208        if check:
209            if not isinstance(cat, category.Category):
210                raise TypeError, "cat (=%s) must be a category"%cat
211            #if not X in cat:
212            #    raise TypeError, "X (=%s) must be in cat (=%s)"%(X, cat)
213            #if not Y in cat:
214            #    raise TypeError, "Y (=%s) must be in cat (=%s)"%(Y, cat)
215
216    def _repr_(self):
217        return "Set of Morphisms from %s to %s in %s"%(
218            self.__domain, self.__codomain, self.__category)
219
220    def __call__(self, x, y=None):
221        """
222        Construct a morphism in this homset from x if possible.
223        """
224        if x in self:
225            return x
226        raise TypeError, "Unable to coerce x (=%s) to a morphism in %s"%(x,self)
227
228    def __cmp__(self, other):
229        if not isinstance(other, Homset):
230            return cmp(type(self), type(other))
231        if self.__domain == other.__domain and self.__codomain == other.__codomain \
232               and self.__category == other.__category:
233            return 0
234        return cmp(self.__domain, other.__domain)
235
236    def __contains__(self, x):
237        try:
238            return x.parent() == self
239        except AttributeError:
240            pass
241        return False
242
243    def natural_map(self):
244        return morphism.FormalCoercionMorphism(self)   # good default in many cases
245
246    def domain(self):
247        return self.__domain
248
249    def codomain(self):
250        return self.__codomain
251
252    def is_endomorphism_set(self):
253        """
254        Return True if the domain and codomain of self are the
255        same object.
256        """
257        return self.__domain is self.__codomain
258
259    def reversed(self):
260        """
261        Return the corresponding homset, but with the domain and codomain
262        reversed.
263        """
264        return Homset(self.__codomain, self.__domain, self.__category)
265
266class HomsetWithBase(ParentWithBase, Homset):
267    def __init__(self, X, Y, cat=None, check=True):
268        Homset.__init__(self, X, Y, cat, check)
269        ParentWithBase.__init__(self, X.base_ring())
270       
271def is_Homset(x):
272    """
273    Return True if x is a set of homomorphisms in a category.
274    """
275    return isinstance(x, Homset)
276
277def is_Endset(x):
278    """
279    Return True if x is a set of endomorphisms in a category.
280    """
281    return isinstance(x, Homset) and x.is_endomorphism_set()
Note: See TracBrowser for help on using the repository browser.