Ticket #11905: 11905_splitting_field.patch

File 11905_splitting_field.patch, 15.6 KB (added by jdemeyer, 8 years ago)
  • sage/rings/arith.py

    # HG changeset patch
    # User Jeroen Demeyer <jdemeyer@cage.ugent.be>
    # Date 1320942319 -3600
    # Node ID ffd0a4aeb77c44b0e1d528e323f87ecffcd86930
    # Parent  3031d21db17bd6f70f1ea54b773e96a7167812f7
    Remove _splitting_field() from elliptic curves
    
    diff --git a/sage/rings/arith.py b/sage/rings/arith.py
    a b  
    23762376
    23772377def prime_divisors(n):   
    23782378    """
    2379     The prime divisors of the integer n, sorted in increasing order. If
    2380     n is negative, we do *not* include -1 among the prime divisors,
    2381     since -1 is not a prime number.
     2379    The prime divisors of ``n``.
     2380
     2381    INPUT:
     2382
     2383    - ``n`` -- any object which can be factored
     2384
     2385    OUTPUT:
     2386
     2387    A list of prime factors of ``n``. For integers, this list is sorted
     2388    in increasing order.
    23822389   
    23832390    EXAMPLES::
    23842391   
     
    23862393        []
    23872394        sage: prime_divisors(100)
    23882395        [2, 5]
     2396        sage: prime_divisors(2004)
     2397        [2, 3, 167]
     2398
     2399    If ``n`` is negative, we do *not* include -1 among the prime
     2400    divisors, since -1 is not a prime number::
     2401   
    23892402        sage: prime_divisors(-100)
    23902403        [2, 5]
    2391         sage: prime_divisors(2004)
    2392         [2, 3, 167]
     2404
     2405    For polynomials we get all irreducible factors::
     2406
     2407        sage: R.<x> = PolynomialRing(QQ)
     2408        sage: prime_divisors(x^12 - 1)
     2409        [x - 1, x + 1, x^2 - x + 1, x^2 + 1, x^2 + x + 1, x^4 - x^2 + 1]
    23932410    """
    2394     return [p for p,_ in factor(n) if p != -1]
     2411    return [p for p,_ in factor(n)]
    23952412
    23962413prime_factors = prime_divisors
    23972414
  • sage/schemes/elliptic_curves/ell_number_field.py

    diff --git a/sage/schemes/elliptic_curves/ell_number_field.py b/sage/schemes/elliptic_curves/ell_number_field.py
    a b  
    288288        prob_gens = [self(P) for P in t[2]]
    289289        self._simon_two_descent_data[lim1,lim3,limtriv,maxprob,limbigprime] = (prob_rank, two_selmer_rank, prob_gens)
    290290        return prob_rank, two_selmer_rank, prob_gens
     291
     292    def division_field(self, p, names, map=False, simplify=True, simplify_all=False):
     293        """
     294        Given an elliptic curve over a number field `F` and a prime number `p`,
     295        construct the field `F(E[p])`.
     296
     297        INPUT:
     298
     299        - ``p`` -- a prime number (an element of `\ZZ`)
     300
     301        - ``names`` -- a variable name for the number field
     302
     303        - ``map`` -- (default: ``False``) also return an embedding of
     304          ``self.base_field()`` into the resulting field.
     305
     306        - ``simplify`` -- (default: ``True``) during the algorithm, try
     307          to find a simpler defining polynomial for the intermediate
     308          number fields.
     309
     310        - ``simplify_all`` -- (default: ``False``) If ``True``, simplify
     311          intermediate fields and also the resulting number field.
     312
     313        OUTPUT:
     314
     315        If ``map`` is ``False``, the division field as an absolute number
     316        field.  If ``map`` is ``True``, a tuple ``(K, phi)`` where ``phi``
     317        is an embedding of ``self`` in the division field ``K``.
     318
     319        .. WARNING::
     320
     321            This takes a very long time when the degree of the division
     322            field is large (e.g. when `p` is large or when the Galois
     323            representation is surjective).  The value of ``simplify`` also
     324            has a big influence on the running time: sometimes
     325            ``simplify=False`` is faster, sometimes ``simplify=True`` is
     326            faster.
     327
     328        EXAMPLES::
     329
     330            sage: E = EllipticCurve('14a1')
     331            sage: K.<b> = E.division_field(2); K
     332            Number Field in b with defining polynomial x^2 + 5*x + 92
     333            sage: K.<b> = E.division_field(3); K
     334            Number Field in b with defining polynomial x^2 + 2*x + 13
     335
     336            sage: E = EllipticCurve('11a1')
     337            sage: K.<b> = E.division_field(5); K
     338            Number Field in b with defining polynomial x^4 - x^3 + x^2 - x + 1
     339            sage: E.division_field(5, 'b', simplify=False)
     340            Number Field in b with defining polynomial x^4 + x^3 + 11*x^2 + 41*x + 101
     341            sage: E.base_extend(K).torsion_subgroup()
     342            Torsion Subgroup isomorphic to Z/5 + Z/5 associated to the Elliptic Curve defined by y^2 + y = x^3 + (-1)*x^2 + (-10)*x + (-20) over Number Field in b with defining polynomial x^4 - x^3 + x^2 - x + 1
     343
     344            sage: E = EllipticCurve('27a1')
     345            sage: K.<b> = E.division_field(3); K
     346            Number Field in b with defining polynomial x^2 + 3*x + 9
     347            sage: K.<b> = E.division_field(2); K
     348            Number Field in b with defining polynomial x^6 - 112*x^3 + 27436
     349            sage: K.<b> = E.division_field(2, simplify_all=True); K
     350            Number Field in b with defining polynomial x^6 - 3*x^5 + 6*x^4 - 5*x^3 + 6*x^2 - 3*x + 1
     351            sage: E = EllipticCurve('27a1')
     352            sage: K.<b> = E.division_field(5); K   # long time (3s on sage.math, 2011)
     353            Number Field in b with defining polynomial x^48 ...
     354           
     355        Even ``E.division_field(7, 'b')`` takes less than a minute.
     356
     357        Over a number field::
     358
     359            sage: R.<x> = PolynomialRing(QQ)
     360            sage: K.<i> = NumberField(x^2 + 1)
     361            sage: E = EllipticCurve([0,0,0,0,i])
     362            sage: L.<b> = E.division_field(2); L
     363            Number Field in b with defining polynomial x^4 - x^2 + 1
     364            sage: L.<b>, phi = E.division_field(2, map=True); phi
     365            Ring morphism:
     366              From: Number Field in i with defining polynomial x^2 + 1
     367              To:   Number Field in b with defining polynomial x^4 - x^2 + 1
     368              Defn: i |--> -b^3
     369            sage: E.division_field(3, 'b')  # not tested, known bug
     370
     371        AUTHORS:
     372
     373        - Jeroen Demeyer (2011-11-10): #11905, use splitting_field() function,
     374          moved from ``gal_reps.py``, make it work over number fields.
     375        """ 
     376        verbose("Adjoining x-coordinates of %s-torsion points"%p)
     377        F = self.base_ring()
     378        f = self.division_polynomial(p)
     379        # Galois group is subgroup of GL(2,p)
     380        deg_bound = F.degree()*p*(p+1)*(p-1)**2
     381        K = f.splitting_field(names, degree_bound=deg_bound, map=map, simplify=simplify, simplify_all=simplify_all)
     382        if map:
     383            K,F_to_K = K
     384
     385        # If 2*[K:F] is not a divisor of #GL(2,p), we cannot find a
     386        # quadratic extension with a Galois group still inside GL(2,p)
     387        if deg_bound % (2*K.degree()) == 0:
     388            # Adding the y-coordinate gives an extension of degree at most 2
     389            verbose("Adjoining y-coordinates of %s-torsion points"%p)
     390            RY = PolynomialRing(F, 'Y')
     391            Y = RY.gen()
     392            RYX = PolynomialRing(RY, 'x')
     393            # For every possible x-coordinate, find a polynomial defining the
     394            # y-coordinate
     395            # We only need to try one x for every factor over F, since other roots
     396            # of the same polynomial are Gal(K/F)-conjugates.
     397            for pe in f.factor():
     398                g = pe[0].change_ring(RY)
     399                yxpol = RYX( [self.a6() - Y*(Y + self.a3()), self.a4() - Y*self.a1(), self.a2(), 1] )
     400                ypol = PolynomialRing(K, 'x')(yxpol.resultant(g))
     401                L = ypol.splitting_field(names, degree_bound = 2*K.degree(), map=map, simplify_all=simplify_all)
     402                if map:
     403                    L,K_to_L = L
     404                if L.degree() > K.degree():
     405                    if map:
     406                        return L, F_to_K.post_compose(K_to_L)
     407                    else:
     408                        return L
     409        if map:
     410            return K, F_to_K
     411        else:
     412            return K
    291413               
    292414    def height_pairing_matrix(self, points=None, precision=None):
    293415        r"""
  • sage/schemes/elliptic_curves/gal_reps.py

    diff --git a/sage/schemes/elliptic_curves/gal_reps.py b/sage/schemes/elliptic_curves/gal_reps.py
    a b  
    165165            res.append(a[0])
    166166    return res
    167167
    168 # these two function could be moved to a better place later
    169 
    170 def _splitting_field(f):
    171     """
    172     Given a polynomial over `\QQ`, this returns the splitting field (as an absolute field over `\QQ`.
    173 
    174     EXAMPLES::
    175 
    176         sage: from sage.schemes.elliptic_curves.gal_reps import _splitting_field
    177         sage: R.<X> = QQ[]
    178         sage: f = X^2 + 1
    179         sage: _splitting_field(f)
    180         Number Field in b with defining polynomial X^2 + 1
    181         sage: f = (X^6-1)*(X^4+1)
    182         sage: _splitting_field(f)
    183         Number Field in b with defining polynomial x^8 + 4*x^7 + 10*x^6 + 16*x^5 + 21*x^4 + 20*x^3 + 4*x^2 - 4*x + 1
    184         sage: f = X^3 - 4*X^2 - 160*X - 1264
    185         sage: _splitting_field(f)
    186         Number Field in b with defining polynomial x^6 - 992*x^4 + 246016*x^2 + 41229056
    187 
    188         sage: f3  = 4*X^3 - 4*X^2 - 40*X - 79                                             
    189         sage: _splitting_field(f3)   
    190          Number Field in b with defining polynomial x^6 - 992*x^4 + 246016*x^2 + 41229056
    191                                
    192         sage: f3  = 4*X^3 - 4*X^2 - 40*X - 79                                             
    193         sage: _splitting_field(f3/4)                                             
    194         Number Field in b with defining polynomial x^6 - 992*x^4 + 246016*x^2 + 41229056
    195 
    196     """
    197     from sage.rings.polynomial.polynomial_ring_constructor import PolynomialRing
    198     from sage.rings.all import QQ
    199     from sage.misc.flatten import flatten
    200     # make an integral monic polynomial out of it
    201     d = f.denominator()
    202     f = d*f
    203     R = PolynomialRing(QQ,'X')
    204     f = R(f)
    205     X = R.gens()[0]
    206     an = f.leading_coefficient()
    207     f = an**(f.degree() - 1) * f(X/an)
    208     if an != 1:
    209         misc.verbose("polynomial changed to %s"%f,3)
    210 
    211     fs = [ff[0] for ff in f.factor() if ff[0].degree() > 1 ]
    212     while fs != []:
    213         K = fs[0].root_field('a')
    214         R = PolynomialRing(K,'X')
    215         fs = [R(f) for f in fs]
    216         K = K.absolute_field('b')
    217         inc = K.structure()[1]
    218         misc.verbose("degree of the field is now %s"%K.degree(), 2)
    219         R = PolynomialRing(K,'X')
    220         fs = [R([inc(u) for u in g.coeffs()]) for g in fs]
    221         fs = [[ff[0] for ff in g.factor() if ff[0].degree() > 1] for g in fs]
    222         fs = flatten(fs) 
    223     return K
    224 
    225 def _division_field(E,p):
    226     """
    227     Given an elliptic curve and a prime `p`, this constructs the field `\QQ(E[p])`.
    228 
    229     Note this takes a LONG time when p is large or when the representation is surjective.
    230 
    231     EXAMPLES::
    232 
    233         sage: from sage.schemes.elliptic_curves.gal_reps import _division_field
    234         sage: E = EllipticCurve('14a1')
    235         sage: _division_field(E,2)
    236         Number Field in b with defining polynomial X^2 + 5*X + 92
    237         sage: _division_field(E,3)
    238         Number Field in b with defining polynomial X^2 + 6*X + 117
    239 
    240         sage: E = EllipticCurve('11a1')
    241         sage: K = _division_field(E,5); K
    242         Number Field in b with defining polynomial x^4 + 5*x^3 + 275*x^2 + 5125*x + 63125
    243         sage: E.base_extend(K).torsion_subgroup()
    244         Torsion Subgroup isomorphic to Z/5 + Z/5 associated to the Elliptic Curve defined by y^2 + y = x^3 + (-1)*x^2 + (-10)*x + (-20) over Number Field in b with defining polynomial x^4 + 5*x^3 + 275*x^2 + 5125*x + 63125
    245 
    246         sage: E = EllipticCurve('27a1')
    247         sage: _division_field(E,3)
    248         Number Field in b with defining polynomial X^2 + 9*X + 81
    249         sage: _division_field(E,2)
    250         Number Field in b with defining polynomial x^6 + 5038848
    251         sage: E = EllipticCurve('27a1')
    252         sage: L = _division_field(E,5); L   # long time (4s on sage.math, 2011)
    253         Number Field in b with defining polynomial x^48 + 24*x^47 - 2634*x^46 - 64906*x^45 + 2726775*x^44 + 70841232*x^43 + 224413842693*x^42 + 4701700599732*x^41 - 3592508072137596/5*x^40 - 15012293781179144*x^39 + 968283011174870355*x^38 + 20267256109653557724*x^37 + 12067484020318191883430*x^36 + 1074616923704149785005406/5*x^35 - 36733858365780941833244052*x^34 - 645743028366047451133249842*x^33 + 220969510763490262549458235143/5*x^32 + 3821508904338000023273602548048/5*x^31 - 116959091827892505647463476639056/5*x^30 - 410999736248972608356551138775366*x^29 - 14893829970063945547808915701339152/5*x^28 - 65364599206437988881942239704947194/5*x^27 + 67673426654602996794997806980859832818/5*x^26 + 881882930983056033772717698410508954006/5*x^25 - 222881687343119655077359346112642829420824/25*x^24 - 2895120823335191010101881263518064564214338/25*x^23 + 45001727573606034388747893503112487075055856/25*x^22 + 123791333776720160716501836669886842723129232/5*x^21 + 33784656476525285313173627304265791556761499182/25*x^20 + 315309937263412002519549766396743184287341740362/25*x^19 - 29809326189907478934703273836943134749630766073937/25*x^18 - 277139669604549129326940625213109992460300794466472/25*x^17 + 48267417458901196371693187503590931071511693353624403/125*x^16 + 417747951937480880271176634423393038757023573062901214/125*x^15 + 2007263826796309855277267487981686566625095650300775449/125*x^14 + 6629329384200142639862088631838847849519261327732912678/125*x^13 - 7890086815228540044028318696011082482007739165946890467526/125*x^12 - 47407282438244289856698339380010252170030182743016263979758/125*x^11 + 3298070588288796211686670268348031992948626610010905491413867/125*x^10 + 16925026780847521477088033404397720576309067225732939278573654/125*x^9 - 12606276975554600131707859641843171596158942063398834295739121081/3125*x^8 - 52976903401697668325123474606327892765221094244312074003749191524/3125*x^7 - 1938266538684772533113390852600216820719603074035866039130578333001/3125*x^6 - 5627590284654484129751875434157935192705922694236805197727447225544/3125*x^5 + 285380988605606088041604497638523394233117370690633546039125252974974/625*x^4 + 2863126544037648956156470697472798773649141080128520101958284622979502/3125*x^3 - 292971118345690446877843351574720458113286307337430973163488739432371577/3125*x^2 - 294403610592013769220290971977947932182340270515731034223504446414069348/3125*x + 128890191901531504726282929609520479109501654595823184011440588325811602871/15625
    254         sage: L.absolute_degree()           # long time
    255         48
    256        
    257     Even  _division_field(E,7) works within a few minutes
    258     """ 
    259     from sage.rings.polynomial.polynomial_ring_constructor import PolynomialRing
    260  
    261     misc.verbose("trying to build the extension by adjoining the %s-torsion poitns"%p,2)
    262     f = E.division_polynomial(p)
    263     K = _splitting_field(f)
    264     EK = E.base_extend(K)
    265     if len(EK._p_primary_torsion_basis(p,1)) < 2:
    266         misc.verbose("the y-coordinate need to be adjoined, too",2)
    267         R = PolynomialRing(K,'Y')
    268         Y = R.gens()[0]
    269         for xxm in R(f).roots():
    270             xx = xxm[0]
    271             g = Y**2 + (EK.a1() * xx + EK.a3() ) * Y - xx**3 - EK.a2()*xx**2 - EK.a4()*xx - EK.a6()
    272             if g.roots() == []:
    273                 K = g.root_field('a').absolute_field('b')
    274                 break
    275     return K
    276 
    277168
    278169class GaloisRepresentation(SageObject):
    279170    r"""
     
    1032923            # That allows us to determine almost all cases.
    1033924   
    1034925            f = self.E.division_polynomial(5)
    1035             K = _splitting_field(f)
     926            K = f.splitting_field('x')
    1036927            #EK = self.E.base_extend(K)
    1037928            #d = K.degree()
    1038929            #if len(EK._p_primary_torsion_basis(5,1)) < 2:
     
    11451036        # is all fails, we probably have a fairly small group and we can try to detect it using the galois_group
    11461037
    11471038        if p <= 13:
    1148             K = _division_field(self.E,p)
     1039            K = self.E.division_field(p, 'b')
    11491040            d = K.absolute_degree()
    11501041
    11511042            misc.verbose("field of degree %s.  try to compute galois group"%(d),2)