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