jumps.sage (7248B)
1 from sage.schemes.elliptic_curves.ell_generic import is_EllipticCurve 2 3 # Pre-tests on E and P 4 def suitable( E, P, ell ): 5 if not is_EllipticCurve(E): 6 print "E is not an elliptic curve" 7 return False 8 if E.base_field() != QQ: 9 print "E is not defined over Q" 10 return False 11 if not P in E: 12 print "P is not in E" 13 return False 14 if P.has_finite_order(): 15 print "P has finite order" 16 return False 17 if not is_prime(ell): 18 print "ell is not prime" 19 return False 20 return True 21 22 23 # Stupid auxiliary function. Returns higest power of n dividing m. 24 def val( n, m ): 25 ret = 0 26 while m % (n^(ret+1)) == 0: 27 ret += 1 28 return ret 29 30 def test_jump_kl2_label( label, ell ): 31 E = EllipticCurve( label ) 32 if E.rank() < 1: 33 print "E has rank 0" 34 return 35 P = E.gens()[0] 36 test_jump_kl2( E, P, ell ) 37 38 def test_jump_kl2( E, P, ell ): 39 if not suitable( E, P, ell ): 40 return 41 42 flag = True 43 for p in Primes(): 44 if p > 10^3: 45 break 46 if p == ell: 47 # print "Skipping", p, "because = ell" 48 continue 49 if E.discriminant() % p == 0: 50 # print "Skipping", p, "because E has bad reduction" 51 continue 52 if P.reduction(p).order() % ell != 0: 53 # print "Skipping", p, "because red of P is infinitely ell-divisible" 54 continue 55 56 # print "Working with prime p =", p 57 58 F = FiniteField(p) 59 60 for i in range(3): 61 # print "Torsion level", i, "..." 62 63 # We can build the division fields for increasing powers of l 64 # incrementally. To get a division field, we first compute the 65 # splitting field of the division polynomial. We may be off by 66 # a degree 2 extension. If so, by finite field magic we know 67 # exactly which degree 2 extension we need: the unique one! 68 R.<x> = PolynomialRing(F) 69 F.<a> = E.reduction(p).division_polynomial(ell^i).splitting_field() 70 E_red = E.reduction(p).base_extend(F) 71 # extend if necessary 72 k = val(ell,E_red.gens()[0].order()) 73 h = val(ell,E_red.order()) - k 74 if k < i or h < i: 75 F.<a> = F.extension(2) 76 E_red = E_red.base_extend(F) 77 78 P_red = E_red.point(P.reduction(p)) 79 80 flag = False 81 if P_red.is_divisible_by(ell): 82 # print "P ell-divisible in this torsion level" 83 flag = True 84 break 85 86 if not flag: 87 print "Point not divisible mod", p 88 print "Stopping here" 89 break 90 if flag: 91 print "*********************************" 92 print "*** Candidate counterexample! ***" 93 print "*********************************" 94 95 # Wrapper 96 def test_jump_den_label( label, ell ): 97 E = EllipticCurve(label) 98 if E.rank() < 1: 99 print "E has rank 0" 100 return 101 P = E.gens()[0] 102 test_jump_den( E, P, ell ) 103 104 def test_jump_den( E, P, ell ): 105 if not suitable( E, P, ell ): 106 return 107 108 n_primes = 0 109 inf_divisible = 0 110 tot_l_part = 0 111 tot_non_l_part = 0 112 113 for p in Primes(): 114 if p > 5*10^3: 115 break 116 if p == ell or E.discriminant() % p == 0: 117 continue 118 119 n_primes += 1 120 121 E_red = E.reduction(p) 122 N = E_red.order() 123 k = val(ell,E_red.gens()[0].order()) 124 h = val(ell,N) - k 125 temp_non_l_part = (N / (ell^(h+k)))-1 126 tot_non_l_part += temp_non_l_part 127 temp_l_part = N - temp_non_l_part 128 tot_l_part += temp_l_part 129 130 if P.reduction(p).order() % ell != 0: 131 inf_divisible += 1 132 133 found = RDF( inf_divisible / n_primes ) 134 expected = RDF( tot_non_l_part / (tot_l_part+tot_non_l_part) ) 135 print "Found: %0.3f, expected: %0.3f"%(found, expected) 136 if abs(found-expected) > 0.05: 137 print "Unexpected density! Checking divisibility in reductions..." 138 test_jump_kl2( E, P, ell ) 139 140 def test_from_file( filename ): 141 attach(filename) 142 for coord in data: 143 label = EllipticCurve(coord).label() 144 print "Trying curve", label, "with ell =", 3 145 test_jump_den_label(label,3)