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

Update the rank function of elliptic curves to use ellrank in pari #35626

Merged
merged 19 commits into from
Jun 11, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
19 changes: 13 additions & 6 deletions src/doc/en/reference/references/index.rst
Original file line number Diff line number Diff line change
Expand Up @@ -3038,6 +3038,9 @@ REFERENCES:

.. [Har1994] Frank Harary. *Graph Theory*. Reading, MA: Addison-Wesley, 1994.

.. [Har2009] Harvey, David. *Efficient computation of p-adic heights*.
LMS J. Comput. Math. **11** (2008), 40–59.

.. [Harako2020] Shuichi Harako. *The second homology group of the commutative
case of Kontsevich's symplectic derivation Lie algebra*.
Preprint, 2020, :arxiv:`2006.06064`.
Expand Down Expand Up @@ -4737,17 +4740,21 @@ REFERENCES:
sharpening of the Parikh mapping*. Theoret. Informatics Appl. 35
(2001) 551-564.

.. [MST2006] Barry Mazur, William Stein, John Tate.
*Computation of p-adic heights and log convergence*.
Doc. Math. 2006, Extra Vol., 577-614.

.. [MSZ2013] Michael Maschler, Solan Eilon, and Zamir Shmuel. *Game
Theory*. Cambridge: Cambridge University Press,
(2013). ISBN 9781107005488.

.. [MT1991] Mazur, B., & Tate, J. (1991). The `p`-adic sigma
function. Duke Mathematical Journal, 62(3), 663-688.
.. [MT1991] Mazur, B., & Tate, J. (1991). *The `p`-adic sigma
function*. Duke Mathematical Journal, **62** (3), 663-688.

.. [MTT1986] \B. Mazur, J. Tate, and J. Teitelbaum, On `p`-adic
analogues of the conjectures of Birch and
Swinnerton-Dyer, Inventiones Mathematicae 84, (1986),
1-48.
.. [MTT1986] \B. Mazur, J. Tate, and J. Teitelbaum,
*On `p`-adic analogues of the conjectures of Birch and
Swinnerton-Dyer*,
Inventiones Mathematicae **84**, (1986), 1-48.

.. [Mu1997] Murty, M. Ram. *Congruences between modular forms*. In "Analytic
Number Theory" (ed. Y. Motohashi), London Math. Soc. Lecture Notes
Expand Down
73 changes: 69 additions & 4 deletions src/sage/schemes/elliptic_curves/BSD.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@

from sage.arith.misc import prime_divisors
from sage.rings.integer_ring import ZZ
from sage.rings.rational_field import QQ
from sage.rings.infinity import Infinity
from sage.rings.number_field.number_field import QuadraticField
from sage.functions.other import ceil
Expand Down Expand Up @@ -89,11 +90,17 @@ def simon_two_descent_work(E, two_tor_rk):
sage: from sage.schemes.elliptic_curves.BSD import simon_two_descent_work
sage: E = EllipticCurve('14a')
sage: simon_two_descent_work(E, E.two_torsion_rank())
doctest:warning
...
DeprecationWarning: Use E.rank(algorithm="pari") instead, as this script has been ported over to pari.
See https://github.com/sagemath/sage/issues/35621 for details.
(0, 0, 0, 0, [])
sage: E = EllipticCurve('37a')
sage: simon_two_descent_work(E, E.two_torsion_rank())
(1, 1, 0, 0, [(0 : 0 : 1)])
"""
from sage.misc.superseded import deprecation
deprecation(35621, 'Use the two-descent in pari instead, as this script has been ported over to pari.')
rank_lower_bd, two_sel_rk, gens = E.simon_two_descent()
rank_upper_bd = two_sel_rk - two_tor_rk
gens = [P for P in gens if P.additive_order() == Infinity]
Expand Down Expand Up @@ -140,6 +147,55 @@ def mwrank_two_descent_work(E, two_tor_rk):
sha2_upper_bd = MWRC.selmer_rank() - two_tor_rk - rank_lower_bd
return rank_lower_bd, rank_upper_bd, sha2_lower_bd, sha2_upper_bd, gens

def pari_two_descent_work(E):
r"""
Prepare the output from pari by two-isogeny.

INPUT:

- ``E`` -- an elliptic curve

OUTPUT: A tuple of 5 elements with the first 4 being integers.

- a lower bound on the rank

- an upper bound on the rank

- a lower bound on the rank of Sha[2]

- an upper bound on the rank of Sha[2]

- a list of the generators found

EXAMPLES::

sage: from sage.schemes.elliptic_curves.BSD import pari_two_descent_work
sage: E = EllipticCurve('14a')
sage: pari_two_descent_work(E)
(0, 0, 0, 0, [])
sage: E = EllipticCurve('37a')
sage: pari_two_descent_work(E) # random, up to sign
(1, 1, 0, 0, [(0 : -1 : 1)])
sage: E = EllipticCurve('210e7')
sage: pari_two_descent_work(E)
(0, 2, 0, 2, [])
sage: E = EllipticCurve('66b3')
sage: pari_two_descent_work(E)
(0, 0, 2, 2, [])

"""
ep = E.pari_curve()
lower, rank_upper_bd, s, pts = ep.ellrank()
gens = sorted([E.point([QQ(x[0]),QQ(x[1])], check=True) for x in pts])
gens = E.saturation(gens)[0]
# this is explained in the pari-gp documentation:
# s is the dimension of Sha[2]/2Sha[4],
# which is a lower bound for dim Sha[2]
# dim Sha[2] = dim Sel2 - rank E(Q) - dim tors
# rank_upper_bd = dim Sel_2 - dim tors - s
sha_upper_bd = rank_upper_bd - len(gens) + s
return len(gens), rank_upper_bd, s, sha_upper_bd, gens
Copy link
Member

Choose a reason for hiding this comment

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

Why return len(gens) instead of pari's 'lower', which you don't use? Can the lower rank bound be greater than the number of gens? But if pari increases the lower rank bound by 1 conditional on parity then I approve of using len(gens) instead.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

That is my understanding of pari, although their documentation does not mention that the lower bound is conditional on the finiteness of the 2-primary part of the Tate-Shafarevich group.

In line 1953 of file ellrank.c the function ell2selmer, we have Β  if (odd(dim - nbpoints)) mwrank++;

I was planning to write to the pari-gp list asking about this (and whether they have plans to port the code for the number fields, too.

Copy link
Member

Choose a reason for hiding this comment

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

OK -- let's just put a comment in that we don't use pari's lower bound as that is sometimes incremented by 1 based on a standard conjecture.



def native_two_isogeny_descent_work(E, two_tor_rk):
"""
Expand Down Expand Up @@ -254,7 +310,7 @@ def prove_BSD(E, verbosity=0, two_desc='mwrank', proof=None, secs_hi=5,
- 2: print information about remaining primes

- ``two_desc`` -- string (default ``'mwrank'``), what to use for the
two-descent. Options are ``'mwrank', 'simon', 'sage'``
two-descent. Options are ``'mwrank', 'pari', 'sage'``

- ``proof`` -- bool or None (default: None, see
proof.elliptic_curve or sage.structure.proof). If False, this
Expand Down Expand Up @@ -317,7 +373,7 @@ def prove_BSD(E, verbosity=0, two_desc='mwrank', proof=None, secs_hi=5,
True for p = 3 by Kolyvagin bound
True for p = 5 by Kolyvagin bound
[]
sage: E.prove_BSD(two_desc='simon')
sage: E.prove_BSD(two_desc='pari')
[]

A rank two curve::
Expand Down Expand Up @@ -433,6 +489,15 @@ def prove_BSD(E, verbosity=0, two_desc='mwrank', proof=None, secs_hi=5,
p = 2: True by 2-descent
True for p not in {2} by Kolyvagin.
[]

::

sage: E = EllipticCurve('66b3')
sage: E.prove_BSD(two_desc="pari",verbosity=1)
p = 2: True by 2-descent
True for p not in {2} by Kolyvagin.
[]

"""
if proof is None:
from sage.structure.proof.proof import get_flag
Expand Down Expand Up @@ -461,8 +526,8 @@ def prove_BSD(E, verbosity=0, two_desc='mwrank', proof=None, secs_hi=5,

if two_desc == 'mwrank':
M = mwrank_two_descent_work(BSD.curve, BSD.two_tor_rk)
elif two_desc == 'simon':
M = simon_two_descent_work(BSD.curve, BSD.two_tor_rk)
elif two_desc == 'pari':
M = pari_two_descent_work(BSD.curve)
elif two_desc == 'sage':
M = native_two_isogeny_descent_work(BSD.curve, BSD.two_tor_rk)
else:
Expand Down
28 changes: 14 additions & 14 deletions src/sage/schemes/elliptic_curves/constructor.py
Original file line number Diff line number Diff line change
Expand Up @@ -308,7 +308,7 @@ class EllipticCurveFactory(UniqueFactory):
TypeError: invalid input to EllipticCurve constructor
"""
def create_key_and_extra_args(self, x=None, y=None, j=None, minimal_twist=True, **kwds):
"""
r"""
Return a ``UniqueFactory`` key and possibly extra parameters.

INPUT: See the documentation for :class:`EllipticCurveFactory`.
Expand All @@ -329,7 +329,7 @@ def create_key_and_extra_args(self, x=None, y=None, j=None, minimal_twist=True,
sage: EllipticCurve.create_key_and_extra_args(j=8000)
((Rational Field, (0, 1, 0, -3, 1)), {})

When constructing a curve over `\\QQ` from a Cremona or LMFDB
When constructing a curve over `\QQ` from a Cremona or LMFDB
label, the invariants from the database are returned as
``extra_args``::

Expand Down Expand Up @@ -454,7 +454,7 @@ def create_key_and_extra_args(self, x=None, y=None, j=None, minimal_twist=True,
return (R, tuple(R(a) for a in x)), kwds

def create_object(self, version, key, **kwds):
"""
r"""
Create an object from a ``UniqueFactory`` key.

EXAMPLES::
Expand All @@ -466,7 +466,7 @@ def create_object(self, version, key, **kwds):
.. NOTE::

Keyword arguments are currently only passed to the
constructor for elliptic curves over `\\QQ`; elliptic
constructor for elliptic curves over `\QQ`; elliptic
curves over other fields do not support them.
"""
R, x = key
Expand Down Expand Up @@ -494,7 +494,7 @@ def create_object(self, version, key, **kwds):


def EllipticCurve_from_Weierstrass_polynomial(f):
"""
r"""
Return the elliptic curve defined by a cubic in (long) Weierstrass
form.

Expand Down Expand Up @@ -534,7 +534,7 @@ def EllipticCurve_from_Weierstrass_polynomial(f):
return EllipticCurve(coefficients_from_Weierstrass_polynomial(f))

def coefficients_from_Weierstrass_polynomial(f):
"""
r"""
Return the coefficients `[a_1, a_2, a_3, a_4, a_6]` of a cubic in
Weierstrass form.

Expand Down Expand Up @@ -582,7 +582,7 @@ def coefficients_from_Weierstrass_polynomial(f):


def EllipticCurve_from_c4c6(c4, c6):
"""
r"""
Return an elliptic curve with given `c_4` and
`c_6` invariants.

Expand Down Expand Up @@ -664,7 +664,7 @@ def EllipticCurve_from_j(j, minimal_twist=True):


def coefficients_from_j(j, minimal_twist=True):
"""
r"""
Return Weierstrass coefficients `(a_1, a_2, a_3, a_4, a_6)` for an
elliptic curve with given `j`-invariant.

Expand All @@ -680,7 +680,7 @@ def coefficients_from_j(j, minimal_twist=True):
sage: coefficients_from_j(1)
[1, 0, 0, 36, 3455]

The ``minimal_twist`` parameter (ignored except over `\\QQ` and
The ``minimal_twist`` parameter (ignored except over `\QQ` and
True by default) controls whether or not a minimal twist is
computed::

Expand Down Expand Up @@ -1238,7 +1238,7 @@ def EllipticCurve_from_cubic(F, P=None, morphism=True):


def tangent_at_smooth_point(C,P):
"""Return the tangent at the smooth point `P` of projective curve `C`.
r"""Return the tangent at the smooth point `P` of projective curve `C`.

INPUT:

Expand Down Expand Up @@ -1278,7 +1278,7 @@ def tangent_at_smooth_point(C,P):
return C.tangents(P,factor=False)[0]

def chord_and_tangent(F, P):
"""Return the third point of intersection of a cubic with the tangent at one point.
r"""Return the third point of intersection of a cubic with the tangent at one point.

INPUT:

Expand Down Expand Up @@ -1352,7 +1352,7 @@ def chord_and_tangent(F, P):


def projective_point(p):
"""
r"""
Return equivalent point with denominators removed

INPUT:
Expand Down Expand Up @@ -1384,7 +1384,7 @@ def projective_point(p):


def are_projectively_equivalent(P, Q, base_ring):
"""
r"""
Test whether ``P`` and ``Q`` are projectively equivalent.

INPUT:
Expand All @@ -1409,7 +1409,7 @@ def are_projectively_equivalent(P, Q, base_ring):

def EllipticCurves_with_good_reduction_outside_S(S=[], proof=None, verbose=False):
r"""
Return a sorted list of all elliptic curves defined over `Q`
Return a sorted list of all elliptic curves defined over `\QQ`
with good reduction outside the set `S` of primes.

INPUT:
Expand Down
Loading