From 37c12b6a776302e3191d0c73374d558d5fe14611 Mon Sep 17 00:00:00 2001 From: John Cremona Date: Thu, 19 Jan 2023 18:07:11 +0000 Subject: [PATCH 01/11] #22697: modularity test for elliptic curves over totally real fields --- .../elliptic_curves/ell_number_field.py | 238 +++++++++++++++++- 1 file changed, 226 insertions(+), 12 deletions(-) diff --git a/src/sage/schemes/elliptic_curves/ell_number_field.py b/src/sage/schemes/elliptic_curves/ell_number_field.py index b9787c1fd6b..45865cd86b9 100644 --- a/src/sage/schemes/elliptic_curves/ell_number_field.py +++ b/src/sage/schemes/elliptic_curves/ell_number_field.py @@ -1,21 +1,25 @@ # -*- coding: utf-8 -*- -r""" -Elliptic curves over number fields +r"""Elliptic curves over number fields An elliptic curve `E` over a number field `K` can be given by a Weierstrass equation whose coefficients lie in `K` or by using ``base_extend`` on an elliptic curve defined over a subfield. -One major difference to elliptic curves over `\QQ` is that there -might not exist a global minimal equation over `K`, when `K` does -not have class number one. -Another difference is the lack of understanding of modularity for -general elliptic curves over general number fields. - -Currently Sage can obtain local information about `E/K_v` for finite places -`v`, it has an interface to Denis Simon's script for 2-descent, it can compute -the torsion subgroup of the Mordell-Weil group `E(K)`, and it can work with -isogenies defined over `K`. +One major difference to elliptic curves over `\QQ` is that there might +not exist a global minimal equation over `K`, when `K` does not have +class number one. When a minimal model does exist the method +:meth:`global_minimal_model()` will compute it, and otherwise compute +a model which is miniaml at all primes except one. Another difference +is the relative lack of understanding of modularity for elliptic +curves over general number fields; the method :meth:`is_modular()` +does implement recent methods to prove modularity of elliptic curves, +over totally real fields only. + +Currently Sage can obtain local information about `E/K_v` for finite +places `v`, it has an interface to Denis Simon's script for 2-descent, +it can compute the torsion subgroup of the Mordell-Weil group `E(K)`, +and it can work with isogenies defined over `K`, including the +determination of the complete isogeny class of any curve. EXAMPLES:: @@ -72,6 +76,7 @@ - [Sil2] Silverman, Joseph H. Advanced topics in the arithmetic of elliptic curves. Graduate Texts in Mathematics, 151. Springer, 1994. + """ # **************************************************************************** @@ -4062,3 +4067,212 @@ def rational_points(self, **kwds): E = E.change_ring(kwds['F']) return [E(pt) for pt in Curve(self).rational_points(**kwds)] + + def is_modular(self, verbose=False): + r"""Returns `True` if the base field is totally real and modularity of + this curve can be proved, otherwise `False`. + + INPUT: + + - ``verbose`` (bool, default ``False``) -- if True, outputs a reason for the conclusion. + + .. NOTE:: + + When `False` is returned, it does not mean that the curve + is not modular! Only that modularity cannot be proved + with current knowledge and implemented methods. It is + expected that the return value will be `True` for all + curves defined over totally real fields; any curve defined + over such fields for which the return value is `False` is + of great interest, as its mod `p` Galois representations + for the primes 3, 5 and 7 are simultaneously nonmaximal. + + There are currently no theoretical results which allow + modularity to be proved over fields other than totally + real fields, with the exception of imaginary quadratic + fields, where it is currently possible to prove modularity + in individual cases by cmputing suitable spaces of Bianchi + modular forms, but this is not implemented. + + ALGORITHM: + + This is based on code provided by S. Siksek and relies on + theorems in the following papers: + + [Chen] Imin Chen, The Jacobian of Modular Curves Associated to Cartan + Subgroups, Oxford DPhil thesis, 1996. + + [FLS] Nuno Freitas, Bao Le Hung, and S. Siksek, Elliptic curves over + Real Quadratic Fields are Modular, Invent. math. (2015) 201, + pp. 159--206. + + [Thorne] Jack Thorne, Automorphy of some residually dihedral Galois + representations. Mathematische Annalen 364 (2016), No. 1--2, + pp. 589--648 + + EXAMPLES. Set ``verbose=True`` to see a reason for the conclusion:: + + sage: E = EllipticCurve('11a1') + sage: E.is_modular(verbose=True) + All elliptic curves over QQ are modular (Wiles et al) + True + sage: K. = QuadraticField(5) + sage: E = EllipticCurve([0,1,0,a,0]) + sage: E.is_modular(verbose=True) + All elliptic curves over real quadratic fields are modular (Freitas, Le Hung and Siksek) + True + sage: E = EllipticCurve([0,0,0,a,0]) + sage: E.is_modular(verbose=True) + All elliptic curves over real quadratic fields are modular (Freitas, Le Hung and Siksek) + True + sage: K. = QuadraticField(-5) + sage: E = EllipticCurve([0,1,0,a,0]) + sage: E.is_modular(verbose=True) + Unable to determine modularity except over totally real fields + False + + Some examples from the LMFDB. Over a totally real cubic field:: + + sage: R. = PolynomialRing(QQ); K. = NumberField(R([-3, -7, -1, 1])) + sage: E = EllipticCurve([K([-4,-1,1]),K([-4,-2,1]),K([-4,-1,1]),K([-2807,-660,446]),K([5874,1376,-933])]) + sage: E.is_modular(verbose=True) + Modularity implied by the mod 3 Galois image being neither reducible nor split + True + + Over a field which is not totally real, no conclusion is currently possible:: + + sage: R. = PolynomialRing(QQ); K. = NumberField(R([1, 0, -1, 1])) + sage: K.is_totally_real() + False + sage: E = EllipticCurve([K([0,0,1]),K([1,0,0]),K([0,0,1]),K([0,0,0]),K([0,0,0])]) + sage: E.is_modular(verbose=True) + Unable to determine modularity except over totally real fields + False + + """ + def not_from(group, p, j): + return len(_modular_polynomial(group, p, j).roots()) == 0 + + K = self.base_field() + if K is QQ: + if verbose: + print("All elliptic curves over QQ are modular (Wiles et al)") + return True + if not K.is_totally_real(): + if verbose: + print("Unable to determine modularity except over totally real fields") + return False # meaning unknown + if K.degree() == 2: + if verbose: + print("All elliptic curves over real quadratic fields are modular (Freitas, Le Hung and Siksek)") + return True + if self.has_cm(): + if verbose: + print("All CM elliptic curves over totally real fields are modular") + return True + + j = self.j_invariant() + + if not_from("borel", 3, j) and not_from("split", 3, j): + if verbose: + print("Modularity implied by the mod 3 Galois image being neither reducible nor split") + return True + + if not_from("borel", 5, j): + if not K(5).is_square(): + if verbose: + print("Modularity implied by the mod 5 Galois image being irreducible and 5 not square") + return True + if not_from("split", 5, j) and not_from("nonsplit", 5, j): + if verbose: + print("Modularity implied by the mod 5 Galois image not being reducible, split, or nonsplit") + return True + + if not_from("borel", 7, j) and not_from("split", 7, j) and not_from("nonsplit", 7, j): + if verbose: + print("Modularity implied by the mod 7 Galois image not being reducible, split, or nonsplit") + return True + + if verbose: + print("Modularity not established: this curve has small image at 3, 5 and 7!") + + return False # We've run out of tricks! + +def _modular_polynomial(group, p, j): + r"""Helper function for the method :meth:`is_modular`. + + INPUT: + + - ``group`` (string) -- one of 'borel', 'split', 'nonsplit'. + + - ``p`` (int) -- a prime number, either 3 or 5 or 7. + + - ``j`` -- an(algebraic number, the `j`-invariant of an elliptic curve. + + OUTPUT: + + A polynomial in one variable `x` with coefficients in the parent + field of ``j`` which has a root if and only if the mod-`p` + representation of elliptic curves with `j`-invariant ``j`` has + image contained in a Borel subgroup, the normaliser of a split + Cartan subgroup, or the normaliser of a non-split Cartan subgroup + respectively (depending on the ``group`` parameter). + + EXAMPLES:: + + sage: from sage.schemes.elliptic_curves.ell_number_field import _modular_polynomial + sage: E = EllipticCurve('11a1').change_ring(QuadraticField(5, 'a')) + sage: j = E.j_invariant() + sage: _modular_polynomial('borel', 3, j) + x^4 + 36*x^3 + 270*x^2 + 243778492/161051*x + 729 + sage: _modular_polynomial('split', 3, j) + x^6 - 18*x^5 + 27*x^4 + 243778492/161051*x^3 - 729*x^2 - 13122*x - 19683 + sage: _modular_polynomial('borel', 5, j) + x^6 + 30*x^5 + 315*x^4 + 1300*x^3 + 1575*x^2 + 242812186/161051*x + 125 + sage: _modular_polynomial('split', 5, j) + x^15 + 30*x^14 + 390*x^13 + 2800*x^12 + 11175*x^11 + 2658577186/161051*x^10 - 8545073600/161051*x^9 - 3318236600/14641*x^8 + 79768901125/161051*x^7 + 950952612750/161051*x^6 + 3261066516250/161051*x^5 + 5917349970000/161051*x^4 + 5381326371875/161051*x^3 + 45039331250/14641*x^2 - 3377861937500/161051*x - 2135097075000/161051 + sage: _modular_polynomial('nonsplit', 5, j) + 43605793936/161051*x^10 + 609382899680/161051*x^9 + 3805439994680/161051*x^8 + 13957069930640/161051*x^7 + 33226111304085/161051*x^6 + 4866186482686/14641*x^5 + 58961494233415/161051*x^4 + 43734191948140/161051*x^3 + 20843516212195/161051*x^2 + 5741876955930/161051*x + 690283481689/161051 + sage: _modular_polynomial('borel', 7, j) + x^8 + 28*x^7 + 322*x^6 + 1904*x^5 + 5915*x^4 + 8624*x^3 + 4018*x^2 + 242490084/161051*x + 49 + sage: _modular_polynomial('split', 7, j) + x^28 - 42*x^27 + 819*x^26 - 9842*x^25 + 81543*x^24 - 493416*x^23 + 2251424*x^22 - 1268191320692/161051*x^21 + 3410611518671/161051*x^20 - 6947130862854/161051*x^19 + 10098387132407/161051*x^18 - 8011521604618/161051*x^17 - 509395128662/14641*x^16 + 32582181402218/161051*x^15 - 62691210143713/161051*x^14 + 73259301822126/161051*x^13 - 46379791168053/161051*x^12 - 6277600417172/161051*x^11 + 46742832789352/161051*x^10 - 49641085864608/161051*x^9 + 2343504014803/14641*x^8 - 861578737314/161051*x^7 - 12167703919007/161051*x^6 + 14278547318070/161051*x^5 - 9423834664881/161051*x^4 + 3112085963896/161051*x^3 - 457632005824/161051*x^2 + 30845635072/161051*x + 122023936/161051 + sage: _modular_polynomial('nonsplit', 7, j) + 400320064/161051*x^21 + 13029623152/161051*x^20 + 228088753900/161051*x^19 + 2408913460821/161051*x^18 + 16642817648786/161051*x^17 + 80889087315407/161051*x^16 + 291040779803200/161051*x^15 + 801917686416123/161051*x^14 + 1729396406547138/161051*x^13 + 2959141014912537/161051*x^12 + 4049663724749832/161051*x^11 + 4450611572214360/161051*x^10 + 3931865527421272/161051*x^9 + 2786855392905248/161051*x^8 + 1576387623537152/161051*x^7 + 704811439294144/161051*x^6 + 22297037611520/14641*x^5 + 5896572491264/14641*x^4 + 12558313746944/161051*x^3 + 152158103552/14641*x^2 + 136821293056/161051*x + 5155295232/161051 + + TESTS:: + + sage: _modular_polynomial('banana', 7, j) + Traceback (most recent call last): + ... + ValueError: (group, p) must be one of ... + sage: _modular_polynomial('borel', 101, j) + Traceback (most recent call last): + ... + ValueError: (group, p) must be one of ... + """ + valid_parameters = [("borel", 3), ("borel", 5), ("borel", 7), + ("split", 3), ("split", 5), ("split", 7), + ("nonsplit", 5), ("nonsplit", 7)] + if (group, p) not in valid_parameters: + raise ValueError("(group, p) must be one of {}".format(valid_parameters)) + + from sage.rings.polynomial.polynomial_ring import polygen + x = polygen(j.parent()) + if group == "borel": + from sage.schemes.elliptic_curves.isogeny_small_degree import Fricke_polynomial + return Fricke_polynomial(p)(x)-j*x + if group == "split": + if p == 3: + return (x-9)**3*(x+3)**3-j*x**3 + if p == 5: + return ((x**2-5)*(x**2+5*x+10)*(x+5))**3-j*(x**2+5*x+5)**5 + if p == 7: + return ((x**2-5*x+8)*(x**2-5*x+1)*(x**4-5*x**3+8*x**2-7*x+7)*(x+1))**3*x-j*(x**3-4*x**2+3*x+1)**7 + if group == "nonsplit": + if p == 5: + return 5**4*(2*x+1)*(x+1)**3*(6*x**2+21*x+19)**3-j*(x**2+x-1)**5 + if p == 7: + return ((4*x**2+5*x+2)*(x**2+3*x+4)*(x**2+10*x+4)*(3*x+1))**3-j*(x**3+x**2-2*x-1)**7 + + raise RuntimeError # cannot happen -- the assertion would have failed. From a752d288b40103c31a9afa8b91eedda64022d1be Mon Sep 17 00:00:00 2001 From: John Cremona Date: Fri, 3 Feb 2023 14:57:07 +0000 Subject: [PATCH 02/11] #22697: modularity test for elliptic curves over imaginary quadratic fields --- src/doc/en/reference/references/index.rst | 17 +++ src/sage/rings/rational_field.py | 33 +++++ .../elliptic_curves/ell_number_field.py | 136 +++++++++++------- 3 files changed, 135 insertions(+), 51 deletions(-) diff --git a/src/doc/en/reference/references/index.rst b/src/doc/en/reference/references/index.rst index e747b14139d..121a2fe1cbb 100644 --- a/src/doc/en/reference/references/index.rst +++ b/src/doc/en/reference/references/index.rst @@ -1317,6 +1317,10 @@ REFERENCES: .. [Can1990] \J. Canny. Generalised characteristic polynomials. J. Symbolic Comput. Vol. 9, No. 3, 1990, 241--250. +.. [CarNew2023] Ana Caraiani and James Newton. + *On the modularity of elliptic curves over imaginary quadratic fields.* + :arxiv:`2301.10509` + .. [Car1972] \R. W. Carter. *Simple groups of Lie type*, volume 28 of Pure and Applied Mathematics. John Wiley and Sons, 1972. @@ -1735,6 +1739,11 @@ REFERENCES: *Counting smaller elements in the tamari and m-tamari lattices*. Journal of Combinatorial Theory, Series A. (2015). :arxiv:`1311.3922`. +.. [Chen1996] Imin Chen. + *The Jacobian of Modular Curves Associated to Cartan Subgroups*. + Oxford DPhil thesis (1996). + https://ora.ouls.ox.ac.uk/objects/uuid:46babaa0-c498-4211-a4ad-8dbabb8f05d9 + .. [CP2016] \N. Cohen, D. Pasechnik, *Implementing Brouwer's database of strongly regular graphs*, Designs, Codes, and Cryptography, 2016 @@ -2454,6 +2463,10 @@ REFERENCES: "Nearly rigid analytic modular forms and their values at CM points", Ph.D. thesis, McGill University, 2011. +.. [FLHS2015] Nuno Freitas, Bao Le Hung, and S. Siksek. + *Elliptic curves over Real Quadratic Fields are Modular.* + Invent. math. (2015) 201, pp. 159--206. + .. [FRT1990] Faddeev, Reshetikhin and Takhtajan. *Quantization of Lie Groups and Lie Algebras*. Leningrad Math. J. vol. **1** (1990), no. 1. @@ -5881,6 +5894,10 @@ REFERENCES: height on elliptic curves over number fields, Math. Comp. 79 (2010), pages 2431-2449. +.. [Thorne2016] Jack Thorne. + *Automorphy of some residually dihedral Galois representations.* + Mathematische Annalen 364 (2016), No. 1--2, pp. 589--648. + .. [Tho2011] Anders Thorup. *ON THE INVARIANTS OF THE SPLITTING ALGEBRA*, 2011, :arxiv:`1105.4478` diff --git a/src/sage/rings/rational_field.py b/src/sage/rings/rational_field.py index 28a4d3b65c0..03a02107e04 100644 --- a/src/sage/rings/rational_field.py +++ b/src/sage/rings/rational_field.py @@ -600,6 +600,39 @@ def signature(self): """ return (Integer(1), Integer(0)) + def is_totally_real(self): + r""" + Return ``True``, since `\QQ` has no non-real complex embeddings. + + EXAMPLES:: + + sage: QQ.is_totally_real() + True + """ + return True + + def is_CM(self): + r""" + Return ``False``, since `\QQ` is not a CM field. + + EXAMPLES:: + + sage: QQ.is_CM() + False + """ + return False + + def is_abelian(self): + r""" + Return ``True``, since `\QQ` is an abelian Galois extension of itself. + + EXAMPLES:: + + sage: QQ.is_abelian() + True + """ + return True + def embeddings(self, K): r""" Return list of the one embedding of `\QQ` into `K`, if it exists. diff --git a/src/sage/schemes/elliptic_curves/ell_number_field.py b/src/sage/schemes/elliptic_curves/ell_number_field.py index 45865cd86b9..95c6af7ea01 100644 --- a/src/sage/schemes/elliptic_curves/ell_number_field.py +++ b/src/sage/schemes/elliptic_curves/ell_number_field.py @@ -13,7 +13,7 @@ class number one. When a minimal model does exist the method is the relative lack of understanding of modularity for elliptic curves over general number fields; the method :meth:`is_modular()` does implement recent methods to prove modularity of elliptic curves, -over totally real fields only. +over totally real and imaginary quadratic fields only. Currently Sage can obtain local information about `E/K_v` for finite places `v`, it has an interface to Denis Simon's script for 2-descent, @@ -2306,9 +2306,9 @@ def gens(self, **kwds): Check that the the point found has infinite order, and that it is on the curve:: - sage: P=gg[0]; P.order() + sage: P=gg[0]; P.order() # long time +Infinity - sage: E.defining_polynomial()(*P) + sage: E.defining_polynomial()(*P) # long time 0 Here is a curve of rank 2:: @@ -4082,71 +4082,93 @@ def is_modular(self, verbose=False): is not modular! Only that modularity cannot be proved with current knowledge and implemented methods. It is expected that the return value will be `True` for all - curves defined over totally real fields; any curve defined - over such fields for which the return value is `False` is - of great interest, as its mod `p` Galois representations - for the primes 3, 5 and 7 are simultaneously nonmaximal. + curves defined over totally real fields, and for all + defined over imaginary quadratic fields over which the + modular curve $X_0(15)$ (with label `15a1`) has rank + zero. Any curve defined over totally real fields for + which the return value is `False` is of interest, as its + mod `p` Galois representations for the primes 3, 5 and 7 + are simultaneously nonmaximal. + + Note that over half of all imaginary quadratic fields, + there exist infinitely many elliptic curves (even up to + twist) whose mod 3 and mod 5 Galois representations are + both reducible (in other words, which posess rational + 15-isogeny). Such curves can be proved to be modular, but + not using the methods implemented here. There are currently no theoretical results which allow modularity to be proved over fields other than totally - real fields, with the exception of imaginary quadratic - fields, where it is currently possible to prove modularity - in individual cases by cmputing suitable spaces of Bianchi - modular forms, but this is not implemented. + real fields and imaginary quadratic fields. ALGORITHM: - This is based on code provided by S. Siksek and relies on - theorems in the following papers: - - [Chen] Imin Chen, The Jacobian of Modular Curves Associated to Cartan - Subgroups, Oxford DPhil thesis, 1996. - - [FLS] Nuno Freitas, Bao Le Hung, and S. Siksek, Elliptic curves over - Real Quadratic Fields are Modular, Invent. math. (2015) 201, - pp. 159--206. - - [Thorne] Jack Thorne, Automorphy of some residually dihedral Galois - representations. Mathematische Annalen 364 (2016), No. 1--2, - pp. 589--648 + This is based on code provided by S. Siksek for the totally + real case, and relies on theorems in the following papers: + [Chen1996]_, [FLHS2015]_, [Thorne2016]_, [CarNew2023]_. EXAMPLES. Set ``verbose=True`` to see a reason for the conclusion:: sage: E = EllipticCurve('11a1') sage: E.is_modular(verbose=True) - All elliptic curves over QQ are modular (Wiles et al) + All elliptic curves over QQ are modular True sage: K. = QuadraticField(5) sage: E = EllipticCurve([0,1,0,a,0]) sage: E.is_modular(verbose=True) - All elliptic curves over real quadratic fields are modular (Freitas, Le Hung and Siksek) + All elliptic curves over real quadratic fields are modular True sage: E = EllipticCurve([0,0,0,a,0]) sage: E.is_modular(verbose=True) - All elliptic curves over real quadratic fields are modular (Freitas, Le Hung and Siksek) + All elliptic curves over real quadratic fields are modular True - sage: K. = QuadraticField(-5) + sage: K. = CyclotomicField(5) sage: E = EllipticCurve([0,1,0,a,0]) sage: E.is_modular(verbose=True) - Unable to determine modularity except over totally real fields + Unable to determine modularity except over totally real and imaginary quadratic fields False Some examples from the LMFDB. Over a totally real cubic field:: - sage: R. = PolynomialRing(QQ); K. = NumberField(R([-3, -7, -1, 1])) + sage: R. = PolynomialRing(QQ) + sage: K. = NumberField(R([-3, -7, -1, 1])) sage: E = EllipticCurve([K([-4,-1,1]),K([-4,-2,1]),K([-4,-1,1]),K([-2807,-660,446]),K([5874,1376,-933])]) sage: E.is_modular(verbose=True) - Modularity implied by the mod 3 Galois image being neither reducible nor split + Modular since the mod 3 Galois image is neither reducible nor split True - Over a field which is not totally real, no conclusion is currently possible:: + Over imaginary quadratic fields `K` over which `X_0(15)` has + positive rank, there are many curves where current results do + not imply modularity:: - sage: R. = PolynomialRing(QQ); K. = NumberField(R([1, 0, -1, 1])) + sage: R. = PolynomialRing(QQ) + sage: K. = NumberField(R([2, -1, 1])) + sage: EllipticCurve('15a1').change_ring(K).rank() + 1 + sage: E = EllipticCurve([K([1,0]),K([1,-1]),K([1,1]),K([-105,98]),K([-615,1188])]) + sage: E.is_modular(verbose=True) + Modularity not established: this curve has small image at 3 and 5 + False + sage: EllipticCurve('15a1').change_ring(K).rank() + 1 + + Nevertheless, over the same field, most curves pass:: + + sage: E = EllipticCurve([K([0,0]),K([0,1]),K([1,1]),K([-8,-3]),K([-5,-5])]) + sage: E.is_modular(verbose=True) + Modular since the mod 3 Galois image is neither reducible nor split + True + + Over a field which is neither totally real nor imaginary + quadratic, no conclusion is currently possible:: + + sage: R. = PolynomialRing(QQ) + sage: K. = NumberField(R([1, 0, -1, 1])) sage: K.is_totally_real() False sage: E = EllipticCurve([K([0,0,1]),K([1,0,0]),K([0,0,1]),K([0,0,0]),K([0,0,0])]) sage: E.is_modular(verbose=True) - Unable to determine modularity except over totally real fields + Unable to determine modularity except over totally real and imaginary quadratic fields False """ @@ -4154,47 +4176,59 @@ def not_from(group, p, j): return len(_modular_polynomial(group, p, j).roots()) == 0 K = self.base_field() - if K is QQ: + d = K.degree() + + if d == 1: if verbose: - print("All elliptic curves over QQ are modular (Wiles et al)") + print("All elliptic curves over QQ are modular") return True - if not K.is_totally_real(): - if verbose: - print("Unable to determine modularity except over totally real fields") - return False # meaning unknown - if K.degree() == 2: + + TR = K.is_totally_real() + + if TR and d == 2: # real quadratic if verbose: - print("All elliptic curves over real quadratic fields are modular (Freitas, Le Hung and Siksek)") + print("All elliptic curves over real quadratic fields are modular") return True + + if d > 2 and not TR: + if verbose: + print("Unable to determine modularity except over totally real and imaginary quadratic fields") + return False # meaning unknown + + # from here either K is totally real (TR True) or imagainary quadratic + if self.has_cm(): if verbose: - print("All CM elliptic curves over totally real fields are modular") + print("All CM elliptic curves over totally real and imaginary quadratic fields are modular") return True j = self.j_invariant() if not_from("borel", 3, j) and not_from("split", 3, j): if verbose: - print("Modularity implied by the mod 3 Galois image being neither reducible nor split") + print("Modular since the mod 3 Galois image is neither reducible nor split") return True if not_from("borel", 5, j): - if not K(5).is_square(): + if not (TR and K(5).is_square()): if verbose: - print("Modularity implied by the mod 5 Galois image being irreducible and 5 not square") + print("Modular since the mod 5 Galois image is irreducible, and 5 not square") return True - if not_from("split", 5, j) and not_from("nonsplit", 5, j): + if TR and not_from("split", 5, j) and not_from("nonsplit", 5, j): if verbose: - print("Modularity implied by the mod 5 Galois image not being reducible, split, or nonsplit") + print("Modular since the mod 5 Galois image is not reducible, split, or nonsplit") return True - if not_from("borel", 7, j) and not_from("split", 7, j) and not_from("nonsplit", 7, j): + if TR and not_from("borel", 7, j) and not_from("split", 7, j) and not_from("nonsplit", 7, j): if verbose: - print("Modularity implied by the mod 7 Galois image not being reducible, split, or nonsplit") + print("Modular since the mod 7 Galois image is not being reducible, split, or nonsplit") return True if verbose: - print("Modularity not established: this curve has small image at 3, 5 and 7!") + if TR: + print("Modularity not established: this curve has small image at 3, 5 and 7") + else: + print("Modularity not established: this curve has small image at 3 and 5") return False # We've run out of tricks! From 9dee295a9c179b85fad900c601d0c9e87e9cb752 Mon Sep 17 00:00:00 2001 From: John Cremona Date: Wed, 8 Feb 2023 10:07:11 +0000 Subject: [PATCH 03/11] fix two lint issues --- src/sage/modular/modform/notes.py | 2 +- src/sage/sat/solvers/dimacs.py | 1 - 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/src/sage/modular/modform/notes.py b/src/sage/modular/modform/notes.py index 474147e22e3..833bb017bfd 100644 --- a/src/sage/modular/modform/notes.py +++ b/src/sage/modular/modform/notes.py @@ -1,4 +1,4 @@ -""" +r""" Design notes The implementation depends on the fact that we have dimension formulas diff --git a/src/sage/sat/solvers/dimacs.py b/src/sage/sat/solvers/dimacs.py index 92d68658eac..ce7dcf41d96 100644 --- a/src/sage/sat/solvers/dimacs.py +++ b/src/sage/sat/solvers/dimacs.py @@ -752,4 +752,3 @@ class Kissat(DIMACS): """ command = "kissat -q {input}" - From d5e0e305d94e858d540916985e14b32463e4ca84 Mon Sep 17 00:00:00 2001 From: John Cremona Date: Fri, 10 Feb 2023 16:45:45 +0000 Subject: [PATCH 04/11] #22697 changes suggested by reviewer --- .../elliptic_curves/ell_number_field.py | 53 +++++++++++++------ 1 file changed, 36 insertions(+), 17 deletions(-) diff --git a/src/sage/schemes/elliptic_curves/ell_number_field.py b/src/sage/schemes/elliptic_curves/ell_number_field.py index ee9ff06157d..687e514c7d2 100644 --- a/src/sage/schemes/elliptic_curves/ell_number_field.py +++ b/src/sage/schemes/elliptic_curves/ell_number_field.py @@ -1,5 +1,6 @@ # -*- coding: utf-8 -*- -r"""Elliptic curves over number fields +r""" +Elliptic curves over number fields An elliptic curve `E` over a number field `K` can be given by a Weierstrass equation whose coefficients lie in `K` or by @@ -4069,8 +4070,10 @@ def rational_points(self, **kwds): return [E(pt) for pt in Curve(self).rational_points(**kwds)] def is_modular(self, verbose=False): - r"""Returns `True` if the base field is totally real and modularity of - this curve can be proved, otherwise `False`. + r""" + Return ``True`` if the base field is totally real or imaginary + quadratic and modularity of this curve can be proved, + otherwise ``False``. INPUT: @@ -4078,15 +4081,15 @@ def is_modular(self, verbose=False): .. NOTE:: - When `False` is returned, it does not mean that the curve + When ``False`` is returned, it does not mean that the curve is not modular! Only that modularity cannot be proved with current knowledge and implemented methods. It is - expected that the return value will be `True` for all + expected that the return value will be ``True`` for all curves defined over totally real fields, and for all defined over imaginary quadratic fields over which the - modular curve $X_0(15)$ (with label `15a1`) has rank + modular curve `X_0(15)` (with label `15a1`) has rank zero. Any curve defined over totally real fields for - which the return value is `False` is of interest, as its + which the return value is ``False`` is of interest, as its mod `p` Galois representations for the primes 3, 5 and 7 are simultaneously nonmaximal. @@ -4107,7 +4110,9 @@ def is_modular(self, verbose=False): real case, and relies on theorems in the following papers: [Chen1996]_, [FLHS2015]_, [Thorne2016]_, [CarNew2023]_. - EXAMPLES. Set ``verbose=True`` to see a reason for the conclusion:: + EXAMPLES: + + Set ``verbose=True`` to see a reason for the conclusion:: sage: E = EllipticCurve('11a1') sage: E.is_modular(verbose=True) @@ -4173,7 +4178,7 @@ def is_modular(self, verbose=False): """ def not_from(group, p, j): - return len(_modular_polynomial(group, p, j).roots()) == 0 + return not _modular_polynomial(group, p, j).roots() K = self.base_field() d = K.degree() @@ -4233,14 +4238,13 @@ def not_from(group, p, j): return False # We've run out of tricks! def _modular_polynomial(group, p, j): - r"""Helper function for the method :meth:`is_modular`. + r""" + Helper function for the method :meth:`is_modular`. INPUT: - - ``group`` (string) -- one of 'borel', 'split', 'nonsplit'. - + - ``group`` (string) -- one of ``'borel'``, ``'split'``, ``'nonsplit'``. - ``p`` (int) -- a prime number, either 3 or 5 or 7. - - ``j`` -- an(algebraic number, the `j`-invariant of an elliptic curve. OUTPUT: @@ -4264,15 +4268,30 @@ def _modular_polynomial(group, p, j): sage: _modular_polynomial('borel', 5, j) x^6 + 30*x^5 + 315*x^4 + 1300*x^3 + 1575*x^2 + 242812186/161051*x + 125 sage: _modular_polynomial('split', 5, j) - x^15 + 30*x^14 + 390*x^13 + 2800*x^12 + 11175*x^11 + 2658577186/161051*x^10 - 8545073600/161051*x^9 - 3318236600/14641*x^8 + 79768901125/161051*x^7 + 950952612750/161051*x^6 + 3261066516250/161051*x^5 + 5917349970000/161051*x^4 + 5381326371875/161051*x^3 + 45039331250/14641*x^2 - 3377861937500/161051*x - 2135097075000/161051 + x^15 + 30*x^14 + 390*x^13 + 2800*x^12 + 11175*x^11 + 2658577186/161051*x^10 - 8545073600/161051*x^9 + - 3318236600/14641*x^8 + 79768901125/161051*x^7 + 950952612750/161051*x^6 + 3261066516250/161051*x^5 + + 5917349970000/161051*x^4 + 5381326371875/161051*x^3 + 45039331250/14641*x^2 - 3377861937500/161051*x + - 2135097075000/161051 sage: _modular_polynomial('nonsplit', 5, j) - 43605793936/161051*x^10 + 609382899680/161051*x^9 + 3805439994680/161051*x^8 + 13957069930640/161051*x^7 + 33226111304085/161051*x^6 + 4866186482686/14641*x^5 + 58961494233415/161051*x^4 + 43734191948140/161051*x^3 + 20843516212195/161051*x^2 + 5741876955930/161051*x + 690283481689/161051 + 43605793936/161051*x^10 + 609382899680/161051*x^9 + 3805439994680/161051*x^8 + 13957069930640/161051*x^7 + + 33226111304085/161051*x^6 + 4866186482686/14641*x^5 + 58961494233415/161051*x^4 + 43734191948140/161051*x^3 + + 20843516212195/161051*x^2 + 5741876955930/161051*x + 690283481689/161051 sage: _modular_polynomial('borel', 7, j) x^8 + 28*x^7 + 322*x^6 + 1904*x^5 + 5915*x^4 + 8624*x^3 + 4018*x^2 + 242490084/161051*x + 49 sage: _modular_polynomial('split', 7, j) - x^28 - 42*x^27 + 819*x^26 - 9842*x^25 + 81543*x^24 - 493416*x^23 + 2251424*x^22 - 1268191320692/161051*x^21 + 3410611518671/161051*x^20 - 6947130862854/161051*x^19 + 10098387132407/161051*x^18 - 8011521604618/161051*x^17 - 509395128662/14641*x^16 + 32582181402218/161051*x^15 - 62691210143713/161051*x^14 + 73259301822126/161051*x^13 - 46379791168053/161051*x^12 - 6277600417172/161051*x^11 + 46742832789352/161051*x^10 - 49641085864608/161051*x^9 + 2343504014803/14641*x^8 - 861578737314/161051*x^7 - 12167703919007/161051*x^6 + 14278547318070/161051*x^5 - 9423834664881/161051*x^4 + 3112085963896/161051*x^3 - 457632005824/161051*x^2 + 30845635072/161051*x + 122023936/161051 + x^28 - 42*x^27 + 819*x^26 - 9842*x^25 + 81543*x^24 - 493416*x^23 + 2251424*x^22 - 1268191320692/161051*x^21 + + 3410611518671/161051*x^20 - 6947130862854/161051*x^19 + 10098387132407/161051*x^18 - 8011521604618/161051*x^17 + - 509395128662/14641*x^16 + 32582181402218/161051*x^15 - 62691210143713/161051*x^14 + 73259301822126/161051*x^13 + - 46379791168053/161051*x^12 - 6277600417172/161051*x^11 + 46742832789352/161051*x^10 - 49641085864608/161051*x^9 + + 2343504014803/14641*x^8 - 861578737314/161051*x^7 - 12167703919007/161051*x^6 + 14278547318070/161051*x^5 + - 9423834664881/161051*x^4 + 3112085963896/161051*x^3 - 457632005824/161051*x^2 + 30845635072/161051*x + 122023936/161051 sage: _modular_polynomial('nonsplit', 7, j) - 400320064/161051*x^21 + 13029623152/161051*x^20 + 228088753900/161051*x^19 + 2408913460821/161051*x^18 + 16642817648786/161051*x^17 + 80889087315407/161051*x^16 + 291040779803200/161051*x^15 + 801917686416123/161051*x^14 + 1729396406547138/161051*x^13 + 2959141014912537/161051*x^12 + 4049663724749832/161051*x^11 + 4450611572214360/161051*x^10 + 3931865527421272/161051*x^9 + 2786855392905248/161051*x^8 + 1576387623537152/161051*x^7 + 704811439294144/161051*x^6 + 22297037611520/14641*x^5 + 5896572491264/14641*x^4 + 12558313746944/161051*x^3 + 152158103552/14641*x^2 + 136821293056/161051*x + 5155295232/161051 + 400320064/161051*x^21 + 13029623152/161051*x^20 + 228088753900/161051*x^19 + 2408913460821/161051*x^18 + + 16642817648786/161051*x^17 + 80889087315407/161051*x^16 + 291040779803200/161051*x^15 + 801917686416123/161051*x^14 + + 1729396406547138/161051*x^13 + 2959141014912537/161051*x^12 + 4049663724749832/161051*x^11 + + 4450611572214360/161051*x^10 + 3931865527421272/161051*x^9 + 2786855392905248/161051*x^8 + + 1576387623537152/161051*x^7 + 704811439294144/161051*x^6 + 22297037611520/14641*x^5 + 5896572491264/14641*x^4 + + 12558313746944/161051*x^3 + 152158103552/14641*x^2 + 136821293056/161051*x + 5155295232/161051 TESTS:: From 392cc1347a3d265e9d961287b3e202c3e257cc0d Mon Sep 17 00:00:00 2001 From: John Cremona Date: Mon, 20 Feb 2023 10:11:07 +0000 Subject: [PATCH 05/11] implemented reviewers' suggestions --- .../elliptic_curves/ell_number_field.py | 26 ++++++++++--------- 1 file changed, 14 insertions(+), 12 deletions(-) diff --git a/src/sage/schemes/elliptic_curves/ell_number_field.py b/src/sage/schemes/elliptic_curves/ell_number_field.py index 05a108f2fd4..9c39f6a5b21 100644 --- a/src/sage/schemes/elliptic_curves/ell_number_field.py +++ b/src/sage/schemes/elliptic_curves/ell_number_field.py @@ -4074,24 +4074,25 @@ def rational_points(self, **kwds): return [E(pt) for pt in Curve(self).rational_points(**kwds)] def is_modular(self, verbose=False): - r"""Returns `True` if the base field is totally real and modularity of + r""" + Returns `True` if the base field is totally real and modularity of this curve can be proved, otherwise `False`. INPUT: - - ``verbose`` (bool, default ``False``) -- if True, outputs a reason for the conclusion. + - ``verbose`` (bool, default ``False``) -- if ``True``, outputs a reason for the conclusion. .. NOTE:: - When `False` is returned, it does not mean that the curve + When ``False`` is returned, it does not mean that the curve is not modular! Only that modularity cannot be proved with current knowledge and implemented methods. It is - expected that the return value will be `True` for all + expected that the return value will be ``True`` for all curves defined over totally real fields, and for all defined over imaginary quadratic fields over which the - modular curve $X_0(15)$ (with label `15a1`) has rank + modular curve `X_0(15)` (with label `15a1`) has rank zero. Any curve defined over totally real fields for - which the return value is `False` is of interest, as its + which the return value is ``False`` is of interest, as its mod `p` Galois representations for the primes 3, 5 and 7 are simultaneously nonmaximal. @@ -4112,7 +4113,9 @@ def is_modular(self, verbose=False): real case, and relies on theorems in the following papers: [Chen1996]_, [FLHS2015]_, [Thorne2016]_, [CarNew2023]_. - EXAMPLES. Set ``verbose=True`` to see a reason for the conclusion:: + EXAMPLES: + + Set ``verbose=True`` to see a reason for the conclusion:: sage: E = EllipticCurve('11a1') sage: E.is_modular(verbose=True) @@ -4178,7 +4181,7 @@ def is_modular(self, verbose=False): """ def not_from(group, p, j): - return len(_modular_polynomial(group, p, j).roots()) == 0 + return not _modular_polynomial(group, p, j).roots() K = self.base_field() d = K.degree() @@ -4238,15 +4241,14 @@ def not_from(group, p, j): return False # We've run out of tricks! def _modular_polynomial(group, p, j): - r"""Helper function for the method :meth:`is_modular`. + r""" + Helper function for the method :meth:`is_modular`. INPUT: - ``group`` (string) -- one of 'borel', 'split', 'nonsplit'. - - ``p`` (int) -- a prime number, either 3 or 5 or 7. - - - ``j`` -- an(algebraic number, the `j`-invariant of an elliptic curve. + - ``j`` -- an algebraic number; the `j`-invariant of an elliptic curve. OUTPUT: From e8cb50f3c5466e8be6797be444b857d65f348238 Mon Sep 17 00:00:00 2001 From: John Cremona Date: Mon, 20 Feb 2023 16:05:04 +0000 Subject: [PATCH 06/11] added new tests for Galois reps over number fields being Borel, Cartan, etc --- .../elliptic_curves/gal_reps_number_field.py | 365 +++++++++++++++++- 1 file changed, 364 insertions(+), 1 deletion(-) diff --git a/src/sage/schemes/elliptic_curves/gal_reps_number_field.py b/src/sage/schemes/elliptic_curves/gal_reps_number_field.py index d484a4a18bd..0e76706b1a3 100644 --- a/src/sage/schemes/elliptic_curves/gal_reps_number_field.py +++ b/src/sage/schemes/elliptic_curves/gal_reps_number_field.py @@ -53,7 +53,7 @@ from sage.arith.all import legendre_symbol, primes from sage.sets.set import Set from sage.rings.all import Integer, ZZ, QQ, Infinity - +from sage.rings.polynomial.polynomial_ring import polygen class GaloisRepresentation(SageObject): r""" @@ -402,6 +402,369 @@ def reducible_primes(self): return [l for l in self.isogeny_bound() if self.E.isogenies_prime_degree(l)] + def is_borel(self, p): + r""" + Return ``True`` if the projective mod-`p` image is contained in a Borel subgroup. + + INPUT: + + - ``p`` (integer) -- a prime number + + OUTPUT: + + (boolean) ``True or ``False``. + + EXAMPLES:: + + sage: from sage.schemes.elliptic_curves.gal_reps_number_field import GaloisRepresentation + sage: E = EllipticCurve('56b1') + sage: G = GaloisRepresentation(E) + sage: G.is_borel(2) + True + sage: E = EllipticCurve('50a1') + sage: G = GaloisRepresentation(E) + sage: G.is_borel(3) + True + sage: G.is_borel(5) + True + sage: E.has_cm() + False + sage: E = EllipticCurve('405d1') + sage: G = GaloisRepresentation(E) + sage: G.is_borel(7) + True + sage: E = EllipticCurve('121a1') + sage: G = GaloisRepresentation(E) + sage: G.is_borel(11) + True + sage: E = EllipticCurve('147c1') + sage: G = GaloisRepresentation(E) + sage: G.is_borel(13) + True + + TESTS:: + + sage: from sage.schemes.elliptic_curves.gal_reps_number_field import GaloisRepresentation + sage: E = EllipticCurve('11a1') + sage: G = GaloisRepresentation(E) + sage: G.is_borel(4) + Traceback (most recent call last): + ... + NotImplementedError: p = 4 should be prime + sage: G.is_borel(x) + Traceback (most recent call last): + ... + ValueError: p = x should be a prime integer + """ + if p == 2: + return not self.E.division_polynomial(2).is_irreducible() + + # for p = 3, 5, 7, 13 we use the fact that X_0(p) has genus 0 + if p in [3, 5, 7, 13]: + from sage.schemes.elliptic_curves.isogeny_small_degree import Fricke_polynomial + j = self.E.j_invariant() + x = polygen(j.parent()) + return bool((Fricke_polynomial(p)(x)-j*x).roots()) # True iff list not empty + + try: + p = ZZ(p) + except TypeError: + raise ValueError("p = {} should be a prime integer".format(p)) + if not p.is_prime(): + raise NotImplementedError("p = {} should be prime".format(p)) + + # the general case requires more work. + # First we see if local conditions pass: + if p not in Frobenius_filter(self.E, [p]): + return False + + # Now there is a p-isogeny modulo many primes of good reduction and we do a final check: + return bool(self.E.isogenies_prime_degree(p)) # True iff list not empty + + is_reducible = is_borel + + def is_split_normaliser(self, p): + r""" + Return ``True`` if the projective mod-`p` image is contained in the normaliser of a split Cartan subgroup. + + INPUT: + + - ``p`` (integer) -- an odd prime number + + OUTPUT: + + (boolean) ``True`` if the projective mod-`p` image is + contained in the normaliser of a split Cartan subgroup, else + ``False``. + + ALGORITHM: + + This method is currently only implemented for primes `p` for + which the modular curve `X_{\text{sp}}^{+}(p)` has genus 0, + namely `p=2,3,5,7`. In these cases we use an explicit formula + for the map from the modular curve to the `j`-line, checking + that the curve's `j`-invariant is in the image. + + .. NOTE:: + + `X_{\text{sp}}^{+}(2)` is the same as `X_0(2)`. + + EXAMPLES:: + + sage: from sage.schemes.elliptic_curves.gal_reps_number_field import GaloisRepresentation + sage: E = EllipticCurve('56b1') + sage: G = GaloisRepresentation(E) + sage: G.is_split_normaliser(2) + True + sage: E = EllipticCurve('54a1') + sage: G = GaloisRepresentation(E) + sage: G.is_split_normaliser(3) + True + sage: E = EllipticCurve('800i1') + sage: G = GaloisRepresentation(E) + sage: G.is_split_normaliser(5) + True + sage: E = EllipticCurve('2450d1') + sage: G = GaloisRepresentation(E) + sage: G.is_split_normaliser(7) + True + + TESTS:: + + sage: from sage.schemes.elliptic_curves.gal_reps_number_field import GaloisRepresentation + sage: E = EllipticCurve('11a1') + sage: G = GaloisRepresentation(E) + sage: G.is_split_normaliser(4) + Traceback (most recent call last): + ... + NotImplementedError: p = 4 should be prime and at most 7 + sage: G.is_split_normaliser(x) + Traceback (most recent call last): + ... + ValueError: p = x should be a prime integer, at most 7 + sage: G.is_split_normaliser(17) + Traceback (most recent call last): + ... + NotImplementedError: Only implemented for p<=7 + """ + if p == 2: + return self.is_borel(2) + j = self.E.j_invariant() + x = polygen(j.parent()) + pol = None + if p == 3: + pol = (x-9)**3 * (x+3)**3 - j * x**3 + if p == 5: + pol = ((x**2-5) * (x**2+5*x+10) * (x+5))**3 - j * (x**2+5*x+5)**5 + if p == 7: + pol = ((x**2-5*x+8) * (x**2-5*x+1) * (x**4-5*x**3+8*x**2-7*x+7) * (x+1))**3*x - j * (x**3-4*x**2+3*x+1)**7 + if pol: + return bool(pol.roots()) + + try: + if ZZ(p).is_prime(): + raise NotImplementedError("Only implemented for p<=7") + else: + raise NotImplementedError("p = {} should be prime and at most 7".format(p)) + except TypeError: + raise ValueError("p = {} should be a prime integer, at most 7".format(p)) + + + def is_split(self, p): + r""" + Return ``True`` if the projective mod-`p` image is contained in a split Cartan subgroup. + + INPUT: + + - ``p`` (integer) -- a prime number + + OUTPUT: + + (boolean) ``True`` if the projective mod-`p` image is + contained in a split Cartan subgroup, else ``False``. + + ALGORITHM: + + This method is currently only implemented for primes `p` for + which the modular curve `X_{\text{sp}}(p)$ has genus 0, + namely `p=2,3,5`. In these cases we use an explicit formula + for the map from the modular curve to the `j`-line, checking + that the curve's `j`-invariant is in the image. + + .. NOTE:: + + `X_{\text{sp}}(2)` is the same as `X(2)`. + + EXAMPLES:: + + sage: from sage.schemes.elliptic_curves.gal_reps_number_field import GaloisRepresentation + sage: E = EllipticCurve('56b1') + sage: G = GaloisRepresentation(E) + sage: G.is_split_normaliser(2) + True + sage: E = EllipticCurve('54a1') + sage: G = GaloisRepresentation(E) + sage: G.is_split_normaliser(3) + True + sage: E = EllipticCurve('800i1') + sage: G = GaloisRepresentation(E) + sage: G.is_split_normaliser(5) + True + sage: E = EllipticCurve('2450d1') + sage: G = GaloisRepresentation(E) + sage: G.is_split_normaliser(7) + True + + TESTS:: + + sage: from sage.schemes.elliptic_curves.gal_reps_number_field import GaloisRepresentation + sage: E = EllipticCurve('11a1') + sage: G = GaloisRepresentation(E) + sage: G.is_split(4) + Traceback (most recent call last): + ... + NotImplementedError: p = 4 should be prime and at most 5 + sage: G.is_split(x) + Traceback (most recent call last): + ... + ValueError: p = x should be a prime integer, at most 5 + sage: G.is_split(7) + Traceback (most recent call last): + ... + NotImplementedError: Only implemented for p<=5 + """ + j = self.E.j_invariant() + x = polygen(j.parent()) + pol = None + if p == 2: + pol = (x**2+192)**3 - j * (x-8)**2 * (x+8)**2 + if p == 3: + pol = x**3 * (x+6)**3 * (x**2-6*x+36)**3 - j * (x-3)**3 * (x**2+3*x+9)**3 + if p == 5: + pol1 = x**30 * (x**2-12*x+16)**3 * (x**4-4*x**3+176*x**2+256*x+4096)**3 * (x**4+16*x**3+176*x**2+896*x+7936)**3 + pol2 = -2**10 * x**30 * (x+4)**5 * (x**4-4*x**3+96*x**2-384*x+2816)**5 + pol = pol1 - j * pol2 + if pol: + return bool(pol.roots()) + + try: + if ZZ(p).is_prime(): + raise NotImplementedError("Only implemented for p<=5") + else: + raise NotImplementedError("p = {} should be prime and at most 5".format(p)) + except TypeError: + raise ValueError("p = {} should be a prime integer, at most 5".format(p)) + + def is_nonsplit_normaliser(self, p): + r""" + Return ``True`` if the projective mod-`p` image is contained in the normaliser of a nonsplit Cartan subgroup. + + INPUT: + + - ``p`` (integer) -- an odd prime number + + OUTPUT: + + (boolean) ``True`` if the projective mod-`p` image is + contained in the normaliser of a nonsplit Cartan subgroup, + else ``False``. + + ALGORITHM: + + This method is currently only implemented for primes `p` for + which the modular curve `X_{\text{ns}}^{+}(p) has genus 0, + namely `p=3,5,7`. In these cases we use an explicit formula + for the map from the modular curve to the `j`-line, checking + that the curve's `j`-invariant is in the image. + + `X_{\text{ns}}^{+}(2)` is not defined. + + EXAMPLES:: + + sage: from sage.schemes.elliptic_curves.gal_reps_number_field import GaloisRepresentation + sage: E = EllipticCurve('54a1') + sage: G = GaloisRepresentation(E) + sage: G.is_nonsplit_normaliser(3) + True + sage: E = EllipticCurve('675b1') + sage: G = GaloisRepresentation(E) + sage: G.is_nonsplit_normaliser(5) + True + sage: E = EllipticCurve([0, -1, 1, -5373758, -9740388623]) # '15341b1' + sage: G = GaloisRepresentation(E) + sage: G.is_nonsplit_normaliser(7) + True + + TESTS:: + + sage: from sage.schemes.elliptic_curves.gal_reps_number_field import GaloisRepresentation + sage: E = EllipticCurve('11a1') + sage: G = GaloisRepresentation(E) + sage: G.is_nonsplit_normaliser(4) + Traceback (most recent call last): + ... + NotImplementedError: p = 4 should be prime, either 3, 5, or 7 + sage: G.is_nonsplit_normaliser(x) + Traceback (most recent call last): + ... + ValueError: p = x should be a prime integer, either 3, 5, or 7 + sage: G.is_nonsplit_normaliser(11) + Traceback (most recent call last): + ... + NotImplementedError: Only implemented for p<=7 + """ + if p == 2: + raise ValueError("Normaliser of nonsplit Cartan not defined for p=2") + j = self.E.j_invariant() + x = polygen(j.parent()) + pol = None + if p == 3: + pol = x**3 - j + if p == 5: + pol = 5**4 * (2*x+1) * (x+1)**3 * (6*x**2+21*x+19)**3 - j * (x**2+x-1)**5 + if p == 7: + pol = ((4*x**2+5*x+2) * (x**2+3*x+4) * (x**2+10*x+4) * (3*x+1))**3 - j * (x**3+x**2-2*x-1)**7 + if pol: + return bool(pol.roots()) + + try: + if ZZ(p).is_prime(): + raise NotImplementedError("Only implemented for p<=7") + else: + raise NotImplementedError("p = {} should be prime, either 3, 5, or 7".format(p)) + except TypeError: + raise ValueError("p = {} should be a prime integer, either 3, 5, or 7".format(p)) + + def is_nonsplit(self, p): + r""" + Return ``True`` if the projective mod-`p` image is contained in a nonsplit Cartan subgroup. + + INPUT: + + - ``p`` (integer) -- a prime number + + OUTPUT: + + (boolean) ``True`` if the projective mod-`p` image is + contained in a nonsplit Cartan subgroup, else ``False``. + + ALGORITHM: + + This method is currently only implemented for primes `p` for + which the modular curve `X_{\text{ns}}(p) has genus 0 and has + a rational point, namely `p=2` only. (For `p=3,5` the genus + is zero but there are no rational points.) In this cases we + use an explicit formula for the map from the modular curve to + the `j`-line, checking that the curve's `j`-invariant is in + the image. For `p=2` this is simply that `j-1728` must be a + square. + """ + j = self.E.j_invariant() + if p == 2: + return (j-1728).is_square() + + raise NotImplementedError("Only implemented for p==2") + def _non_surjective(E, patience=100): r""" Return a list of primes `p` including all primes for which the mod-`p` From 7891a96e4d06baef60dcd627ce3ff0d761da9e86 Mon Sep 17 00:00:00 2001 From: John Cremona Date: Mon, 20 Feb 2023 19:03:55 +0000 Subject: [PATCH 07/11] rewrite is_modular to use new GalRep functionality --- .../elliptic_curves/ell_number_field.py | 135 ++++-------------- .../elliptic_curves/gal_reps_number_field.py | 4 +- 2 files changed, 32 insertions(+), 107 deletions(-) diff --git a/src/sage/schemes/elliptic_curves/ell_number_field.py b/src/sage/schemes/elliptic_curves/ell_number_field.py index 9c39f6a5b21..f1fad977153 100644 --- a/src/sage/schemes/elliptic_curves/ell_number_field.py +++ b/src/sage/schemes/elliptic_curves/ell_number_field.py @@ -4075,8 +4075,8 @@ def rational_points(self, **kwds): def is_modular(self, verbose=False): r""" - Returns `True` if the base field is totally real and modularity of - this curve can be proved, otherwise `False`. + Returns ``True`` if the base field is totally real and modularity of + this curve can be proved, otherwise ``False``. INPUT: @@ -4084,22 +4084,23 @@ def is_modular(self, verbose=False): .. NOTE:: - When ``False`` is returned, it does not mean that the curve - is not modular! Only that modularity cannot be proved - with current knowledge and implemented methods. It is - expected that the return value will be ``True`` for all + When ``False`` is returned, it does not mean that the + curve is not modular! Only that modularity cannot be + proved with current knowledge and implemented methods. It + is expected that the return value will be ``True`` for all curves defined over totally real fields, and for all defined over imaginary quadratic fields over which the - modular curve `X_0(15)` (with label `15a1`) has rank - zero. Any curve defined over totally real fields for - which the return value is ``False`` is of interest, as its - mod `p` Galois representations for the primes 3, 5 and 7 - are simultaneously nonmaximal. - - Note that over half of all imaginary quadratic fields, + modular curve `X_0(15)` (which is the elliptic curve with + label `15a1`) has rank zero. Any curve defined over + totally real fields for which the return value is + ``False`` is of interest, as its mod `p` Galois + representations for the primes 3, 5 and 7 are + simultaneously small. + + Note that for over half of all imaginary quadratic fields, there exist infinitely many elliptic curves (even up to twist) whose mod 3 and mod 5 Galois representations are - both reducible (in other words, which posess rational + both reducible (in other words, which posess a rational 15-isogeny). Such curves can be proved to be modular, but not using the methods implemented here. @@ -4111,7 +4112,12 @@ def is_modular(self, verbose=False): This is based on code provided by S. Siksek for the totally real case, and relies on theorems in the following papers: - [Chen1996]_, [FLHS2015]_, [Thorne2016]_, [CarNew2023]_. + [Chen1996]_, [FLHS2015]_, [Thorne2016]_, [CarNew2023]_. It + relies on checking that the images of the mod-`p` Galois + representation attached to the elliptic curve for `p=3,5,7` + are not simultaneously small expcept for the cases (base field + `\QQ` or real quadratic) where theoretical results show this to + be impossible. EXAMPLES: @@ -4180,20 +4186,17 @@ def is_modular(self, verbose=False): False """ - def not_from(group, p, j): - return not _modular_polynomial(group, p, j).roots() - K = self.base_field() d = K.degree() - if d == 1: + if d == 1: # base field QQ if verbose: print("All elliptic curves over QQ are modular") return True TR = K.is_totally_real() - if TR and d == 2: # real quadratic + if TR and d == 2: # base field real quadratic if verbose: print("All elliptic curves over real quadratic fields are modular") return True @@ -4201,33 +4204,33 @@ def not_from(group, p, j): if d > 2 and not TR: if verbose: print("Unable to determine modularity except over totally real and imaginary quadratic fields") - return False # meaning unknown + return False # meaning 'unknown' - # from here either K is totally real (TR True) or imagainary quadratic + # from here either K is totally real (TR is True) or imagainary quadratic if self.has_cm(): if verbose: print("All CM elliptic curves over totally real and imaginary quadratic fields are modular") return True - j = self.j_invariant() + G = self.galois_representation() - if not_from("borel", 3, j) and not_from("split", 3, j): + if not (G.is_borel(3) or G.is_split_normaliser(3)): if verbose: print("Modular since the mod 3 Galois image is neither reducible nor split") return True - if not_from("borel", 5, j): + if not G.is_borel(5): if not (TR and K(5).is_square()): if verbose: print("Modular since the mod 5 Galois image is irreducible, and 5 not square") return True - if TR and not_from("split", 5, j) and not_from("nonsplit", 5, j): + if TR and not (G.is_split_normaliser(5) or G.is_nonsplit_normaliser(5)): if verbose: print("Modular since the mod 5 Galois image is not reducible, split, or nonsplit") return True - if TR and not_from("borel", 7, j) and not_from("split", 7, j) and not_from("nonsplit", 7, j): + if TR and not (G.is_borel(7) or G.is_split_normaliser(7) or G.is_nonsplit_normaliser(7)): if verbose: print("Modular since the mod 7 Galois image is not being reducible, split, or nonsplit") return True @@ -4239,81 +4242,3 @@ def not_from(group, p, j): print("Modularity not established: this curve has small image at 3 and 5") return False # We've run out of tricks! - -def _modular_polynomial(group, p, j): - r""" - Helper function for the method :meth:`is_modular`. - - INPUT: - - - ``group`` (string) -- one of 'borel', 'split', 'nonsplit'. - - ``p`` (int) -- a prime number, either 3 or 5 or 7. - - ``j`` -- an algebraic number; the `j`-invariant of an elliptic curve. - - OUTPUT: - - A polynomial in one variable `x` with coefficients in the parent - field of ``j`` which has a root if and only if the mod-`p` - representation of elliptic curves with `j`-invariant ``j`` has - image contained in a Borel subgroup, the normaliser of a split - Cartan subgroup, or the normaliser of a non-split Cartan subgroup - respectively (depending on the ``group`` parameter). - - EXAMPLES:: - - sage: from sage.schemes.elliptic_curves.ell_number_field import _modular_polynomial - sage: E = EllipticCurve('11a1').change_ring(QuadraticField(5, 'a')) - sage: j = E.j_invariant() - sage: _modular_polynomial('borel', 3, j) - x^4 + 36*x^3 + 270*x^2 + 243778492/161051*x + 729 - sage: _modular_polynomial('split', 3, j) - x^6 - 18*x^5 + 27*x^4 + 243778492/161051*x^3 - 729*x^2 - 13122*x - 19683 - sage: _modular_polynomial('borel', 5, j) - x^6 + 30*x^5 + 315*x^4 + 1300*x^3 + 1575*x^2 + 242812186/161051*x + 125 - sage: _modular_polynomial('split', 5, j) - x^15 + 30*x^14 + 390*x^13 + 2800*x^12 + 11175*x^11 + 2658577186/161051*x^10 - 8545073600/161051*x^9 - 3318236600/14641*x^8 + 79768901125/161051*x^7 + 950952612750/161051*x^6 + 3261066516250/161051*x^5 + 5917349970000/161051*x^4 + 5381326371875/161051*x^3 + 45039331250/14641*x^2 - 3377861937500/161051*x - 2135097075000/161051 - sage: _modular_polynomial('nonsplit', 5, j) - 43605793936/161051*x^10 + 609382899680/161051*x^9 + 3805439994680/161051*x^8 + 13957069930640/161051*x^7 + 33226111304085/161051*x^6 + 4866186482686/14641*x^5 + 58961494233415/161051*x^4 + 43734191948140/161051*x^3 + 20843516212195/161051*x^2 + 5741876955930/161051*x + 690283481689/161051 - sage: _modular_polynomial('borel', 7, j) - x^8 + 28*x^7 + 322*x^6 + 1904*x^5 + 5915*x^4 + 8624*x^3 + 4018*x^2 + 242490084/161051*x + 49 - sage: _modular_polynomial('split', 7, j) - x^28 - 42*x^27 + 819*x^26 - 9842*x^25 + 81543*x^24 - 493416*x^23 + 2251424*x^22 - 1268191320692/161051*x^21 + 3410611518671/161051*x^20 - 6947130862854/161051*x^19 + 10098387132407/161051*x^18 - 8011521604618/161051*x^17 - 509395128662/14641*x^16 + 32582181402218/161051*x^15 - 62691210143713/161051*x^14 + 73259301822126/161051*x^13 - 46379791168053/161051*x^12 - 6277600417172/161051*x^11 + 46742832789352/161051*x^10 - 49641085864608/161051*x^9 + 2343504014803/14641*x^8 - 861578737314/161051*x^7 - 12167703919007/161051*x^6 + 14278547318070/161051*x^5 - 9423834664881/161051*x^4 + 3112085963896/161051*x^3 - 457632005824/161051*x^2 + 30845635072/161051*x + 122023936/161051 - sage: _modular_polynomial('nonsplit', 7, j) - 400320064/161051*x^21 + 13029623152/161051*x^20 + 228088753900/161051*x^19 + 2408913460821/161051*x^18 + 16642817648786/161051*x^17 + 80889087315407/161051*x^16 + 291040779803200/161051*x^15 + 801917686416123/161051*x^14 + 1729396406547138/161051*x^13 + 2959141014912537/161051*x^12 + 4049663724749832/161051*x^11 + 4450611572214360/161051*x^10 + 3931865527421272/161051*x^9 + 2786855392905248/161051*x^8 + 1576387623537152/161051*x^7 + 704811439294144/161051*x^6 + 22297037611520/14641*x^5 + 5896572491264/14641*x^4 + 12558313746944/161051*x^3 + 152158103552/14641*x^2 + 136821293056/161051*x + 5155295232/161051 - - TESTS:: - - sage: _modular_polynomial('banana', 7, j) - Traceback (most recent call last): - ... - ValueError: (group, p) must be one of ... - sage: _modular_polynomial('borel', 101, j) - Traceback (most recent call last): - ... - ValueError: (group, p) must be one of ... - """ - valid_parameters = [("borel", 3), ("borel", 5), ("borel", 7), - ("split", 3), ("split", 5), ("split", 7), - ("nonsplit", 5), ("nonsplit", 7)] - if (group, p) not in valid_parameters: - raise ValueError("(group, p) must be one of {}".format(valid_parameters)) - - from sage.rings.polynomial.polynomial_ring import polygen - x = polygen(j.parent()) - if group == "borel": - from sage.schemes.elliptic_curves.isogeny_small_degree import Fricke_polynomial - return Fricke_polynomial(p)(x)-j*x - if group == "split": - if p == 3: - return (x-9)**3*(x+3)**3-j*x**3 - if p == 5: - return ((x**2-5)*(x**2+5*x+10)*(x+5))**3-j*(x**2+5*x+5)**5 - if p == 7: - return ((x**2-5*x+8)*(x**2-5*x+1)*(x**4-5*x**3+8*x**2-7*x+7)*(x+1))**3*x-j*(x**3-4*x**2+3*x+1)**7 - if group == "nonsplit": - if p == 5: - return 5**4*(2*x+1)*(x+1)**3*(6*x**2+21*x+19)**3-j*(x**2+x-1)**5 - if p == 7: - return ((4*x**2+5*x+2)*(x**2+3*x+4)*(x**2+10*x+4)*(3*x+1))**3-j*(x**3+x**2-2*x-1)**7 - - raise RuntimeError # cannot happen -- the assertion would have failed. diff --git a/src/sage/schemes/elliptic_curves/gal_reps_number_field.py b/src/sage/schemes/elliptic_curves/gal_reps_number_field.py index 0e76706b1a3..5be48275b16 100644 --- a/src/sage/schemes/elliptic_curves/gal_reps_number_field.py +++ b/src/sage/schemes/elliptic_curves/gal_reps_number_field.py @@ -641,8 +641,8 @@ def is_split(self, p): if p == 3: pol = x**3 * (x+6)**3 * (x**2-6*x+36)**3 - j * (x-3)**3 * (x**2+3*x+9)**3 if p == 5: - pol1 = x**30 * (x**2-12*x+16)**3 * (x**4-4*x**3+176*x**2+256*x+4096)**3 * (x**4+16*x**3+176*x**2+896*x+7936)**3 - pol2 = -2**10 * x**30 * (x+4)**5 * (x**4-4*x**3+96*x**2-384*x+2816)**5 + pol1 = 2**15 * x**30 * (x**2-12*x+16)**3 * (x**4-4*x**3+176*x**2+256*x+4096)**3 * (x**4+16*x**3+176*x**2+896*x+7936)**3 + pol2 = - x**30 * (x+4)**5 * (x**4-4*x**3+96*x**2-384*x+2816)**5 pol = pol1 - j * pol2 if pol: return bool(pol.roots()) From f891f775be55c88306bf2e9dec4910217381fbb3 Mon Sep 17 00:00:00 2001 From: John Cremona Date: Mon, 20 Feb 2023 19:41:27 +0000 Subject: [PATCH 08/11] small fixes after review --- .../elliptic_curves/ell_number_field.py | 2 +- .../elliptic_curves/gal_reps_number_field.py | 30 +++++++++---------- 2 files changed, 16 insertions(+), 16 deletions(-) diff --git a/src/sage/schemes/elliptic_curves/ell_number_field.py b/src/sage/schemes/elliptic_curves/ell_number_field.py index 7646ad9e553..43b7e14da95 100644 --- a/src/sage/schemes/elliptic_curves/ell_number_field.py +++ b/src/sage/schemes/elliptic_curves/ell_number_field.py @@ -4102,7 +4102,7 @@ def is_modular(self, verbose=False): Note that for over half of all imaginary quadratic fields, there exist infinitely many elliptic curves (even up to twist) whose mod 3 and mod 5 Galois representations are - both reducible (in other words, which posess a rational + both reducible (in other words, which possess a rational 15-isogeny). Such curves can be proved to be modular, but not using the methods implemented here. diff --git a/src/sage/schemes/elliptic_curves/gal_reps_number_field.py b/src/sage/schemes/elliptic_curves/gal_reps_number_field.py index 5be48275b16..47970f31573 100644 --- a/src/sage/schemes/elliptic_curves/gal_reps_number_field.py +++ b/src/sage/schemes/elliptic_curves/gal_reps_number_field.py @@ -545,7 +545,7 @@ def is_split_normaliser(self, p): sage: G.is_split_normaliser(17) Traceback (most recent call last): ... - NotImplementedError: Only implemented for p<=7 + NotImplementedError: only implemented for p<=7 """ if p == 2: return self.is_borel(2) @@ -563,7 +563,7 @@ def is_split_normaliser(self, p): try: if ZZ(p).is_prime(): - raise NotImplementedError("Only implemented for p<=7") + raise NotImplementedError("only implemented for p<=7") else: raise NotImplementedError("p = {} should be prime and at most 7".format(p)) except TypeError: @@ -631,7 +631,7 @@ def is_split(self, p): sage: G.is_split(7) Traceback (most recent call last): ... - NotImplementedError: Only implemented for p<=5 + NotImplementedError: only implemented for p<=5 """ j = self.E.j_invariant() x = polygen(j.parent()) @@ -649,7 +649,7 @@ def is_split(self, p): try: if ZZ(p).is_prime(): - raise NotImplementedError("Only implemented for p<=5") + raise NotImplementedError("only implemented for p<=5") else: raise NotImplementedError("p = {} should be prime and at most 5".format(p)) except TypeError: @@ -711,10 +711,10 @@ def is_nonsplit_normaliser(self, p): sage: G.is_nonsplit_normaliser(11) Traceback (most recent call last): ... - NotImplementedError: Only implemented for p<=7 + NotImplementedError: only implemented for p<=7 """ if p == 2: - raise ValueError("Normaliser of nonsplit Cartan not defined for p=2") + raise ValueError("normaliser of nonsplit Cartan not defined for p=2") j = self.E.j_invariant() x = polygen(j.parent()) pol = None @@ -729,7 +729,7 @@ def is_nonsplit_normaliser(self, p): try: if ZZ(p).is_prime(): - raise NotImplementedError("Only implemented for p<=7") + raise NotImplementedError("only implemented for p<=7") else: raise NotImplementedError("p = {} should be prime, either 3, 5, or 7".format(p)) except TypeError: @@ -763,7 +763,7 @@ def is_nonsplit(self, p): if p == 2: return (j-1728).is_square() - raise NotImplementedError("Only implemented for p==2") + raise NotImplementedError("only implemented for p==2") def _non_surjective(E, patience=100): r""" @@ -793,10 +793,10 @@ def _non_surjective(E, patience=100): sage: sage.schemes.elliptic_curves.gal_reps_number_field._non_surjective(E) Traceback (most recent call last): ... - ValueError: The curve E should not have CM. + ValueError: the curve E should not have CM. """ if E.has_cm(): - raise ValueError("The curve E should not have CM.") + raise ValueError("the curve E should not have CM.") E = _over_numberfield(E) K = E.base_field() @@ -970,10 +970,10 @@ def _exceptionals(E, L, patience=1000): sage: sage.schemes.elliptic_curves.gal_reps_number_field._exceptionals(E,[2,3,5]) Traceback (most recent call last): ... - ValueError: The curve E should not have CM. + ValueError: the curve E should not have CM. """ if E.has_cm(): - raise ValueError("The curve E should not have CM.") + raise ValueError("the curve E should not have CM.") E = _over_numberfield(E) K = E.base_field() @@ -1326,7 +1326,7 @@ def _semistable_reducible_primes(E, verbose=False): if patience == 0: # We suspect that E has CM, so we check: if E.has_cm(): - raise ValueError("In _semistable_reducible_primes, the curve E should not have CM.") + raise ValueError("in _semistable_reducible_primes, the curve E should not have CM.") assert div != 0 # We found our divisibility constraint. @@ -1376,10 +1376,10 @@ def _possible_normalizers(E, SA): sage: sage.schemes.elliptic_curves.gal_reps_number_field._possible_normalizers(E, []) Traceback (most recent call last): ... - ValueError: The curve E should not have CM. + ValueError: the curve E should not have CM. """ if E.has_cm(): - raise ValueError("The curve E should not have CM.") + raise ValueError("the curve E should not have CM.") E = _over_numberfield(E) K = E.base_field() From d369bd384723d720a33c408d53db69c4ca331977 Mon Sep 17 00:00:00 2001 From: John Cremona Date: Tue, 21 Feb 2023 08:58:41 +0000 Subject: [PATCH 09/11] fix docstring typos --- src/sage/schemes/elliptic_curves/gal_reps_number_field.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/sage/schemes/elliptic_curves/gal_reps_number_field.py b/src/sage/schemes/elliptic_curves/gal_reps_number_field.py index 47970f31573..bbfccc46583 100644 --- a/src/sage/schemes/elliptic_curves/gal_reps_number_field.py +++ b/src/sage/schemes/elliptic_curves/gal_reps_number_field.py @@ -672,7 +672,7 @@ def is_nonsplit_normaliser(self, p): ALGORITHM: This method is currently only implemented for primes `p` for - which the modular curve `X_{\text{ns}}^{+}(p) has genus 0, + which the modular curve `X_{\text{ns}}^{+}(p)` has genus 0, namely `p=3,5,7`. In these cases we use an explicit formula for the map from the modular curve to the `j`-line, checking that the curve's `j`-invariant is in the image. @@ -751,7 +751,7 @@ def is_nonsplit(self, p): ALGORITHM: This method is currently only implemented for primes `p` for - which the modular curve `X_{\text{ns}}(p) has genus 0 and has + which the modular curve `X_{\text{ns}}(p)` has genus 0 and has a rational point, namely `p=2` only. (For `p=3,5` the genus is zero but there are no rational points.) In this cases we use an explicit formula for the map from the modular curve to From 22f547b28bbfca6850c5b3ddb53e3f121425a830 Mon Sep 17 00:00:00 2001 From: John Cremona Date: Fri, 24 Feb 2023 11:36:30 +0000 Subject: [PATCH 10/11] added the t.r. cubic and quartic cases --- src/doc/en/reference/references/index.rst | 8 +++++ .../elliptic_curves/ell_number_field.py | 33 ++++++++++++------- 2 files changed, 29 insertions(+), 12 deletions(-) diff --git a/src/doc/en/reference/references/index.rst b/src/doc/en/reference/references/index.rst index bbd43dbd9b9..c2e48538281 100644 --- a/src/doc/en/reference/references/index.rst +++ b/src/doc/en/reference/references/index.rst @@ -736,6 +736,10 @@ REFERENCES: Cambridge Univ Press, 2001. :doi:`10.1017/S0963548301004813`. +.. [Box2022] Josha Box. + Elliptic curves over totally real quartic fields not containing `\sqrt{5}` are modular. + Trans. Amer. Math. Soc. 375 (2022), 3129-3172. + .. [BF2005] \R.L. Burden and J.D. Faires. *Numerical Analysis*. 8th edition, Thomson Brooks/Cole, 2005. @@ -1979,6 +1983,10 @@ REFERENCES: Chapman & Hall/CRC 2012 +.. [DNS2020] Maarten Derickx, Filip Najman, Samir Siksek + *Elliptic curves over totally real cubic fields are modular.* + Algebra and Number Theory. (2020) 14 no.7, pp. 1791--1800. + .. [DerZak1980] Nachum Dershowitz and Schmuel Zaks, *Enumerations of ordered trees*, Discrete Mathematics (1980), 31: 9-28. diff --git a/src/sage/schemes/elliptic_curves/ell_number_field.py b/src/sage/schemes/elliptic_curves/ell_number_field.py index 43b7e14da95..f9dcf04d473 100644 --- a/src/sage/schemes/elliptic_curves/ell_number_field.py +++ b/src/sage/schemes/elliptic_curves/ell_number_field.py @@ -4089,7 +4089,7 @@ def is_modular(self, verbose=False): When ``False`` is returned, it does not mean that the curve is not modular! Only that modularity cannot be proved with current knowledge and implemented methods. It - is expected that the return value will be ``True`` for all + is expected that the return value will be ``True`` for most curves defined over totally real fields, and for all defined over imaginary quadratic fields over which the modular curve `X_0(15)` (which is the elliptic curve with @@ -4114,11 +4114,14 @@ def is_modular(self, verbose=False): This is based on code provided by S. Siksek for the totally real case, and relies on theorems in the following papers: - [Chen1996]_, [FLHS2015]_, [Thorne2016]_, [CarNew2023]_. It - relies on checking that the images of the mod-`p` Galois + [Chen1996]_, [FLHS2015]_, [Thorne2016]_, [CarNew2023]_, + [DNS2020]_, [Box2022]_. + + It relies on checking that the images of the mod-`p` Galois representation attached to the elliptic curve for `p=3,5,7` - are not simultaneously small expcept for the cases (base field - `\QQ` or real quadratic) where theoretical results show this to + are not simultaneously small, except for the cases (base field + `\QQ`, real quadratic, totally real cubic, or totally real quartic + not containing `\sqrt{5}`) where theoretical results show this to be impossible. EXAMPLES: @@ -4144,11 +4147,11 @@ def is_modular(self, verbose=False): Unable to determine modularity except over totally real and imaginary quadratic fields False - Some examples from the LMFDB. Over a totally real cubic field:: + Some examples from the LMFDB. Over a totally real quintic field:: sage: R. = PolynomialRing(QQ) - sage: K. = NumberField(R([-3, -7, -1, 1])) - sage: E = EllipticCurve([K([-4,-1,1]),K([-4,-2,1]),K([-4,-1,1]),K([-2807,-660,446]),K([5874,1376,-933])]) + sage: K. = NumberField(R([1, 3, -1, -5, 0, 1])) + sage: E = EllipticCurve([K([3,0,-5,0,1]),K([-3,-7,9,2,-2]),K([1,0,0,0,0]),K([-22,-79,-92,14,21]),K([12,-87,-324,7,74])]) sage: E.is_modular(verbose=True) Modular since the mod 3 Galois image is neither reducible nor split True @@ -4186,7 +4189,6 @@ def is_modular(self, verbose=False): sage: E.is_modular(verbose=True) Unable to determine modularity except over totally real and imaginary quadratic fields False - """ K = self.base_field() d = K.degree() @@ -4198,17 +4200,24 @@ def is_modular(self, verbose=False): TR = K.is_totally_real() - if TR and d == 2: # base field real quadratic + if TR and d <= 3: # base field real quadratic or totally real cubic if verbose: - print("All elliptic curves over real quadratic fields are modular") + if d==2: + print("All elliptic curves over real quadratic fields are modular") + else: + print("All elliptic curves over totaly real cubic fields are modular") return True + if TR and d==4 and not K(5).is_square(): + if verbose: + print("All elliptic curves over totally real quartic fields not containing sqrt(5) are modular") + if d > 2 and not TR: if verbose: print("Unable to determine modularity except over totally real and imaginary quadratic fields") return False # meaning 'unknown' - # from here either K is totally real (TR is True) or imagainary quadratic + # from here either K is totally real of degree at least 4 (TR is True) or imaginary quadratic if self.has_cm(): if verbose: From d09e52a8e05df300aa18ceb34d03de995b7e99b0 Mon Sep 17 00:00:00 2001 From: John Cremona Date: Tue, 14 Nov 2023 11:40:36 +0000 Subject: [PATCH 11/11] #22697 modularity: work in progress --- src/doc/en/reference/references/index.rst | 8 ++++ .../elliptic_curves/ell_number_field.py | 43 ++++++++++++++++--- .../elliptic_curves/gal_reps_number_field.py | 2 +- 3 files changed, 45 insertions(+), 8 deletions(-) diff --git a/src/doc/en/reference/references/index.rst b/src/doc/en/reference/references/index.rst index 2023180ba1c..bbcc623b026 100644 --- a/src/doc/en/reference/references/index.rst +++ b/src/doc/en/reference/references/index.rst @@ -1171,6 +1171,10 @@ REFERENCES: .. [Bre1997] \T. Breuer "Integral bases for subfields of cyclotomic fields" AAECC 8, 279--289 (1997). +.. [Breuil2001] Breuil, Christophe, Brian Conrad, Fred Diamond, and Richard Taylor. + *On the modularity of elliptic curves over Q: wild 3-adic exercises*. + Journal of the American Mathematical Society 14, no. 4 (2001): 843-940. + .. [Bre2000] Enno Brehm, *3-Orientations and Schnyder 3-Tree-Decompositions*, 2000. https://page.math.tu-berlin.de/~felsner/Diplomarbeiten/brehm.ps.gz @@ -6212,6 +6216,10 @@ REFERENCES: .. [Wie2000] \B. Wieland. *A large dihedral symmetry of the set of alternating sign matrices*. Electron. J. Combin. 7 (2000). +.. [Wiles1995] Andrew Wiles. + *Modular elliptic curves and Fermat's last theorem*. + Annals of mathematics, 141(3), 443-551. + .. [Wilson2008] Steve Wilson. *Rose Window Graphs*. Ars Mathematica Contemporanea 1(1):7-19, 2008. :doi:`10.26493/1855-3974.13.5bb` diff --git a/src/sage/schemes/elliptic_curves/ell_number_field.py b/src/sage/schemes/elliptic_curves/ell_number_field.py index f9dcf04d473..334aa1ab4ca 100644 --- a/src/sage/schemes/elliptic_curves/ell_number_field.py +++ b/src/sage/schemes/elliptic_curves/ell_number_field.py @@ -10,7 +10,7 @@ not exist a global minimal equation over `K`, when `K` does not have class number one. When a minimal model does exist the method :meth:`global_minimal_model()` will compute it, and otherwise compute -a model which is miniaml at all primes except one. Another difference +a model which is minimal at all primes except one. Another difference is the relative lack of understanding of modularity for elliptic curves over general number fields; the method :meth:`is_modular()` does implement recent methods to prove modularity of elliptic curves, @@ -4075,8 +4075,7 @@ def rational_points(self, **kwds): return [E(pt) for pt in Curve(self).rational_points(**kwds)] def is_modular(self, verbose=False): - r""" - Return ``True`` if the base field is totally real or imaginary + r"""Return ``True`` if the base field is totally real or imaginary quadratic and modularity of this curve can be proved, otherwise ``False``. @@ -4114,8 +4113,8 @@ def is_modular(self, verbose=False): This is based on code provided by S. Siksek for the totally real case, and relies on theorems in the following papers: - [Chen1996]_, [FLHS2015]_, [Thorne2016]_, [CarNew2023]_, - [DNS2020]_, [Box2022]_. + [Wiles1995]_, [Breuil2001]_, [Chen1996]_, [FLHS2015]_, + [Thorne2016]_, [CarNew2023]_, [DNS2020]_, [Box2022]_. It relies on checking that the images of the mod-`p` Galois representation attached to the elliptic curve for `p=3,5,7` @@ -4124,6 +4123,35 @@ def is_modular(self, verbose=False): not containing `\sqrt{5}`) where theoretical results show this to be impossible. + Over `\QQ`: all curves are modular with no further checks + needed, by [Wiles1995]_ and [Breuil2001]_. + + Over real quadratic fields: all curves are modular with no further checks + needed, by [FLHS2015]_. + + Over totally real cubic fields: all curves are modular with no further checks + needed, by [DNS2020]_. + + Over totally real quartic fields not containing `\sqrt{5}`: + all curves are modular with no further checks needed, by + [Box2022]_. + + Over other totally real fields: modularity is implied by + conditions on the mod-`\ell` representations for `\ell=3,5,7` + by [FLHS2015]_. It is sufficient for one of the following to + hold: (1) the image of the mod-3 representation is not + contained in either a Borel or the normaliser of a split + Cartan subgroup; (2) image of the mod-5 representation is + irreducible, and either 5 is not square in the field, or the + image is not contained in the normaliser of either a split or + nonsplt Cartan subgroup; (3) the image of the mod-7 + representation is be not contained in either a Borel or the + normaliser of a split or nonsplt Cartan subgroup. + + Over imaginary quadratic fields: by [CarNew2023]_, it is + sufficient for the mod-3 or mod-5 images to satisfy conditions + (1) or (2) above, respectively. + EXAMPLES: Set ``verbose=True`` to see a reason for the conclusion:: @@ -4168,7 +4196,7 @@ def is_modular(self, verbose=False): sage: E.is_modular(verbose=True) Modularity not established: this curve has small image at 3 and 5 False - sage: EllipticCurve('15a1').change_ring(K).rank() + sage: EllipticCurve('15a1').change_ring(K).rank() # long time 1 Nevertheless, over the same field, most curves pass:: @@ -4189,11 +4217,12 @@ def is_modular(self, verbose=False): sage: E.is_modular(verbose=True) Unable to determine modularity except over totally real and imaginary quadratic fields False + """ K = self.base_field() d = K.degree() - if d == 1: # base field QQ + if d == 1: # base field QQ: [Wiles1995], [Breuil2001] if verbose: print("All elliptic curves over QQ are modular") return True diff --git a/src/sage/schemes/elliptic_curves/gal_reps_number_field.py b/src/sage/schemes/elliptic_curves/gal_reps_number_field.py index bbfccc46583..4b297f513c6 100644 --- a/src/sage/schemes/elliptic_curves/gal_reps_number_field.py +++ b/src/sage/schemes/elliptic_curves/gal_reps_number_field.py @@ -435,7 +435,7 @@ def is_borel(self, p): True sage: E = EllipticCurve('121a1') sage: G = GaloisRepresentation(E) - sage: G.is_borel(11) + sage: G.is_borel(11) # long time True sage: E = EllipticCurve('147c1') sage: G = GaloisRepresentation(E)