Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
sagemath
GitHub Repository: sagemath/sagelib
Path: blob/master/sage/schemes/elliptic_curves/BSD.py
4128 views
1
# -*- coding: utf-8 -*-
2
#import ell_point
3
#import formal_group
4
#import ell_torsion
5
#from ell_generic import EllipticCurve_generic, is_EllipticCurve
6
#from ell_number_field import EllipticCurve_number_field
7
8
#import sage.groups.all
9
import sage.rings.arith as arith
10
import sage.rings.all as rings
11
from sage.rings.all import ZZ, Infinity
12
from sage.functions.all import ceil
13
14
class BSD_data:
15
"""
16
Helper class used to keep track of information in proving BSD.
17
18
EXAMPLE::
19
20
sage: from sage.schemes.elliptic_curves.BSD import BSD_data
21
sage: D = BSD_data()
22
sage: D.Sha is None
23
True
24
sage: D.curve=EllipticCurve('11a')
25
sage: D.update()
26
sage: D.Sha
27
Tate-Shafarevich group for the Elliptic Curve defined by y^2 + y = x^3 - x^2 - 10*x - 20 over Rational Field
28
29
"""
30
def __init__(self):
31
self.curve = None
32
self.two_tor_rk = None
33
self.Sha = None
34
self.sha_an = None
35
self.N = None
36
37
self.rank = None
38
self.gens = None
39
self.bounds = {} # p : (low_bd, up_bd) bounds on ord_p(#sha)
40
self.primes = None # BSD(E,p) holds for odd primes p outside this set
41
self.heegner_indexes = {} # D : I_K, K = QQ(\sqrt(D))
42
self.heegner_index_upper_bound = {} # D : M, I_K <= M
43
self.N_factorization = None
44
self.proof = {}
45
46
def update(self):
47
"""
48
Updates some properties from ``curve``.
49
50
EXAMPLE::
51
52
sage: from sage.schemes.elliptic_curves.BSD import BSD_data
53
sage: D = BSD_data()
54
sage: D.Sha is None
55
True
56
sage: D.curve=EllipticCurve('11a')
57
sage: D.update()
58
sage: D.Sha
59
Tate-Shafarevich group for the Elliptic Curve defined by y^2 + y = x^3 - x^2 - 10*x - 20 over Rational Field
60
"""
61
self.two_tor_rk = self.curve.two_torsion_rank()
62
self.Sha = self.curve.sha()
63
self.sha_an = self.Sha.an(use_database=True)
64
self.N = self.curve.conductor()
65
66
def simon_two_descent_work(E, two_tor_rk):
67
"""
68
Prepares the output from Simon two-descent.
69
70
INPUT:
71
72
- ``E`` - an elliptic curve
73
74
- ``two_tor_rk`` - its two-torsion rank
75
76
OUTPUT:
77
78
- a lower bound on the rank
79
80
- an upper bound on the rank
81
82
- a lower bound on the rank of Sha[2]
83
84
- an upper bound on the rank of Sha[2]
85
86
- a list of the generators found
87
88
EXAMPLES::
89
90
sage: from sage.schemes.elliptic_curves.BSD import simon_two_descent_work
91
sage: E = EllipticCurve('14a')
92
sage: simon_two_descent_work(E, E.two_torsion_rank())
93
(0, 0, 0, 0, [])
94
sage: E = EllipticCurve('37a')
95
sage: simon_two_descent_work(E, E.two_torsion_rank())
96
(1, 1, 0, 0, [(0 : 0 : 1)])
97
98
"""
99
rank_lower_bd, two_sel_rk, gens = E.simon_two_descent()
100
rank_upper_bd = two_sel_rk - two_tor_rk
101
gens = [P for P in gens if P.additive_order() == Infinity]
102
return rank_lower_bd, rank_upper_bd, 0, rank_upper_bd - rank_lower_bd, gens
103
104
def mwrank_two_descent_work(E, two_tor_rk):
105
"""
106
Prepares the output from mwrank two-descent.
107
108
INPUT:
109
110
- ``E`` - an elliptic curve
111
112
- ``two_tor_rk`` - its two-torsion rank
113
114
OUTPUT:
115
116
- a lower bound on the rank
117
118
- an upper bound on the rank
119
120
- a lower bound on the rank of Sha[2]
121
122
- an upper bound on the rank of Sha[2]
123
124
- a list of the generators found
125
126
EXAMPLES::
127
128
sage: from sage.schemes.elliptic_curves.BSD import mwrank_two_descent_work
129
sage: E = EllipticCurve('14a')
130
sage: mwrank_two_descent_work(E, E.two_torsion_rank())
131
(0, 0, 0, 0, [])
132
sage: E = EllipticCurve('37a')
133
sage: mwrank_two_descent_work(E, E.two_torsion_rank())
134
(1, 1, 0, 0, [(0 : -1 : 1)])
135
136
"""
137
MWRC = E.mwrank_curve()
138
rank_upper_bd = MWRC.rank_bound()
139
rank_lower_bd = MWRC.rank()
140
gens = [E(P) for P in MWRC.gens()]
141
sha2_lower_bd = MWRC.selmer_rank() - two_tor_rk - rank_upper_bd
142
sha2_upper_bd = MWRC.selmer_rank() - two_tor_rk - rank_lower_bd
143
return rank_lower_bd, rank_upper_bd, sha2_lower_bd, sha2_upper_bd, gens
144
145
def native_two_isogeny_descent_work(E, two_tor_rk):
146
"""
147
Prepares the output from two-descent by two-isogeny.
148
149
INPUT:
150
151
- ``E`` - an elliptic curve
152
153
- ``two_tor_rk`` - its two-torsion rank
154
155
OUTPUT:
156
157
- a lower bound on the rank
158
159
- an upper bound on the rank
160
161
- a lower bound on the rank of Sha[2]
162
163
- an upper bound on the rank of Sha[2]
164
165
- a list of the generators found (currently None, since we don't store them)
166
167
EXAMPLES::
168
169
sage: from sage.schemes.elliptic_curves.BSD import native_two_isogeny_descent_work
170
sage: E = EllipticCurve('14a')
171
sage: native_two_isogeny_descent_work(E, E.two_torsion_rank())
172
(0, 0, 0, 0, None)
173
sage: E = EllipticCurve('65a')
174
sage: native_two_isogeny_descent_work(E, E.two_torsion_rank())
175
(1, 1, 0, 0, None)
176
177
"""
178
from sage.schemes.elliptic_curves.descent_two_isogeny import two_descent_by_two_isogeny
179
n1, n2, n1p, n2p = two_descent_by_two_isogeny(E)
180
# bring n1 and n1p up to the nearest power of two
181
two = ZZ(2) # otherwise "log" is symbolic >.<
182
e1 = ceil(ZZ(n1).log(two))
183
e1p = ceil(ZZ(n1p).log(two))
184
e2 = ZZ(n2).log(two)
185
e2p = ZZ(n2p).log(two)
186
rank_lower_bd = e1 + e1p - 2
187
rank_upper_bd = e2 + e2p - 2
188
sha_upper_bd = e2 + e2p - e1 - e1p
189
gens = None # right now, we are not keeping track of them
190
return rank_lower_bd, rank_upper_bd, 0, sha_upper_bd, gens
191
192
def heegner_index_work(E):
193
"""
194
Prepares the input and output for computing the heegner index.
195
196
INPUT:
197
198
- ``E`` - an elliptic curve
199
200
OUTPUT:
201
202
- a Heegner index
203
204
- the discriminant used
205
206
EXAMPLE::
207
208
sage: from sage.schemes.elliptic_curves.BSD import heegner_index_work
209
sage: heegner_index_work(EllipticCurve('14a'))
210
(1, -31)
211
212
"""
213
for D in E.heegner_discriminants_list(10):
214
I = None
215
while I is None:
216
dsl=15
217
try:
218
I = E.heegner_index(D, descent_second_limit=dsl)
219
except RuntimeError as err:
220
if err.args[0][-33:] == 'Generators not provably computed.':
221
dsl += 1
222
else: raise RuntimeError(err)
223
J = I.is_int()
224
if J[0] and J[1]>0:
225
I = J[1]
226
else:
227
J = (2*I).is_int()
228
if J[0] and J[1]>0:
229
I = J[1]
230
else:
231
I = None
232
if I is not None:
233
return I, D
234
235
236
def prove_BSD(E, verbosity=0, two_desc='mwrank', proof=None, secs_hi=5,
237
return_BSD=False):
238
r"""
239
Attempts to prove the Birch and Swinnerton-Dyer conjectural
240
formula for `E`, returning a list of primes `p` for which this
241
function fails to prove BSD(E,p). Here, BSD(E,p) is the
242
statement: "the Birch and Swinnerton-Dyer formula holds up to a
243
rational number coprime to `p`."
244
245
INPUT:
246
247
- ``E`` - an elliptic curve
248
249
- ``verbosity`` - int, how much information about the proof to print.
250
251
- 0 - print nothing
252
- 1 - print sketch of proof
253
- 2 - print information about remaining primes
254
255
- ``two_desc`` - string (default ``'mwrank'``), what to use for the
256
two-descent. Options are ``'mwrank', 'simon', 'sage'``
257
258
- ``proof`` - bool or None (default: None, see
259
proof.elliptic_curve or sage.structure.proof). If False, this
260
function just immediately returns the empty list.
261
262
- ``secs_hi`` - maximum number of seconds to try to compute the
263
Heegner index before switching over to trying to compute the
264
Heegner index bound. (Rank 0 only!)
265
266
- ``return_BSD`` - bool (default: False) whether to return an object
267
which contains information to reconstruct a proof
268
269
NOTE:
270
271
When printing verbose output, phrases such as "by Mazur" are referring
272
to the following list of papers:
273
274
REFERENCES:
275
276
.. [Cha] B. Cha. Vanishing of some cohomology goups and bounds for the
277
Shafarevich-Tate groups of elliptic curves. J. Number Theory, 111:154-
278
178, 2005.
279
.. [Jetchev] D. Jetchev. Global divisibility of Heegner points and
280
Tamagawa numbers. Compos. Math. 144 (2008), no. 4, 811--826.
281
.. [Kato] K. Kato. p-adic Hodge theory and values of zeta functions of
282
modular forms. Astérisque, (295):ix, 117-290, 2004.
283
.. [Kolyvagin] V. A. Kolyvagin. On the structure of Shafarevich-Tate
284
groups. Algebraic geometry, 94--121, Lecture Notes in Math., 1479,
285
Springer, Berlin, 1991.
286
.. [LumStein] A. Lum, W. Stein. Verification of the Birch and
287
Swinnerton-Dyer Conjecture for Elliptic Curves with Complex
288
Multiplication (unpublished)
289
.. [Mazur] B. Mazur. Modular curves and the Eisenstein ideal. Inst.
290
Hautes Études Sci. Publ. Math. No. 47 (1977), 33--186 (1978).
291
.. [Rubin] K. Rubin. The "main conjectures" of Iwasawa theory for
292
imaginary quadratic fields. Invent. Math. 103 (1991), no. 1, 25--68.
293
.. [SteinWuthrich] W. Stein and C. Wuthrich. Computations about
294
Tate-Shafarevich groups using Iwasawa theory.
295
http://wstein.org/papers/shark, February 2008.
296
.. [SteinEtAl] G. Grigorov, A. Jorza, S. Patrikis, W. Stein,
297
C. Tarniţǎ. Computational verification of the Birch and
298
Swinnerton-Dyer conjecture for individual elliptic curves.
299
Math. Comp. 78 (2009), no. 268, 2397--2425.
300
301
302
EXAMPLES::
303
304
sage: EllipticCurve('11a').prove_BSD(verbosity=2)
305
p = 2: True by 2-descent...
306
True for p not in {2, 5} by Kolyvagin.
307
True for p=5 by Mazur
308
[]
309
310
sage: EllipticCurve('14a').prove_BSD(verbosity=2)
311
p = 2: True by 2-descent
312
True for p not in {2, 3} by Kolyvagin.
313
Remaining primes:
314
p = 3: reducible, not surjective, good ordinary, divides a Tamagawa number
315
(no bounds found)
316
ord_p(#Sha_an) = 0
317
[3]
318
sage: EllipticCurve('14a').prove_BSD(two_desc='simon')
319
[3]
320
321
A rank two curve::
322
323
sage: E = EllipticCurve('389a')
324
325
We know nothing with proof=True::
326
327
sage: E.prove_BSD()
328
Set of all prime numbers: 2, 3, 5, 7, ...
329
330
We (think we) know everything with proof=False::
331
332
sage: E.prove_BSD(proof=False)
333
[]
334
335
A curve of rank 0 and prime conductor::
336
337
sage: E = EllipticCurve('19a')
338
sage: E.prove_BSD(verbosity=2)
339
p = 2: True by 2-descent...
340
True for p not in {2, 3} by Kolyvagin.
341
True for p=3 by Mazur
342
[]
343
344
sage: E = EllipticCurve('37a')
345
sage: E.rank()
346
1
347
sage: E._EllipticCurve_rational_field__rank
348
{True: 1}
349
sage: E.analytic_rank = lambda : 0
350
sage: E.prove_BSD()
351
Traceback (most recent call last):
352
...
353
RuntimeError: It seems that the rank conjecture does not hold for this curve (Elliptic Curve defined by y^2 + y = x^3 - x over Rational Field)! This may be a counterexample to BSD, but is more likely a bug.
354
355
We test the consistency check for the 2-part of Sha::
356
357
sage: E = EllipticCurve('37a')
358
sage: S = E.sha(); S
359
Tate-Shafarevich group for the Elliptic Curve defined by y^2 + y = x^3 - x over Rational Field
360
sage: def foo(use_database):
361
... return 4
362
sage: S.an = foo
363
sage: E.prove_BSD()
364
Traceback (most recent call last):
365
...
366
RuntimeError: Apparent contradiction: 0 <= rank(sha[2]) <= 0, but ord_2(sha_an) = 2
367
368
An example with a Tamagawa number at 5::
369
370
sage: E = EllipticCurve('123a1')
371
sage: E.prove_BSD(verbosity=2)
372
p = 2: True by 2-descent
373
True for p not in {2, 5} by Kolyvagin.
374
Remaining primes:
375
p = 5: reducible, not surjective, good ordinary, divides a Tamagawa number
376
(no bounds found)
377
ord_p(#Sha_an) = 0
378
[5]
379
380
A curve for which 3 divides the order of the Tate-Shafarevich group::
381
382
sage: E = EllipticCurve('681b')
383
sage: E.prove_BSD(verbosity=2) # long time
384
p = 2: True by 2-descent...
385
True for p not in {2, 3} by Kolyvagin....
386
Remaining primes:
387
p = 3: irreducible, surjective, non-split multiplicative
388
(0 <= ord_p <= 2)
389
ord_p(#Sha_an) = 2
390
[3]
391
392
A curve for which we need to use ``heegner_index_bound``::
393
394
sage: E = EllipticCurve('198b')
395
sage: E.prove_BSD(verbosity=1, secs_hi=1)
396
p = 2: True by 2-descent
397
True for p not in {2, 3} by Kolyvagin.
398
[3]
399
400
The ``return_BSD`` option gives an object with detailed information
401
about the proof::
402
403
sage: E = EllipticCurve('26b')
404
sage: B = E.prove_BSD(return_BSD=True)
405
sage: B.two_tor_rk
406
0
407
sage: B.N
408
26
409
sage: B.gens
410
[]
411
sage: B.primes
412
[7]
413
sage: B.heegner_indexes
414
{-23: 2}
415
416
TESTS:
417
418
This was fixed by trac #8184 and #7575::
419
420
sage: EllipticCurve('438e1').prove_BSD(verbosity=1)
421
p = 2: True by 2-descent...
422
True for p not in {2} by Kolyvagin.
423
[]
424
425
::
426
427
sage: E = EllipticCurve('960d1')
428
sage: E.prove_BSD(verbosity=1) # long time (4s on sage.math, 2011)
429
p = 2: True by 2-descent
430
True for p not in {2} by Kolyvagin.
431
[]
432
433
"""
434
if proof is None:
435
from sage.structure.proof.proof import get_flag
436
proof = get_flag(proof, "elliptic_curve")
437
else:
438
proof = bool(proof)
439
if not proof:
440
return []
441
from copy import copy
442
BSD = BSD_data()
443
# We replace this curve by the optimal curve, which we can do since
444
# truth of BSD(E,p) is invariant under isogeny.
445
BSD.curve = E.optimal_curve()
446
if BSD.curve.has_cm():
447
# ensure that CM is by a maximal order
448
non_max_j_invs = [-12288000, 54000, 287496, 16581375]
449
if BSD.curve.j_invariant() in non_max_j_invs: # is this possible for optimal curves?
450
if verbosity > 0:
451
print 'CM by non maximal order: switching curves'
452
for E in BSD.curve.isogeny_class()[0]:
453
if E.j_invariant() not in non_max_j_invs:
454
BSD.curve = E
455
break
456
BSD.update()
457
galrep = BSD.curve.galois_representation()
458
459
if two_desc=='mwrank':
460
M = mwrank_two_descent_work(BSD.curve, BSD.two_tor_rk)
461
elif two_desc=='simon':
462
M = simon_two_descent_work(BSD.curve, BSD.two_tor_rk)
463
elif two_desc=='sage':
464
M = native_two_isogeny_descent_work(BSD.curve, BSD.two_tor_rk)
465
else:
466
raise NotImplementedError()
467
rank_lower_bd, rank_upper_bd, sha2_lower_bd, sha2_upper_bd, gens = M
468
assert sha2_lower_bd <= sha2_upper_bd
469
if gens is not None: gens = BSD.curve.saturation(gens)[0]
470
if rank_lower_bd > rank_upper_bd:
471
raise RuntimeError("Apparent contradiction: %d <= rank <= %d."%(rank_lower_bd, rank_upper_bd))
472
BSD.two_selmer_rank = rank_upper_bd + sha2_lower_bd + BSD.two_tor_rk
473
if sha2_upper_bd == sha2_lower_bd:
474
BSD.rank = rank_lower_bd
475
BSD.bounds[2] = (sha2_lower_bd, sha2_upper_bd)
476
else:
477
BSD.rank = BSD.curve.rank(use_database=True)
478
sha2_upper_bd -= (BSD.rank - rank_lower_bd)
479
BSD.bounds[2] = (sha2_lower_bd, sha2_upper_bd)
480
if verbosity > 0:
481
print "Unable to compute the rank exactly -- used database."
482
if rank_lower_bd > 1:
483
# We do not know BSD(E,p) for even a single p, since it's
484
# an open problem to show that L^r(E,1)/(Reg*Omega) is
485
# rational for any curve with r >= 2.
486
from sage.sets.all import Primes
487
BSD.primes = Primes()
488
if return_BSD:
489
BSD.rank = rank_lower_bd
490
return BSD
491
return BSD.primes
492
if (BSD.sha_an.ord(2) == 0) != (BSD.bounds[2][1] == 0):
493
raise RuntimeError("Apparent contradiction: %d <= rank(sha[2]) <= %d, but ord_2(sha_an) = %d"%(sha2_lower_bd, sha2_upper_bd, BSD.sha_an.ord(2)))
494
if BSD.bounds[2][0] == BSD.sha_an.ord(2) and BSD.sha_an.ord(2) == BSD.bounds[2][1]:
495
if verbosity > 0:
496
print 'p = 2: True by 2-descent'
497
BSD.primes = []
498
BSD.bounds.pop(2)
499
BSD.proof[2] = ['2-descent']
500
else:
501
BSD.primes = [2]
502
BSD.proof[2] = [('2-descent',)+BSD.bounds[2]]
503
if len(gens) > rank_lower_bd or \
504
rank_lower_bd > rank_upper_bd:
505
raise RuntimeError("Something went wrong with 2-descent.")
506
if BSD.rank != len(gens):
507
if BSD.rank != len(BSD.curve._EllipticCurve_rational_field__gens[True]):
508
raise RuntimeError("Could not get generators")
509
gens = BSD.curve._EllipticCurve_rational_field__gens[True]
510
BSD.gens = [BSD.curve.point(x, check=True) for x in gens]
511
512
if BSD.rank != BSD.curve.analytic_rank():
513
raise RuntimeError("It seems that the rank conjecture does not hold for this curve (%s)! This may be a counterexample to BSD, but is more likely a bug."%(BSD.curve))
514
515
# reduce set of remaining primes to a finite set
516
import signal
517
kolyvagin_primes = []
518
heegner_index = None
519
if BSD.rank == 0:
520
for D in BSD.curve.heegner_discriminants_list(10):
521
max_height = max(13,BSD.curve.quadratic_twist(D).CPS_height_bound())
522
heegner_primes = -1
523
while heegner_primes == -1:
524
if max_height > 21: break
525
heegner_primes, _, exact = BSD.curve.heegner_index_bound(D, max_height=max_height)
526
max_height += 1
527
if isinstance(heegner_primes, list):
528
break
529
if not isinstance(heegner_primes, list):
530
raise RuntimeError("Tried 10 Heegner discriminants, and heegner_index_bound failed each time.")
531
if exact is not False:
532
heegner_index = exact
533
BSD.heegner_indexes[D] = exact
534
else:
535
BSD.heegner_index_upper_bound[D] = max(heegner_primes+[1])
536
if 2 in heegner_primes:
537
heegner_primes.remove(2)
538
else: # rank 1
539
for D in BSD.curve.heegner_discriminants_list(10):
540
I = BSD.curve.heegner_index(D)
541
J = I.is_int()
542
if J[0] and J[1]>0:
543
I = J[1]
544
else:
545
J = (2*I).is_int()
546
if J[0] and J[1]>0:
547
I = J[1]
548
else:
549
continue
550
heegner_index = I
551
BSD.heegner_indexes[D] = I
552
break
553
heegner_primes = [p for p in arith.prime_divisors(heegner_index) if p!=2]
554
555
assert BSD.sha_an in ZZ and BSD.sha_an > 0
556
if BSD.curve.has_cm():
557
if BSD.curve.analytic_rank() == 0:
558
if verbosity > 0:
559
print ' p >= 5: true by Rubin'
560
BSD.primes.append(3)
561
else:
562
K = rings.QuadraticField(BSD.curve.cm_discriminant(), 'a')
563
D_K = K.disc()
564
D_E = BSD.curve.discriminant()
565
if len(K.factor(3)) == 1: # 3 does not split in K
566
BSD.primes.append(3)
567
for p in arith.prime_divisors(D_K):
568
if p >= 5:
569
BSD.primes.append(p)
570
for p in arith.prime_divisors(D_E):
571
if p >= 5 and D_K%p and len(K.factor(p)) == 1: # p is inert in K
572
BSD.primes.append(p)
573
for p in heegner_primes:
574
if p >= 5 and D_E%p != 0 and D_K%p != 0 and len(K.factor(p)) == 1: # p is good for E and inert in K
575
kolyvagin_primes.append(p)
576
for p in arith.prime_divisors(BSD.sha_an):
577
if p >= 5 and D_K%p != 0 and len(K.factor(p)) == 1:
578
if BSD.curve.is_good(p):
579
if verbosity > 2 and p in heegner_primes and heegner_index is None:
580
print 'ALERT: Prime p (%d) >= 5 dividing sha_an, good for E, inert in K, in heegner_primes, should not divide the actual Heegner index'
581
# Note that the following check is not entirely
582
# exhaustive, in case there is a p not dividing
583
# the Heegner index in heegner_primes,
584
# for which only an outer bound was computed
585
if p not in heegner_primes:
586
raise RuntimeError("p = %d divides sha_an, is of good reduction for E, inert in K, and does not divide the Heegner index. This may be a counterexample to BSD, but is more likely a bug. %s"%(p,BSD.curve))
587
if verbosity > 0:
588
print 'True for p not in {%s} by Kolyvagin (via Stein & Lum -- unpublished) and Rubin.'%str(list(set(BSD.primes).union(set(kolyvagin_primes))))[1:-1]
589
BSD.proof['finite'] = copy(BSD.primes)
590
else: # no CM
591
# do some tricks to get to a finite set without calling bound_kolyvagin
592
BSD.primes += [p for p in galrep.non_surjective() if p != 2]
593
for p in heegner_primes:
594
if p not in BSD.primes:
595
BSD.primes.append(p)
596
for p in arith.prime_divisors(BSD.sha_an):
597
if p not in BSD.primes and p != 2:
598
BSD.primes.append(p)
599
if verbosity > 0:
600
s = str(BSD.primes)[1:-1]
601
if 2 not in BSD.primes:
602
if len(s) == 0: s = '2'
603
else: s = '2, '+s
604
print 'True for p not in {' + s + '} by Kolyvagin.'
605
BSD.proof['finite'] = copy(BSD.primes)
606
primes_to_remove = []
607
for p in BSD.primes:
608
if p == 2: continue
609
if galrep.is_surjective(p) and not BSD.curve.has_additive_reduction(p):
610
if BSD.curve.has_nonsplit_multiplicative_reduction(p):
611
if BSD.rank > 0:
612
continue
613
if p==3:
614
if (not (BSD.curve.is_ordinary(p) and BSD.curve.is_good(p))) and (not BSD.curve.has_split_multiplicative_reduction(p)):
615
continue
616
if BSD.rank > 0:
617
continue
618
if verbosity > 1:
619
print ' p = %d: Trying p_primary_bound'%p
620
p_bound = BSD.Sha.p_primary_bound(p)
621
if BSD.proof.has_key(p):
622
BSD.proof[p].append(('Stein-Wuthrich', p_bound))
623
else:
624
BSD.proof[p] = [('Stein-Wuthrich', p_bound)]
625
if BSD.sha_an.ord(p) == 0 and p_bound == 0:
626
if verbosity > 0:
627
print 'True for p=%d by Stein-Wuthrich.'%p
628
primes_to_remove.append(p)
629
else:
630
if BSD.bounds.has_key(p):
631
BSD.bounds[p][1] = min(BSD.bounds[p][1], p_bound)
632
else:
633
BSD.bounds[p] = (0, p_bound)
634
print 'Analytic %d-rank is '%p + str(BSD.sha_an.ord(p)) + ', actual %d-rank is at most %d.'%(p, p_bound)
635
print ' by Stein-Wuthrich.\n'
636
for p in primes_to_remove:
637
BSD.primes.remove(p)
638
kolyvagin_primes = []
639
for p in BSD.primes:
640
if p == 2: continue
641
if galrep.is_surjective(p):
642
kolyvagin_primes.append(p)
643
for p in kolyvagin_primes:
644
BSD.primes.remove(p)
645
# apply other hypotheses which imply Kolyvagin's bound holds
646
bounded_primes = []
647
D_K = rings.QuadraticField(D, 'a').disc()
648
649
# Cha's hypothesis
650
for p in BSD.primes:
651
if p == 2: continue
652
if D_K%p != 0 and BSD.N%(p**2) != 0 and galrep.is_irreducible(p):
653
if verbosity > 0:
654
print 'Kolyvagin\'s bound for p = %d applies by Cha.'%p
655
if BSD.proof.has_key(p):
656
BSD.proof[p].append('Cha')
657
else:
658
BSD.proof[p] = ['Cha']
659
kolyvagin_primes.append(p)
660
# Stein et al.
661
if not BSD.curve.has_cm():
662
L = arith.lcm([F.torsion_order() for F in BSD.curve.isogeny_class()[0]])
663
for p in BSD.primes:
664
if p in kolyvagin_primes or p == 2: continue
665
if L%p != 0:
666
if len(arith.prime_divisors(D_K)) == 1:
667
if D_K%p == 0: continue
668
if verbosity > 0:
669
print 'Kolyvagin\'s bound for p = %d applies by Stein et al.'%p
670
kolyvagin_primes.append(p)
671
if BSD.proof.has_key(p):
672
BSD.proof[p].append('Stein et al.')
673
else:
674
BSD.proof[p] = ['Stein et al.']
675
for p in kolyvagin_primes:
676
if p in BSD.primes:
677
BSD.primes.remove(p)
678
679
# apply Kolyvagin's bound
680
primes_to_remove = []
681
for p in kolyvagin_primes:
682
if p == 2: continue
683
if p not in heegner_primes:
684
ord_p_bound = 0
685
elif heegner_index is not None: # p must divide heegner_index
686
ord_p_bound = 2*heegner_index.ord(p)
687
# Here Jetchev's results apply.
688
m_max = max([BSD.curve.tamagawa_number(q).ord(p) for q in BSD.N.prime_divisors()])
689
if m_max > 0:
690
if verbosity > 0:
691
print 'Jetchev\'s results apply (at p = %d) with m_max ='%p, m_max
692
if BSD.proof.has_key(p):
693
BSD.proof[p].append(('Jetchev',m_max))
694
else:
695
BSD.proof[p] = [('Jetchev',m_max)]
696
ord_p_bound -= 2*m_max
697
else: # Heegner index is None
698
for D in BSD.heegner_index_upper_bound:
699
M = BSD.heegner_index_upper_bound[D]
700
ord_p_bound = 0
701
while p**(ord_p_bound+1) <= M**2:
702
ord_p_bound += 1
703
# now ord_p_bound is one on I_K!!!
704
ord_p_bound *= 2 # by Kolyvagin, now ord_p_bound is one on #Sha
705
break
706
if BSD.proof.has_key(p):
707
BSD.proof[p].append(('Kolyvagin',ord_p_bound))
708
else:
709
BSD.proof[p] = [('Kolyvagin',ord_p_bound)]
710
if BSD.sha_an.ord(p) == 0 and ord_p_bound == 0:
711
if verbosity > 0:
712
print 'True for p = %d by Kolyvagin bound'%p
713
primes_to_remove.append(p)
714
elif BSD.sha_an.ord(p) > ord_p_bound:
715
raise RuntimeError("p = %d: ord_p_bound == %d, but sha_an.ord(p) == %d. This appears to be a counterexample to BSD, but is more likely a bug."%(p,ord_p_bound,BSD.sha_an.ord(p)))
716
else: # BSD.sha_an.ord(p) <= ord_p_bound != 0:
717
if BSD.bounds.has_key(p):
718
low = BSD.bounds[p][0]
719
BSD.bounds[p] = (low, min(BSD.bounds[p][1], ord_p_bound))
720
else:
721
BSD.bounds[p] = (0, ord_p_bound)
722
for p in primes_to_remove:
723
kolyvagin_primes.remove(p)
724
BSD.primes = list( set(BSD.primes).union(set(kolyvagin_primes)) )
725
726
# Kato's bound
727
if BSD.rank == 0 and not BSD.curve.has_cm():
728
L_over_Omega = BSD.curve.lseries().L_ratio()
729
kato_primes = BSD.Sha.bound_kato()
730
primes_to_remove = []
731
for p in BSD.primes:
732
if p == 2: continue
733
if p not in kato_primes:
734
if verbosity > 0:
735
print 'Kato further implies that #Sha[%d] is trivial.'%p
736
primes_to_remove.append(p)
737
if BSD.proof.has_key(p):
738
BSD.proof[p].append(('Kato',0))
739
else:
740
BSD.proof[p] = [('Kato',0)]
741
if p not in [2,3] and BSD.N%p != 0:
742
if galrep.is_surjective(p):
743
bd = L_over_Omega.valuation(p)
744
if verbosity > 1:
745
print 'Kato implies that ord_p(#Sha[%d]) <= %d '%(p,bd)
746
if BSD.proof.has_key(p):
747
BSD.proof[p].append(('Kato',bd))
748
else:
749
BSD.proof[p] = [('Kato',bd)]
750
if BSD.bounds.has_key(p):
751
low = BSD.bounds[p][0]
752
BSD.bounds[p][1] = (low, min(BSD.bounds[p][1], bd))
753
else:
754
BSD.bounds[p] = (0, bd)
755
for p in primes_to_remove:
756
BSD.primes.remove(p)
757
758
# Mazur
759
primes_to_remove = []
760
if BSD.N.is_prime():
761
for p in BSD.primes:
762
if p == 2: continue
763
if galrep.is_reducible(p):
764
primes_to_remove.append(p)
765
if verbosity > 0:
766
print 'True for p=%s by Mazur'%p
767
for p in primes_to_remove:
768
BSD.primes.remove(p)
769
if BSD.proof.has_key(p):
770
BSD.proof[p].append('Mazur')
771
else:
772
BSD.proof[p] = ['Mazur']
773
774
BSD.primes.sort()
775
776
# Try harder to compute the Heegner index, where it matters
777
if heegner_index is None:
778
if max_height < 18:
779
max_height = 18
780
for D in BSD.heegner_index_upper_bound:
781
M = BSD.heegner_index_upper_bound[D]
782
for p in kolyvagin_primes:
783
if p not in BSD.primes or p == 3: continue
784
if verbosity > 0:
785
print ' p = %d: Trying harder for Heegner index'%p
786
obt = 0
787
while p**(BSD.sha_an.ord(p)/2+1) <= M and max_height < 22:
788
if verbosity > 2:
789
print ' trying max_height =', max_height
790
old_bound = M
791
M, _, exact = BSD.curve.heegner_index_bound(D, max_height=max_height, secs_dc=secs_dc)
792
if M == -1:
793
max_height += 1
794
continue
795
if exact is not False:
796
heegner_index = exact
797
BSD.heegner_indexes[D] = exact
798
M = exact
799
if verbosity > 2:
800
print ' heegner index =', M
801
else:
802
M = max(M+[1])
803
if verbosity > 2:
804
print ' bound =', M
805
if old_bound == M:
806
obt += 1
807
if obt == 2:
808
break
809
max_height += 1
810
BSD.heegner_index_upper_bound[D] = min(M,BSD.heegner_index_upper_bound[D])
811
low, upp = BSD.bounds[p]
812
expn = 0
813
while p**(expn+1) <= M:
814
expn += 1
815
if 2*expn < upp:
816
upp = 2*expn
817
BSD.bounds[p] = (low,upp)
818
if verbosity > 0:
819
print ' got better bound on ord_p =', upp
820
if low == upp:
821
if upp != BSD.sha_an.ord(p):
822
raise RuntimeError
823
else:
824
if verbosity > 0:
825
print ' proven!'
826
BSD.primes.remove(p)
827
break
828
for p in kolyvagin_primes:
829
if p not in BSD.primes or p == 3: continue
830
for D in BSD.curve.heegner_discriminants_list(4):
831
if D in BSD.heegner_index_upper_bound: continue
832
print ' discriminant', D
833
if verbosity > 0:
834
print 'p = %d: Trying discriminant = %d for Heegner index'%(p,D)
835
max_height = max(10, BSD.curve.quadratic_twist(D).CPS_height_bound())
836
obt = 0
837
while True:
838
if verbosity > 2:
839
print ' trying max_height =', max_height
840
old_bound = M
841
if p**(BSD.sha_an.ord(p)/2+1) > M or max_height >= 22:
842
break
843
M, _, exact = BSD.curve.heegner_index_bound(D, max_height=max_height, secs_dc=secs_dc)
844
if M == -1:
845
max_height += 1
846
continue
847
if exact is not False:
848
heegner_index = exact
849
BSD.heegner_indexes[D] = exact
850
M = exact
851
if verbosity > 2:
852
print ' heegner index =', M
853
else:
854
M = max(M+[1])
855
if verbosity > 2:
856
print ' bound =', M
857
if old_bound == M:
858
obt += 1
859
if obt == 2:
860
break
861
max_height += 1
862
BSD.heegner_index_upper_bound[D] = M
863
low, upp = BSD.bounds[p]
864
expn = 0
865
while p**(expn+1) <= M:
866
expn += 1
867
if 2*expn < upp:
868
upp = 2*expn
869
BSD.bounds[p] = (low,upp)
870
if verbosity > 0:
871
print ' got better bound =', upp
872
if low == upp:
873
if upp != BSD.sha_an.ord(p):
874
raise RuntimeError
875
else:
876
if verbosity > 0:
877
print ' proven!'
878
BSD.primes.remove(p)
879
break
880
881
# print some extra information
882
if verbosity > 1:
883
if len(BSD.primes) > 0:
884
print 'Remaining primes:'
885
for p in BSD.primes:
886
s = 'p = ' + str(p) + ': '
887
if galrep.is_irreducible(p):
888
s += 'ir'
889
s += 'reducible, '
890
if not galrep.is_surjective(p):
891
s += 'not '
892
s += 'surjective, '
893
a_p = BSD.curve.an(p)
894
if BSD.curve.is_good(p):
895
if a_p%p != 0:
896
s += 'good ordinary'
897
else:
898
s += 'good, non-ordinary'
899
else:
900
assert BSD.curve.is_minimal()
901
if a_p == 0:
902
s += 'additive'
903
elif a_p == 1:
904
s += 'split multiplicative'
905
elif a_p == -1:
906
s += 'non-split multiplicative'
907
if BSD.curve.tamagawa_product()%p==0:
908
s += ', divides a Tamagawa number'
909
if BSD.bounds.has_key(p):
910
s += '\n (%d <= ord_p <= %d)'%BSD.bounds[p]
911
else:
912
s += '\n (no bounds found)'
913
s += '\n ord_p(#Sha_an) = %d'%BSD.sha_an.ord(p)
914
if heegner_index is None:
915
may_divide = True
916
for D in BSD.heegner_index_upper_bound:
917
if p > BSD.heegner_index_upper_bound[D] or p not in kolyvagin_primes:
918
may_divide = False
919
if may_divide:
920
s += '\n may divide the Heegner index, for which only a bound was computed'
921
print s
922
923
if BSD.curve.has_cm():
924
if BSD.rank == 1:
925
BSD.proof['reason_finite'] = 'Rubin&Kolyvagin'
926
else:
927
BSD.proof['reason_finite'] = 'Rubin'
928
else:
929
BSD.proof['reason_finite'] = 'Kolyvagin'
930
# reduce memory footprint of BSD object:
931
BSD.curve = BSD.curve.label()
932
BSD.Sha = None
933
return BSD if return_BSD else BSD.primes
934
935
936