Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
sagemath
GitHub Repository: sagemath/sagesmc
Path: blob/master/src/sage/schemes/generic/morphism.py
8820 views
1
r"""
2
Scheme morphism
3
4
.. note::
5
6
You should never create the morphisms directy. Instead, use the
7
:meth:`~sage.schemes.generic.scheme.hom` and
8
:meth:`~sage.structure.parent.Hom` methods that are inherited by
9
all schemes.
10
11
If you want to extend the Sage library with some new kind of scheme,
12
your new class (say, ``myscheme``) should provide a method
13
14
* ``myscheme._morphism(*args, **kwds)`` returning a morphism
15
between two schemes in your category, usually defined via
16
polynomials. Your morphism class should derive from
17
:class:`SchemeMorphism_polynomial`. These morphisms will usually be
18
elements of the Hom-set
19
:class:`~sage.schemes.generic.homset.SchemeHomset_generic`.
20
21
Optionally, you can also provide a special Hom-set class for your
22
subcategory of schemes. If you want to do this, you should also
23
provide a method
24
25
* ``myscheme._homset(*args, **kwds)`` returning a
26
Hom-set, which must be an element of a derived class of
27
`class:`~sage.schemes.generic.homset.SchemeHomset_generic`. If your
28
new Hom-set class does not use ``myscheme._morphism`` then you
29
do not have to provide it.
30
31
Note that points on schemes are morphisms `Spec(K)\to X`, too. But we
32
typically use a different notation, so they are implemented in a
33
different derived class. For this, you should implement a method
34
35
* ``myscheme._point(*args, **kwds)`` returning a point, that is,
36
a morphism `Spec(K)\to X`. Your point class should derive from
37
:class:`SchemeMorphism_point`.
38
39
Optionally, you can also provide a special Hom-set for the points, for
40
example the point Hom-set can provide a method to enumerate all
41
points. If you want to do this, you should also provide a method
42
43
* ``myscheme._point_homset(*args, **kwds)`` returning
44
the :mod:`~sage.schemes.generic.homset` of points. The Hom-sets of
45
points are implemented in classes named ``SchemeHomset_points_...``.
46
If your new Hom-set class does not use ``myscheme._point`` then
47
you do not have to provide it.
48
49
AUTHORS:
50
51
- David Kohel, William Stein
52
53
- William Stein (2006-02-11): fixed bug where P(0,0,0) was allowed as
54
a projective point.
55
56
- Volker Braun (2011-08-08): Renamed classes, more documentation, misc
57
cleanups.
58
59
- Ben Hutz (June 2012): added support for projective ring
60
"""
61
62
# Historical note: in trac #11599, V.B. renamed
63
# * _point_morphism_class -> _morphism
64
# * _homset_class -> _point_homset
65
66
#*****************************************************************************
67
# Copyright (C) 2011 Volker Braun <[email protected]>
68
# Copyright (C) 2006 David Kohel <[email protected]>
69
# Copyright (C) 2006 William Stein <[email protected]>
70
#
71
# Distributed under the terms of the GNU General Public License (GPL)
72
# as published by the Free Software Foundation; either version 2 of
73
# the License, or (at your option) any later version.
74
# http://www.gnu.org/licenses/
75
#*****************************************************************************
76
77
78
from sage.structure.element import AdditiveGroupElement, RingElement, Element, generic_power
79
from sage.structure.sequence import Sequence
80
from sage.categories.homset import Homset
81
from sage.rings.all import Integer
82
from sage.rings.commutative_ring import is_CommutativeRing
83
from sage.rings.morphism import is_RingHomomorphism
84
from point import is_SchemeTopologicalPoint
85
from sage.rings.infinity import infinity
86
import scheme
87
88
from sage.rings.arith import gcd, lcm
89
from sage.categories.gcd_domains import GcdDomains
90
from sage.rings.quotient_ring import QuotientRing_generic
91
from sage.categories.homset import Hom
92
93
94
def is_SchemeMorphism(f):
95
"""
96
Test whether ``f`` is a scheme morphism.
97
98
INPUT:
99
100
- ``f`` -- anything.
101
102
OUTPUT:
103
104
Boolean. Return ``True`` if ``f`` is a scheme morphism or a point
105
on an elliptic curve.
106
107
EXAMPLES::
108
109
sage: A.<x,y> = AffineSpace(QQ,2); H = A.Hom(A)
110
sage: f = H([y,x^2+y]); f
111
Scheme endomorphism of Affine Space of dimension 2 over Rational Field
112
Defn: Defined on coordinates by sending (x, y) to
113
(y, x^2 + y)
114
sage: from sage.schemes.generic.morphism import is_SchemeMorphism
115
sage: is_SchemeMorphism(f)
116
True
117
"""
118
from sage.schemes.elliptic_curves.ell_point import EllipticCurvePoint_field
119
return isinstance(f, (SchemeMorphism, EllipticCurvePoint_field));
120
121
122
class SchemeMorphism(Element):
123
"""
124
Base class for scheme morphisms
125
126
INPUT:
127
128
- ``parent`` -- the parent of the morphism.
129
130
EXAMPLES::
131
132
sage: X = Spec(ZZ)
133
sage: Hom = X.Hom(X)
134
sage: from sage.schemes.generic.morphism import SchemeMorphism
135
sage: f = SchemeMorphism(Hom)
136
sage: type(f)
137
<class 'sage.schemes.generic.morphism.SchemeMorphism'>
138
"""
139
def __init__(self, parent):
140
"""
141
The Python constructor.
142
143
EXAMPLES::
144
145
sage: X = Spec(ZZ)
146
sage: Hom = X.Hom(X)
147
sage: from sage.schemes.generic.morphism import SchemeMorphism
148
sage: f = SchemeMorphism(Hom)
149
sage: type(f)
150
<class 'sage.schemes.generic.morphism.SchemeMorphism'>
151
"""
152
if not isinstance(parent, Homset):
153
raise TypeError, "parent (=%s) must be a Homspace"%parent
154
Element.__init__(self, parent)
155
self._domain = parent.domain()
156
self._codomain = parent.codomain()
157
158
def _repr_defn(self):
159
r"""
160
Return a string representation of the definition of ``self``.
161
162
OUTPUT:
163
164
String.
165
166
EXAMPLES::
167
168
sage: X = Spec(ZZ)
169
sage: Hom = X.Hom(X)
170
sage: from sage.schemes.generic.morphism import SchemeMorphism
171
sage: f = SchemeMorphism(Hom)
172
sage: f._repr_defn()
173
Traceback (most recent call last):
174
...
175
NotImplementedError
176
"""
177
raise NotImplementedError
178
179
def _repr_type(self):
180
r"""
181
Return a string representation of the type of ``self``.
182
183
OUTPUT:
184
185
String.
186
187
EXAMPLES::
188
189
sage: from sage.schemes.generic.scheme import Scheme
190
sage: X = Scheme(ZZ)
191
sage: Hom = X.Hom(X)
192
sage: from sage.schemes.generic.morphism import SchemeMorphism
193
sage: f = SchemeMorphism(Hom)
194
sage: f._repr_type()
195
'Scheme'
196
"""
197
return "Scheme"
198
199
def _repr_(self):
200
r"""
201
Return a string representation of ``self``.
202
203
OUTPUT:
204
205
String.
206
207
EXAMPLES::
208
209
sage: X = Spec(ZZ)
210
sage: Hom = X.Hom(X)
211
sage: from sage.schemes.generic.morphism import SchemeMorphism
212
sage: f = SchemeMorphism(Hom)
213
sage: f._repr_()
214
Traceback (most recent call last):
215
...
216
NotImplementedError
217
"""
218
if self.is_endomorphism():
219
s = "%s endomorphism of %s"%(self._repr_type(), self.domain())
220
else:
221
s = "%s morphism:"%self._repr_type()
222
s += "\n From: %s"%self.domain()
223
s += "\n To: %s"%self.codomain()
224
d = self._repr_defn()
225
if d != '':
226
s += "\n Defn: %s"%('\n '.join(self._repr_defn().split('\n')))
227
return s
228
229
def domain(self):
230
"""
231
Return the domain of the morphism.
232
233
OUTPUT:
234
235
A scheme. The domain of the morphism ``self``.
236
237
EXAMPLES::
238
239
sage: A2 = AffineSpace(QQ,2)
240
sage: A2.structure_morphism().domain()
241
Affine Space of dimension 2 over Rational Field
242
"""
243
return self._domain
244
245
def codomain(self):
246
"""
247
Return the codomain (range) of the morphism.
248
249
OUTPUT:
250
251
A scheme. The codomain of the morphism ``self``.
252
253
EXAMPLES::
254
255
sage: A2 = AffineSpace(QQ,2)
256
sage: A2.structure_morphism().codomain()
257
Spectrum of Rational Field
258
"""
259
return self.parent().codomain()
260
261
def category(self):
262
"""
263
Return the category of the Hom-set.
264
265
OUTPUT:
266
267
A category.
268
269
EXAMPLES::
270
271
sage: A2 = AffineSpace(QQ,2)
272
sage: A2.structure_morphism().category()
273
Category of hom sets in Category of Schemes
274
"""
275
return self.parent().category()
276
277
def is_endomorphism(self):
278
"""
279
Return wether the morphism is an endomorphism.
280
281
OUTPUT:
282
283
Boolean. Whether the domain and codomain are identical.
284
285
EXAMPLES::
286
287
sage: X = AffineSpace(QQ,2)
288
sage: X.structure_morphism().is_endomorphism()
289
False
290
sage: X.identity_morphism().is_endomorphism()
291
True
292
"""
293
return self.parent().is_endomorphism_set()
294
295
def _composition_(self, right, homset):
296
"""
297
Helper to construct the composition of two morphisms.
298
299
EXAMPLES::
300
301
sage: X = AffineSpace(QQ,2)
302
sage: f = X.structure_morphism()
303
sage: g = X.identity_morphism()
304
sage: f._composition_(g, f.parent())
305
Traceback (most recent call last):
306
...
307
NotImplementedError
308
309
sage: f * g
310
Traceback (most recent call last):
311
...
312
TypeError: unsupported operand type(s) for *:
313
'SchemeMorphism_structure_map' and 'SchemeMorphism_id'
314
"""
315
raise NotImplementedError
316
317
def __pow__(self, n, dummy=None):
318
"""
319
Exponentiate an endomorphism.
320
321
INPUT:
322
323
- ``n`` -- integer. The exponent.
324
325
OUTPUT:
326
327
A scheme morphism in the same endomorphism set as ``self``.
328
329
EXAMPLES::
330
331
sage: X = AffineSpace(QQ,2)
332
sage: id = X.identity_morphism()
333
sage: id^0
334
Scheme endomorphism of Affine Space of dimension 2 over Rational Field
335
Defn: Identity map
336
sage: id^2
337
Traceback (most recent call last):
338
...
339
TypeError: unsupported operand type(s) for *:
340
'SchemeMorphism_id' and 'SchemeMorphism_id'
341
"""
342
if not self.is_endomorphism():
343
raise TypeError, "self must be an endomorphism."
344
if n==0:
345
return self.domain().identity_morphism()
346
return generic_power(self, n)
347
348
def glue_along_domains(self, other):
349
r"""
350
Glue two morphism
351
352
INPUT:
353
354
- ``other`` -- a scheme morphism with the same domain.
355
356
OUTPUT:
357
358
Assuming that self and other are open immersions with the same
359
domain, return scheme obtained by gluing along the images.
360
361
EXAMPLES:
362
363
We construct a scheme isomorphic to the projective line over
364
`\mathrm{Spec}(\QQ)` by gluing two copies of `\mathbb{A}^1`
365
minus a point::
366
367
sage: R.<x,y> = PolynomialRing(QQ, 2)
368
sage: S.<xbar, ybar> = R.quotient(x*y - 1)
369
sage: Rx = PolynomialRing(QQ, 'x')
370
sage: i1 = Rx.hom([xbar])
371
sage: Ry = PolynomialRing(QQ, 'y')
372
sage: i2 = Ry.hom([ybar])
373
sage: Sch = Schemes()
374
sage: f1 = Sch(i1)
375
sage: f2 = Sch(i2)
376
377
Now f1 and f2 have the same domain, which is a
378
`\mathbb{A}^1` minus a point. We glue along the domain::
379
380
sage: P1 = f1.glue_along_domains(f2)
381
sage: P1
382
Scheme obtained by gluing X and Y along U, where
383
X: Spectrum of Univariate Polynomial Ring in x over Rational Field
384
Y: Spectrum of Univariate Polynomial Ring in y over Rational Field
385
U: Spectrum of Quotient of Multivariate Polynomial Ring in x, y
386
over Rational Field by the ideal (x*y - 1)
387
388
sage: a, b = P1.gluing_maps()
389
sage: a
390
Affine Scheme morphism:
391
From: Spectrum of Quotient of Multivariate Polynomial Ring in x, y
392
over Rational Field by the ideal (x*y - 1)
393
To: Spectrum of Univariate Polynomial Ring in x over Rational Field
394
Defn: Ring morphism:
395
From: Univariate Polynomial Ring in x over Rational Field
396
To: Quotient of Multivariate Polynomial Ring in x, y over
397
Rational Field by the ideal (x*y - 1)
398
Defn: x |--> xbar
399
sage: b
400
Affine Scheme morphism:
401
From: Spectrum of Quotient of Multivariate Polynomial Ring in x, y
402
over Rational Field by the ideal (x*y - 1)
403
To: Spectrum of Univariate Polynomial Ring in y over Rational Field
404
Defn: Ring morphism:
405
From: Univariate Polynomial Ring in y over Rational Field
406
To: Quotient of Multivariate Polynomial Ring in x, y over
407
Rational Field by the ideal (x*y - 1)
408
Defn: y |--> ybar
409
"""
410
import glue
411
return glue.GluedScheme(self, other)
412
413
class SchemeMorphism_id(SchemeMorphism):
414
"""
415
Return the identity morphism from `X` to itself.
416
417
INPUT:
418
419
- ``X`` -- the scheme.
420
421
EXAMPLES::
422
423
sage: X = Spec(ZZ)
424
sage: X.identity_morphism() # indirect doctest
425
Scheme endomorphism of Spectrum of Integer Ring
426
Defn: Identity map
427
"""
428
def __init__(self, X):
429
"""
430
The Python constructor.
431
432
See :class:`SchemeMorphism_id` for details.
433
434
TESTS::
435
436
sage: Spec(ZZ).identity_morphism()
437
Scheme endomorphism of Spectrum of Integer Ring
438
Defn: Identity map
439
"""
440
SchemeMorphism.__init__(self, X.Hom(X))
441
442
def _repr_defn(self):
443
r"""
444
Return a string representation of the definition of ``self``.
445
446
OUTPUT:
447
448
String.
449
450
EXAMPLES::
451
452
sage: Spec(ZZ).identity_morphism()._repr_defn()
453
'Identity map'
454
"""
455
return 'Identity map'
456
457
458
class SchemeMorphism_structure_map(SchemeMorphism):
459
r"""
460
The structure morphism
461
462
INPUT:
463
464
- ``parent`` -- Hom-set with codomain equal to the base scheme of
465
the domain.
466
467
EXAMPLES::
468
469
sage: Spec(ZZ).structure_morphism() # indirect doctest
470
Scheme morphism:
471
From: Spectrum of Integer Ring
472
To: Spectrum of Integer Ring
473
Defn: Structure map
474
"""
475
def __init__(self, parent):
476
"""
477
The Python constuctor.
478
479
See :class:`SchemeMorphism_structure_map` for details.
480
481
TESTS::
482
483
sage: from sage.schemes.generic.morphism import SchemeMorphism_structure_map
484
sage: SchemeMorphism_structure_map( Spec(QQ).Hom(Spec(ZZ)) )
485
Scheme morphism:
486
From: Spectrum of Rational Field
487
To: Spectrum of Integer Ring
488
Defn: Structure map
489
"""
490
SchemeMorphism.__init__(self, parent)
491
if self.domain().base_scheme() != self.codomain():
492
raise ValueError, "parent must have codomain equal the base scheme of domain."
493
494
def _repr_defn(self):
495
r"""
496
Return a string representation of the definition of ``self``.
497
498
OUTPUT:
499
500
String.
501
502
EXAMPLES::
503
504
sage: Spec(ZZ).structure_morphism()._repr_defn()
505
'Structure map'
506
"""
507
return 'Structure map'
508
509
510
class SchemeMorphism_spec(SchemeMorphism):
511
"""
512
Morphism of spectra of rings
513
514
INPUT:
515
516
- ``parent`` -- Hom-set whose domain and codomain are affine schemes.
517
518
- ``phi`` -- a ring morphism with matching domain and codomain.
519
520
- ``check`` -- boolean (optional, default:``True``). Whether to
521
check the input for consistency.
522
523
EXAMPLES::
524
525
sage: R.<x> = PolynomialRing(QQ)
526
sage: phi = R.hom([QQ(7)]); phi
527
Ring morphism:
528
From: Univariate Polynomial Ring in x over Rational Field
529
To: Rational Field
530
Defn: x |--> 7
531
532
sage: X = Spec(QQ); Y = Spec(R)
533
sage: f = X.hom(phi); f
534
Affine Scheme morphism:
535
From: Spectrum of Rational Field
536
To: Spectrum of Univariate Polynomial Ring in x over Rational Field
537
Defn: Ring morphism:
538
From: Univariate Polynomial Ring in x over Rational Field
539
To: Rational Field
540
Defn: x |--> 7
541
542
sage: f.ring_homomorphism()
543
Ring morphism:
544
From: Univariate Polynomial Ring in x over Rational Field
545
To: Rational Field
546
Defn: x |--> 7
547
"""
548
def __init__(self, parent, phi, check=True):
549
"""
550
The Python constuctor.
551
552
See :class:`SchemeMorphism_structure_map` for details.
553
554
TESTS::
555
556
sage: from sage.schemes.generic.morphism import SchemeMorphism_spec
557
sage: SchemeMorphism_spec(Spec(QQ).Hom(Spec(ZZ)), ZZ.hom(QQ))
558
Affine Scheme morphism:
559
From: Spectrum of Rational Field
560
To: Spectrum of Integer Ring
561
Defn: Ring Coercion morphism:
562
From: Integer Ring
563
To: Rational Field
564
"""
565
SchemeMorphism.__init__(self, parent)
566
if check:
567
if not is_RingHomomorphism(phi):
568
raise TypeError("phi (=%s) must be a ring homomorphism" % phi)
569
if phi.domain() != parent.codomain().coordinate_ring():
570
raise TypeError("phi (=%s) must have domain %s"
571
% (phi, parent.codomain().coordinate_ring()))
572
if phi.codomain() != parent.domain().coordinate_ring():
573
raise TypeError("phi (=%s) must have codomain %s"
574
% (phi, parent.domain().coordinate_ring()))
575
self.__ring_homomorphism = phi
576
577
def __call__(self, P):
578
r"""
579
Make morphisms callable.
580
581
INPUT:
582
583
- ``P`` -- a scheme point.
584
585
OUTPUT:
586
587
The image scheme point.
588
589
EXAMPLES::
590
591
sage: R.<x> = PolynomialRing(QQ)
592
sage: phi = R.hom([QQ(7)])
593
sage: X = Spec(QQ); Y = Spec(R)
594
sage: f = X.hom(phi)
595
sage: f(X.an_element())
596
Traceback (most recent call last):
597
...
598
NotImplementedError
599
"""
600
if not is_SchemeTopologicalPoint(P) and P in self.domain():
601
raise TypeError, "P (=%s) must be a topological scheme point of %s"%(P, self)
602
S = self.ring_homomorphism().inverse_image(P.prime_ideal())
603
return self.codomain()(S)
604
605
def _repr_type(self):
606
r"""
607
Return a string representation of the type of ``self``.
608
609
OUTPUT:
610
611
String.
612
613
EXAMPLES::
614
615
sage: R.<x> = PolynomialRing(QQ)
616
sage: phi = R.hom([QQ(7)])
617
sage: X = Spec(QQ); Y = Spec(R)
618
sage: f = X.hom(phi)
619
sage: f._repr_type()
620
'Affine Scheme'
621
"""
622
return "Affine Scheme"
623
624
def _repr_defn(self):
625
r"""
626
Return a string representation of the definition of ``self``.
627
628
OUTPUT:
629
630
String.
631
632
EXAMPLES::
633
634
sage: R.<x> = PolynomialRing(QQ)
635
sage: phi = R.hom([QQ(7)])
636
sage: X = Spec(QQ); Y = Spec(R)
637
sage: f = X.hom(phi)
638
sage: print f._repr_defn()
639
Ring morphism:
640
From: Univariate Polynomial Ring in x over Rational Field
641
To: Rational Field
642
Defn: x |--> 7
643
"""
644
return repr(self.ring_homomorphism())
645
646
def ring_homomorphism(self):
647
"""
648
Return the underlying ring homomorphism.
649
650
OUTPUT:
651
652
A ring homomorphism.
653
654
EXAMPLES::
655
656
sage: R.<x> = PolynomialRing(QQ)
657
sage: phi = R.hom([QQ(7)])
658
sage: X = Spec(QQ); Y = Spec(R)
659
sage: f = X.hom(phi)
660
sage: f.ring_homomorphism()
661
Ring morphism:
662
From: Univariate Polynomial Ring in x over Rational Field
663
To: Rational Field
664
Defn: x |--> 7
665
"""
666
return self.__ring_homomorphism
667
668
669
############################################################################
670
# Morphisms between schemes given on points
671
# The _affine and _projective below refer to the CODOMAIN.
672
# The domain can be either affine or projective regardless
673
# of the class
674
############################################################################
675
class SchemeMorphism_polynomial(SchemeMorphism):
676
"""
677
A morphism of schemes determined by polynomials that define what
678
the morphism does on points in the ambient space.
679
680
INPUT:
681
682
- ``parent`` -- Hom-set whose domain and codomain are affine schemes.
683
684
- ``polys`` -- a list/tuple/iterable of polynomials defining the
685
scheme morphism.
686
687
- ``check`` -- boolean (optional, default:``True``). Whether to
688
check the input for consistency.
689
690
EXAMPLES:
691
692
An example involving the affine plane::
693
694
sage: R.<x,y> = QQ[]
695
sage: A2 = AffineSpace(R)
696
sage: H = A2.Hom(A2)
697
sage: f = H([x-y, x*y])
698
sage: f([0,1])
699
(-1, 0)
700
701
An example involving the projective line::
702
703
sage: R.<x,y> = QQ[]
704
sage: P1 = ProjectiveSpace(R)
705
sage: H = P1.Hom(P1)
706
sage: f = H([x^2+y^2,x*y])
707
sage: f([0,1])
708
(1 : 0)
709
710
Some checks are performed to make sure the given polynomials
711
define a morphism::
712
713
sage: f = H([exp(x),exp(y)])
714
Traceback (most recent call last):
715
...
716
TypeError: polys (=[e^x, e^y]) must be elements of
717
Multivariate Polynomial Ring in x, y over Rational Field
718
"""
719
def __init__(self, parent, polys, check=True):
720
"""
721
The Python constructor.
722
723
See :class:`SchemeMorphism_polynomial` for details.
724
725
EXAMPLES::
726
727
sage: A2.<x,y> = AffineSpace(QQ,2)
728
sage: H = A2.Hom(A2)
729
sage: H([x-y, x*y])
730
Scheme endomorphism of Affine Space of dimension 2 over Rational Field
731
Defn: Defined on coordinates by sending (x, y) to
732
(x - y, x*y)
733
"""
734
if check:
735
if not isinstance(polys, (list, tuple)):
736
raise TypeError, "polys (=%s) must be a list or tuple"%polys
737
source_ring = parent.domain().coordinate_ring()
738
target = parent.codomain().ambient_space()
739
if len(polys) != target.ngens():
740
raise ValueError, "there must be %s polynomials"%target.ngens()
741
try:
742
polys = [source_ring(poly) for poly in polys]
743
except TypeError:
744
raise TypeError, "polys (=%s) must be elements of %s"%(polys,source_ring)
745
if isinstance(source_ring, QuotientRing_generic):
746
lift_polys = [f.lift() for f in polys]
747
else:
748
lift_polys = polys
749
polys = Sequence(lift_polys)
750
self._polys = polys
751
SchemeMorphism.__init__(self, parent)
752
753
def defining_polynomials(self):
754
"""
755
Return the defining polynomials.
756
757
OUTPUT:
758
759
An immutable sequence of polynomials that defines this scheme
760
morphism.
761
762
EXAMPLES::
763
764
sage: R.<x,y> = QQ[]
765
sage: A.<x,y> = AffineSpace(R)
766
sage: H = A.Hom(A)
767
sage: H([x^3+y, 1-x-y]).defining_polynomials()
768
[x^3 + y, -x - y + 1]
769
"""
770
return self._polys
771
772
def __call__(self, x,check=True):
773
"""
774
Apply this morphism to a point in the domain.
775
776
INPUT:
777
778
- ``x`` -- a point in the domain or a list or tuple that defines a point in the domain.
779
780
OUTPUT:
781
782
A point in the codomain.
783
784
EXAMPLES::
785
786
sage: R.<x,y> = QQ[]
787
sage: A.<x,y> = AffineSpace(R)
788
sage: H = A.Hom(A)
789
sage: f = H([y,x^2+y])
790
sage: f([2,3])
791
(3, 7)
792
793
An example with algebraic schemes::
794
795
sage: A.<x,y> = AffineSpace(QQ, 2)
796
sage: X = A.subscheme(x)
797
sage: Y = A.subscheme(y)
798
sage: Hom_XY = X.Hom(Y)
799
sage: f = Hom_XY([y,0]) # (0,y) |-> (y,0)
800
sage: f
801
Scheme morphism:
802
From: Closed subscheme of Affine Space of dimension 2 over Rational Field defined by:
803
x
804
To: Closed subscheme of Affine Space of dimension 2 over Rational Field defined by:
805
y
806
Defn: Defined on coordinates by sending (x, y) to
807
(y, 0)
808
sage: f([0,3])
809
(3, 0)
810
811
We illustrate type checking of the input::
812
813
sage: f(0)
814
Traceback (most recent call last):
815
...
816
TypeError: Argument v (=(0,)) must have 2 coordinates.
817
818
::
819
820
It is possible to avoid the checks on the resulting point which can be useful for indeterminacies,
821
but be careful!!
822
823
sage: PS.<x,y>=ProjectiveSpace(QQ,1)
824
sage: H=Hom(PS,PS)
825
sage: f=H([x^3,x*y^2])
826
sage: P=PS(0,1)
827
sage: f(P,check=False)
828
(0 : 0)
829
830
::
831
832
sage: P.<x,y,z>=ProjectiveSpace(ZZ,2)
833
sage: X=P.subscheme(x^2-y^2);
834
sage: H=Hom(X,X)
835
sage: f=H([x^2,y^2,z^2]);
836
sage: f([4,4,1])
837
(16 : 16 : 1)
838
839
::
840
841
sage: P.<x,y,z>=ProjectiveSpace(ZZ,2)
842
sage: X=P.subscheme(x^2-y^2);
843
sage: H=Hom(X,X)
844
sage: f=H([x^2,y^2,z^2]);
845
sage: f(P([4,4,1]))
846
Traceback (most recent call last):
847
...
848
TypeError: Point must be in the domain of the function
849
850
"""
851
if check:
852
if not isinstance(x,SchemeMorphism_point):
853
x = self.domain()(x)
854
elif x.codomain()!=self.domain():
855
raise TypeError, "Point must be in the domain of the function"
856
P = [f(x._coords) for f in self.defining_polynomials()]
857
return self.codomain().point(P,check)
858
859
860
def _repr_defn(self):
861
"""
862
Return a string representation of the definition of ``self``.
863
864
OUTPUT:
865
866
String.
867
868
EXAMPLES::
869
870
sage: R.<x,y> = QQ[]
871
sage: A.<x,y> = AffineSpace(R)
872
sage: H = A.Hom(A)
873
sage: f = H([y,x^2+y])
874
sage: print f._repr_defn()
875
Defined on coordinates by sending (x, y) to
876
(y, x^2 + y)
877
"""
878
i = self.domain().ambient_space()._repr_generic_point()
879
o = self.codomain().ambient_space()._repr_generic_point(self.defining_polynomials())
880
return "Defined on coordinates by sending %s to\n%s"%(i,o)
881
882
def __getitem__(self,i):
883
"""
884
returns the ith poly with self[i]
885
886
INPUT::
887
888
- ``i``- integer
889
890
OTUPUT::
891
892
- element of the coordinate ring of the domain
893
894
Examples::
895
896
sage: P.<x,y>=ProjectiveSpace(QQ,1)
897
sage: H=Hom(P,P)
898
sage: f=H([3/5*x^2,6*y^2])
899
sage: f[1]
900
6*y^2
901
"""
902
return(self._polys[i])
903
904
def __copy__(self):
905
r"""
906
Returns a copy of ``self``.
907
908
OUTPUT:
909
910
- :class:`SchemeMorphism_polynomial`
911
912
EXAMPLES::
913
914
sage: P.<x,y>=ProjectiveSpace(QQ,1)
915
sage: H=Hom(P,P)
916
sage: f=H([3/5*x^2,6*y^2])
917
sage: g =copy(f)
918
sage: f==g
919
True
920
sage: f is g
921
False
922
923
::
924
925
sage: P.<x,y,z>=ProjectiveSpace(QQ,2)
926
sage: X=P.subscheme(x^2-y^2);
927
sage: Q=X(23,23,46)
928
sage: P=X(1,1,1)
929
sage: P!=Q
930
True
931
"""
932
H=Hom(self.domain(),self.codomain())
933
return(H(self._polys))
934
935
def base_ring(self):
936
r"""
937
Return the base ring of ``self``, that is, the ring over which the coefficients
938
of ``self`` is given as polynomials.
939
940
OUTPUT:
941
942
- ring
943
944
EXAMPLES::
945
946
sage: P.<x,y>=ProjectiveSpace(QQ,1)
947
sage: H=Hom(P,P)
948
sage: f=H([3/5*x^2,6*y^2])
949
sage: f.base_ring()
950
Rational Field
951
952
::
953
954
sage: R.<t>=PolynomialRing(ZZ,1)
955
sage: P.<x,y>=ProjectiveSpace(R,1)
956
sage: H=Hom(P,P)
957
sage: f=H([3*x^2,y^2])
958
sage: f.base_ring()
959
Multivariate Polynomial Ring in t over Integer Ring
960
"""
961
return(self.domain().base_ring())
962
963
def coordinate_ring(self):
964
r"""
965
Returns the coordinate ring of the ambient projective space
966
the multivariable polynomial ring over the base ring
967
968
OUTPUT:
969
970
- ring
971
972
EXAMPLES::
973
974
sage: P.<x,y>=ProjectiveSpace(QQ,1)
975
sage: H=Hom(P,P)
976
sage: f=H([3/5*x^2,6*y^2])
977
sage: f.coordinate_ring()
978
Multivariate Polynomial Ring in x, y over Rational Field
979
980
::
981
982
sage: R.<t>=PolynomialRing(ZZ,1)
983
sage: P.<x,y>=ProjectiveSpace(R,1)
984
sage: H=Hom(P,P)
985
sage: f=H([3*x^2,y^2])
986
sage: f.coordinate_ring()
987
Multivariate Polynomial Ring in x, y over Multivariate Polynomial Ring
988
in t over Integer Ring
989
"""
990
return(self._polys[0].parent())
991
992
def change_ring(self,R, check=True):
993
r"""
994
Returns a new :class:`SchemeMorphism_polynomial` which is ``self`` coerced to `R`. If ``check``
995
is ``True``, then the initialization checks are performed.
996
997
INPUT:
998
999
- ``R`` -- ring
1000
1001
- ``check`` -- Boolean
1002
1003
OUTPUT:
1004
1005
- element of the coordinate ring of the domain
1006
1007
EXAMPLES::
1008
1009
sage: P.<x,y>=ProjectiveSpace(ZZ,1)
1010
sage: H=Hom(P,P)
1011
sage: f=H([3*x^2,y^2])
1012
sage: f.change_ring(GF(3))
1013
Traceback (most recent call last):
1014
...
1015
ValueError: polys (=[0, y^2]) must be of the same degree
1016
1017
::
1018
1019
sage: P.<x,y,z>=ProjectiveSpace(QQ,2)
1020
sage: H=Hom(P,P)
1021
sage: f=H([5/2*x^3 + 3*x*y^2-y^3,3*z^3 + y*x^2, x^3-z^3])
1022
sage: f.change_ring(GF(3))
1023
Scheme endomorphism of Projective Space of dimension 2 over Finite Field of size 3
1024
Defn: Defined on coordinates by sending (x : y : z) to
1025
(x^3 - y^3 : x^2*y : x^3 - z^3)
1026
1027
::
1028
1029
sage: P.<x,y>=ProjectiveSpace(QQ,1)
1030
sage: X=P.subscheme([5*x^2-y^2])
1031
sage: H=Hom(X,X)
1032
sage: f=H([x,y])
1033
sage: f.change_ring(GF(3))
1034
Scheme endomorphism of Closed subscheme of Projective Space of dimension
1035
1 over Finite Field of size 3 defined by:
1036
-x^2 - y^2
1037
Defn: Defined on coordinates by sending (x : y) to
1038
(x : y)
1039
"""
1040
F=self._polys
1041
S=self.codomain().change_ring(R)
1042
H=Hom(S,S)
1043
G=[]
1044
for i in range(self.codomain().ambient_space().dimension_relative()+1):
1045
G.append(F[i].change_ring(R))
1046
return(H(G,check))
1047
1048
1049
############################################################################
1050
# Rational points on schemes, which we view as morphisms determined
1051
# by coordinates.
1052
############################################################################
1053
1054
class SchemeMorphism_point(SchemeMorphism):
1055
"""
1056
Base class for rational points on schemes.
1057
1058
Recall that the `K`-rational points of a scheme `X` over `k` can
1059
be identified with the set of morphisms `Spec(K) \to X`. In Sage,
1060
the rational points are implemented by such scheme morphisms.
1061
1062
EXAMPLES::
1063
1064
sage: from sage.schemes.generic.morphism import SchemeMorphism
1065
sage: f = SchemeMorphism(Spec(ZZ).Hom(Spec(ZZ)))
1066
sage: type(f)
1067
<class 'sage.schemes.generic.morphism.SchemeMorphism'>
1068
"""
1069
def _repr_(self):
1070
r"""
1071
Return a string representation of ``self``.
1072
1073
OUTPUT:
1074
1075
String.
1076
1077
EXAMPLES::
1078
1079
sage: A = AffineSpace(2, QQ)
1080
sage: a = A(1,2)
1081
sage: a._repr_()
1082
'(1, 2)'
1083
"""
1084
return self.codomain().ambient_space()._repr_generic_point(self._coords)
1085
1086
def _latex_(self):
1087
r"""
1088
Return a latex representation of ``self``.
1089
1090
OUTPUT:
1091
1092
String.
1093
1094
EXAMPLES::
1095
1096
sage: A = AffineSpace(2, QQ)
1097
sage: a = A(1,2)
1098
sage: latex(a) == a._latex_()
1099
True
1100
sage: a._latex_()
1101
'\\left(1, 2\\right)'
1102
"""
1103
return self.codomain().ambient_space()._latex_generic_point(self._coords)
1104
1105
def __getitem__(self, n):
1106
"""
1107
Return the ``n``-th coordinate.
1108
1109
OUTPUT:
1110
1111
The coordinate values as an element of the base ring.
1112
1113
EXAMPLES::
1114
1115
sage: A = AffineSpace(2, QQ)
1116
sage: a = A(1,2)
1117
sage: a[0]
1118
1
1119
sage: a[1]
1120
2
1121
"""
1122
return self._coords[n]
1123
1124
def __iter__(self):
1125
"""
1126
Iterate over the coordinates of the point.
1127
1128
OUTPUT:
1129
1130
An iterator.
1131
1132
EXAMPLES::
1133
1134
sage: A = AffineSpace(2, QQ)
1135
sage: a = A(1,2)
1136
sage: iter = a.__iter__()
1137
sage: iter.next()
1138
1
1139
sage: iter.next()
1140
2
1141
sage: list(a)
1142
[1, 2]
1143
"""
1144
return iter(self._coords)
1145
1146
def __tuple__(self):
1147
"""
1148
Return the coordinates as a tuple.
1149
1150
OUTPUT:
1151
1152
A tuple.
1153
1154
EXAMPLES::
1155
1156
sage: A = AffineSpace(2, QQ)
1157
sage: a = A(1,2)
1158
sage: tuple(a)
1159
(1, 2)
1160
"""
1161
return self._coords
1162
1163
def __len__(self):
1164
"""
1165
Return the number of coordinates.
1166
1167
OUTPUT:
1168
1169
Integer. The number of coordinates used to describe the point.
1170
1171
EXAMPLES::
1172
1173
sage: A = AffineSpace(2, QQ)
1174
sage: a = A(1,2)
1175
sage: len(a)
1176
2
1177
"""
1178
return len(self._coords)
1179
1180
def __cmp__(self, other):
1181
"""
1182
Compare two scheme morphisms.
1183
1184
INPUT:
1185
1186
- ``other`` -- anything. To compare against the scheme
1187
morphism ``self``.
1188
1189
OUTPUT:
1190
1191
``+1``, ``0``, or ``-1``.
1192
1193
EXAMPLES::
1194
1195
sage: A = AffineSpace(2, QQ)
1196
sage: a = A(1,2)
1197
sage: b = A(3,4)
1198
sage: a.__cmp__(b)
1199
-1
1200
sage: a != b
1201
True
1202
"""
1203
if not isinstance(other, SchemeMorphism_point):
1204
try:
1205
other = self.codomain().ambient_space()(other)
1206
except TypeError:
1207
return -1
1208
return cmp(self._coords, other._coords)
1209
1210
def scheme(self):
1211
"""
1212
Return the scheme whose point is represented.
1213
1214
OUTPUT:
1215
1216
A scheme.
1217
1218
EXAMPLES::
1219
1220
sage: A = AffineSpace(2, QQ)
1221
sage: a = A(1,2)
1222
sage: a.scheme()
1223
Affine Space of dimension 2 over Rational Field
1224
"""
1225
return self.codomain()
1226
1227
def change_ring(self,R, check=True):
1228
r"""
1229
Returns a new :class:`SchemeMorphism_point` which is self coerced to R. If `check`
1230
is true, then the initialization checks are performed.
1231
1232
INPUT:
1233
1234
- ``R`` -- a ring
1235
1236
- ``check`` -- Boolean (optional)
1237
1238
OUTPUT:
1239
1240
- :class:`SchemeMorphism_point`
1241
1242
EXAMPLES::
1243
1244
sage: P.<x,y,z>=ProjectiveSpace(ZZ,2)
1245
sage: X=P.subscheme(x^2-y^2)
1246
sage: X(23,23,1).change_ring(GF(13))
1247
(10 : 10 : 1)
1248
1249
::
1250
1251
sage: P.<x,y>=ProjectiveSpace(QQ,1)
1252
sage: P(-2/3,1).change_ring(CC)
1253
(-0.666666666666667 : 1.00000000000000)
1254
1255
::
1256
1257
sage: P.<x,y>=ProjectiveSpace(ZZ,1)
1258
sage: P(152,113).change_ring(Zp(5))
1259
(2 + 5^2 + 5^3 + O(5^20) : 3 + 2*5 + 4*5^2 + O(5^20))
1260
"""
1261
S=self.codomain().change_ring(R)
1262
Q=[]
1263
for i in range(len(self._coords)):
1264
Q.append(R(self._coords[i]))
1265
return(S.point(Q,check))
1266
1267
def __copy__(self):
1268
r"""
1269
Returns a copy of the :class:`SchemeMorphism_point` self coerced to `R`.
1270
1271
OUTPUT:
1272
1273
- :class:`SchemeMorphism_point`
1274
1275
EXAMPLES::
1276
1277
sage: P.<x,y>=ProjectiveSpace(ZZ,1)
1278
sage: Q=P(152,113)
1279
sage: copy(Q) is Q
1280
False
1281
sage: copy(Q) == Q
1282
True
1283
"""
1284
return(self.codomain().point(self._coords,False))
1285
1286