Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
sagemath
GitHub Repository: sagemath/sagelib
Path: blob/master/sage/rings/homset.py
4077 views
1
"""
2
Space of homomorphisms between two rings
3
"""
4
5
#*****************************************************************************
6
# Copyright (C) 2006 William Stein <[email protected]>
7
#
8
# Distributed under the terms of the GNU General Public License (GPL)
9
#
10
# http://www.gnu.org/licenses/
11
#*****************************************************************************
12
13
from sage.categories.homset import HomsetWithBase
14
from sage.categories.rings import Rings
15
_Rings = Rings()
16
17
import morphism
18
import quotient_ring
19
20
def is_RingHomset(H):
21
return isinstance(H, RingHomset_generic)
22
23
def RingHomset(R, S, category = None):
24
if quotient_ring.is_QuotientRing(R):
25
return RingHomset_quo_ring(R, S, category = category)
26
return RingHomset_generic(R, S, category = category)
27
28
29
class RingHomset_generic(HomsetWithBase):
30
def __init__(self, R, S, category = None):
31
if category is None:
32
category = _Rings
33
HomsetWithBase.__init__(self, R, S, category)
34
35
def _repr_(self):
36
return "Set of Homomorphisms from %s to %s"%(self.domain(), self.codomain())
37
38
def has_coerce_map_from(self, x):
39
"""
40
The default for coercion maps between ring homomorphism spaces is
41
very restrictive (until more implementation work is done).
42
"""
43
return (x.domain() == self.domain() and x.codomain() == self.codomain())
44
45
def _coerce_impl(self, x):
46
if not isinstance(x, morphism.RingHomomorphism):
47
raise TypeError
48
if x.parent() is self:
49
return x
50
# Case 1: the parent fits
51
if x.parent() == self:
52
if isinstance(x, morphism.RingHomomorphism_im_gens):
53
return morphism.RingHomomorphism_im_gens(self, x.im_gens())
54
elif isinstance(x, morphism.RingHomomorphism_cover):
55
return morphism.RingHomomorphism_cover(self)
56
elif isinstance(x, morphism.RingHomomorphism_from_base):
57
return morphism.RingHomomorphism_from_base(self, x.underlying_map())
58
# Case 2: unique extension via fraction field
59
try:
60
if isinstance(x, morphism.RingHomomorphism_im_gens) and x.domain().fraction_field().has_coerce_map_from(self.domain()):
61
return morphism.RingHomomorphism_im_gens(self, x.im_gens())
62
except:
63
pass
64
# Case 3: the homomorphism can be extended by coercion
65
try:
66
return x.extend_codomain(self.codomain()).extend_domain(self.domain())
67
except:
68
pass
69
# Last resort, case 4: the homomorphism is induced from the base ring
70
if self.domain()==self.domain().base() or self.codomain()==self.codomain().base():
71
raise TypeError
72
try:
73
x = self.domain().base().Hom(self.codomain().base())(x)
74
return morphism.RingHomomorphism_from_base(self, x)
75
except:
76
raise TypeError
77
78
def __call__(self, im_gens, check=True):
79
"""
80
EXAMPLES::
81
82
sage: H = Hom(ZZ, QQ)
83
sage: phi = H([])
84
Traceback (most recent call last):
85
...
86
TypeError: images do not define a valid homomorphism
87
88
TESTS::
89
90
sage: H = Hom(ZZ, QQ)
91
sage: H == loads(dumps(H))
92
True
93
"""
94
if isinstance(im_gens, (morphism.RingHomomorphism_im_gens, morphism.RingHomomorphism_cover, morphism.RingHomomorphism_from_base) ):
95
return self._coerce_impl(im_gens)
96
try:
97
return morphism.RingHomomorphism_im_gens(self, im_gens, check=check)
98
except (NotImplementedError, ValueError), err:
99
try:
100
return self._coerce_impl(im_gens)
101
except TypeError:
102
raise TypeError, "images do not define a valid homomorphism"
103
104
105
def natural_map(self):
106
return morphism.RingHomomorphism_coercion(self)
107
108
109
class RingHomset_quo_ring(RingHomset_generic):
110
"""
111
Space of ring homomorphism where the domain is a (formal) quotient
112
ring.
113
114
EXAMPLES::
115
116
sage: R.<x,y> = PolynomialRing(QQ, 2)
117
sage: S.<a,b> = R.quotient(x^2 + y^2)
118
sage: phi = S.hom([b,a]); phi
119
Ring endomorphism of Quotient of Multivariate Polynomial Ring in x, y over Rational Field by the ideal (x^2 + y^2)
120
Defn: a |--> b
121
b |--> a
122
sage: phi(a)
123
b
124
sage: phi(b)
125
a
126
127
TESTS:
128
129
We test pickling of a homset from a quotient.
130
131
::
132
133
sage: R.<x,y> = PolynomialRing(QQ, 2)
134
sage: S.<a,b> = R.quotient(x^2 + y^2)
135
sage: H = S.Hom(R)
136
sage: H == loads(dumps(H))
137
True
138
139
We test pickling of actual homomorphisms in a quotient::
140
141
sage: phi = S.hom([b,a])
142
sage: phi == loads(dumps(phi))
143
True
144
"""
145
def __call__(self, im_gens, check=True):
146
if isinstance(im_gens, morphism.RingHomomorphism_from_quotient):
147
return morphism.RingHomomorphism_from_quotient(self, im_gens._phi())
148
try:
149
pi = self.domain().cover()
150
phi = pi.domain().hom(im_gens, check=check)
151
return morphism.RingHomomorphism_from_quotient(self, phi)
152
except (NotImplementedError, ValueError), err:
153
try:
154
return self._coerce_impl(im_gens)
155
except TypeError:
156
raise TypeError, "images do not define a valid homomorphism"
157
158
def _coerce_impl(self, x):
159
if not isinstance(x, morphism.RingHomomorphism_from_quotient):
160
raise TypeError
161
if x.parent() is self:
162
return x
163
if x.parent() == self:
164
return morphism.RingHomomorphism_from_quotient(self, x._phi())
165
raise TypeError
166
167
168