kummer-notes-code

Notes and code from my early research in Kummer Theory for Elliptic Curves.
git clone https://git.tronto.net/kummer-notes-code
Download | Log | Files | Refs | README

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)