# 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 def prime_divisors(n): """ The prime divisors of the integer n, sorted in increasing order. If n is negative, we do *not* include -1 among the prime divisors, since -1 is not a prime number. The prime divisors of ``n``. INPUT: - ``n`` -- any object which can be factored OUTPUT: A list of prime factors of ``n``. For integers, this list is sorted in increasing order. EXAMPLES:: [] sage: prime_divisors(100) [2, 5] sage: prime_divisors(2004) [2, 3, 167] If ``n`` is negative, we do *not* include -1 among the prime divisors, since -1 is not a prime number:: sage: prime_divisors(-100) [2, 5] sage: prime_divisors(2004) [2, 3, 167] For polynomials we get all irreducible factors:: sage: R. = PolynomialRing(QQ) sage: prime_divisors(x^12 - 1) [x - 1, x + 1, x^2 - x + 1, x^2 + 1, x^2 + x + 1, x^4 - x^2 + 1] """ return [p for p,_ in factor(n) if p != -1] return [p for p,_ in factor(n)] prime_factors = prime_divisors
• ## 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 prob_gens = [self(P) for P in t] self._simon_two_descent_data[lim1,lim3,limtriv,maxprob,limbigprime] = (prob_rank, two_selmer_rank, prob_gens) return prob_rank, two_selmer_rank, prob_gens def division_field(self, p, names, map=False, simplify=True, simplify_all=False): """ Given an elliptic curve over a number field `F` and a prime number `p`, construct the field `F(E[p])`. INPUT: - ``p`` -- a prime number (an element of `\ZZ`) - ``names`` -- a variable name for the number field - ``map`` -- (default: ``False``) also return an embedding of ``self.base_field()`` into the resulting field. - ``simplify`` -- (default: ``True``) during the algorithm, try to find a simpler defining polynomial for the intermediate number fields. - ``simplify_all`` -- (default: ``False``) If ``True``, simplify intermediate fields and also the resulting number field. OUTPUT: If ``map`` is ``False``, the division field as an absolute number field.  If ``map`` is ``True``, a tuple ``(K, phi)`` where ``phi`` is an embedding of ``self`` in the division field ``K``. .. WARNING:: This takes a very long time when the degree of the division field is large (e.g. when `p` is large or when the Galois representation is surjective).  The value of ``simplify`` also has a big influence on the running time: sometimes ``simplify=False`` is faster, sometimes ``simplify=True`` is faster. EXAMPLES:: sage: E = EllipticCurve('14a1') sage: K. = E.division_field(2); K Number Field in b with defining polynomial x^2 + 5*x + 92 sage: K. = E.division_field(3); K Number Field in b with defining polynomial x^2 + 2*x + 13 sage: E = EllipticCurve('11a1') sage: K. = E.division_field(5); K Number Field in b with defining polynomial x^4 - x^3 + x^2 - x + 1 sage: E.division_field(5, 'b', simplify=False) Number Field in b with defining polynomial x^4 + x^3 + 11*x^2 + 41*x + 101 sage: E.base_extend(K).torsion_subgroup() 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 sage: E = EllipticCurve('27a1') sage: K. = E.division_field(3); K Number Field in b with defining polynomial x^2 + 3*x + 9 sage: K. = E.division_field(2); K Number Field in b with defining polynomial x^6 - 112*x^3 + 27436 sage: K. = E.division_field(2, simplify_all=True); K Number Field in b with defining polynomial x^6 - 3*x^5 + 6*x^4 - 5*x^3 + 6*x^2 - 3*x + 1 sage: E = EllipticCurve('27a1') sage: K. = E.division_field(5); K   # long time (3s on sage.math, 2011) Number Field in b with defining polynomial x^48 ... Even ``E.division_field(7, 'b')`` takes less than a minute. Over a number field:: sage: R. = PolynomialRing(QQ) sage: K. = NumberField(x^2 + 1) sage: E = EllipticCurve([0,0,0,0,i]) sage: L. = E.division_field(2); L Number Field in b with defining polynomial x^4 - x^2 + 1 sage: L., phi = E.division_field(2, map=True); phi Ring morphism: From: Number Field in i with defining polynomial x^2 + 1 To:   Number Field in b with defining polynomial x^4 - x^2 + 1 Defn: i |--> -b^3 sage: E.division_field(3, 'b')  # not tested, known bug AUTHORS: - Jeroen Demeyer (2011-11-10): #11905, use splitting_field() function, moved from ``gal_reps.py``, make it work over number fields. """ verbose("Adjoining x-coordinates of %s-torsion points"%p) F = self.base_ring() f = self.division_polynomial(p) # Galois group is subgroup of GL(2,p) deg_bound = F.degree()*p*(p+1)*(p-1)**2 K = f.splitting_field(names, degree_bound=deg_bound, map=map, simplify=simplify, simplify_all=simplify_all) if map: K,F_to_K = K # If 2*[K:F] is not a divisor of #GL(2,p), we cannot find a # quadratic extension with a Galois group still inside GL(2,p) if deg_bound % (2*K.degree()) == 0: # Adding the y-coordinate gives an extension of degree at most 2 verbose("Adjoining y-coordinates of %s-torsion points"%p) RY = PolynomialRing(F, 'Y') Y = RY.gen() RYX = PolynomialRing(RY, 'x') # For every possible x-coordinate, find a polynomial defining the # y-coordinate # We only need to try one x for every factor over F, since other roots # of the same polynomial are Gal(K/F)-conjugates. for pe in f.factor(): g = pe.change_ring(RY) yxpol = RYX( [self.a6() - Y*(Y + self.a3()), self.a4() - Y*self.a1(), self.a2(), 1] ) ypol = PolynomialRing(K, 'x')(yxpol.resultant(g)) L = ypol.splitting_field(names, degree_bound = 2*K.degree(), map=map, simplify_all=simplify_all) if map: L,K_to_L = L if L.degree() > K.degree(): if map: return L, F_to_K.post_compose(K_to_L) else: return L if map: return K, F_to_K else: return K def height_pairing_matrix(self, points=None, precision=None): 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 res.append(a) return res # these two function could be moved to a better place later def _splitting_field(f): """ Given a polynomial over `\QQ`, this returns the splitting field (as an absolute field over `\QQ`. EXAMPLES:: sage: from sage.schemes.elliptic_curves.gal_reps import _splitting_field sage: R. = QQ[] sage: f = X^2 + 1 sage: _splitting_field(f) Number Field in b with defining polynomial X^2 + 1 sage: f = (X^6-1)*(X^4+1) sage: _splitting_field(f) 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 sage: f = X^3 - 4*X^2 - 160*X - 1264 sage: _splitting_field(f) Number Field in b with defining polynomial x^6 - 992*x^4 + 246016*x^2 + 41229056 sage: f3  = 4*X^3 - 4*X^2 - 40*X - 79 sage: _splitting_field(f3) Number Field in b with defining polynomial x^6 - 992*x^4 + 246016*x^2 + 41229056 sage: f3  = 4*X^3 - 4*X^2 - 40*X - 79 sage: _splitting_field(f3/4) Number Field in b with defining polynomial x^6 - 992*x^4 + 246016*x^2 + 41229056 """ from sage.rings.polynomial.polynomial_ring_constructor import PolynomialRing from sage.rings.all import QQ from sage.misc.flatten import flatten # make an integral monic polynomial out of it d = f.denominator() f = d*f R = PolynomialRing(QQ,'X') f = R(f) X = R.gens() an = f.leading_coefficient() f = an**(f.degree() - 1) * f(X/an) if an != 1: misc.verbose("polynomial changed to %s"%f,3) fs = [ff for ff in f.factor() if ff.degree() > 1 ] while fs != []: K = fs.root_field('a') R = PolynomialRing(K,'X') fs = [R(f) for f in fs] K = K.absolute_field('b') inc = K.structure() misc.verbose("degree of the field is now %s"%K.degree(), 2) R = PolynomialRing(K,'X') fs = [R([inc(u) for u in g.coeffs()]) for g in fs] fs = [[ff for ff in g.factor() if ff.degree() > 1] for g in fs] fs = flatten(fs) return K def _division_field(E,p): """ Given an elliptic curve and a prime `p`, this constructs the field `\QQ(E[p])`. Note this takes a LONG time when p is large or when the representation is surjective. EXAMPLES:: sage: from sage.schemes.elliptic_curves.gal_reps import _division_field sage: E = EllipticCurve('14a1') sage: _division_field(E,2) Number Field in b with defining polynomial X^2 + 5*X + 92 sage: _division_field(E,3) Number Field in b with defining polynomial X^2 + 6*X + 117 sage: E = EllipticCurve('11a1') sage: K = _division_field(E,5); K Number Field in b with defining polynomial x^4 + 5*x^3 + 275*x^2 + 5125*x + 63125 sage: E.base_extend(K).torsion_subgroup() 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 sage: E = EllipticCurve('27a1') sage: _division_field(E,3) Number Field in b with defining polynomial X^2 + 9*X + 81 sage: _division_field(E,2) Number Field in b with defining polynomial x^6 + 5038848 sage: E = EllipticCurve('27a1') sage: L = _division_field(E,5); L   # long time (4s on sage.math, 2011) 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 sage: L.absolute_degree()           # long time 48 Even  _division_field(E,7) works within a few minutes """ from sage.rings.polynomial.polynomial_ring_constructor import PolynomialRing misc.verbose("trying to build the extension by adjoining the %s-torsion poitns"%p,2) f = E.division_polynomial(p) K = _splitting_field(f) EK = E.base_extend(K) if len(EK._p_primary_torsion_basis(p,1)) < 2: misc.verbose("the y-coordinate need to be adjoined, too",2) R = PolynomialRing(K,'Y') Y = R.gens() for xxm in R(f).roots(): xx = xxm g = Y**2 + (EK.a1() * xx + EK.a3() ) * Y - xx**3 - EK.a2()*xx**2 - EK.a4()*xx - EK.a6() if g.roots() == []: K = g.root_field('a').absolute_field('b') break return K class GaloisRepresentation(SageObject): r""" # That allows us to determine almost all cases. f = self.E.division_polynomial(5) K = _splitting_field(f) K = f.splitting_field('x') #EK = self.E.base_extend(K) #d = K.degree() #if len(EK._p_primary_torsion_basis(5,1)) < 2: # is all fails, we probably have a fairly small group and we can try to detect it using the galois_group if p <= 13: K = _division_field(self.E,p) K = self.E.division_field(p, 'b') d = K.absolute_degree() misc.verbose("field of degree %s.  try to compute galois group"%(d),2)