diff options
Diffstat (limited to 'divisibility_reductions/jumps.sage')
| -rwxr-xr-x | divisibility_reductions/jumps.sage | 145 |
1 files changed, 145 insertions, 0 deletions
diff --git a/divisibility_reductions/jumps.sage b/divisibility_reductions/jumps.sage new file mode 100755 index 0000000..7517464 --- /dev/null +++ b/divisibility_reductions/jumps.sage | |||
| @@ -0,0 +1,145 @@ | |||
| 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) | ||
