Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
sagemath
GitHub Repository: sagemath/sagesmc
Path: blob/master/src/sage/rings/homset.py
8817 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
"""
22
Return ``True`` if ``H`` is a space of homomorphisms between two rings.
23
24
EXAMPLES::
25
26
sage: from sage.rings.homset import is_RingHomset as is_RH
27
sage: is_RH(Hom(ZZ, QQ))
28
True
29
sage: is_RH(ZZ)
30
False
31
sage: is_RH(Hom(RR, CC))
32
True
33
sage: is_RH(Hom(FreeModule(ZZ,1), FreeModule(QQ,1)))
34
False
35
"""
36
return isinstance(H, RingHomset_generic)
37
38
def RingHomset(R, S, category = None):
39
"""
40
Construct a space of homomorphisms between the rings ``R`` and ``S``.
41
42
For more on homsets, see :func:`Hom()`.
43
44
EXAMPLES::
45
46
sage: Hom(ZZ, QQ) # indirect doctest
47
Set of Homomorphisms from Integer Ring to Rational Field
48
49
"""
50
if quotient_ring.is_QuotientRing(R):
51
return RingHomset_quo_ring(R, S, category = category)
52
return RingHomset_generic(R, S, category = category)
53
54
55
class RingHomset_generic(HomsetWithBase):
56
"""
57
A generic space of homomorphisms between two rings.
58
59
EXAMPLES::
60
61
sage: Hom(ZZ, QQ)
62
Set of Homomorphisms from Integer Ring to Rational Field
63
sage: QQ.Hom(ZZ)
64
Set of Homomorphisms from Rational Field to Integer Ring
65
"""
66
def __init__(self, R, S, category = None):
67
"""
68
Initialize ``self``.
69
70
EXAMPLES::
71
72
sage: Hom(ZZ, QQ)
73
Set of Homomorphisms from Integer Ring to Rational Field
74
"""
75
if category is None:
76
category = _Rings
77
HomsetWithBase.__init__(self, R, S, category)
78
79
def _repr_(self):
80
"""
81
Return a string representation of ``self``.
82
83
EXAMPLES::
84
85
sage: Hom(ZZ, QQ) # indirect doctest
86
Set of Homomorphisms from Integer Ring to Rational Field
87
"""
88
return "Set of Homomorphisms from %s to %s"%(self.domain(), self.codomain())
89
90
def has_coerce_map_from(self, x):
91
"""
92
The default for coercion maps between ring homomorphism spaces is
93
very restrictive (until more implementation work is done).
94
95
Currently this checks if the domains and the codomains are equal.
96
97
EXAMPLES::
98
99
sage: H = Hom(ZZ, QQ)
100
sage: H2 = Hom(QQ, ZZ)
101
sage: H.has_coerce_map_from(H2)
102
False
103
"""
104
return (x.domain() == self.domain() and x.codomain() == self.codomain())
105
106
def _coerce_impl(self, x):
107
"""
108
Check to see if we can coerce ``x`` into a homomorphism with the
109
correct rings.
110
111
EXAMPLES::
112
113
sage: H = Hom(ZZ, QQ)
114
sage: phi = H([1])
115
sage: H2 = Hom(QQ, QQ)
116
sage: phi2 = H2(phi); phi2 # indirect doctest
117
Ring endomorphism of Rational Field
118
Defn: 1 |--> 1
119
sage: H(phi2) # indirect doctest
120
Ring morphism:
121
From: Integer Ring
122
To: Rational Field
123
Defn: 1 |--> 1
124
"""
125
if not isinstance(x, morphism.RingHomomorphism):
126
raise TypeError
127
if x.parent() is self:
128
return x
129
# Case 1: the parent fits
130
if x.parent() == self:
131
if isinstance(x, morphism.RingHomomorphism_im_gens):
132
return morphism.RingHomomorphism_im_gens(self, x.im_gens())
133
elif isinstance(x, morphism.RingHomomorphism_cover):
134
return morphism.RingHomomorphism_cover(self)
135
elif isinstance(x, morphism.RingHomomorphism_from_base):
136
return morphism.RingHomomorphism_from_base(self, x.underlying_map())
137
# Case 2: unique extension via fraction field
138
try:
139
if isinstance(x, morphism.RingHomomorphism_im_gens) and x.domain().fraction_field().has_coerce_map_from(self.domain()):
140
return morphism.RingHomomorphism_im_gens(self, x.im_gens())
141
except Exception:
142
pass
143
# Case 3: the homomorphism can be extended by coercion
144
try:
145
return x.extend_codomain(self.codomain()).extend_domain(self.domain())
146
except Exception:
147
pass
148
# Last resort, case 4: the homomorphism is induced from the base ring
149
if self.domain()==self.domain().base() or self.codomain()==self.codomain().base():
150
raise TypeError
151
try:
152
x = self.domain().base().Hom(self.codomain().base())(x)
153
return morphism.RingHomomorphism_from_base(self, x)
154
except Exception:
155
raise TypeError
156
157
def __call__(self, im_gens, check=True):
158
"""
159
Create a homomorphism.
160
161
EXAMPLES::
162
163
sage: H = Hom(ZZ, QQ)
164
sage: H([1])
165
Ring morphism:
166
From: Integer Ring
167
To: Rational Field
168
Defn: 1 |--> 1
169
170
TESTS::
171
172
sage: H = Hom(ZZ, QQ)
173
sage: H == loads(dumps(H))
174
True
175
"""
176
if isinstance(im_gens, morphism.RingHomomorphism):
177
return self._coerce_impl(im_gens)
178
try:
179
return morphism.RingHomomorphism_im_gens(self, im_gens, check=check)
180
except (NotImplementedError, ValueError), err:
181
try:
182
return self._coerce_impl(im_gens)
183
except TypeError:
184
raise TypeError, "images do not define a valid homomorphism"
185
186
187
def natural_map(self):
188
"""
189
Returns the natural map from the domain to the codomain.
190
191
The natural map is the coercion map from the domain ring to the
192
codomain ring.
193
194
EXAMPLES::
195
196
sage: H = Hom(ZZ, QQ)
197
sage: H.natural_map()
198
Ring Coercion morphism:
199
From: Integer Ring
200
To: Rational Field
201
"""
202
return morphism.RingHomomorphism_coercion(self)
203
204
205
class RingHomset_quo_ring(RingHomset_generic):
206
"""
207
Space of ring homomorphisms where the domain is a (formal) quotient
208
ring.
209
210
EXAMPLES::
211
212
sage: R.<x,y> = PolynomialRing(QQ, 2)
213
sage: S.<a,b> = R.quotient(x^2 + y^2)
214
sage: phi = S.hom([b,a]); phi
215
Ring endomorphism of Quotient of Multivariate Polynomial Ring in x, y over Rational Field by the ideal (x^2 + y^2)
216
Defn: a |--> b
217
b |--> a
218
sage: phi(a)
219
b
220
sage: phi(b)
221
a
222
223
TESTS:
224
225
We test pickling of a homset from a quotient.
226
227
::
228
229
sage: R.<x,y> = PolynomialRing(QQ, 2)
230
sage: S.<a,b> = R.quotient(x^2 + y^2)
231
sage: H = S.Hom(R)
232
sage: H == loads(dumps(H))
233
True
234
235
We test pickling of actual homomorphisms in a quotient::
236
237
sage: phi = S.hom([b,a])
238
sage: phi == loads(dumps(phi))
239
True
240
"""
241
def __call__(self, im_gens, check=True):
242
"""
243
Create a homomorphism.
244
245
EXAMPLES::
246
247
sage: R.<x,y> = PolynomialRing(QQ, 2)
248
sage: S.<a,b> = R.quotient(x^2 + y^2)
249
sage: H = S.Hom(R)
250
sage: phi = H([b,a]); phi
251
Ring morphism:
252
From: Quotient of Multivariate Polynomial Ring in x, y over Rational Field by the ideal (x^2 + y^2)
253
To: Multivariate Polynomial Ring in x, y over Rational Field
254
Defn: a |--> b
255
b |--> a
256
257
"""
258
if isinstance(im_gens, morphism.RingHomomorphism_from_quotient):
259
return morphism.RingHomomorphism_from_quotient(self, im_gens._phi())
260
try:
261
pi = self.domain().cover()
262
phi = pi.domain().hom(im_gens, check=check)
263
return morphism.RingHomomorphism_from_quotient(self, phi)
264
except (NotImplementedError, ValueError), err:
265
try:
266
return self._coerce_impl(im_gens)
267
except TypeError:
268
raise TypeError, "images do not define a valid homomorphism"
269
270
def _coerce_impl(self, x):
271
"""
272
Check to see if we can coerce ``x`` into a homomorphism with the
273
correct rings.
274
275
EXAMPLES::
276
277
sage: R.<x,y> = PolynomialRing(QQ, 2)
278
sage: S.<a,b> = R.quotient(x^2 + y^2)
279
sage: H = S.Hom(R)
280
sage: phi = H([b,a])
281
sage: R2.<x,y> = PolynomialRing(ZZ, 2)
282
sage: H2 = Hom(R2, S)
283
sage: H2(phi) # indirect doctest
284
Composite map:
285
From: Multivariate Polynomial Ring in x, y over Integer Ring
286
To: Quotient of Multivariate Polynomial Ring in x, y over Rational Field by the ideal (x^2 + y^2)
287
Defn: Conversion map:
288
From: Multivariate Polynomial Ring in x, y over Integer Ring
289
To: Quotient of Multivariate Polynomial Ring in x, y over Rational Field by the ideal (x^2 + y^2)
290
then
291
Composite map:
292
From: Quotient of Multivariate Polynomial Ring in x, y over Rational Field by the ideal (x^2 + y^2)
293
To: Quotient of Multivariate Polynomial Ring in x, y over Rational Field by the ideal (x^2 + y^2)
294
Defn: Ring morphism:
295
From: Quotient of Multivariate Polynomial Ring in x, y over Rational Field by the ideal (x^2 + y^2)
296
To: Multivariate Polynomial Ring in x, y over Rational Field
297
Defn: a |--> b
298
b |--> a
299
then
300
Conversion map:
301
From: Multivariate Polynomial Ring in x, y over Rational Field
302
To: Quotient of Multivariate Polynomial Ring in x, y over Rational Field by the ideal (x^2 + y^2)
303
304
"""
305
if not isinstance(x, morphism.RingHomomorphism_from_quotient):
306
raise TypeError
307
if x.parent() is self:
308
return x
309
if x.parent() == self:
310
return morphism.RingHomomorphism_from_quotient(self, x._phi())
311
raise TypeError
312
313
314