Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
sagemath
GitHub Repository: sagemath/sagelib
Path: blob/master/sage/schemes/generic/divisor.py
4079 views
1
"""
2
Divisors on schemes
3
4
AUTHORS:
5
6
- William Stein
7
8
- David Kohel
9
10
- David Joyner
11
12
- Volker Braun (2010-07-16): Documentation, doctests, coercion fixes, bugfixes.
13
14
EXAMPLES::
15
16
sage: x,y,z = ProjectiveSpace(2, GF(5), names='x,y,z').gens()
17
sage: C = Curve(y^2*z^7 - x^9 - x*z^8)
18
sage: pts = C.rational_points(); pts
19
[(0 : 0 : 1), (0 : 1 : 0), (2 : 2 : 1), (2 : 3 : 1), (3 : 1 : 1), (3 : 4 : 1)]
20
sage: D1 = C.divisor(pts[0])*3
21
sage: D2 = C.divisor(pts[1])
22
sage: D3 = 10*C.divisor(pts[5])
23
sage: D1.parent() is D2.parent()
24
True
25
sage: D = D1 - D2 + D3; D
26
-(x, z) + 3*(x, y) + 10*(x + 2*z, y + z)
27
sage: D[1][0]
28
3
29
sage: D[1][1]
30
Ideal (x, y) of Multivariate Polynomial Ring in x, y, z over Finite Field of size 5
31
sage: C.divisor([(3, pts[0]), (-1, pts[1]), (10,pts[5])])
32
-(x, z) + 3*(x, y) + 10*(x + 2*z, y + z)
33
"""
34
#*******************************************************************************
35
# Copyright (C) 2010 Volker Braun <[email protected]>
36
# Copyright (C) 2005 David Kohel <[email protected]>
37
# Copyright (C) 2005 William Stein
38
#
39
# Distributed under the terms of the GNU General Public License (GPL)
40
# http://www.gnu.org/licenses/
41
#*******************************************************************************
42
43
from sage.misc.all import latex
44
from sage.misc.misc import repr_lincomb
45
from sage.misc.search import search
46
from sage.rings.all import ZZ
47
from sage.structure.formal_sum import FormalSum
48
49
from morphism import is_SchemeMorphism
50
from affine_space import is_AffineSpace
51
from projective_space import is_ProjectiveSpace
52
53
54
def CurvePointToIdeal(C,P):
55
r"""
56
Return the vanishing ideal of a point on a curve.
57
58
EXAMPLES::
59
60
sage: x,y = AffineSpace(2, QQ, names='xy').gens()
61
sage: C = Curve(y^2 - x^9 - x)
62
sage: from sage.schemes.generic.divisor import CurvePointToIdeal
63
sage: CurvePointToIdeal(C, (0,0))
64
Ideal (x, y) of Multivariate Polynomial Ring in x, y over Rational Field
65
"""
66
A = C.ambient_space()
67
R = A.coordinate_ring()
68
n = A.ngens()
69
x = A.gens()
70
polys = [ ]
71
m = n-1
72
while m > 0 and P[m] == 0:
73
m += -1
74
if is_ProjectiveSpace(A):
75
a_m = P[m]
76
x_m = x[m]
77
for i in range(m):
78
ai = P[i]
79
if ai == 0:
80
polys.append(x[i])
81
else:
82
polys.append(a_m*x[i]-ai*x_m)
83
elif is_AffineSpace(A):
84
for i in range(m+1):
85
ai = P[i]
86
if ai == 0:
87
polys.append(x[i])
88
else:
89
polys.append(x[i]-ai)
90
for i in range(m+1,n):
91
polys.append(x[i])
92
return R.ideal(polys)
93
94
95
def is_Divisor(x):
96
r"""
97
Test whether ``x`` is an instance of :class:`Divisor_generic`
98
99
INPUT:
100
101
- ``x`` -- anything.
102
103
OUTPUT:
104
105
``True`` or ``False``.
106
107
EXAMPLES::
108
109
sage: from sage.schemes.generic.divisor import is_Divisor
110
sage: x,y = AffineSpace(2, GF(5), names='xy').gens()
111
sage: C = Curve(y^2 - x^9 - x)
112
sage: is_Divisor( C.divisor([]) )
113
True
114
sage: is_Divisor("Ceci n'est pas un diviseur")
115
False
116
"""
117
return isinstance(x, Divisor_generic)
118
119
120
class Divisor_generic(FormalSum):
121
r"""
122
A Divisor.
123
"""
124
125
def __init__(self, v, parent, check=True, reduce=True):
126
r"""
127
Construct a :class:`Divisor_generic`.
128
129
INPUT:
130
131
INPUT:
132
133
- ``v`` -- object. Usually a list of pairs
134
``(coefficient,divisor)``.
135
136
- ``parent`` -- FormalSums(R) module (default: FormalSums(ZZ))
137
138
- ``check`` -- bool (default: True). Whether to coerce
139
coefficients into base ring. Setting it to ``False`` can
140
speed up construction.
141
142
- ``reduce`` -- reduce (default: True). Whether to combine
143
common terms. Setting it to ``False`` can speed up
144
construction.
145
146
.. WARNING::
147
148
The coefficients of the divisor must be in the base ring
149
and the terms must be reduced. If you set ``check=False``
150
and/or ``reduce=False`` it is your responsibility to pass
151
a valid object ``v``.
152
153
EXAMPLES::
154
155
sage: from sage.schemes.generic.divisor import Divisor_generic
156
sage: from sage.schemes.generic.divisor_group import DivisorGroup
157
sage: Divisor_generic( [(4,5)], DivisorGroup(Spec(ZZ)), False, False)
158
4*V(5)
159
"""
160
FormalSum.__init__(self, v, parent, check, reduce)
161
162
def _latex_(self):
163
r"""
164
Return a LaTeX representation of ``self``.
165
166
OUTPUT:
167
168
- string.
169
170
TESTS::
171
172
sage: R.<x, y> = ZZ[]
173
sage: S = Spec(R)
174
sage: from sage.schemes.generic.divisor import Divisor_generic
175
sage: from sage.schemes.generic.divisor_group import DivisorGroup
176
sage: Div = DivisorGroup(S)
177
sage: D = Divisor_generic([(4, x), (-5, y), (1, x+2*y)], Div)
178
sage: D._latex_()
179
'\\mathrm{V}\\left(x + 2 y\\right)
180
+ 4\\mathrm{V}\\left(x\\right)
181
+ \\left(-5\\right)\\mathrm{V}\\left(y\\right)'
182
"""
183
# The code is copied from _repr_ with latex adjustments
184
terms = list(self)
185
# We sort the terms by variety. The order is "reversed" to keep it
186
# straight - as the test above demonstrates, it results in the first
187
# generator being in front of the second one
188
terms.sort(key=lambda x: x[1], reverse=True)
189
return repr_lincomb([(r"\mathrm{V}\left(%s\right)" % latex(v), c) for c,v in terms],
190
is_latex=True)
191
192
def _repr_(self):
193
r"""
194
Return a string representation of ``self``.
195
196
OUTPUT:
197
198
- string.
199
200
TESTS::
201
202
sage: R.<x, y> = ZZ[]
203
sage: S = Spec(R)
204
sage: from sage.schemes.generic.divisor import Divisor_generic
205
sage: from sage.schemes.generic.divisor_group import DivisorGroup
206
sage: Div = DivisorGroup(S)
207
sage: D = Divisor_generic([(4, x), (-5, y), (1, x+2*y)], Div)
208
sage: D._repr_()
209
'V(x + 2*y) + 4*V(x) - 5*V(y)'
210
"""
211
# The default representation coming from formal sums does not look
212
# very nice for divisors
213
terms = list(self)
214
# We sort the terms by variety. The order is "reversed" to keep it
215
# straight - as the test above demonstrates, it results in the first
216
# generator being in front of the second one
217
terms.sort(key=lambda x: x[1], reverse=True)
218
return repr_lincomb([("V(%s)" % v, c) for c,v in terms])
219
220
def scheme(self):
221
"""
222
Return the scheme that this divisor is on.
223
224
EXAMPLES::
225
226
sage: A.<x, y> = AffineSpace(2, GF(5))
227
sage: C = Curve(y^2 - x^9 - x)
228
sage: pts = C.rational_points(); pts
229
[(0, 0), (2, 2), (2, 3), (3, 1), (3, 4)]
230
sage: D = C.divisor(pts[0])*3 - C.divisor(pts[1]); D
231
3*(x, y) - (x - 2, y - 2)
232
sage: D.scheme()
233
Affine Curve over Finite Field of size 5 defined by -x^9 + y^2 - x
234
"""
235
return self.parent().scheme()
236
237
238
class Divisor_curve(Divisor_generic):
239
r"""
240
For any curve `C`, use ``C.divisor(v)`` to
241
construct a divisor on `C`. Here `v` can be either
242
243
244
- a rational point on `C`
245
246
- a list of rational points
247
248
- a list of 2-tuples `(c,P)`, where `c` is an
249
integer and `P` is a rational point.
250
251
252
TODO: Divisors shouldn't be restricted to rational points. The
253
problem is that the divisor group is the formal sum of the group of
254
points on the curve, and there's no implemented notion of point on
255
`E/K` that has coordinates in `L`. This is what
256
should be implemented, by adding an appropriate class to
257
``schemes/generic/morphism.py``.
258
259
EXAMPLES::
260
261
sage: E = EllipticCurve([0, 0, 1, -1, 0])
262
sage: P = E(0,0)
263
sage: 10*P
264
(161/16 : -2065/64 : 1)
265
sage: D = E.divisor(P)
266
sage: D
267
(x, y)
268
sage: 10*D
269
10*(x, y)
270
sage: E.divisor([P, P])
271
2*(x, y)
272
sage: E.divisor([(3,P), (-4,5*P)])
273
3*(x, y) - 4*(x - 1/4*z, y + 5/8*z)
274
"""
275
def __init__(self, v, parent=None, check=True, reduce=True):
276
"""
277
Construct a divisor on a curve.
278
279
INPUT:
280
281
- ``v`` -- a list of pairs ``(c, P)``, where ``c`` is an
282
integer and ``P`` is a point on a curve. The P's must all
283
lie on the same curve.
284
285
286
- To create the divisor 0 use ``[(0, P)]``, so as to give the curve.
287
288
EXAMPLES::
289
290
sage: E = EllipticCurve([0, 0, 1, -1, 0])
291
sage: P = E(0,0)
292
sage: from sage.schemes.generic.divisor import Divisor_curve
293
sage: from sage.schemes.generic.divisor_group import DivisorGroup
294
sage: Divisor_curve([(1,P)], parent=DivisorGroup(E))
295
(x, y)
296
"""
297
from sage.schemes.generic.divisor_group import DivisorGroup_generic, DivisorGroup_curve
298
if not isinstance(v, (list, tuple)):
299
v = [(1,v)]
300
301
if parent is None:
302
if len(v) > 0:
303
t = v[0]
304
if isinstance(t, tuple) and len(t) == 2:
305
try:
306
C = t[1].scheme()
307
except (TypeError, AttributeError):
308
raise TypeError, \
309
"Argument v (= %s) must consist of multiplicities and points on a scheme."
310
else:
311
try:
312
C = t.scheme()
313
except TypeError:
314
raise TypeError, \
315
"Argument v (= %s) must consist of multiplicities and points on a scheme."
316
parent = DivisorGroup(C)
317
else:
318
raise TypeError, \
319
"Argument v (= %s) must consist of multiplicities and points on a scheme."
320
else:
321
if not isinstance(parent, DivisorGroup_curve):
322
raise TypeError, "parent (of type %s) must be a DivisorGroup_curve"%type(parent)
323
C = parent.scheme()
324
325
if len(v) < 1:
326
check = False
327
know_points = False
328
if check:
329
w = []
330
points = []
331
know_points = True
332
for t in v:
333
if isinstance(t, tuple) and len(t) == 2:
334
n = ZZ(t[0])
335
I = t[1]
336
points.append((n,I))
337
else:
338
n = ZZ(1)
339
I = t
340
if is_SchemeMorphism(I):
341
I = CurvePointToIdeal(C,I)
342
else:
343
know_points = False
344
w.append((n,I))
345
v = w
346
Divisor_generic.__init__(
347
self, v, check=False, reduce=True, parent=parent)
348
349
if know_points:
350
self._points = points
351
352
def _repr_(self):
353
r"""
354
Return a string representation.
355
356
OUTPUT:
357
358
A string.
359
360
EXAMPLES::
361
362
sage: E = EllipticCurve([0, 0, 1, -1, 0])
363
sage: E.divisor( E(0,0) )._repr_()
364
'(x, y)'
365
"""
366
return repr_lincomb([(tuple(I.gens()), c) for c, I in self])
367
368
def support(self):
369
"""
370
Return the support of this divisor, which is the set of points that
371
occur in this divisor with nonzero coefficients.
372
373
EXAMPLES::
374
375
sage: x,y = AffineSpace(2, GF(5), names='xy').gens()
376
sage: C = Curve(y^2 - x^9 - x)
377
sage: pts = C.rational_points(); pts
378
[(0, 0), (2, 2), (2, 3), (3, 1), (3, 4)]
379
sage: D = C.divisor_group()([(3,pts[0]), (-1, pts[1])]); D
380
3*(x, y) - (x - 2, y - 2)
381
sage: D.support()
382
[(0, 0), (2, 2)]
383
"""
384
try:
385
return self._support
386
except AttributeError:
387
try:
388
self._support = [s[1] for s in self._points]
389
return self._support
390
except AttributeError:
391
raise NotImplementedError
392
393
def coefficient(self, P):
394
"""
395
Return the coefficient of a given point P in this divisor.
396
397
EXAMPLES::
398
399
sage: x,y = AffineSpace(2, GF(5), names='xy').gens()
400
sage: C = Curve(y^2 - x^9 - x)
401
sage: pts = C.rational_points(); pts
402
[(0, 0), (2, 2), (2, 3), (3, 1), (3, 4)]
403
sage: D = C.divisor(pts[0])
404
sage: D.coefficient(pts[0])
405
1
406
sage: D = C.divisor([(3,pts[0]), (-1,pts[1])]); D
407
3*(x, y) - (x - 2, y - 2)
408
sage: D.coefficient(pts[0])
409
3
410
sage: D.coefficient(pts[1])
411
-1
412
"""
413
P = self.parent().scheme()(P)
414
if not(P in self.support()):
415
return self.base_ring().zero()
416
t, i = search(self.support(), P)
417
assert t
418
try:
419
return self._points[i][0]
420
except AttributeError:
421
raise NotImplementedError
422
423
def coef(self,P):
424
r"""
425
Synonym for :meth:`coefficient`
426
427
.. WARNING::
428
429
This method is deprecated. It will be removed in a future
430
release of Sage. Please use the ``coefficient(P)`` method
431
instead.
432
433
EXAMPLES::
434
435
sage: x,y = AffineSpace(2, GF(5), names='xy').gens()
436
sage: C = Curve(y^2 - x^9 - x)
437
sage: pts = C.rational_points(); pts
438
[(0, 0), (2, 2), (2, 3), (3, 1), (3, 4)]
439
sage: D = C.divisor(pts[0])
440
sage: D.coefficient(pts[0])
441
1
442
"""
443
from sage.misc.misc import deprecation
444
deprecation("This method is deprecated. It will be removed in a future release of Sage. Please use the coefficient() method instead.")
445
return self.coefficient(P)
446
447
448
449