Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Implement modularity test for elliptic curves #34989

Draft
wants to merge 20 commits into
base: develop
Choose a base branch
from

Conversation

JohnCremona
Copy link
Member

@JohnCremona JohnCremona commented Feb 6, 2023

Fixes #22697

@yyyyx4
Copy link
Member

yyyyx4 commented Feb 6, 2023

You can use one of a few select keywords to link a pull request to an issue. For example, editing the description to include "fixes #22697" will instruct GitHub to automatically close #22697 when this pull request gets merged.

@JohnCremona JohnCremona changed the title Addresses Issue #22697 (modularity of elliptic curves) fixes issue #22697 (modularity of elliptic curves) Feb 6, 2023
@JohnCremona
Copy link
Member Author

Thanks for adding the label. I could not. It's an enhancement, not a bug fix.

@JohnCremona JohnCremona changed the title fixes issue #22697 (modularity of elliptic curves) Closes issue #22697 (modularity of elliptic curves) Feb 6, 2023
@codecov-commenter
Copy link

codecov-commenter commented Feb 8, 2023

Codecov Report

Base: 88.59% // Head: 88.59% // Decreases project coverage by -0.01% ⚠️

Coverage data is based on head (d369bd3) compared to base (104dde9).
Patch coverage: 96.26% of modified lines in pull request are covered.

❗ Current head d369bd3 differs from pull request most recent head 22f547b. Consider uploading reports for the commit 22f547b to get more accurate results

Additional details and impacted files
@@             Coverage Diff             @@
##           develop   #34989      +/-   ##
===========================================
- Coverage    88.59%   88.59%   -0.01%     
===========================================
  Files         2136     2140       +4     
  Lines       396142   397131     +989     
===========================================
+ Hits        350948   351819     +871     
- Misses       45194    45312     +118     
Impacted Files Coverage Δ
src/sage/algebras/free_algebra_element.py 82.50% <ø> (ø)
src/sage/algebras/fusion_rings/fusion_ring.py 93.93% <ø> (ø)
src/sage/algebras/lie_algebras/free_lie_algebra.py 95.43% <ø> (ø)
src/sage/algebras/lie_algebras/lie_algebra.py 91.10% <ø> (ø)
src/sage/algebras/lie_algebras/morphism.py 90.07% <ø> (ø)
src/sage/algebras/quatalg/quaternion_algebra.py 92.68% <ø> (ø)
src/sage/arith/misc.py 90.99% <ø> (ø)
src/sage/categories/category_with_axiom.py 98.71% <ø> (ø)
src/sage/categories/coxeter_groups.py 94.59% <ø> (ø)
...age/categories/finite_complex_reflection_groups.py 79.12% <ø> (ø)
... and 165 more

Help us with your feedback. Take ten seconds to tell us how you rate us. Have a feature suggestion? Share it here.

☔ View full report at Codecov.
📢 Do you have feedback about the report comment? Let us know in this issue.

@JohnCremona
Copy link
Member Author

I fixed the two minor lint failures (not in my code!)

@JohnCremona
Copy link
Member Author

...and then I merged the latest develop and fixed a merge conflict

@JohnCremona JohnCremona changed the title Closes issue #22697 (modularity of elliptic curves) Implement modularity test for elliptic curves Feb 8, 2023
Copy link
Collaborator

@tscrim tscrim left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I didn't check the mathematics behind it as it is too far outside my expertise. However, the code has been reviewed.

r"""
Elliptic curves over number fields
r"""Elliptic curves over number fields
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would revert this as our convention is one-line on a new line from the """.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Will do. My emacs python mode always does this, I wish it would not!

Comment on lines 4072 to 4077
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.
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
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.
r"""
Return ``True`` if the base field is totally real and modularity of
this curve can be proved, otherwise ``False``.
INPUT:
- ``verbose`` -- boolean (default: ``False``); if ``True``, outputs a reason for the conclusion

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

OK

Comment on lines 4081 to 4091
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.
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
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.
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.

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::
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
EXAMPLES. Set ``verbose=True`` to see a reason for the conclusion::
EXAMPLES:
Set ``verbose=True`` to see a reason for the conclusion::


"""
def not_from(group, p, j):
return len(_modular_polynomial(group, p, j).roots()) == 0
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
return len(_modular_polynomial(group, p, j).roots()) == 0
return not _modular_polynomial(group, p, j).roots()

This should be slightly faster.

return False # We've run out of tricks!

def _modular_polynomial(group, p, j):
r"""Helper function for the method :meth:`is_modular`.
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
r"""Helper function for the method :meth:`is_modular`.
r"""
Helper function for the method :meth:`is_modular`.

Comment on lines 4240 to 4244
- ``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.
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
- ``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.
- ``group`` -- string; one of ``'borel'``, ``'split'``, ``'nonsplit'``
- ``p`` -- integer; a prime number, either 3 or 5 or 7
- ``j`` -- an algebraic number; the `j`-invariant of an elliptic curve

Comment on lines 4266 to 4275
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
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
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
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

Splitting up some long lines. Since this @#$% editor window is so small, I am not sure that it is cut around 80 char/line. It can be a bit longer, but they need a few cuts.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

OK -- I willl make all the changes suggested an update my branch. Thanks!

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done -- I hope I did not miss anything. If you are happy @tscrim could you click on the Resolve Conversation button -- I assume that is what it is for.

@tscrim
Copy link
Collaborator

tscrim commented Feb 11, 2023

@JohnCremona Thank you. I am happy with the doc. As far as I can tell the code does what it says it does, but I can't say that with any sort of confidence. If nobody can verify the math in a week or so, just ping me again (if I forget about this) and I will positively review this.

@tscrim tscrim requested a review from tornaria February 11, 2023 12:32
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.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

so this line is useless and should be removed

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I find there is some utility in this as it would catch bugs (or at least make it easier to see where they are coming from) by raising a specific type of exception rather that silently returning None.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

but this line cannot be reached at all, I think

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That's the point. It should never be reached. I am treating it like an assert statement; something that should never be false/reached. Actually, would that be okay with you: assert False?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I am sorry, but I do not see the point. We are first checking the input parameters to belong to an explicit list. Then, for each member of the list, the code path ends by a return. So this proves that the final line can never happen.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You're exactly right that this code is currently bug-free. Yet, suppose I change this method, but I introduce a bug for some case. Then I run this code, and without this raise, the code silently returns a wrong answer of None. Now this is highly likely to fail, but somewhere else. However, the failure is not guaranteed (no reasonable person should trap a RuntimeError or an AssertionError), which means a wrong answer could actually be returned. Thus, this one extra line makes the code more robust against future errors that could be introduced.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ok, ok. I do not agree, but will not oppose any longer, for doc and code inside a hidden method. Good for me


INPUT:

- ``verbose`` (bool, default ``False``) -- if True, outputs a reason for the conclusion.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

please write "if True"

Traceback (most recent call last):
...
ValueError: (group, p) must be one of ...
sage: _modular_polynomial('borel', 101, j)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

one test would be enough

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is testing a different type of failure, that group is correct but not one of the correct primes. So I find some utility in this test.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

but this is running through the same code path, no ?

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sort of. However, it is passing an equality of one part of the pair, but not the second. Putting aside the pedagogical aspects, I am treating this block of code like

if group in [A,B,C]:
    if p in [X, Y, Z]:  # Although this depends on if A, B, or C

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

But this is not how the code is written, so I persist to say that could just keep one test here.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No, but it demonstrates what the behavior should be: there is a dependency on p as well. I don't see the harm in another test being there.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

idem, if you insist, I will not oppose

print("Modularity not established: this curve has small image at 3 and 5")

return False # We've run out of tricks!

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

two blank lines here (pep8)

@JohnCremona
Copy link
Member Author

Thanks to both @fchapoton anf @tscrim for taking their time with this. I'm sorry that my little utility function caused so much not very fruitful discussion!

I have an alternative suggestion (at the risk of you both cursing me). What the code does is to test that the elliptic curve has certain properties at some of all of the primes 3, 5, 7. The properties concern the mod-p Galois representation attached the curve, specifically whether the projective image of the representation is or is not contained in one of the standard subgroups of the codomain (which is the group PGL(2,p)): Borel, split Cartan etc. In each case the condition can be tested by checking whether or not a certain polynomial whose coefficients depend on the curve (just its j-invariant) have a root over the field of definition of the curve. For all the cases needed here, the corresponding modular curve has genus 0 (it is P^1) so one is simply testing if some rational function with coefficients in QQ takes j as a value.

Anyway, it would be neater to implement this tests via methods of the class GaloisRepresentation defined in gal_reps_number_field. The constructor for that does no work at all, and I would add methods with names like "is_Borel(p)" which would return True/False accordingly, for certain primes p (and calling the method on other primes would raise a NotImplementedError). I would do this not just for the primes and subgroups needed for this application but for some more, and that would be more useful.

I will do this refactoring in the next day or two; and I will also take on board @fchapoton 's usual useful points about my docstring hygiene.

Hence I'll change the tag on this to "needs work" until I have updated the PR.

@JohnCremona
Copy link
Member Author

I have done what I said above. I'll set the PR back to "needs review" once the automatic tests have run and passed (or I have fixed any issues arising).

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
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

possess (with more s) ?

return (j-1728).is_square()

raise NotImplementedError("Only implemented for p==2")

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Error messages should rather start with a smallcap letter, i.e. not with a capital. This is python convention, don't ask me why..

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

OK, I am editing now, how will I know you have finished?

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

OK, I am editing now, how will I know you have finished?

These are submitted in a batch AFAIK. So I think @fchapoton finished looking at things.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yes, sorry, busy with other matters. I have no other comment

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yes, sorry, busy with other matters. I have no other comment

thanks -- as always -- for your attention to detail

@tscrim
Copy link
Collaborator

tscrim commented Feb 24, 2023

Then let's get this in. Thank you.

@JohnCremona
Copy link
Member Author

I have added references to two more cases recently proved: all curves over totally real cubic fields and t.r. quartic fields not containing sqrt(5).

Also, while I appreciate the code reviews by @tscrim and @fchapoton but I really want someone who knows the field to look at this so I am setting it back to needs review (and will email come people). If I am wrong about the expertise of either existing reviewer, I apologise!

Copy link
Contributor

@tornaria tornaria left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm yet to look carefully at the galreps new methods. Perhaps if you have a specific reference for each test it would help me double check.

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
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
a model which is miniaml at all primes except one. Another difference
a model which is minimal at all primes except one. Another difference

@@ -4067,3 +4073,183 @@ 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):
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I wonder if this is the right name for the function, since E.is_modular() == False does not mean E is not modular, only that this code doesn't know how to prove it.

Perhaps: is_known_modular? is_provable_modular?

Alternatively, maybe is_modular() could return None instead of False when it doesn't know? So:

  • True: proved modular
  • False: proved non-modular (??)
  • None: unknown to current code

I'm just thinking out loud; I don't know what is done in other similar cases (are there?).

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this needs wider discussion, I will leave it for now

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Perhaps raising a NotImplementedError, with a suitable comment, instead of returning False?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

After talking to a few people at COUNT I have a different suggestion: call the method prove_modularity, to be similar to E.prove_BSD(). I'll look at this furthher on Tuesday.

True
sage: E = EllipticCurve('121a1')
sage: G = GaloisRepresentation(E)
sage: G.is_borel(11)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
sage: G.is_borel(11)
sage: G.is_borel(11) # long time

On a fast machine (i7-9700 CPU @ 3.00GHz):

Warning, slow doctest:
    G.is_borel(11)
Test ran for 1.57 s, check ran for 0.00 s

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

OK (this one is longer since X_0(11) has genus >0)

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()
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
sage: EllipticCurve('15a1').change_ring(K).rank()
sage: EllipticCurve('15a1').change_ring(K).rank() # long time

On a fast machine (i7-9700 CPU @ 3.00GHz):

Warning, slow doctest:
    EllipticCurve('15a1').change_ring(K).rank()
Test ran for 0.72 s, check ran for 0.00 s

This is borderline (0.72s is less than 1s, although on a slower/server machine/CI it will be > 1s). But since this is not really a doctest to the current method, I don't see any harm in marking it long time.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

OK, but I did not know that 1s was the criterion for long time!

.. [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`

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I noted Wiles, etc. are missing. Maybe they could be added as a reference for All elliptic curves over QQ are modular?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

OK, will do

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I added two references for the Q case, and expanded the ALGORITHM section to be much more explicit, explaining the exact checks carried out. So the extra information is in the docstring, not in the message output with verbose=True. Is That OK?


if d == 1: # base field QQ
if verbose:
print("All elliptic curves over QQ are modular")
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Perhaps add here references to theorems that prove the fact used in each case?

Could be in a comment, or maybe nicer in the string printed in the verbose case.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

See previous reply. It would not be possible to give the citations in the verbose message without duplicating the citations I already put in, which would be very tedious to do. Perhaps it is possible to give a URL for the official docstring in the reference manual on the sagemath website.

try:
p = ZZ(p)
except TypeError:
raise ValueError("p = {} should be a prime integer".format(p))
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
raise ValueError("p = {} should be a prime integer".format(p))
raise ValueError(f"{p = } should be a prime integer")

Do you know about f-strings? They are very useful (https://docs.python.org/3/tutorial/inputoutput.html#tut-f-strings)

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I will look these up and use them in future, but do not feel inclined to change all these strings now.

@JohnCremona
Copy link
Member Author

Thanks for the review @tornaria ! I will follow your suggestions soon (at the COUNT conference)

@JohnCremona JohnCremona marked this pull request as draft February 28, 2023 20:34
@JohnCremona
Copy link
Member Author

I converted this to draft since it is likely that I will not finish with working on it until next week.

Copy link

github-actions bot commented Nov 15, 2023

Documentation preview for this PR (built with commit 03a0823; changes) is ready! 🎉
This preview will update shortly after each push to this PR.

@fchapoton
Copy link
Contributor

hello ? any hope to move forward here ?

@JohnCremona
Copy link
Member Author

hello ? any hope to move forward here ?

Sorry, I had forgotten about this. I got stuck trying to work out exactly under what conditions published results allow concluding with essentially no work, or with only the work I had already implemented. (For example, if you take a curve defined over Q it is certainly modular as a curve defined over Q but not, I think, aafter an abitrary base change -- there are results on "solvable base change" but not all extensions are solvable.

I will try to revert to something fairly simple which does not try to be best possible.

@JohnCremona
Copy link
Member Author

Thanks for the reminder, I will move this up my list of things to do. Classic case of something reasonable being delayed by the desire to do something better...

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Modularity of elliptic curves
7 participants