Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
sagemath
GitHub Repository: sagemath/sagelib
Path: blob/master/sage/schemes/generic/scheme.py
4076 views
1
"""
2
Schemes
3
4
AUTHORS:
5
6
- William Stein, David Kohel, Kiran Kedlaya (2008): added zeta_series
7
8
- Volker Braun (2011-08-11): documenting, improving, refactoring.
9
"""
10
11
12
#*****************************************************************************
13
# Copyright (C) 2011 Volker Braun <[email protected]>
14
# Copyright (C) 2008 Kiran Kedlaya <[email protected]>
15
# Copyright (C) 2005 David Kohel <[email protected]>
16
# Copyright (C) 2005 William Stein
17
#
18
# Distributed under the terms of the GNU General Public License (GPL)
19
# as published by the Free Software Foundation; either version 2 of
20
# the License, or (at your option) any later version.
21
# http://www.gnu.org/licenses/
22
#*****************************************************************************
23
24
25
from sage.structure.parent import Parent
26
from sage.misc.all import cached_method
27
from sage.rings.all import (IntegerRing, is_CommutativeRing,
28
ZZ, is_RingHomomorphism, GF, PowerSeriesRing,
29
Rationals)
30
31
def is_Scheme(x):
32
"""
33
Test whether ``x`` is a scheme.
34
35
INPUT:
36
37
- ``x`` -- anything.
38
39
OUTPUT:
40
41
Boolean. Whether ``x`` derives from :class:`Scheme`.
42
43
EXAMPLES::
44
45
sage: from sage.schemes.generic.scheme import is_Scheme
46
sage: is_Scheme(5)
47
False
48
sage: X = Spec(QQ)
49
sage: is_Scheme(X)
50
True
51
"""
52
return isinstance(x, Scheme)
53
54
55
56
class Scheme(Parent):
57
"""
58
The base class for all schemes.
59
60
INPUT:
61
62
- ``X`` -- a scheme, scheme morphism, commutative ring,
63
commutative ring morphism, or ``None`` (optional). Determines
64
the base scheme. If a commutative ring is passed, the spectrum
65
of the ring will be used as base.
66
67
- ``category`` -- the category (optional). Will be automatically
68
construted by default.
69
70
EXAMPLES::
71
72
sage: from sage.schemes.generic.scheme import Scheme
73
sage: Scheme(ZZ)
74
<class 'sage.schemes.generic.scheme.Scheme_with_category'>
75
76
A scheme is in the category of all schemes over its base::
77
78
sage: ProjectiveSpace(4, QQ).category()
79
Category of schemes over Rational Field
80
81
There is a special and unique `Spec(\ZZ)` that is the default base
82
scheme::
83
84
sage: Spec(ZZ).base_scheme() is Spec(QQ).base_scheme()
85
True
86
"""
87
88
def __init__(self, X=None, category=None):
89
"""
90
Construct a scheme.
91
92
TESTS::
93
94
sage: R.<x, y> = QQ[]
95
sage: I = (x^2 - y^2)*R
96
sage: RmodI = R.quotient(I)
97
sage: X = Spec(RmodI)
98
sage: TestSuite(X).run(skip = ["_test_an_element", "_test_elements",
99
... "_test_some_elements", "_test_category"]) # See #7946
100
"""
101
from sage.schemes.generic.spec import is_Spec
102
from sage.schemes.generic.morphism import is_SchemeMorphism
103
104
if X is None:
105
try:
106
from sage.schemes.generic.spec import SpecZ
107
self._base_scheme = SpecZ
108
except ImportError: # we are currently constructing SpecZ
109
self._base_ring = ZZ
110
elif is_Scheme(X):
111
self._base_scheme = X
112
elif is_SchemeMorphism(X):
113
self._base_morphism = X
114
elif is_CommutativeRing(X):
115
self._base_ring = X
116
elif is_RingHomomorphism(X):
117
self._base_ring = X.codomain()
118
else:
119
raise ValueError('The base must be define by a scheme, '
120
'scheme morphism, or commutative ring.')
121
122
from sage.categories.schemes import Schemes
123
if not X:
124
default_category = Schemes()
125
else:
126
default_category = Schemes(self.base_scheme())
127
if category is None:
128
category = default_category
129
else:
130
assert category.is_subcategory(default_category), \
131
"%s is not a subcategory of %s"%(category, default_category)
132
133
Parent.__init__(self, self.base_ring(), category = category)
134
135
def __cmp__(left, right):
136
"""
137
Compare two schemes.
138
139
INPUT:
140
141
- ``right`` -- anything. To compare against the scheme
142
``left``.
143
144
OUTPUT:
145
146
``+1``, ``0``, or ``-1``.
147
148
EXAMPLES::
149
150
sage: X = Spec(QQ); Y = Spec(QQ)
151
sage: X == Y
152
True
153
sage: X is Y
154
False
155
"""
156
if not is_Scheme(right):
157
return -1
158
return left._cmp_(right)
159
160
def union(self, X):
161
"""
162
Return the disjoint union of the schemes ``self`` and ``X``.
163
164
EXAMPLES::
165
166
sage: S = Spec(QQ)
167
sage: X = AffineSpace(1, QQ)
168
sage: S.union(X)
169
Traceback (most recent call last):
170
...
171
NotImplementedError
172
"""
173
raise NotImplementedError
174
175
__add__ = union
176
177
def _morphism(self, *args, **kwds):
178
"""
179
Construct a morphism determined by action on points of ``self``.
180
181
EXAMPLES::
182
183
sage: X = Spec(QQ)
184
sage: X._morphism()
185
Traceback (most recent call last):
186
...
187
NotImplementedError
188
189
TESTS:
190
191
This shows that issue at trac ticket 7389 is solved::
192
193
sage: S = Spec(ZZ)
194
sage: f = S.identity_morphism()
195
sage: from sage.schemes.generic.glue import GluedScheme
196
sage: T = GluedScheme(f,f)
197
sage: S.hom([1],T)
198
Traceback (most recent call last):
199
...
200
NotImplementedError
201
"""
202
raise NotImplementedError
203
204
def base_extend(self, Y):
205
"""
206
Extend the base of the scheme.
207
208
Derived clases must override this method.
209
210
EXAMPLES::
211
212
sage: from sage.schemes.generic.scheme import Scheme
213
sage: X = Scheme(ZZ)
214
sage: X.base_scheme()
215
Spectrum of Integer Ring
216
sage: X.base_extend(QQ)
217
Traceback (most recent call last):
218
...
219
NotImplementedError
220
"""
221
raise NotImplementedError
222
223
def __call__(self, *args):
224
"""
225
Call syntax for schemes.
226
227
INPUT/OUTPUT:
228
229
The arguments must be one of the following:
230
231
- a ring or a scheme `S`. Output will be the set `X(S)` of
232
`S`-valued points on `X`.
233
234
- If `S` is a list or tuple or just the coordinates, return a
235
point in `X(T)`, where `T` is the base scheme of self.
236
237
EXAMPLES::
238
239
sage: A = AffineSpace(2, QQ)
240
241
We create some point sets::
242
243
sage: A(QQ)
244
Set of rational points of Affine Space of dimension 2 over Rational Field
245
sage: A(RR)
246
Set of rational points of Affine Space of dimension 2 over Real Field
247
with 53 bits of precision
248
249
Space of dimension 2 over Rational Field::
250
251
sage: R.<x> = PolynomialRing(QQ)
252
sage: A(NumberField(x^2+1, 'a'))
253
Set of rational points of Affine Space of dimension 2 over Number Field
254
in a with defining polynomial x^2 + 1
255
sage: A(GF(7))
256
Traceback (most recent call last):
257
...
258
ValueError: There must be a natural map S --> R, but
259
S = Rational Field and R = Finite Field of size 7
260
261
We create some points::
262
263
sage: A(QQ)([1,0])
264
(1, 0)
265
266
We create the same point by giving the coordinates of the point
267
directly::
268
269
sage: A( 1,0 )
270
(1, 0)
271
"""
272
if len(args) == 0:
273
raise TypeError('You need to specify at least one argument.')
274
275
S = args[0]
276
if is_CommutativeRing(S):
277
return self.point_homset(S)
278
if is_Scheme(S):
279
return S.Hom(self)
280
from sage.schemes.generic.morphism import SchemeMorphism_point
281
if isinstance(S, (list, tuple)):
282
args = S
283
elif isinstance(S, SchemeMorphism_point):
284
if S.codomain() == self:
285
return S
286
else:
287
# TODO: fix circular import resulting from non-multiple inheritance
288
from sage.schemes.elliptic_curves.ell_point import EllipticCurvePoint_field
289
if isinstance(S, EllipticCurvePoint_field):
290
if S.codomain() == self:
291
return S
292
else:
293
return self.point(S)
294
return self.point(args)
295
296
@cached_method
297
def point_homset(self, S = None):
298
"""
299
Return the set of S-valued points of this scheme.
300
301
INPUT:
302
303
- ``S`` -- a commutative ring.
304
305
OUTPUT:
306
307
The set of morphisms `Spec(S)\to X`.
308
309
EXAMPLES::
310
311
sage: P = ProjectiveSpace(ZZ, 3)
312
sage: P.point_homset(ZZ)
313
Set of rational points of Projective Space of dimension 3 over Integer Ring
314
sage: P.point_homset(QQ)
315
Set of rational points of Projective Space of dimension 3 over Rational Field
316
sage: P.point_homset(GF(11))
317
Set of rational points of Projective Space of dimension 3 over
318
Finite Field of size 11
319
320
TESTS::
321
322
sage: P = ProjectiveSpace(QQ,3)
323
sage: P.point_homset(GF(11))
324
Traceback (most recent call last):
325
...
326
ValueError: There must be a natural map S --> R, but
327
S = Rational Field and R = Finite Field of size 11
328
"""
329
if S is None:
330
S = self.base_ring()
331
from sage.schemes.generic.spec import Spec
332
SpecS = Spec(S, self.base_ring())
333
from sage.schemes.generic.homset import SchemeHomset
334
return SchemeHomset(SpecS, self)
335
336
def point(self, v, check=True):
337
"""
338
Create a point.
339
340
INPUT:
341
342
- ``v`` -- anything that defines a point.
343
344
- ``check`` -- boolean (optional, default=``True``). Whether
345
to check the defining data for consistency.
346
347
OUTPUT:
348
349
A point of the scheme.
350
351
EXAMPLES::
352
353
sage: A2 = AffineSpace(QQ,2)
354
sage: A2.point([4,5])
355
(4, 5)
356
"""
357
# todo: update elliptic curve stuff to take point_homset as argument
358
from sage.schemes.elliptic_curves.ell_generic import is_EllipticCurve
359
if is_EllipticCurve(self):
360
return self._point(self, v, check=check)
361
362
return self.point_homset() (v, check=check)
363
364
def _point(self):
365
"""
366
Return the Hom-set from some affine scheme to ``self``.
367
368
OUTPUT:
369
370
A scheme Hom-set, see :mod:`~sage.schemes.generic.homset`.
371
372
EXAMPLES::
373
374
sage: X = Spec(QQ)
375
sage: X._point()
376
Traceback (most recent call last):
377
...
378
NotImplementedError
379
"""
380
raise NotImplementedError
381
382
def _point_homset(self, *args, **kwds):
383
"""
384
Return the Hom-set from ``self`` to another scheme.
385
386
EXAMPLES::
387
388
sage: from sage.schemes.generic.scheme import Scheme
389
sage: X = Scheme(QQ)
390
sage: X._point_homset()
391
Traceback (most recent call last):
392
...
393
NotImplementedError
394
"""
395
raise NotImplementedError
396
397
def __div__(self, Y):
398
"""
399
Return the base extension of self to Y.
400
401
See :meth:`base_extend` for details.
402
403
EXAMPLES::
404
405
sage: A = AffineSpace(3, ZZ)
406
sage: A
407
Affine Space of dimension 3 over Integer Ring
408
sage: A/QQ
409
Affine Space of dimension 3 over Rational Field
410
sage: A/GF(7)
411
Affine Space of dimension 3 over Finite Field of size 7
412
"""
413
return self.base_extend(Y)
414
415
def base_ring(self):
416
"""
417
Return the base ring of the scheme self.
418
419
OUTPUT:
420
421
A commutative ring.
422
423
EXAMPLES::
424
425
sage: A = AffineSpace(4, QQ)
426
sage: A.base_ring()
427
Rational Field
428
429
sage: X = Spec(QQ)
430
sage: X.base_ring()
431
Integer Ring
432
"""
433
try:
434
return self._base_ring
435
except AttributeError:
436
if hasattr(self, '_base_morphism'):
437
self._base_ring = self._base_morphism.codomain().coordinate_ring()
438
elif hasattr(self, '_base_scheme'):
439
self._base_ring = self._base_scheme.coordinate_ring()
440
else:
441
self._base_ring = ZZ
442
return self._base_ring
443
444
def base_scheme(self):
445
"""
446
Return the base scheme.
447
448
OUTPUT:
449
450
A scheme.
451
452
EXAMPLES::
453
454
sage: A = AffineSpace(4, QQ)
455
sage: A.base_scheme()
456
Spectrum of Rational Field
457
458
sage: X = Spec(QQ)
459
sage: X.base_scheme()
460
Spectrum of Integer Ring
461
"""
462
try:
463
return self._base_scheme
464
except AttributeError:
465
if hasattr(self, '_base_morphism'):
466
self._base_scheme = self._base_morphism.codomain()
467
elif hasattr(self, '_base_ring'):
468
from sage.schemes.generic.spec import Spec
469
self._base_scheme = Spec(self._base_ring)
470
else:
471
from sage.schemes.generic.spec import SpecZ
472
self._base_scheme = SpecZ
473
return self._base_scheme
474
475
def base_morphism(self):
476
"""
477
Return the structure morphism from ``self`` to its base
478
scheme.
479
480
OUTPUT:
481
482
A scheme morphism.
483
484
EXAMPLES::
485
486
sage: A = AffineSpace(4, QQ)
487
sage: A.base_morphism()
488
Scheme morphism:
489
From: Affine Space of dimension 4 over Rational Field
490
To: Spectrum of Rational Field
491
Defn: Structure map
492
493
sage: X = Spec(QQ)
494
sage: X.base_morphism()
495
Scheme morphism:
496
From: Spectrum of Rational Field
497
To: Spectrum of Integer Ring
498
Defn: Structure map
499
"""
500
try:
501
return self._base_morphism
502
except AttributeError:
503
from sage.categories.schemes import Schemes
504
from sage.schemes.generic.spec import Spec, SpecZ
505
SCH = Schemes()
506
if hasattr(self, '_base_scheme'):
507
self._base_morphism = self.Hom(self._base_scheme, category=SCH).natural_map()
508
elif hasattr(self, '_base_ring'):
509
self._base_morphism = self.Hom(Spec(self._base_ring), category=SCH).natural_map()
510
else:
511
self._base_morphism = self.Hom(SpecZ, category=SCH).natural_map()
512
return self._base_morphism
513
514
structure_morphism = base_morphism
515
516
def coordinate_ring(self):
517
"""
518
Return the coordinate ring.
519
520
OUTPUT:
521
522
The global coordinate ring of this scheme, if
523
defined. Otherwise raise a ``ValueError``.
524
525
EXAMPLES::
526
527
sage: R.<x, y> = QQ[]
528
sage: I = (x^2 - y^2)*R
529
sage: X = Spec(R.quotient(I))
530
sage: X.coordinate_ring()
531
Quotient of Multivariate Polynomial Ring in x, y over Rational Field by the ideal (x^2 - y^2)
532
"""
533
try:
534
return self._coordinate_ring
535
except AttributeError:
536
raise ValueError, "This scheme has no associated coordinated ring (defined)."
537
538
def dimension_absolute(self):
539
"""
540
Return the absolute dimension of this scheme.
541
542
OUTPUT:
543
544
Integer.
545
546
EXAMPLES::
547
548
sage: R.<x, y> = QQ[]
549
sage: I = (x^2 - y^2)*R
550
sage: X = Spec(R.quotient(I))
551
sage: X.dimension_absolute()
552
Traceback (most recent call last):
553
...
554
NotImplementedError
555
sage: X.dimension()
556
Traceback (most recent call last):
557
...
558
NotImplementedError
559
"""
560
raise NotImplementedError # override in derived class
561
562
dimension = dimension_absolute
563
564
def dimension_relative(self):
565
"""
566
Return the relative dimension of this scheme over its base.
567
568
OUTPUT:
569
570
Integer.
571
572
EXAMPLES::
573
574
sage: R.<x, y> = QQ[]
575
sage: I = (x^2 - y^2)*R
576
sage: X = Spec(R.quotient(I))
577
sage: X.dimension_relative()
578
Traceback (most recent call last):
579
...
580
NotImplementedError
581
"""
582
raise NotImplementedError # override in derived class
583
584
def identity_morphism(self):
585
"""
586
Return the identity morphism.
587
588
OUTPUT:
589
590
The identity morphism of the scheme ``self``.
591
592
EXAMPLES::
593
594
sage: X = Spec(QQ)
595
sage: X.identity_morphism()
596
Scheme endomorphism of Spectrum of Rational Field
597
Defn: Identity map
598
"""
599
from sage.schemes.generic.morphism import SchemeMorphism_id
600
return SchemeMorphism_id(self)
601
602
def hom(self, x, Y=None, check=True):
603
"""
604
Return the scheme morphism from ``self`` to ``Y`` defined by ``x``.
605
606
INPUT:
607
608
- ``x`` -- anything hat determines a scheme morphism. If ``x``
609
is a scheme, try to determine a natural map to ``x``.
610
611
- ``Y`` -- the codomain scheme (optional). If ``Y`` is not
612
given, try to determine ``Y`` from context.
613
614
- ``check`` -- boolean (optional, default=``True``). Whether
615
to check the defining data for consistency.
616
617
OUTPUT:
618
619
The scheme morphism from ``self`` to ``Y`` defined by ``x``.
620
621
EXAMPLES::
622
623
sage: P = ProjectiveSpace(ZZ, 3)
624
sage: P.hom(Spec(ZZ))
625
Scheme morphism:
626
From: Projective Space of dimension 3 over Integer Ring
627
To: Spectrum of Integer Ring
628
Defn: Structure map
629
"""
630
if Y is None:
631
if is_Scheme(x):
632
return self.Hom(x).natural_map()
633
else:
634
raise TypeError, "unable to determine codomain"
635
return self.Hom(Y)(x, check)
636
637
def _Hom_(self, Y, category=None, check=True):
638
"""
639
Return the set of scheme morphisms from ``self`` to ``Y``.
640
641
INPUT:
642
643
- ``Y`` -- a scheme. The codomain of the Hom-set.
644
645
- ``category`` -- a category (optional). The category of the
646
Hom-set.
647
648
- ``check`` -- boolean (optional, default=``True``). Whether
649
to check the defining data for consistency.
650
651
OUTPUT:
652
653
The set of morphisms from ``self`` to ``Y``.
654
655
EXAMPLES::
656
657
sage: P = ProjectiveSpace(ZZ, 3)
658
sage: S = Spec(ZZ)
659
sage: S._Hom_(P)
660
Set of rational points of Projective Space of dimension 3 over Integer Ring
661
"""
662
from sage.schemes.generic.homset import SchemeHomset
663
return SchemeHomset(self, Y, category=category, check=check)
664
665
point_set = point_homset
666
667
def count_points(self, n):
668
r"""
669
Count points over finite fields.
670
671
INPUT:
672
673
- ``n`` -- integer.
674
675
OUTPUT:
676
677
An integer. The number of points over `\GF{q}, \ldots,
678
\GF{q^n}` on a scheme over a finite field `\GF{q}`.
679
680
.. note::
681
682
This is currently only implemented for schemes over prime
683
order finite fields.
684
685
EXAMPLES::
686
687
sage: P.<x> = PolynomialRing(GF(3))
688
sage: C = HyperellipticCurve(x^3+x^2+1)
689
sage: C.count_points(4)
690
[6, 12, 18, 96]
691
sage: C.base_extend(GF(9,'a')).count_points(2)
692
Traceback (most recent call last):
693
...
694
NotImplementedError: Point counting only implemented for schemes over prime fields
695
"""
696
F = self.base_ring()
697
if not F.is_finite():
698
raise TypeError, "Point counting only defined for schemes over finite fields"
699
q = F.cardinality()
700
if not q.is_prime():
701
raise NotImplementedError, "Point counting only implemented for schemes over prime fields"
702
a = []
703
for i in range(1, n+1):
704
F1 = GF(q**i, name='z')
705
S1 = self.base_extend(F1)
706
a.append(len(S1.rational_points()))
707
return(a)
708
709
def zeta_series(self, n, t):
710
"""
711
Return the zeta series.
712
713
Compute a power series approximation to the zeta function of a
714
scheme over a finite field.
715
716
INPUT:
717
718
- ``n`` - the number of terms of the power series to
719
compute
720
721
- ``t`` - the variable which the series should be
722
returned
723
724
725
OUTPUT:
726
727
A power series approximating the zeta function of self
728
729
EXAMPLES::
730
731
sage: P.<x> = PolynomialRing(GF(3))
732
sage: C = HyperellipticCurve(x^3+x^2+1)
733
sage: R.<t> = PowerSeriesRing(Integers())
734
sage: C.zeta_series(4,t)
735
1 + 6*t + 24*t^2 + 78*t^3 + 240*t^4 + O(t^5)
736
sage: (1+2*t+3*t^2)/(1-t)/(1-3*t) + O(t^5)
737
1 + 6*t + 24*t^2 + 78*t^3 + 240*t^4 + O(t^5)
738
739
Note that this function depends on count_points, which is only
740
defined for prime order fields::
741
742
sage: C.base_extend(GF(9,'a')).zeta_series(4,t)
743
Traceback (most recent call last):
744
...
745
NotImplementedError: Point counting only implemented for schemes over prime fields
746
"""
747
748
F = self.base_ring()
749
if not F.is_finite():
750
raise TypeError, "Zeta functions only defined for schemes over finite fields"
751
a = self.count_points(n)
752
R = PowerSeriesRing(Rationals(), 'u')
753
u = R.gen()
754
temp = sum(a[i-1]*(u.O(n+1))**i/i for i in range(1,n+1))
755
temp2 = temp.exp()
756
return(temp2(t).O(n+1))
757
758
def is_AffineScheme(x):
759
"""
760
Return True if `x` is an affine scheme.
761
762
EXAMPLES::
763
764
sage: from sage.schemes.generic.scheme import is_AffineScheme
765
sage: is_AffineScheme(5)
766
False
767
sage: E = Spec(QQ)
768
sage: is_AffineScheme(E)
769
True
770
"""
771
return isinstance(x, AffineScheme)
772
773
class AffineScheme(Scheme):
774
"""
775
An abstract affine scheme.
776
"""
777
def hom(self, x, Y=None):
778
r"""
779
Return the scheme morphism from ``self`` to ``Y`` defined by ``x``.
780
781
INPUT:
782
783
- ``x`` -- anything hat determines a scheme morphism. If ``x``
784
is a scheme, try to determine a natural map to ``x``.
785
786
- ``Y`` -- the codomain scheme (optional). If ``Y`` is not
787
given, try to determine ``Y`` from context.
788
789
- ``check`` -- boolean (optional, default=``True``). Whether
790
to check the defining data for consistency.
791
792
OUTPUT:
793
794
The scheme morphism from ``self`` to ``Y`` defined by ``x``.
795
796
EXAMPLES:
797
798
We construct the inclusion from `\mathrm{Spec}(\QQ)` into
799
`\mathrm{Spec}(\ZZ)` induced by the inclusion from `\ZZ` into
800
`\QQ`::
801
802
sage: X = Spec(QQ)
803
sage: X.hom(ZZ.hom(QQ))
804
Affine Scheme morphism:
805
From: Spectrum of Rational Field
806
To: Spectrum of Integer Ring
807
Defn: Ring Coercion morphism:
808
From: Integer Ring
809
To: Rational Field
810
"""
811
if is_Scheme(x):
812
return self.Hom(x).natural_map()
813
if Y is None:
814
if is_RingHomomorphism(x):
815
import spec
816
Y = spec.Spec(x.domain())
817
return Scheme.hom(self, x, Y)
818
819