From 7719f89dbcd5ba215a524248ac6be86f7c3089b8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fr=C3=A9d=C3=A9ric=20Chapoton?= Date: Thu, 18 Dec 2025 15:05:17 +0100 Subject: [PATCH] remove method simon_two_descent --- .../elliptic_curves/ell_rational_field.py | 222 ++---------------- 1 file changed, 22 insertions(+), 200 deletions(-) diff --git a/src/sage/schemes/elliptic_curves/ell_rational_field.py b/src/sage/schemes/elliptic_curves/ell_rational_field.py index 6cae5d79f37..59eeeba43b7 100644 --- a/src/sage/schemes/elliptic_curves/ell_rational_field.py +++ b/src/sage/schemes/elliptic_curves/ell_rational_field.py @@ -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 @@ -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 @@ -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 @@ -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(): @@ -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""" @@ -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 ################################