Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
sagemath
GitHub Repository: sagemath/sagelib
Path: blob/master/sage/schemes/elliptic_curves/ell_egros.py
4159 views
1
"""
2
Construction of elliptic curves with good reduction outside a finite
3
set of primes
4
5
A theorem of Shafarevich states that, over a number field `K`, given
6
any finite set `S` of primes of `K`, there are (up to isomorphism)
7
only a finite set of elliptic curves defined over `K` with good
8
reduction at all primes outside `S`. An explicit form of the theorem
9
with an algorithm for finding this finite set was given in "Finding
10
all elliptic curves with good reduction outside a given set of primes"
11
by John Cremona and Mark Lingham, Experimental Mathematics 16 No.3
12
(2007), 303-312. The method requires computation of the class and
13
unit groups of `K` as well as all the `S`-integral points on a
14
collection of auxiliary elliptic curves defined over `K`.
15
16
This implementation (April 2009) is only for the case `K=\Q`, where in
17
many cases the determination of the necessary sets of `S`-integral
18
points is possible. The main user-level function is
19
EllipticCurves_with_good_reduction_outside_S(), defined in
20
constrictor.py. Users should note carefully the following points:
21
22
(1) the number of auxiliary curves to be considered is exponential in
23
the size of `S` (specifically, `2.6**s` where `s=|S|`).
24
25
(2) For some of the auxiliary curves it is impossible at present to
26
provably find all the `S`-integral points using the current
27
algorithms, which rely on first finding a basis for their Mordell-Weil
28
groups using 2-descent. A warning is output in cases where the set of
29
points (and hence the final output) is not guaranteed to be complete.
30
Using the "proof=False" flag suppresses these warnings.
31
32
EXAMPLES: We find all elliptic curves with good reduction outside 2,
33
listing the label of each:
34
35
sage: [e.label() for e in EllipticCurves_with_good_reduction_outside_S([2])]
36
['32a1',
37
'32a2',
38
'32a3',
39
'32a4',
40
'64a1',
41
'64a2',
42
'64a3',
43
'64a4',
44
'128a1',
45
'128a2',
46
'128b1',
47
'128b2',
48
'128c1',
49
'128c2',
50
'128d1',
51
'128d2',
52
'256a1',
53
'256a2',
54
'256b1',
55
'256b2',
56
'256c1',
57
'256c2',
58
'256d1',
59
'256d2']
60
61
Secondly we try the same with `S={11}`; note that warning messages are
62
printed without proof=False (unless the optional database is
63
installed: two of the auxiliary curves whose Mordell-Weil bases are
64
required have conductors 13068 and 52272 so are in the database)::
65
66
sage: [e.label() for e in EllipticCurves_with_good_reduction_outside_S([11], proof=False)] # long time (13s on sage.math, 2011)
67
['11a1', '11a2', '11a3', '121a1', '121a2', '121b1', '121b2', '121c1', '121c2', '121d1', '121d2', '121d3']
68
69
70
AUTHORS:
71
* John Cremona (6 April 2009): initial version (over Q only).
72
"""
73
74
#*****************************************************************************
75
# Copyright (C) 2009 John Cremona <[email protected]>
76
#
77
# Distributed under the terms of the GNU General Public License (GPL)
78
#
79
# This code is distributed in the hope that it will be useful,
80
# but WITHOUT ANY WARRANTY; without even the implied warranty of
81
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
82
# General Public License for more details.
83
#
84
# The full text of the GPL is available at:
85
#
86
# http://www.gnu.org/licenses/
87
#*****************************************************************************
88
89
from sage.misc.misc import prod
90
from sage.misc.all import xmrange
91
from sage.rings.all import QQ
92
from constructor import EllipticCurve, EllipticCurve_from_j
93
94
def is_possible_j(j,S=[]):
95
r"""
96
Tests if the rational `j` is a possible `j`-invariant of an
97
elliptic curve with good reduction outside `S`.
98
99
.. note::
100
101
The condition used is necessary but not sufficient unless S
102
contains both 2 and 3.
103
104
EXAMPLES::
105
sage: from sage.schemes.elliptic_curves.ell_egros import is_possible_j
106
sage: is_possible_j(0,[])
107
False
108
sage: is_possible_j(1728,[])
109
True
110
sage: is_possible_j(-4096/11,[11])
111
True
112
"""
113
j = QQ(j)
114
return (j.is_zero() and 3 in S) \
115
or (j==1728) \
116
or (j.is_S_integral(S) \
117
and j.prime_to_S_part(S).is_nth_power(3) \
118
and (j-1728).prime_to_S_part(S).abs().is_square())
119
120
121
def curve_cmp(E1,E2):
122
r"""
123
Comparison function for elliptic curves over `Q`.
124
125
Order by label if in the database, else first by conductor, then
126
by c_invariants.
127
"""
128
t = cmp(E1.conductor(),E2.conductor())
129
if t:
130
return t
131
132
# Now they have the same conductor
133
try:
134
from sage.databases.cremona import parse_cremona_label, class_to_int
135
k1 = parse_cremona_label(E1.label())
136
k2 = parse_cremona_label(E2.label())
137
t = cmp(class_to_int(k1[1]),class_to_int(k2[1]))
138
if t:
139
return t
140
return cmp(k1[2],k2[2])
141
except RuntimeError: # if not in database, label() will fail
142
pass
143
144
return cmp(E1.ainvs(),E2.ainvs())
145
146
def egros_from_j_1728(S=[]):
147
r"""
148
Given a list of primes S, returns a list of elliptic curves over Q
149
with j-invariant 1728 and good reduction outside S, by checking
150
all relevant quartic twists.
151
152
INPUT:
153
154
- S - list of primes (default: empty list).
155
156
.. note::
157
158
Primality of elements of S is not checked, and the output
159
is undefined if S is not a list or contains non-primes.
160
161
OUTPUT:
162
163
A sorted list of all elliptic curves defined over `Q` with
164
`j`-invariant equal to `1728` and with good reduction at
165
all primes outside the list ``S``.
166
167
EXAMPLES::
168
169
sage: from sage.schemes.elliptic_curves.ell_egros import egros_from_j_1728
170
sage: egros_from_j_1728([])
171
[]
172
sage: egros_from_j_1728([3])
173
[]
174
sage: [e.cremona_label() for e in egros_from_j_1728([2])]
175
['32a1', '32a2', '64a1', '64a4', '256b1', '256b2', '256c1', '256c2']
176
177
"""
178
Elist=[]
179
no2 = not 2 in S
180
for ei in xmrange([2] + [4]*len(S)):
181
u = prod([p**e for p,e in zip([-1]+S,ei)],QQ(1))
182
if no2:
183
u*=4 ## make sure 12|val(D,2)
184
Eu = EllipticCurve([0,0,0,u,0]).minimal_model()
185
if Eu.has_good_reduction_outside_S(S):
186
Elist += [Eu]
187
Elist.sort(cmp=curve_cmp)
188
return Elist
189
190
def egros_from_j_0(S=[]):
191
r"""
192
Given a list of primes S, returns a list of elliptic curves over Q
193
with j-invariant 0 and good reduction outside S, by checking all
194
relevant sextic twists.
195
196
INPUT:
197
198
- S - list of primes (default: empty list).
199
200
.. note::
201
202
Primality of elements of S is not checked, and the output
203
is undefined if S is not a list or contains non-primes.
204
205
OUTPUT:
206
207
A sorted list of all elliptic curves defined over `Q` with
208
`j`-invariant equal to `0` and with good reduction at
209
all primes outside the list ``S``.
210
211
EXAMPLES::
212
213
sage: from sage.schemes.elliptic_curves.ell_egros import egros_from_j_0
214
sage: egros_from_j_0([])
215
[]
216
sage: egros_from_j_0([2])
217
[]
218
sage: [e.label() for e in egros_from_j_0([3])]
219
['27a1', '27a3', '243a1', '243a2', '243b1', '243b2']
220
sage: len(egros_from_j_0([2,3,5]))
221
432
222
"""
223
Elist=[]
224
if not 3 in S:
225
return Elist
226
no2 = not 2 in S
227
for ei in xmrange([2] + [6]*len(S)):
228
u = prod([p**e for p,e in zip([-1]+S,ei)],QQ(1))
229
if no2:
230
u*=16 ## make sure 12|val(D,2)
231
Eu = EllipticCurve([0,0,0,0,u]).minimal_model()
232
if Eu.has_good_reduction_outside_S(S):
233
Elist += [Eu]
234
Elist.sort(cmp=curve_cmp)
235
return Elist
236
237
def egros_from_j(j,S=[]):
238
r"""
239
Given a rational j and a list of primes S, returns a list of
240
elliptic curves over Q with j-invariant j and good reduction
241
outside S, by checking all relevant quadratic twists.
242
243
INPUT:
244
245
- j - a rational number.
246
247
- S - list of primes (default: empty list).
248
249
.. note::
250
251
Primality of elements of S is not checked, and the output
252
is undefined if S is not a list or contains non-primes.
253
254
OUTPUT:
255
256
A sorted list of all elliptic curves defined over `Q` with
257
`j`-invariant equal to `j` and with good reduction at
258
all primes outside the list ``S``.
259
260
EXAMPLES::
261
262
sage: from sage.schemes.elliptic_curves.ell_egros import egros_from_j
263
sage: [e.label() for e in egros_from_j(0,[3])]
264
['27a1', '27a3', '243a1', '243a2', '243b1', '243b2']
265
sage: [e.label() for e in egros_from_j(1728,[2])]
266
['32a1', '32a2', '64a1', '64a4', '256b1', '256b2', '256c1', '256c2']
267
sage: elist=egros_from_j(-4096/11,[11])
268
sage: [e.label() for e in elist]
269
['11a3', '121d1']
270
271
"""
272
if j == 1728:
273
return egros_from_j_1728(S)
274
275
if j == 0:
276
return egros_from_j_0(S)
277
278
# Now j != 0, 1728
279
280
E = EllipticCurve_from_j(j)
281
Elist=[]
282
283
for ei in xmrange([2]*(1+len(S))):
284
u = prod([p**e for p,e in zip(reversed([-1]+S),ei)],QQ(1))
285
Eu = E.quadratic_twist(u).minimal_model()
286
if Eu.has_good_reduction_outside_S(S):
287
Elist += [Eu]
288
289
Elist.sort(cmp=curve_cmp)
290
return Elist
291
292
def egros_from_jlist(jlist,S=[]):
293
r"""
294
Given a list of rational j and a list of primes S, returns a list
295
of elliptic curves over Q with j-invariant in the list and good
296
reduction outside S.
297
298
INPUT:
299
300
- j - list of rational numbers.
301
302
- S - list of primes (default: empty list).
303
304
.. note::
305
306
Primality of elements of S is not checked, and the output
307
is undefined if S is not a list or contains non-primes.
308
309
OUTPUT:
310
311
A sorted list of all elliptic curves defined over `Q` with
312
`j`-invariant in the list ``jlist`` and with good reduction at
313
all primes outside the list ``S``.
314
315
EXAMPLES::
316
317
sage: from sage.schemes.elliptic_curves.ell_egros import egros_get_j, egros_from_jlist
318
sage: jlist=egros_get_j([3])
319
sage: elist=egros_from_jlist(jlist,[3])
320
sage: [e.label() for e in elist]
321
['27a1', '27a2', '27a3', '27a4', '243a1', '243a2', '243b1', '243b2']
322
sage: [e.ainvs() for e in elist]
323
[(0, 0, 1, 0, -7),
324
(0, 0, 1, -270, -1708),
325
(0, 0, 1, 0, 0),
326
(0, 0, 1, -30, 63),
327
(0, 0, 1, 0, -1),
328
(0, 0, 1, 0, 20),
329
(0, 0, 1, 0, 2),
330
(0, 0, 1, 0, -61)]
331
"""
332
elist = sum([egros_from_j(j,S) for j in jlist],[])
333
elist.sort(cmp=curve_cmp)
334
return elist
335
336
def egros_get_j(S=[], proof=None, verbose=False):
337
r"""
338
Returns a list of rational `j` such that all elliptic curves
339
defined over `Q` with good reduction outside `S` have
340
`j`-invariant in the list, sorted by height.
341
342
INPUT:
343
344
- ``S`` - list of primes (default: empty list).
345
346
- ``proof`` - True/False (default True): the MW basis for
347
auxiliary curves will be computed with this proof flag.
348
349
- ``verbose`` - True/False (default False): if True, some
350
details of the computation will be output.
351
352
.. note::
353
354
Proof flag: The algorithm used requires determining all
355
S-integral points on several auxiliary curves, which in turn
356
requires the computation of their generators. This is not
357
always possible (even in theory) using current knowledge.
358
359
The value of this flag is passed to the function which
360
computes generators of various auxiliary elliptic curves, in
361
order to find their S-integral points. Set to False if the
362
default (True) causes warning messages, but note that you can
363
then not rely on the set of invariants returned being
364
complete.
365
366
EXAMPLES::
367
368
sage: from sage.schemes.elliptic_curves.ell_egros import egros_get_j
369
sage: egros_get_j([])
370
[1728]
371
sage: egros_get_j([2])
372
[128, 432, -864, 1728, 3375/2, -3456, 6912, 8000, 10976, -35937/4, 287496, -784446336, -189613868625/128]
373
sage: egros_get_j([3])
374
[0, -576, 1536, 1728, -5184, -13824, 21952/9, -41472, 140608/3, -12288000]
375
sage: jlist=egros_get_j([2,3]); len(jlist) # long time (30s)
376
83
377
378
"""
379
if not all([p.is_prime() for p in S]):
380
raise ValueError, "Elements of S must be prime."
381
382
if proof is None:
383
from sage.structure.proof.proof import get_flag
384
proof = get_flag(proof, "elliptic_curve")
385
else:
386
proof = bool(proof)
387
388
if verbose:
389
import sys # so we can flush stdout for debugging
390
391
SS = [-1] + S
392
393
jlist=[]
394
wcount=0
395
nw = 6**len(S) * 2
396
397
if verbose:
398
print "Finding possible j invariants for S = ",S
399
print "Using ", nw, " twists of base curve"
400
sys.stdout.flush()
401
402
for ei in xmrange([6]*len(S) + [2]):
403
w = prod([p**e for p,e in zip(reversed(SS),ei)],QQ(1))
404
wcount+=1
405
if verbose:
406
print "Curve #",wcount, "/",nw,":";
407
print "w = ",w,"=",w.factor()
408
sys.stdout.flush()
409
a6 = -1728*w
410
d2 = 0
411
d3 = 0
412
u0 = (2**d2)*(3**d3)
413
E = EllipticCurve([0,0,0,0,a6])
414
# This curve may not be minimal at 2 or 3, but the
415
# S-integral_points function requires minimality at primes in
416
# S, so we find a new model which is p-minimal at both 2 and 3
417
# if they are in S. Note that the isomorphism between models
418
# will preserve S-integrality of points.
419
E2 = E.local_minimal_model(2) if 2 in S else E
420
E23 = E2.local_minimal_model(3) if 3 in S else E2
421
urst = E23.isomorphism_to(E)
422
423
try:
424
pts = E23.S_integral_points(S,proof=proof)
425
except RuntimeError:
426
pts=[]
427
print "Failed to find S-integral points on ",E23.ainvs()
428
if proof:
429
if verbose:
430
print "--trying again with proof=False"
431
sys.stdout.flush()
432
pts = E23.S_integral_points(S,proof=False)
433
if verbose:
434
print "--done"
435
if verbose:
436
print len(pts), " S-integral points: ",pts
437
sys.stdout.flush()
438
for P in pts:
439
P = urst(P)
440
x = P[0]
441
y = P[1]
442
j = x**3 /w
443
assert j-1728 == y**2 /w
444
if is_possible_j(j,S):
445
if not j in jlist:
446
if verbose:
447
print "Adding possible j = ",j
448
sys.stdout.flush()
449
jlist += [j]
450
else:
451
if True: #verbose:
452
print "Discarding illegal j = ",j
453
sys.stdout.flush()
454
height_cmp = lambda j1,j2: cmp(j1.height(),j2.height())
455
jlist.sort(cmp=height_cmp)
456
return jlist
457
458
459