Skip to content
Open
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
222 changes: 22 additions & 200 deletions src/sage/schemes/elliptic_curves/ell_rational_field.py
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,6 @@
from sage.rings.power_series_ring import PowerSeriesRing
from sage.rings.rational_field import QQ
from sage.rings.rational_field import RationalField
from sage.rings.real_mpfi import RealIntervalField
from sage.rings.real_mpfr import RealField, RR
from sage.structure.coerce import py_scalar_to_element
from sage.structure.element import Element, RingElement
Expand Down Expand Up @@ -930,9 +929,9 @@ def anlist(self, n, python_ints=False):
raise RuntimeError("anlist: n (=%s) must be < 2147483648." % n)

v = [0] + e.ellan(n, python_ints=True)
if not python_ints:
v = [Integer(x) for x in v]
return v
if python_ints:
return v
return [Integer(x) for x in v]

# There is some overhead associated with coercing the PARI
# list back to Python, but it's not bad. It's better to do it
Expand Down Expand Up @@ -1783,181 +1782,6 @@ def analytic_rank_upper_bound(self,
ncpus=ncpus)
return bound

def simon_two_descent(self, verbose=0, lim1=5, lim3=50, limtriv=3,
maxprob=20, limbigprime=30, known_points=None):
r"""
Return lower and upper bounds on the rank of the Mordell-Weil
group `E(\QQ)` and a list of points of infinite order.

.. WARNING::

This function is deprecated as the functionality of
Simon's script for elliptic curves over the rationals
has been ported over to pari.
Use :meth:`.rank` with the keyword ``algorithm='pari'`` instead.

INPUT:

- ``verbose`` -- 0, 1, 2, or 3 (default: 0), the verbosity level

- ``lim1`` -- (default: 5) limit on trivial points on quartics

- ``lim3`` -- (default: 50) limit on points on ELS quartics

- ``limtriv`` -- (default: 3) limit on trivial points on `E`

- ``maxprob`` -- (default: 20)

- ``limbigprime`` -- (default: 30) to distinguish between small
and large prime numbers. Use probabilistic tests for large
primes. If 0, don't any probabilistic tests.

- ``known_points`` -- (default: ``None``) list of known points on
the curve

OUTPUT: a triple ``(lower, upper, list)`` consisting of

- ``lower`` -- integer; lower bound on the rank

- ``upper`` -- integer; upper bound on the rank

- ``list`` -- list of points of infinite order in `E(\QQ)`

The integer ``upper`` is in fact an upper bound on the
dimension of the 2-Selmer group, hence on the dimension of
`E(\QQ)/2E(\QQ)`. It is equal to the dimension of the
2-Selmer group except possibly if `E(\QQ)[2]` has dimension 1.
In that case, ``upper`` may exceed the dimension of the
2-Selmer group by an even number, due to the fact that the
algorithm does not perform a second descent.

To obtain a list of generators, use E.gens().

IMPLEMENTATION:

Uses Denis Simon's PARI/GP scripts from
http://www.math.unicaen.fr/~simon/

EXAMPLES:

We compute the ranks of the curves of lowest known conductor up to
rank `8`. Amazingly, each of these computations finishes
almost instantly!

::

sage: E = EllipticCurve('11a1')
sage: E.simon_two_descent()
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.
doctest:warning
...
DeprecationWarning: please use the 2-descent algorithm over QQ inside pari
See https://github.com/sagemath/sage/issues/38461 for details.
(0, 0, [])
sage: E = EllipticCurve('37a1')
sage: E.simon_two_descent()
(1, 1, [(0 : 0 : 1)])
sage: E = EllipticCurve('389a1')
sage: E._known_points = [] # clear cached points
sage: E.simon_two_descent()
(2, 2, [(-3/4 : 7/8 : 1), (5/4 : 5/8 : 1)])
sage: E = EllipticCurve('5077a1')
sage: E.simon_two_descent()
(3, 3, [(1 : 0 : 1), (2 : 0 : 1), (0 : 2 : 1)])

In this example Simon's program does not find any points, though it
does correctly compute the rank of the 2-Selmer group.

::

sage: E = EllipticCurve([1, -1, 0, -751055859, -7922219731979])
sage: E.simon_two_descent()
(1, 1, [])

The rest of these entries were taken from Tom Womack's page
http://tom.womack.net/maths/conductors.htm

::

sage: E = EllipticCurve([1, -1, 0, -79, 289])
sage: E.simon_two_descent()
(4, 4, [(6 : -1 : 1), (4 : 3 : 1), (5 : -2 : 1), (8 : 7 : 1)])
sage: E = EllipticCurve([0, 0, 1, -79, 342])
sage: E.simon_two_descent() # long time (9s on sage.math, 2011)
(5, 5, [(5 : 8 : 1), (10 : 23 : 1), (3 : 11 : 1), (-3 : 23 : 1), (0 : 18 : 1)])
sage: E = EllipticCurve([1, 1, 0, -2582, 48720])
sage: r, s, G = E.simon_two_descent(); r,s
(6, 6)
sage: E = EllipticCurve([0, 0, 0, -10012, 346900])
sage: r, s, G = E.simon_two_descent(); r,s # long time
(7, 7)
sage: E = EllipticCurve([0, 0, 1, -23737, 960366])
sage: r, s, G = E.simon_two_descent(); r,s # long time
(8, 8)

Example from :issue:`10832`::

sage: E = EllipticCurve([1,0,0,-6664,86543])
sage: E.simon_two_descent()
(2, 3, [(-1/4 : 2377/8 : 1), (323/4 : 1891/8 : 1)])
sage: E.rank()
2
sage: E.gens()
[(-1/4 : 2377/8 : 1), (323/4 : 1891/8 : 1)]

Example where the lower bound is known to be 1
despite that the algorithm has not found any
points of infinite order ::

sage: E = EllipticCurve([1, 1, 0, -23611790086, 1396491910863060])
sage: E.simon_two_descent()
(1, 2, [])
sage: E.rank()
1
sage: E.gens() # uses mwrank
[(4311692542083/48594841 : -13035144436525227/338754636611 : 1)]

Example for :issue:`5153`::

sage: E = EllipticCurve([3,0])
sage: E.simon_two_descent()
(1, 2, [(1 : 2 : 1)])

The upper bound on the 2-Selmer rank returned by this method
need not be sharp. In following example, the upper bound
equals the actual 2-Selmer rank plus 2 (see :issue:`10735`)::

sage: E = EllipticCurve('438e1')
sage: E.simon_two_descent()
(0, 3, [])
sage: E.selmer_rank() # uses mwrank
1
"""
from sage.misc.superseded import deprecation
deprecation(35621, 'Use E.rank(algorithm="pari") instead, as this script has been ported over to pari.')

t = EllipticCurve_number_field.simon_two_descent(self, verbose=verbose,
lim1=lim1, lim3=lim3, limtriv=limtriv,
maxprob=maxprob, limbigprime=limbigprime,
known_points=known_points)
rank_low_bd = t[0]
two_selmer_rank = t[1]
pts = t[2]
if rank_low_bd == two_selmer_rank - self.two_torsion_rank():
if verbose > 0:
print("Rank determined successfully, saturating...")
gens = self.saturation(pts)[0]
if len(gens) == rank_low_bd:
self.__gens = (gens, True)
self.__rank = (Integer(rank_low_bd), True)

return rank_low_bd, two_selmer_rank, pts

two_descent_simon = simon_two_descent # deprecated in #35621

def three_selmer_rank(self, algorithm='UseSUnits'):
r"""
Return the 3-selmer rank of this elliptic curve, computed using
Expand Down Expand Up @@ -2798,7 +2622,7 @@ def saturation(self, points, verbose=False, max_prime=-1, min_prime=2):
if not isinstance(P, ell_point.EllipticCurvePoint_field):
P = self(P)
elif P.curve() != self:
raise ArithmeticError("point (=%s) must be %s." % (P,self))
raise ArithmeticError("point (=%s) must be %s." % (P, self))

minimal = True
if not self.is_minimal():
Expand Down Expand Up @@ -5308,17 +5132,16 @@ def manin_constant(self):

if cinf_C == cinf_E:
return n
# otherwise they have different number of connected component and we have to adjust for this
elif cinf_C > cinf_E:
if ZZ(n_plus) % 2 == 0 and ZZ(n_minus) % 2 == 0:
# otherwise they have different number of connected component
# and we have to adjust for this
if cinf_C > cinf_E:
if not ZZ(n_plus) % 2 and not ZZ(n_minus) % 2:
return n // 2
else:
return n
else: #if cinf_C < cinf_E:
if q_plus.denominator() % 2 == 0 and q_minus.denominator() % 2 == 0:
return n
else:
return n*2
return n
# if cinf_C < cinf_E:
if not q_plus.denominator() % 2 and not q_minus.denominator() % 2:
return n
return n*2

def _shortest_paths(self):
r"""
Expand Down Expand Up @@ -6182,16 +6005,15 @@ def point_preprocessing(free, tor):
for i in range(r):
if not free_id[i]:
newfree[i] += T
else:
if not all(free_id):
i0 = free_id.index(False)
P = free[i0]
for i in range(r):
if not free_id[i]:
if i == i0:
newfree[i] = 2*newfree[i]
else:
newfree[i] += P
elif not all(free_id):
i0 = free_id.index(False)
P = free[i0]
for i in range(r):
if not free_id[i]:
if i == i0:
newfree[i] = 2*newfree[i]
else:
newfree[i] += P
return newfree
############################## end ################################

Expand Down
Loading