Path: blob/master/sage/schemes/elliptic_curves/ell_rational_field.py
4159 views
# -*- coding: utf-8 -*-1"""2Elliptic curves over the rational numbers34AUTHORS:56- William Stein (2005): first version78- William Stein (2006-02-26): fixed Lseries_extended which didn't work9because of changes elsewhere in Sage.1011- David Harvey (2006-09): Added padic_E2, padic_sigma, padic_height,12padic_regulator methods.1314- David Harvey (2007-02): reworked padic-height related code1516- Christian Wuthrich (2007): added padic sha computation1718- David Roe (2007-09): moved sha, l-series and p-adic functionality to19separate files.2021- John Cremona (2008-01)2223- Tobias Nagel and Michael Mardaus (2008-07): added integral_points2425- John Cremona (2008-07): further work on integral_points2627- Christian Wuthrich (2010-01): moved Galois reps and modular28parametrization in a separate file2930"""3132##############################################################################33# Copyright (C) 2005,2006,2007 William Stein <[email protected]>34#35# Distributed under the terms of the GNU General Public License (GPL)36#37# This code is distributed in the hope that it will be useful,38# but WITHOUT ANY WARRANTY; without even the implied warranty of39# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU40# General Public License for more details.41#42# The full text of the GPL is available at:43#44# http://www.gnu.org/licenses/45##############################################################################4647import constructor48import BSD49from ell_generic import EllipticCurve_generic, is_EllipticCurve50import ell_modular_symbols51from ell_number_field import EllipticCurve_number_field52import ell_point53import ell_tate_curve54import ell_torsion55import heegner56from gp_simon import simon_two_descent57from lseries_ell import Lseries_ell58import mod5family59from modular_parametrization import ModularParameterization60import padic_lseries61import padics6263import sage.modular.modform.constructor64import sage.modular.modform.element65import sage.libs.mwrank.all as mwrank66import sage.databases.cremona6768import sage.rings.arith as arith69import sage.rings.all as rings70from sage.rings.all import (71PowerSeriesRing, LaurentSeriesRing, O,72infinity as oo,73ZZ, QQ,74Integer,75IntegerRing, RealField,76ComplexField, RationalField)7778import sage.misc.misc as misc79from sage.misc.all import verbose8081from sage.misc.functional import log82from sage.sets.set import Set8384# Use some interval arithmetic to guarantee correctness. We assume85# that alpha is computed to the precision of a float.86# IR = rings.RIF87#from sage.rings.interval import IntervalRing; IR = IntervalRing()8889import sage.matrix.all as matrix90from sage.libs.pari.all import pari, PariError91from sage.functions.other import gamma_inc92from math import sqrt93from sage.interfaces.all import gp94from sage.misc.cachefunc import cached_method95from copy import copy9697factor = arith.factor98mul = misc.mul99next_prime = arith.next_prime100101Q = RationalField()102C = ComplexField()103R = RealField()104Z = IntegerRing()105IR = rings.RealIntervalField(20)106107_MAX_HEIGHT=21108109# complex multiplication dictionary:110# CMJ is a dict of pairs (j,D) where j is a rational CM j-invariant111# and D is the corresponding quadratic discriminant112113CMJ={ 0: -3, 54000: -12, -12288000: -27, 1728: -4, 287496: -16,114-3375: -7, 16581375: -28, 8000: -8, -32768: -11, -884736: -19,115-884736000: -43, -147197952000: -67, -262537412640768000: -163}116117118119class EllipticCurve_rational_field(EllipticCurve_number_field):120r"""121Elliptic curve over the Rational Field.122123INPUT:124125- ``ainvs`` (list or string) -- either `[a_1,a_2,a_3,a_4,a_6]` or126`[a_4,a_6]` (with `a_1=a_2=a_3=0`) or a valid label from the127database.128129.. note::130131See constructor.py for more variants.132133EXAMPLES:134135Construction from Weierstrass coefficients (`a`-invariants), long form::136137sage: E = EllipticCurve([1,2,3,4,5]); E138Elliptic Curve defined by y^2 + x*y + 3*y = x^3 + 2*x^2 + 4*x + 5 over Rational Field139140Construction from Weierstrass coefficients (`a`-invariants),141short form (sets `a_1=a_2=a_3=0`)::142143sage: EllipticCurve([4,5]).ainvs()144(0, 0, 0, 4, 5)145146Construction from a database label::147148sage: EllipticCurve('389a1')149Elliptic Curve defined by y^2 + y = x^3 + x^2 - 2*x over Rational Field150151"""152def __init__(self, ainvs, extra=None):153r"""154Constructor for the EllipticCurve_rational_field class.155156INPUT:157158- ``ainvs`` (list or string) -- either `[a_1,a_2,a_3,a_4,a_6]`159or `[a_4,a_6]` (with `a_1=a_2=a_3=0`) or a valid label from160the database.161162.. note::163164See constructor.py for more variants.165166EXAMPLES::167168sage: E = EllipticCurve([1,2,3,4,5]); E169Elliptic Curve defined by y^2 + x*y + 3*y = x^3 + 2*x^2 + 4*x + 5 over Rational Field170171Constructor from `[a_4,a_6]` sets `a_1=a_2=a_3=0`::172173sage: EllipticCurve([4,5]).ainvs()174(0, 0, 0, 4, 5)175176Constructor from a label::177178sage: EllipticCurve('389a1')179Elliptic Curve defined by y^2 + y = x^3 + x^2 - 2*x over Rational Field180181TESTS:182183When constructing a curve from the large database using a184label, we must be careful that the copied generators have the185right curve (see #10999: the following used not to work when186the large database was installed)::187188sage: E=EllipticCurve('389a1')189sage: [P.curve() is E for P in E.gens()]190[True, True]191192"""193if extra != None: # possibility of two arguments (the first would be the field)194ainvs = extra195if isinstance(ainvs, str):196label = ainvs197X = sage.databases.cremona.CremonaDatabase()[label]198EllipticCurve_number_field.__init__(self, Q, list(X.a_invariants()))199self.__np = {}200self.__gens = {}201self.__rank = {}202self.__regulator = {}203for attr in ['rank', 'torsion_order', 'cremona_label', 'conductor',204'modular_degree', 'gens', 'regulator']:205s = "_EllipticCurve_rational_field__"+attr206if hasattr(X,s):207if attr == 'gens': # see #10999208gens_dict = getattr(X, s)209for boo in gens_dict.keys():210gens_dict[boo] = [self(P) for P in gens_dict[boo]]211setattr(self, s, gens_dict)212else:213setattr(self, s, getattr(X, s))214return215EllipticCurve_number_field.__init__(self, Q, ainvs)216self.__np = {}217self.__gens = {}218self.__rank = {}219self.__regulator = {}220if self.base_ring() != Q:221raise TypeError, "Base field (=%s) must be the Rational Field."%self.base_ring()222223def _set_rank(self, r):224"""225Internal function to set the cached rank of this elliptic curve to226r.227228.. warning::229230No checking is done! Not intended for use by users.231232EXAMPLES::233234sage: E = EllipticCurve('37a1')235sage: E._set_rank(99) # bogus value -- not checked236sage: E.rank() # returns bogus cached value23799238sage: E._EllipticCurve_rational_field__rank={} # undo the damage239sage: E.rank() # the correct rank2401241"""242self.__rank = {}243self.__rank[True] = Integer(r)244245def _set_torsion_order(self, t):246"""247Internal function to set the cached torsion order of this elliptic248curve to t.249250.. warning::251252No checking is done! Not intended for use by users.253254EXAMPLES::255256sage: E=EllipticCurve('37a1')257sage: E._set_torsion_order(99) # bogus value -- not checked258sage: E.torsion_order() # returns bogus cached value25999260sage: T = E.torsion_subgroup() # causes actual torsion to be computed261sage: E.torsion_order() # the correct value2621263"""264self.__torsion_order = Integer(t)265266def _set_cremona_label(self, L):267"""268Internal function to set the cached label of this elliptic curve to269L.270271.. warning::272273No checking is done! Not intended for use by users.274275EXAMPLES::276277sage: E=EllipticCurve('37a1')278sage: E._set_cremona_label('bogus')279sage: E.label()280'bogus'281sage: E.database_curve().label()282'37a1'283sage: E.label() # no change284'bogus'285sage: E._set_cremona_label(E.database_curve().label())286sage: E.label() # now it is correct287'37a1'288"""289self.__cremona_label = L290291def _set_conductor(self, N):292"""293Internal function to set the cached conductor of this elliptic294curve to N.295296.. warning::297298No checking is done! Not intended for use by users.299Setting to the wrong value will cause strange problems (see300examples).301302EXAMPLES::303304sage: E=EllipticCurve('37a1')305sage: E._set_conductor(99) # bogus value -- not checked306sage: E.conductor() # returns bogus cached value30799308"""309self.__conductor_pari = Integer(N)310311def _set_modular_degree(self, deg):312"""313Internal function to set the cached modular degree of this elliptic314curve to deg.315316.. warning::317318No checking is done!319320EXAMPLES::321322sage: E=EllipticCurve('5077a1')323sage: E.modular_degree()3241984325sage: E._set_modular_degree(123456789)326sage: E.modular_degree()327123456789328sage: E._set_modular_degree(E.database_curve().modular_degree())329sage: E.modular_degree()3301984331"""332self.__modular_degree = Integer(deg)333334def _set_gens(self, gens):335"""336Internal function to set the cached generators of this elliptic337curve to gens.338339.. warning::340341No checking is done!342343EXAMPLES::344345sage: E=EllipticCurve('5077a1')346sage: E.rank()3473348sage: E.gens() # random349[(-2 : 3 : 1), (-7/4 : 25/8 : 1), (1 : -1 : 1)]350sage: E._set_gens([]) # bogus list351sage: E.rank() # unchanged3523353sage: E._set_gens([E(-2,3), E(-1,3), E(0,2)])354sage: E.gens()355[(-2 : 3 : 1), (-1 : 3 : 1), (0 : 2 : 1)]356"""357self.__gens = {}358self.__gens[True] = [self.point(x, check=True) for x in gens]359self.__gens[True].sort()360361def is_p_integral(self, p):362r"""363Returns True if this elliptic curve has `p`-integral364coefficients.365366INPUT:367368369- ``p`` - a prime integer370371372EXAMPLES::373374sage: E=EllipticCurve(QQ,[1,1]); E375Elliptic Curve defined by y^2 = x^3 + x + 1 over Rational Field376sage: E.is_p_integral(2)377True378sage: E2=E.change_weierstrass_model(2,0,0,0); E2379Elliptic Curve defined by y^2 = x^3 + 1/16*x + 1/64 over Rational Field380sage: E2.is_p_integral(2)381False382sage: E2.is_p_integral(3)383True384"""385if not arith.is_prime(p):386raise ArithmeticError, "p must be prime"387if self.is_integral():388return True389return bool(misc.mul([x.valuation(p) >= 0 for x in self.ainvs()]))390391def is_integral(self):392"""393Returns True if this elliptic curve has integral coefficients (in394Z)395396EXAMPLES::397398sage: E=EllipticCurve(QQ,[1,1]); E399Elliptic Curve defined by y^2 = x^3 + x + 1 over Rational Field400sage: E.is_integral()401True402sage: E2=E.change_weierstrass_model(2,0,0,0); E2403Elliptic Curve defined by y^2 = x^3 + 1/16*x + 1/64 over Rational Field404sage: E2.is_integral()405False406"""407try:408return self.__is_integral409except AttributeError:410one = Integer(1)411self.__is_integral = bool(misc.mul([x.denominator() == 1 for x in self.ainvs()]))412return self.__is_integral413414415def mwrank(self, options=''):416r"""417Run Cremona's mwrank program on this elliptic curve and return the418result as a string.419420INPUT:421422423- ``options`` (string) -- run-time options passed when starting mwrank.424The format is as follows (see below for examples of usage):425426- ``-v n`` (verbosity level) sets verbosity to n (default=1)427- ``-o`` (PARI/GP style output flag) turns ON extra PARI/GP short output (default is OFF)428- ``-p n`` (precision) sets precision to `n` decimals (default=15)429- ``-b n`` (quartic bound) bound on quartic point search (default=10)430- ``-x n`` (n_aux) number of aux primes used for sieving (default=6)431- ``-l`` (generator list flag) turns ON listing of points (default ON unless v=0)432- ``-s`` (selmer_only flag) if set, computes Selmer rank only (default: not set)433- ``-d`` (skip_2nd_descent flag) if set, skips the second descent for curves with 2-torsion (default: not set)434- ``-S n`` (sat_bd) upper bound on saturation primes (default=100, -1 for automatic)435436OUTPUT:437438- ``string`` - output of mwrank on this curve439440441.. note::442443The output is a raw string and completely illegible using444automatic display, so it is recommended to use print for445legible output.446447EXAMPLES::448449sage: E = EllipticCurve('37a1')450sage: E.mwrank() #random451...452sage: print E.mwrank()453Curve [0,0,1,-1,0] : Basic pair: I=48, J=-432454disc=255744455...456Generator 1 is [0:-1:1]; height 0.05111...457458Regulator = 0.05111...459460The rank and full Mordell-Weil basis have been determined unconditionally.461...462463Options to mwrank can be passed::464465sage: E = EllipticCurve([0,0,0,877,0])466467Run mwrank with 'verbose' flag set to 0 but list generators if468found469470::471472sage: print E.mwrank('-v0 -l')473Curve [0,0,0,877,0] : 0 <= rank <= 1474Regulator = 1475476Run mwrank again, this time with a higher bound for point searching477on homogeneous spaces::478479sage: print E.mwrank('-v0 -l -b11')480Curve [0,0,0,877,0] : Rank = 1481Generator 1 is [29604565304828237474403861024284371796799791624792913256602210:-256256267988926809388776834045513089648669153204356603464786949:490078023219787588959802933995928925096061616470779979261000]; height 95.980371987964482Regulator = 95.980371987964483"""484if options == "":485from sage.interfaces.all import mwrank486else:487from sage.interfaces.all import Mwrank488mwrank = Mwrank(options=options)489return mwrank(list(self.a_invariants()))490491def conductor(self, algorithm="pari"):492"""493Returns the conductor of the elliptic curve.494495INPUT:496497498- ``algorithm`` - str, (default: "pari")499500- ``"pari"`` - use the PARI C-library ellglobalred501implementation of Tate's algorithm502503- ``"mwrank"`` - use Cremona's mwrank implementation504of Tate's algorithm; can be faster if the curve has integer505coefficients (TODO: limited to small conductor until mwrank gets506integer factorization)507508- ``"gp"`` - use the GP interpreter.509510- ``"generic"`` - use the general number field511implementation512513- ``"all"`` - use all four implementations, verify514that the results are the same (or raise an error), and output the515common value.516517518EXAMPLE::519520sage: E = EllipticCurve([1, -1, 1, -29372, -1932937])521sage: E.conductor(algorithm="pari")5223006523sage: E.conductor(algorithm="mwrank")5243006525sage: E.conductor(algorithm="gp")5263006527sage: E.conductor(algorithm="generic")5283006529sage: E.conductor(algorithm="all")5303006531532.. note::533534The conductor computed using each algorithm is cached535separately. Thus calling ``E.conductor('pari')``, then536``E.conductor('mwrank')`` and getting the same result537checks that both systems compute the same answer.538"""539540if algorithm == "pari":541try:542return self.__conductor_pari543except AttributeError:544self.__conductor_pari = Integer(self.pari_mincurve().ellglobalred()[0])545return self.__conductor_pari546547elif algorithm == "gp":548try:549return self.__conductor_gp550except AttributeError:551self.__conductor_gp = Integer(gp.eval('ellglobalred(ellinit(%s,0))[1]'%list(self.a_invariants())))552return self.__conductor_gp553554elif algorithm == "mwrank":555try:556return self.__conductor_mwrank557except AttributeError:558if self.is_integral():559self.__conductor_mwrank = Integer(self.mwrank_curve().conductor())560else:561self.__conductor_mwrank = Integer(self.minimal_model().mwrank_curve().conductor())562return self.__conductor_mwrank563564elif algorithm == "generic":565try:566return self.__conductor_generic567except AttributeError:568self.__conductor_generic = sage.schemes.elliptic_curves.ell_number_field.EllipticCurve_number_field.conductor(self).gen()569return self.__conductor_generic570571elif algorithm == "all":572N1 = self.conductor("pari")573N2 = self.conductor("mwrank")574N3 = self.conductor("gp")575N4 = self.conductor("generic")576if N1 != N2 or N2 != N3 or N2 != N4:577raise ArithmeticError, "PARI, mwrank, gp and Sage compute different conductors (%s,%s,%s,%3) for %s"%(578N1, N2, N3, N4, self)579return N1580else:581raise RuntimeError, "algorithm '%s' is not known."%algorithm582583####################################################################584# Access to PARI curves related to this curve.585####################################################################586587def pari_curve(self, prec = None, factor = 1):588"""589Return the PARI curve corresponding to this elliptic curve.590591INPUT:592593594- ``prec`` - The precision of quantities calculated for the595returned curve, in bits. If None, defaults to factor596multiplied by the precision of the largest cached curve (or597the default real precision if none yet computed).598599- ``factor`` - The factor by which to increase the600precision over the maximum previously computed precision. Only used601if prec (which gives an explicit precision) is None.602603604EXAMPLES::605606sage: E = EllipticCurve([0, 0, 1, -1, 0])607sage: e = E.pari_curve()608sage: type(e)609<type 'sage.libs.pari.gen.gen'>610sage: e.type()611't_VEC'612sage: e.ellan(10)613[1, -2, -3, 2, -2, 6, -1, 0, 6, 4]614615::616617sage: E = EllipticCurve(RationalField(), ['1/3', '2/3'])618sage: e = E.pari_curve(prec = 100)619sage: E._pari_curve.has_key(100)620True621sage: e.type()622't_VEC'623sage: e[:5]624[0, 0, 0, 1/3, 2/3]625626This shows that the bug uncovered by trac #3954 is fixed::627628sage: E._pari_curve.has_key(100)629True630631::632633sage: E = EllipticCurve('37a1').pari_curve()634sage: E[14].python().prec()63564636sage: [a.precision() for a in E]637[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 4, 4, 4, 4] # 32-bit638[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 3, 3, 3, 3] # 64-bit639640This shows that the bug uncovered by trac #4715 is fixed::641642sage: Ep = EllipticCurve('903b3').pari_curve()643"""644try:645# if the PARI curve has already been computed to this646# precision, returned the cached copy647return self._pari_curve[prec]648except AttributeError:649# no PARI curves have been computed for this elliptic curve650self._pari_curve = {}651if prec is None:652prec = rings.RealField().precision()653except KeyError:654# PARI curves are cached for this elliptic curve, but they655# are not of the requested precision (or prec = None)656if prec is None:657L = self._pari_curve.keys()658L.sort()659if factor == 1:660return self._pari_curve[L[-1]]661else:662prec = int(factor * L[-1])663self._pari_curve[prec] = pari(list(self.a_invariants())).ellinit(precision=prec)664return self._pari_curve[prec]665666def pari_mincurve(self, prec = None, factor = 1):667"""668Return the PARI curve corresponding to a minimal model for this669elliptic curve.670671INPUT:672673674- ``prec`` - The precision of quantities calculated for the675returned curve, in bits. If None, defaults to factor676multiplied by the precision of the largest cached curve (or677the default real precision if none yet computed).678679- ``factor`` - The factor by which to increase the680precision over the maximum previously computed precision. Only used681if prec (which gives an explicit precision) is None.682683684EXAMPLES::685686sage: E = EllipticCurve(RationalField(), ['1/3', '2/3'])687sage: e = E.pari_mincurve()688sage: e[:5]689[0, 0, 0, 27, 486]690sage: E.conductor()69147232692sage: e.ellglobalred()693[47232, [1, 0, 0, 0], 2]694"""695try:696# if the PARI curve has already been computed to this697# precision, returned the cached copy698return self._pari_mincurve[prec]699except AttributeError:700# no PARI curves have been computed for this elliptic curve701self._pari_mincurve = {}702except KeyError:703# PARI curves are cached for this elliptic curve, but they704# are not of the requested precision (or prec = None)705if prec is None:706L = self._pari_mincurve.keys()707L.sort()708if factor == 1:709return self._pari_mincurve[L[-1]]710else:711prec = int(factor * L[-1])712e = self.pari_curve(prec)713mc, change = e.ellminimalmodel()714self._pari_mincurve[prec] = mc715# self.__min_transform = change716return mc717718def database_curve(self):719"""720Return the curve in the elliptic curve database isomorphic to this721curve, if possible. Otherwise raise a RuntimeError exception.722723EXAMPLES::724725sage: E = EllipticCurve([0,1,2,3,4])726sage: E.database_curve()727Elliptic Curve defined by y^2 = x^3 + x^2 + 3*x + 5 over Rational Field728729.. note::730731The model of the curve in the database can be different732from the Weierstrass model for this curve, e.g., database733models are always minimal.734"""735try:736return self.__database_curve737except AttributeError:738misc.verbose("Looking up %s in the database."%self)739D = sage.databases.cremona.CremonaDatabase()740ainvs = list(self.minimal_model().ainvs())741try:742self.__database_curve = D.elliptic_curve_from_ainvs(ainvs)743except RuntimeError:744raise RuntimeError, "Elliptic curve %s not in the database."%self745return self.__database_curve746747748def Np(self, p):749r"""750The number of points on `E` modulo `p`.751752INPUT:753754- ``p`` (int) -- a prime, not necessarily of good reduction.755756757OUTPUT:758759(int) The number ofpoints on the reduction of `E` modulo `p`760(including the singular point when `p` is a prime of bad761reduction).762763EXAMPLES::764765sage: E = EllipticCurve([0, -1, 1, -10, -20])766sage: E.Np(2)7675768sage: E.Np(3)7695770sage: E.conductor()77111772sage: E.Np(11)77311774775This even works when the prime is large::776777sage: E = EllipticCurve('37a')778sage: E.Np(next_prime(10^30))7791000000000000001426441464441649780"""781if self.conductor() % p == 0:782return p + 1 - self.ap(p)783return p+1 - self.ap(p)784785#def __pari_double_prec(self):786# EllipticCurve_number_field._EllipticCurve__pari_double_prec(self)787# try:788# del self._pari_mincurve789# except AttributeError:790# pass791792####################################################################793# Access to mwrank794####################################################################795def mwrank_curve(self, verbose=False):796"""797Construct an mwrank_EllipticCurve from this elliptic curve798799The resulting mwrank_EllipticCurve has available methods from John800Cremona's eclib library.801802EXAMPLES::803804sage: E=EllipticCurve('11a1')805sage: EE=E.mwrank_curve()806sage: EE807y^2+ y = x^3 - x^2 - 10*x - 20808sage: type(EE)809<class 'sage.libs.mwrank.interface.mwrank_EllipticCurve'>810sage: EE.isogeny_class()811([[0, -1, 1, -10, -20], [0, -1, 1, -7820, -263580], [0, -1, 1, 0, 0]],812[[0, 5, 5], [5, 0, 0], [5, 0, 0]])813"""814try:815return self.__mwrank_curve816except AttributeError:817pass818self.__mwrank_curve = mwrank.mwrank_EllipticCurve(819list(self.ainvs()), verbose=verbose)820return self.__mwrank_curve821822def two_descent(self, verbose=True,823selmer_only = False,824first_limit = 20,825second_limit = 8,826n_aux = -1,827second_descent = 1):828"""829Compute 2-descent data for this curve.830831INPUT:832833834- ``verbose`` - (default: True) print what mwrank is835doing. If False, **no output** is printed.836837- ``selmer_only`` - (default: False) selmer_only838switch839840- ``first_limit`` - (default: 20) firstlim is bound841on x+z second_limit- (default: 8) secondlim is bound on log max842x,z , i.e. logarithmic843844- ``n_aux`` - (default: -1) n_aux only relevant for845general 2-descent when 2-torsion trivial; n_aux=-1 causes default846to be used (depends on method)847848- ``second_descent`` - (default: True)849second_descent only relevant for descent via 2-isogeny850851852OUTPUT:853854Returns ``True`` if the descent succeeded, i.e. if the lower bound and855the upper bound for the rank are the same. In this case, generators and856the rank are cached. A return value of ``False`` indicates that either857rational points were not found, or that Sha[2] is nontrivial and mwrank858was unable to determine this for sure.859860EXAMPLES::861862sage: E=EllipticCurve('37a1')863sage: E.two_descent(verbose=False)864True865866"""867misc.verbose("Calling mwrank C++ library.")868C = self.mwrank_curve()869C.two_descent(verbose, selmer_only,870first_limit, second_limit,871n_aux, second_descent)872if C.certain():873self.__gens[True] = [self.point(x, check=True) for x in C.gens()]874self.__gens[True].sort()875self.__rank[True] = len(self.__gens[True])876return C.certain()877878####################################################################879# Etc.880####################################################################881882def aplist(self, n, python_ints=False):883r"""884The Fourier coefficients `a_p` of the modular form885attached to this elliptic curve, for all primes `p\leq n`.886887INPUT:888889890- ``n`` - integer891892- ``python_ints`` - bool (default: False); if True893return a list of Python ints instead of Sage integers.894895896OUTPUT: list of integers897898EXAMPLES::899900sage: e = EllipticCurve('37a')901sage: e.aplist(1)902[]903sage: e.aplist(2)904[-2]905sage: e.aplist(10)906[-2, -3, -2, -1]907sage: v = e.aplist(13); v908[-2, -3, -2, -1, -5, -2]909sage: type(v[0])910<type 'sage.rings.integer.Integer'>911sage: type(e.aplist(13, python_ints=True)[0])912<type 'int'>913"""914e = self.pari_mincurve()915v = e.ellaplist(n, python_ints=True)916if python_ints:917return v918else:919return [Integer(a) for a in v]920921922923def anlist(self, n, python_ints=False):924"""925The Fourier coefficients up to and including `a_n` of the926modular form attached to this elliptic curve. The i-th element of927the return list is a[i].928929INPUT:930931932- ``n`` - integer933934- ``python_ints`` - bool (default: False); if True935return a list of Python ints instead of Sage integers.936937938OUTPUT: list of integers939940EXAMPLES::941942sage: E = EllipticCurve([0, -1, 1, -10, -20])943sage: E.anlist(3)944[0, 1, -2, -1]945946::947948sage: E = EllipticCurve([0,1])949sage: E.anlist(20)950[0, 1, 0, 0, 0, 0, 0, -4, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 8, 0]951"""952n = int(n)953e = self.pari_mincurve()954if n >= 2147483648:955raise RuntimeError, "anlist: n (=%s) must be < 2147483648."%n956957v = [0] + e.ellan(n, python_ints=True)958if not python_ints:959v = [Integer(x) for x in v]960return v961962963# There is some overheard associated with coercing the PARI964# list back to Python, but it's not bad. It's better to do it965# this way instead of trying to eval the whole list, since the966# int conversion is done very sensibly. NOTE: This would fail967# if a_n won't fit in a C int, i.e., is bigger than968# 2147483648; however, we wouldn't realistically compute969# anlist for n that large anyway.970#971# Some relevant timings:972#973# E <--> [0, 1, 1, -2, 0] 389A974# E = EllipticCurve([0, 1, 1, -2, 0]); // Sage or MAGMA975# e = E.pari_mincurve()976# f = ellinit([0,1,1,-2,0]);977#978# Computation Time (1.6Ghz Pentium-4m laptop)979# time v:=TracesOfFrobenius(E,10000); // MAGMA 0.120980# gettime;v=ellan(f,10000);gettime/1000 0.046981# time v=e.ellan (10000) 0.04982# time v=E.anlist(10000) 0.07983984# time v:=TracesOfFrobenius(E,100000); // MAGMA 1.620985# gettime;v=ellan(f,100000);gettime/1000 0.676986# time v=e.ellan (100000) 0.7987# time v=E.anlist(100000) 0.83988989# time v:=TracesOfFrobenius(E,1000000); // MAGMA 20.850990# gettime;v=ellan(f,1000000);gettime/1000 9.238991# time v=e.ellan (1000000) 9.61992# time v=E.anlist(1000000) 10.95 (13.171 in cygwin vmware)993994# time v:=TracesOfFrobenius(E,10000000); //MAGMA 257.850995# gettime;v=ellan(f,10000000);gettime/1000 FAILS no matter how many allocatemem()'s!!996# time v=e.ellan (10000000) 139.37997# time v=E.anlist(10000000) 136.32998#999# The last Sage comp retries with stack size 40MB,1000# 80MB, 160MB, and succeeds last time. It's very interesting that this1001# last computation is *not* possible in GP, but works in py_pari!1002#10031004def q_expansion(self, prec):1005r"""1006Return the `q`-expansion to precision prec of the newform1007attached to this elliptic curve.10081009INPUT:101010111012- ``prec`` - an integer101310141015OUTPUT:10161017a power series (in the variable 'q')10181019.. note::10201021If you want the output to be a modular form and not just a1022`q`-expansion, use :meth:`.modular_form`.10231024EXAMPLES::10251026sage: E=EllipticCurve('37a1')1027sage: E.q_expansion(20)1028q - 2*q^2 - 3*q^3 + 2*q^4 - 2*q^5 + 6*q^6 - q^7 + 6*q^9 + 4*q^10 - 5*q^11 - 6*q^12 - 2*q^13 + 2*q^14 + 6*q^15 - 4*q^16 - 12*q^18 + O(q^20)1029"""1030return PowerSeriesRing(Q, 'q')(self.anlist(prec), prec, check=True)10311032def modular_form(self):1033r"""1034Return the cuspidal modular form associated to this elliptic1035curve.10361037EXAMPLES::10381039sage: E = EllipticCurve('37a')1040sage: f = E.modular_form()1041sage: f1042q - 2*q^2 - 3*q^3 + 2*q^4 - 2*q^5 + O(q^6)10431044If you need to see more terms in the `q`-expansion::10451046sage: f.q_expansion(20)1047q - 2*q^2 - 3*q^3 + 2*q^4 - 2*q^5 + 6*q^6 - q^7 + 6*q^9 + 4*q^10 - 5*q^11 - 6*q^12 - 2*q^13 + 2*q^14 + 6*q^15 - 4*q^16 - 12*q^18 + O(q^20)10481049.. note::10501051If you just want the `q`-expansion, use1052:meth:`.q_expansion`.1053"""1054try:1055return self.__modular_form1056except AttributeError:1057M = sage.modular.modform.constructor.ModularForms(self.conductor(),weight=2)1058f = sage.modular.modform.element.ModularFormElement_elliptic_curve(M, self)1059self.__modular_form = f1060return f10611062def modular_symbol_space(self, sign=1, base_ring=Q, bound=None):1063r"""1064Return the space of cuspidal modular symbols associated to this1065elliptic curve, with given sign and base ring.10661067INPUT:106810691070- ``sign`` - 0, -1, or 110711072- ``base_ring`` - a ring107310741075EXAMPLES::10761077sage: f = EllipticCurve('37b')1078sage: f.modular_symbol_space()1079Modular Symbols subspace of dimension 1 of Modular Symbols space of dimension 3 for Gamma_0(37) of weight 2 with sign 1 over Rational Field1080sage: f.modular_symbol_space(-1)1081Modular Symbols subspace of dimension 1 of Modular Symbols space of dimension 2 for Gamma_0(37) of weight 2 with sign -1 over Rational Field1082sage: f.modular_symbol_space(0, bound=3)1083Modular Symbols subspace of dimension 2 of Modular Symbols space of dimension 5 for Gamma_0(37) of weight 2 with sign 0 over Rational Field10841085.. note::10861087If you just want the `q`-expansion, use1088:meth:`.q_expansion`.1089"""1090typ = (sign, base_ring)1091try:1092return self.__modular_symbol_space[typ]1093except AttributeError:1094self.__modular_symbol_space = {}1095except KeyError:1096pass1097M = ell_modular_symbols.modular_symbol_space(self, sign, base_ring, bound=bound)1098self.__modular_symbol_space[typ] = M1099return M11001101def modular_symbol(self, sign=1, use_eclib = False, normalize = "L_ratio"):1102r"""1103Return the modular symbol associated to this elliptic curve,1104with given sign and base ring. This is the map that sends `r/s`1105to a fixed multiple of the integral of `2 \pi i f(z) dz`1106from `\infty` to `r/s`, normalized so that all values of this map take1107values in `\QQ`.11081109The normalization is such that for sign +1,1110the value at the cusp 0 is equal to the quotient of `L(E,1)`1111by the least positive period of `E` (unlike in ``L_ratio``1112of ``lseries()``, where the value is also divided by the1113number of connected components of `E(\RR)`). In particular the1114modular symbol depends on `E` and not only the isogeny class of `E`.11151116INPUT:11171118- ``sign`` - -1, or 111191120- ``base_ring`` - a ring11211122- ``normalize`` - (default: True); if True, the1123modular symbol is correctly normalized (up to possibly a factor of1124-1 or 2). If False, the modular symbol is almost certainly not1125correctly normalized, i.e., all values will be a fixed scalar1126multiple of what they should be. But the initial computation of the1127modular symbol is much faster, though evaluation of it after1128computing it won't be any faster.11291130- ``use_eclib`` - (default: False); if True the computation is1131done with John Cremona's implementation of modular1132symbols in ``eclib``11331134- ``normalize`` - (default: 'L_ratio'); either 'L_ratio', 'period', or 'none';1135For 'L_ratio', the modular symbol is correctly normalized1136as explained above by comparing it to ``L_ratio`` for the1137curve and some small twists.1138The normalization 'period' is only available if1139``use_eclib=False``. It uses the ``integral_period_map`` for modular1140symbols and is known to be equal to the above normalization1141up to the sign and a possible power of 2.1142For 'none', the modular symbol is almost certainly1143not correctly normalized, i.e. all values will be a1144fixed scalar multiple of what they should be. But1145the initial computation of the modular symbol is1146much faster if ``use_eclib=False``, though evaluation of1147it after computing it won't be any faster.114811491150EXAMPLES::11511152sage: E=EllipticCurve('37a1')1153sage: M=E.modular_symbol(); M1154Modular symbol with sign 1 over Rational Field attached to Elliptic Curve defined by y^2 + y = x^3 - x over Rational Field1155sage: M(1/2)115601157sage: M(1/5)1158111591160::11611162sage: E=EllipticCurve('121b1')1163sage: M=E.modular_symbol()1164Warning : Could not normalize the modular symbols, maybe all further results will be multiplied by -1, 2 or -2.1165sage: M(1/7)1166-111671168::11691170sage: E=EllipticCurve('11a1')1171sage: E.modular_symbol()(0)11721/51173sage: E=EllipticCurve('11a2')1174sage: E.modular_symbol()(0)117511176sage: E=EllipticCurve('11a3')1177sage: E.modular_symbol()(0)11781/2511791180::11811182sage: E=EllipticCurve('11a2')1183sage: E.modular_symbol(use_eclib=True, normalize='L_ratio')(0)118411185sage: E.modular_symbol(use_eclib=True, normalize='none')(0)11862/51187sage: E.modular_symbol(use_eclib=True, normalize='period')(0)1188Traceback (most recent call last):1189...1190ValueError: no normalization 'period' known for modular symbols using John Cremona's eclib1191sage: E.modular_symbol(use_eclib=False, normalize='L_ratio')(0)119211193sage: E.modular_symbol(use_eclib=False, normalize='none')(0)119411195sage: E.modular_symbol(use_eclib=False, normalize='period')(0)1196111971198::11991200sage: E=EllipticCurve('11a3')1201sage: E.modular_symbol(use_eclib=True, normalize='L_ratio')(0)12021/251203sage: E.modular_symbol(use_eclib=True, normalize='none')(0)12042/51205sage: E.modular_symbol(use_eclib=True, normalize='period')(0)1206Traceback (most recent call last):1207...1208ValueError: no normalization 'period' known for modular symbols using John Cremona's eclib1209sage: E.modular_symbol(use_eclib=False, normalize='L_ratio')(0)12101/251211sage: E.modular_symbol(use_eclib=False, normalize='none')(0)121211213sage: E.modular_symbol(use_eclib=False, normalize='period')(0)12141/2512151216"""1217typ = (sign, normalize, use_eclib)1218try:1219return self.__modular_symbol[typ]1220except AttributeError:1221self.__modular_symbol = {}1222except KeyError:1223pass1224if use_eclib :1225M = ell_modular_symbols.ModularSymbolECLIB(self, sign, normalize=normalize)1226else :1227M = ell_modular_symbols.ModularSymbolSage(self, sign, normalize=normalize)1228self.__modular_symbol[typ] = M1229return M12301231padic_lseries = padics.padic_lseries12321233def newform(self):1234r"""1235Same as ``self.modular_form()``.12361237EXAMPLES::12381239sage: E=EllipticCurve('37a1')1240sage: E.newform()1241q - 2*q^2 - 3*q^3 + 2*q^4 - 2*q^5 + O(q^6)1242sage: E.newform() == E.modular_form()1243True1244"""1245return self.modular_form()12461247def q_eigenform(self, prec):1248r"""1249Synonym for ``self.q_expansion(prec)``.12501251EXAMPLES::12521253sage: E=EllipticCurve('37a1')1254sage: E.q_eigenform(10)1255q - 2*q^2 - 3*q^3 + 2*q^4 - 2*q^5 + 6*q^6 - q^7 + 6*q^9 + O(q^10)1256sage: E.q_eigenform(10) == E.q_expansion(10)1257True1258"""1259return self.q_expansion(prec)12601261def analytic_rank(self, algorithm="pari", leading_coefficient=False):1262r"""1263Return an integer that is *probably* the analytic rank of this1264elliptic curve. If leading_coefficient is ``True`` (only implemented1265for PARI), return a tuple `(rank, lead)` where `lead` is the value of1266the first non-zero derivative of the L-function of the elliptic1267curve.12681269INPUT:12701271- algorithm -12721273- 'pari' (default) - use the PARI library function.12741275- 'sympow' -use Watkins's program sympow12761277- 'rubinstein' - use Rubinstein's L-function C++ program lcalc.12781279- 'magma' - use MAGMA12801281- 'all' - compute with all other free algorithms, check that1282the answers agree, and return the common answer.12831284.. note::12851286If the curve is loaded from the large Cremona database,1287then the modular degree is taken from the database.12881289Of the three above, probably Rubinstein's is the most1290efficient (in some limited testing I've done).12911292.. note::12931294It is an open problem to *prove* that *any* particular1295elliptic curve has analytic rank `\geq 4`.12961297EXAMPLES::12981299sage: E = EllipticCurve('389a')1300sage: E.analytic_rank(algorithm='pari')130121302sage: E.analytic_rank(algorithm='rubinstein')130321304sage: E.analytic_rank(algorithm='sympow')130521306sage: E.analytic_rank(algorithm='magma') # optional - magma130721308sage: E.analytic_rank(algorithm='all')1309213101311With the optional parameter leading_coefficient set to ``True``, a1312tuple of both the analytic rank and the leading term of the1313L-series at `s = 1` is returned::13141315sage: EllipticCurve([0,-1,1,-10,-20]).analytic_rank(leading_coefficient=True)1316(0, 0.25384186085591068...)1317sage: EllipticCurve([0,0,1,-1,0]).analytic_rank(leading_coefficient=True)1318(1, 0.30599977383405230...)1319sage: EllipticCurve([0,1,1,-2,0]).analytic_rank(leading_coefficient=True)1320(2, 1.518633000576853...)1321sage: EllipticCurve([0,0,1,-7,6]).analytic_rank(leading_coefficient=True)1322(3, 10.39109940071580...)1323sage: EllipticCurve([0,0,1,-7,36]).analytic_rank(leading_coefficient=True)1324(4, 196.170903794579...)13251326TESTS:13271328When the input is horrendous, some of the algorithms just bomb out with a RuntimeError::13291330sage: EllipticCurve([1234567,89101112]).analytic_rank(algorithm='rubinstein')1331Traceback (most recent call last):1332...1333RuntimeError: unable to compute analytic rank using rubinstein algorithm ('unable to convert x (= 6.19283e+19 and is too large) to an integer')1334sage: EllipticCurve([1234567,89101112]).analytic_rank(algorithm='sympow')1335Traceback (most recent call last):1336...1337RuntimeError: failed to compute analytic rank1338"""1339if algorithm == 'pari':1340rank_lead = self.pari_curve().ellanalyticrank()1341if leading_coefficient:1342return (rings.Integer(rank_lead[0]), rank_lead[1].python())1343else:1344return rings.Integer(self.pari_curve().ellanalyticrank()[0])1345elif algorithm == 'rubinstein':1346if leading_coefficient:1347raise NotImplementedError, "Cannot compute leading coefficient using rubinstein algorithm"1348try:1349from sage.lfunctions.lcalc import lcalc1350return lcalc.analytic_rank(L=self)1351except TypeError,msg:1352raise RuntimeError, "unable to compute analytic rank using rubinstein algorithm ('%s')"%msg1353elif algorithm == 'sympow':1354if leading_coefficient:1355raise NotImplementedError, "Cannot compute leading coefficient using sympow"1356from sage.lfunctions.sympow import sympow1357return sympow.analytic_rank(self)[0]1358elif algorithm == 'magma':1359if leading_coefficient:1360raise NotImplementedError, "Cannot compute leading coefficient using magma"1361from sage.interfaces.all import magma1362return rings.Integer(magma(self).AnalyticRank())1363elif algorithm == 'all':1364if leading_coefficient:1365S = set([self.analytic_rank('pari', True)])1366else:1367S = set([self.analytic_rank('pari'),1368self.analytic_rank('rubinstein'), self.analytic_rank('sympow')])1369if len(S) != 1:1370raise RuntimeError, "Bug in analytic_rank; algorithms don't agree! (E=%s)"%E1371return list(S)[0]1372else:1373raise ValueError, "algorithm %s not defined"%algorithm137413751376def simon_two_descent(self, verbose=0, lim1=5, lim3=50, limtriv=10, maxprob=20, limbigprime=30):1377r"""1378Computes a lower bound for the rank of the Mordell-Weil group `E(Q)`,1379the rank of the 2-Selmer group, and a list of independent points on1380`E(Q)/2E(Q)`.13811382INPUT:138313841385- ``verbose`` - integer, 0,1,2,3; (default: 0), the1386verbosity level13871388- ``lim1`` - (default: 5) limite des points triviaux1389sur les quartiques13901391- ``lim3`` - (default: 50) limite des points sur les1392quartiques ELS13931394- ``limtriv`` - (default: 10) limite des points1395triviaux sur la courbe elliptique13961397- ``maxprob`` - (default: 20)13981399- ``limbigprime`` - (default: 30) to distinguish1400between small and large prime numbers. Use probabilistic tests for1401large primes. If 0, don't any probabilistic tests.140214031404OUTPUT:140514061407- ``integer`` - lower bound on the rank of self14081409- ``integer`` - the 2-rank of the Selmer group14101411- ``list`` - list of independent points on the1412quotient `E(Q)/2E(Q)`.141314141415IMPLEMENTATION: Uses Denis Simon's PARI/GP scripts from1416http://www.math.unicaen.fr/~simon/14171418EXAMPLES: These computations use pseudo-random numbers, so we set1419the seed for reproducible testing.14201421We compute the ranks of the curves of lowest known conductor up to1422rank `8`. Amazingly, each of these computations finishes1423almost instantly!14241425::14261427sage: E = EllipticCurve('11a1')1428sage: set_random_seed(0)1429sage: E.simon_two_descent()1430(0, 0, [])1431sage: E = EllipticCurve('37a1')1432sage: set_random_seed(0)1433sage: E.simon_two_descent()1434(1, 1, [(0 : 0 : 1)])1435sage: E = EllipticCurve('389a1')1436sage: set_random_seed(0)1437sage: E.simon_two_descent()1438(2, 2, [(1 : 0 : 1), (-11/9 : -55/27 : 1)])1439sage: E = EllipticCurve('5077a1')1440sage: set_random_seed(0)1441sage: E.simon_two_descent()1442(3, 3, [(1 : -1 : 1), (2 : 0 : 1), (0 : 2 : 1)])14431444In this example Simon's program does not find any points, though it1445does correctly compute the rank of the 2-Selmer group.14461447::14481449sage: E = EllipticCurve([1, -1, 0, -751055859, -7922219731979])1450sage: set_random_seed(0)1451sage: E.simon_two_descent()1452(1, 1, [])14531454The rest of these entries were taken from Tom Womack's page1455http://tom.womack.net/maths/conductors.htm14561457::14581459sage: E = EllipticCurve([1, -1, 0, -79, 289])1460sage: set_random_seed(0)1461sage: E.simon_two_descent()1462(4, 4, [(4 : 3 : 1), (5 : -2 : 1), (6 : -1 : 1), (8 : 7 : 1)])1463sage: E = EllipticCurve([0, 0, 1, -79, 342])1464sage: set_random_seed(0)1465sage: E.simon_two_descent() # long time (9s on sage.math, 2011)1466(5, 5, [(5 : 8 : 1), (4 : 9 : 1), (3 : 11 : 1), (-1 : 20 : 1), (-6 : -25 : 1)])1467sage: E = EllipticCurve([1, 1, 0, -2582, 48720])1468sage: set_random_seed(0)1469sage: r, s, G = E.simon_two_descent(); r,s1470(6, 6)1471sage: E = EllipticCurve([0, 0, 0, -10012, 346900])1472sage: set_random_seed(0)1473sage: r, s, G = E.simon_two_descent(); r,s1474(7, 7)1475sage: E = EllipticCurve([0, 0, 1, -23737, 960366])1476sage: set_random_seed(0)1477sage: r, s, G = E.simon_two_descent(); r,s1478(8, 8)14791480Example from trac 10832::14811482sage: E = EllipticCurve([1,0,0,-6664,86543])1483sage: E.simon_two_descent()1484(2, 3, [(173 : 1943 : 1), (-73 : -394 : 1), (323/4 : 1891/8 : 1)])1485sage: E.rank()148621487sage: E.gens()1488[(-73 : -394 : 1), (323/4 : 1891/8 : 1)]14891490Example from Trac #11372::14911492sage: E = EllipticCurve([1, 1, 0, -23611790086, 1396491910863060])1493sage: E.simon_two_descent()1494(1, 2, [(88716 : -44358 : 1)])1495sage: E.rank()149611497sage: E.gens()1498[(4311692542083/48594841 : -13035144436525227/338754636611 : 1)]1499"""1500verbose = int(verbose)1501t = simon_two_descent(self, verbose=verbose, lim1=lim1, lim3=lim3, limtriv=limtriv,1502maxprob=maxprob, limbigprime=limbigprime)1503if t=='fail':1504raise RuntimeError, 'Run-time error in simon_two_descent.'1505if verbose>0:1506print "simon_two_descent returns", t1507rank_low_bd = rings.Integer(t[0])1508two_selmer_rank = rings.Integer(t[1])1509gens_mod_two = [self(P) for P in t[2]]1510if rank_low_bd == two_selmer_rank - self.two_torsion_rank():1511if verbose>0:1512print "Rank determined successfully, saturating..."1513gens = [P for P in gens_mod_two if P.has_infinite_order()]1514gens = self.saturation(gens)[0]1515if len(gens) == rank_low_bd:1516self.__gens[True] = gens1517self.__gens[True].sort()1518self.__rank[True] = rank_low_bd1519return rank_low_bd, two_selmer_rank, gens_mod_two15201521two_descent_simon = simon_two_descent15221523def three_selmer_rank(self, algorithm='UseSUnits'):1524r"""1525Return the 3-selmer rank of this elliptic curve, computed using1526Magma.15271528INPUT:152915301531- ``algorithm`` - 'Heuristic' (which is usually much1532faster in large examples), 'FindCubeRoots', or 'UseSUnits'1533(default)153415351536OUTPUT: nonnegative integer15371538EXAMPLES: A rank 0 curve::15391540sage: EllipticCurve('11a').three_selmer_rank() # optional - magma1541015421543A rank 0 curve with rational 3-isogeny but no 3-torsion15441545::15461547sage: EllipticCurve('14a3').three_selmer_rank() # optional - magma1548015491550A rank 0 curve with rational 3-torsion::15511552sage: EllipticCurve('14a1').three_selmer_rank() # optional - magma1553115541555A rank 1 curve with rational 3-isogeny::15561557sage: EllipticCurve('91b').three_selmer_rank() # optional - magma1558215591560A rank 0 curve with nontrivial 3-Sha. The Heuristic option makes1561this about twice as fast as without it.15621563::15641565sage: EllipticCurve('681b').three_selmer_rank(algorithm='Heuristic') # long time (10 seconds); optional - magma156621567"""1568from sage.interfaces.all import magma1569E = magma(self)1570return Integer(E.ThreeSelmerGroup(MethodForFinalStep = magma('"%s"'%algorithm)).Ngens())15711572def rank(self, use_database=False, verbose=False,1573only_use_mwrank=True,1574algorithm='mwrank_lib',1575proof=None):1576"""1577Return the rank of this elliptic curve, assuming no conjectures.15781579If we fail to provably compute the rank, raises a RuntimeError1580exception.15811582INPUT:158315841585- ``use_database (bool)`` - (default: False), if1586True, try to look up the regulator in the Cremona database.15871588- ``verbose`` - (default: None), if specified changes1589the verbosity of mwrank computations. algorithm -15901591- ``- 'mwrank_shell'`` - call mwrank shell command15921593- ``- 'mwrank_lib'`` - call mwrank c library15941595- ``only_use_mwrank`` - (default: True) if False try1596using analytic rank methods first.15971598- ``proof`` - bool or None (default: None, see1599proof.elliptic_curve or sage.structure.proof). Note that results1600obtained from databases are considered proof = True160116021603OUTPUT:160416051606- ``rank (int)`` - the rank of the elliptic curve.160716081609IMPLEMENTATION: Uses L-functions, mwrank, and databases.16101611EXAMPLES::16121613sage: EllipticCurve('11a').rank()161401615sage: EllipticCurve('37a').rank()161611617sage: EllipticCurve('389a').rank()161821619sage: EllipticCurve('5077a').rank()162031621sage: EllipticCurve([1, -1, 0, -79, 289]).rank() # This will use the default proof behavior of True162241623sage: EllipticCurve([0, 0, 1, -79, 342]).rank(proof=False)162451625sage: EllipticCurve([0, 0, 1, -79, 342]).simon_two_descent()[0]1626516271628Examples with denominators in defining equations::16291630sage: E = EllipticCurve([0, 0, 0, 0, -675/4])1631sage: E.rank()163201633sage: E = EllipticCurve([0, 0, 1/2, 0, -1/5])1634sage: E.rank()163511636sage: E.minimal_model().rank()1637116381639A large example where mwrank doesn't determine the result with certainty::16401641sage: EllipticCurve([1,0,0,0,37455]).rank(proof=False)164201643sage: EllipticCurve([1,0,0,0,37455]).rank(proof=True)1644Traceback (most recent call last):1645...1646RuntimeError: Rank not provably correct.1647"""1648if proof is None:1649from sage.structure.proof.proof import get_flag1650proof = get_flag(proof, "elliptic_curve")1651else:1652proof = bool(proof)1653try:1654return self.__rank[proof]1655except KeyError:1656if proof is False and self.__rank.has_key(True):1657return self.__rank[True]1658if use_database:1659try:1660self.__rank[True] = self.database_curve().rank()1661return self.__rank[True]1662except (AttributeError, RuntimeError):1663pass1664if not only_use_mwrank:1665N = self.conductor()1666prec = int(4*float(sqrt(N))) + 101667if self.root_number() == 1:1668L, err = self.lseries().at1(prec)1669if abs(L) > err + R(0.0001): # definitely doesn't vanish1670misc.verbose("rank 0 because L(E,1)=%s"%L)1671self.__rank[proof] = 01672return self.__rank[proof]1673else:1674Lprime, err = self.lseries().deriv_at1(prec)1675if abs(Lprime) > err + R(0.0001): # definitely doesn't vanish1676misc.verbose("rank 1 because L'(E,1)=%s"%Lprime)1677self.__rank[proof] = 11678return self.__rank[proof]16791680if algorithm == 'mwrank_lib':1681misc.verbose("using mwrank lib")1682if self.is_integral(): E = self1683else: E = self.integral_model()1684C = E.mwrank_curve()1685C.set_verbose(verbose)1686r = C.rank()1687if C.certain():1688proof = True1689else:1690if proof:1691print "Unable to compute the rank with certainty (lower bound=%s)."%C.rank()1692print "This could be because Sha(E/Q)[2] is nontrivial."1693print "Try calling something like two_descent(second_limit=13) on the"1694print "curve then trying this command again. You could also try rank"1695print "with only_use_mwrank=False."1696del E.__mwrank_curve1697raise RuntimeError, 'Rank not provably correct.'1698else:1699misc.verbose("Warning -- rank not proven correct", level=1)1700self.__rank[proof] = r1701elif algorithm == 'mwrank_shell':1702misc.verbose("using mwrank shell")1703X = self.mwrank()1704if 'determined unconditionally' not in X or 'only a lower bound of' in X:1705if proof:1706X= "".join(X.split("\n")[-4:-2])1707print X1708raise RuntimeError, 'Rank not provably correct.'1709else:1710misc.verbose("Warning -- rank not proven correct", level=1)17111712s = "lower bound of"1713X = X[X.rfind(s)+len(s)+1:]1714r = Integer(X.split()[0])1715else:1716if proof is False:1717proof = True #since we actually provably found the rank1718match = 'Rank ='1719i = X.find(match)1720if i == -1:1721match = 'found points of rank'1722i = X.find(match)1723if i == -1:1724raise RuntimeError, "%s\nbug -- tried to find 'Rank =' or 'found points of rank' in mwrank output but couldn't."%X1725j = i + X[i:].find('\n')1726r = Integer(X[i+len(match)+1:j])1727self.__rank[proof] = r17281729return self.__rank[proof]17301731def gens(self, verbose=False, rank1_search=10,1732algorithm='mwrank_lib',1733only_use_mwrank=True,1734proof = None,1735use_database = True,1736descent_second_limit=12,1737sat_bound = 1000):1738"""1739Compute and return generators for the Mordell-Weil group E(Q)1740*modulo* torsion.17411742.. warning::17431744If the program fails to give a provably correct result, it1745prints a warning message, but does not raise an1746exception. Use the gens_certain command to find out if this1747warning message was printed.17481749INPUT:175017511752- ``verbose`` - (default: None), if specified changes1753the verbosity of mwrank computations.17541755- ``rank1_search`` - (default: 10), if the curve has1756analytic rank 1, try to find a generator by a direct search up to1757this logarithmic height. If this fails the usual mwrank procedure1758is called. algorithm -17591760- ``- 'mwrank_shell' (default)`` - call mwrank shell1761command17621763- ``- 'mwrank_lib'`` - call mwrank c library17641765- ``only_use_mwrank`` - bool (default True) if1766False, attempts to first use more naive, natively implemented1767methods.17681769- ``proof`` - bool or None (default None, see1770proof.elliptic_curve or sage.structure.proof).17711772- ``use_database`` - bool (default True) if True,1773attempts to find curve and gens in the (optional) database17741775- ``descent_second_limit`` - (default: 12)- used in 2-descent17761777- ``sat_bound`` - (default: 1000) - bound on primes used in1778saturation. If the computed bound on the index of the1779points found by two-descent in the Mordell-Weil group is1780greater than this, a warning message will be displayed.17811782OUTPUT:178317841785- ``generators`` - List of generators for the1786Mordell-Weil group modulo torsion.178717881789IMPLEMENTATION: Uses Cremona's mwrank C library.17901791EXAMPLES::17921793sage: E = EllipticCurve('389a')1794sage: E.gens() # random output1795[(-1 : 1 : 1), (0 : 0 : 1)]17961797A non-integral example::17981799sage: E = EllipticCurve([-3/8,-2/3])1800sage: E.gens() # random (up to sign)1801[(10/9 : 29/54 : 1)]18021803A non-minimal example::18041805sage: E = EllipticCurve('389a1')1806sage: E1 = E.change_weierstrass_model([1/20,0,0,0]); E11807Elliptic Curve defined by y^2 + 8000*y = x^3 + 400*x^2 - 320000*x over Rational Field1808sage: E1.gens() # random (if database not used)1809[(-400 : 8000 : 1), (0 : -8000 : 1)]1810"""1811if proof is None:1812from sage.structure.proof.proof import get_flag1813proof = get_flag(proof, "elliptic_curve")1814else:1815proof = bool(proof)18161817# If the gens are already cached, return them:1818try:1819return list(self.__gens[proof]) # return copy so not changed1820except AttributeError:1821pass1822except KeyError:1823if proof is False and self.__gens.has_key(True):1824return self.__gens[True]18251826# At this point, either self.__gens does not exist, or1827# self.__gens[False] exists but not self.__gens[True], and1828# proof is True18291830# If the optional extended database is installed and an1831# isomorphic curve is in the database then its gens will be1832# known; if only the default database is installed, the rank1833# will be known but not the gens.18341835if use_database:1836try:1837E = self.database_curve()1838iso = E.isomorphism_to(self)1839try:1840self.__gens[True] = [iso(P) for P in E.__gens[True]]1841return self.__gens[True]1842except (KeyError,AttributeError): # database curve does not have the gens1843pass1844except (RuntimeError, KeyError): # curve or gens not in database1845pass18461847if self.conductor() > 10**7:1848only_use_mwrank = True18491850if not only_use_mwrank:1851try:1852misc.verbose("Trying to compute rank.")1853r = self.rank(only_use_mwrank = False)1854misc.verbose("Got r = %s."%r)1855if r == 0:1856misc.verbose("Rank = 0, so done.")1857self.__gens[True] = []1858return self.__gens[True]1859if r == 1 and rank1_search:1860misc.verbose("Rank = 1, so using direct search.")1861h = 61862while h <= rank1_search:1863misc.verbose("Trying direct search up to height %s"%h)1864G = self.point_search(h, verbose)1865G = [P for P in G if P.order() == oo]1866if len(G) > 0:1867misc.verbose("Direct search succeeded.")1868G, _, _ = self.saturation(G, verbose=verbose)1869misc.verbose("Computed saturation.")1870self.__gens[True] = G1871return self.__gens[True]1872h += 21873misc.verbose("Direct search FAILED.")1874except RuntimeError:1875pass1876# end if (not_use_mwrank)1877if algorithm == "mwrank_lib":1878misc.verbose("Calling mwrank C++ library.")1879if not self.is_integral():1880xterm = 1; yterm = 11881ai = self.a_invariants()1882for a in ai:1883if not a.is_integral():1884for p, _ in a.denom().factor():1885e = min([(ai[i].valuation(p)/[1,2,3,4,6][i]) for i in range(5)]).floor()1886ai = [ai[i]/p**(e*[1,2,3,4,6][i]) for i in range(5)]1887xterm *= p**(2*e)1888yterm *= p**(3*e)1889E = constructor.EllipticCurve(list(ai))1890else:1891E = self; xterm = 1; yterm = 11892C = E.mwrank_curve(verbose)1893if not (verbose is None):1894C.set_verbose(verbose)1895C.two_descent(verbose=verbose, second_limit=descent_second_limit)1896C.saturate(bound=sat_bound)1897G = C.gens()1898if proof is True and C.certain() is False:1899del self.__mwrank_curve1900raise RuntimeError, "Unable to compute the rank, hence generators, with certainty (lower bound=%s, generators found=%s). This could be because Sha(E/Q)[2] is nontrivial."%(C.rank(),G) + \1901"\nTry increasing descent_second_limit then trying this command again."1902else:1903proof = C.certain()1904G = [[x*xterm,y*yterm,z] for x,y,z in G]1905else:1906# when gens() calls mwrank it passes the command-line1907# parameter "-p 100" which helps curves with large1908# coefficients and 2-torsion and is otherwise harmless.1909# This is pending a more intelligent handling of mwrank1910# options in gens() (which is nontrivial since gens() needs1911# to parse the output from mwrank and this is seriously1912# affected by what parameters the user passes!).1913# In fact it would be much better to avoid the mwrank console at1914# all for gens() and just use the library. This is in1915# progress (see trac #1949).1916X = self.mwrank('-p 100 -S '+str(sat_bound))1917misc.verbose("Calling mwrank shell.")1918if not 'The rank and full Mordell-Weil basis have been determined unconditionally' in X:1919msg = 'Generators not provably computed.'1920if proof:1921raise RuntimeError, '%s\n%s'%(X,msg)1922else:1923misc.verbose("Warning -- %s"%msg, level=1)1924elif proof is False:1925proof = True1926G = []1927i = X.find('Generator ')1928while i != -1:1929j = i + X[i:].find(';')1930k = i + X[i:].find('[')1931G.append(eval(X[k:j].replace(':',',')))1932X = X[j:]1933i = X.find('Generator ')1934####1935self.__gens[proof] = [self.point(x, check=True) for x in G]1936self.__gens[proof].sort()1937self.__rank[proof] = len(self.__gens[proof])1938return self.__gens[proof]19391940def gens_certain(self):1941"""1942Return True if the generators have been proven correct.19431944EXAMPLES::19451946sage: E=EllipticCurve('37a1')1947sage: E.gens() # random (up to sign)1948[(0 : -1 : 1)]1949sage: E.gens_certain()1950True1951"""1952return self.__gens.has_key(True)19531954def ngens(self, proof = None):1955"""1956Return the number of generators of this elliptic curve.19571958.. note::19591960See :meth:'.gens' for further documentation. The function1961:meth:`.ngens` calls :meth:`.gens` if not already done, but1962only with default parameters. Better results may be1963obtained by calling ``mwrank()`` with carefully chosen1964parameters.19651966EXAMPLES::19671968sage: E=EllipticCurve('37a1')1969sage: E.ngens()1970119711972TO DO: This example should not cause a run-time error.19731974::19751976sage: E=EllipticCurve([0,0,0,877,0])1977sage: # E.ngens() ######## causes run-time error19781979::19801981sage: print E.mwrank('-v0 -b12 -l')1982Curve [0,0,0,877,0] : Rank = 11983Generator 1 is [29604565304828237474403861024284371796799791624792913256602210:-256256267988926809388776834045513089648669153204356603464786949:490078023219787588959802933995928925096061616470779979261000]; height 95.9803719879641984Regulator = 95.980...1985"""1986return len(self.gens(proof = proof))19871988def regulator(self, use_database=True, proof=None, precision=None,1989descent_second_limit=12, verbose=False):1990"""1991Returns the regulator of this curve, which must be defined over Q.19921993INPUT:199419951996- ``use_database`` - bool (default: False), if True,1997try to look up the generators in the Cremona database.19981999- ``proof`` - bool or None (default: None, see2000proof.[tab] or sage.structure.proof). Note that results from2001databases are considered proof = True20022003- ``precision`` - int or None (default: None): the2004precision in bits of the result (default real precision if None)20052006- ``descent_second_limit`` - (default: 12)- used in 2-descent20072008- ``verbose`` - whether to print mwrank's verbose output20092010EXAMPLES::20112012sage: E = EllipticCurve([0, 0, 1, -1, 0])2013sage: E.regulator()20140.05111140823996882015sage: EllipticCurve('11a').regulator()20161.000000000000002017sage: EllipticCurve('37a').regulator()20180.05111140823996882019sage: EllipticCurve('389a').regulator()20200.1524601779431442021sage: EllipticCurve('5077a').regulator()20220.41714355875838...2023sage: EllipticCurve([1, -1, 0, -79, 289]).regulator()20241.504344888275282025sage: EllipticCurve([0, 0, 1, -79, 342]).regulator(proof=False) # long time (6s on sage.math, 2011)202614.790527570131...2027"""2028if precision is None:2029RR = rings.RealField()2030precision = RR.precision()2031else:2032RR = rings.RealField(precision)20332034if proof is None:2035from sage.structure.proof.proof import get_flag2036proof = get_flag(proof, "elliptic_curve")2037else:2038proof = bool(proof)20392040# We return a cached value if it exists and has sufficient precision:2041try:2042reg = self.__regulator[proof]2043if reg.parent().precision() >= precision:2044return RR(reg)2045else: # Found regulator value but precision is too low2046pass2047except KeyError:2048if proof is False and self.__regulator.has_key(True):2049reg = self.__regulator[True]2050if reg.parent().precision() >= precision:2051return RR(reg)2052else: # Found regulator value but precision is too low2053pass20542055# Next we find the gens, taking them from the database if they2056# are there and use_database is True, else computing them:20572058G = self.gens(proof=proof, use_database=use_database, descent_second_limit=descent_second_limit, verbose=verbose)20592060# Finally compute the regulator of the generators found:20612062self.__regulator[proof] = self.regulator_of_points(G,precision=precision)2063return self.__regulator[proof]20642065def saturation(self, points, verbose=False, max_prime=0, odd_primes_only=False):2066"""2067Given a list of rational points on E, compute the saturation in2068E(Q) of the subgroup they generate.20692070INPUT:207120722073- ``points (list)`` - list of points on E20742075- ``verbose (bool)`` - (default: False), if True, give2076verbose output20772078- ``max_prime (int)`` - (default: 0), saturation is2079performed for all primes up to max_prime. If max_prime==0,2080perform saturation at *all* primes, i.e., compute the true2081saturation.20822083- ``odd_primes_only (bool)`` - only do saturation at2084odd primes208520862087OUTPUT:208820892090- ``saturation (list)`` - points that form a basis for2091the saturation20922093- ``index (int)`` - the index of the group generated2094by points in their saturation20952096- ``regulator (real with default precision)`` -2097regulator of saturated points.209820992100ALGORITHM: Uses Cremona's ``mwrank`` package. With ``max_prime=0``,2101we call ``mwrank`` with successively larger prime bounds until the full2102saturation is provably found. The results of saturation at the2103previous primes is stored in each case, so this should be2104reasonably fast.21052106EXAMPLES::21072108sage: E=EllipticCurve('37a1')2109sage: P=E(0,0)2110sage: Q=5*P; Q2111(1/4 : -5/8 : 1)2112sage: E.saturation([Q])2113([(0 : 0 : 1)], 5, 0.0511114082399688)21142115TESTS:21162117See #10590. This example would loop for ever at default precision::21182119sage: E = EllipticCurve([1, 0, 1, -977842, -372252745])2120sage: P = E([-192128125858676194585718821667542660822323528626273/336995568430319276695106602174283479617040716649, 70208213492933395764907328787228427430477177498927549075405076353624188436/195630373799784831667835900062564586429333568841391304129067339731164107, 1])2121sage: P.height()2122113.3029109260802123sage: E.saturation([P])2124([(-192128125858676194585718821667542660822323528626273/336995568430319276695106602174283479617040716649 : 70208213492933395764907328787228427430477177498927549075405076353624188436/195630373799784831667835900062564586429333568841391304129067339731164107 : 1)], 1, 113.302910926080)2125sage: E.saturation([2*P]) ## needs higher precision2126...2127([(1755450733726721618440965414535034458701302721700399/970334851896750960577261378321772998240802013604 : -59636173615502879504846810677646864329901430096139563516090202443694810309127/955833935771565601591243078845907133814963790187832340692216425242529192 : 1)], 2, 113.302910926080)21282129See #10840. This causes eclib to crash since the curve is2130non-minimal at 2::21312132sage: E = EllipticCurve([0,0,0,-13711473216,0])2133sage: P = E([-19992,16313472])2134sage: Q = E([-24108,-17791704])2135sage: R = E([-97104,-20391840])2136sage: S = E([-113288,-9969344])2137sage: E.saturation([P,Q,R,S])2138([(-19992 : 16313472 : 1), (-24108 : -17791704 : 1), (-97104 : -20391840 : 1), (-113288 : -9969344 : 1)], 1, 172.792031341679)21392140"""2141if not isinstance(points, list):2142raise TypeError, "points (=%s) must be a list."%points2143if len(points) == 0:2144return [], None, R(1)21452146v = []2147for P in points:2148if not isinstance(P, ell_point.EllipticCurvePoint_field):2149P = self(P)2150elif P.curve() != self:2151raise ArithmeticError, "point (=%s) must be %s."%(P,self)21522153minimal = True2154if not self.is_minimal():2155minimal = False2156Emin = self.minimal_model()2157phi = self.isomorphism_to(Emin)2158points = [phi(P) for P in points]2159else:2160Emin = self21612162for P in points:2163x, y = P.xy()2164d = x.denominator().lcm(y.denominator())2165v.append((x*d, y*d, d))21662167c = Emin.mwrank_curve()2168mw = mwrank.mwrank_MordellWeil(c, verbose)2169mw.process(v)2170if max_prime == 0:2171repeat_until_saturated = True2172max_prime = 972173from sage.libs.all import mwrank_get_precision, mwrank_set_precision2174prec0 = mwrank_get_precision()2175prec = 1002176if prec0<prec:2177mwrank_set_precision(prec)2178else:2179prec = prec02180while True:2181ok, index, unsat = mw.saturate(max_prime=max_prime, odd_primes_only = odd_primes_only)2182reg = mw.regulator()2183if ok or not repeat_until_saturated: break2184max_prime = arith.next_prime(max_prime + 100)2185prec += 502186#print "Increasing precision to ",prec," and max_prime to ",max_prime2187mwrank_set_precision(prec)2188if prec!=prec0: mwrank_set_precision(prec0)2189#print "precision was originally ",prec0," and is now ",mwrank_get_precision()2190sat = mw.points()2191sat = [Emin(P) for P in sat]2192if not minimal:2193phi_inv = ~phi2194sat = [phi_inv(P) for P in sat]2195reg = self.regulator_of_points(sat)2196return sat, index, R(reg)219721982199def CPS_height_bound(self):2200r"""2201Return the Cremona-Prickett-Siksek height bound. This is a2202floating point number B such that if P is a rational point on2203the curve, then `h(P) \le \hat{h}(P) + B`, where `h(P)` is2204the naive logarithmic height of `P` and `\hat{h}(P)` is the2205canonical height.22062207SEE ALSO: silverman_height_bound for a bound that also works for2208points over number fields.22092210EXAMPLES::22112212sage: E = EllipticCurve("11a")2213sage: E.CPS_height_bound()22142.87747432735804452215sage: E = EllipticCurve("5077a")2216sage: E.CPS_height_bound()22170.02218sage: E = EllipticCurve([1,2,3,4,1])2219sage: E.CPS_height_bound()2220Traceback (most recent call last):2221...2222RuntimeError: curve must be minimal.2223sage: F = E.quadratic_twist(-19)2224sage: F2225Elliptic Curve defined by y^2 + x*y + y = x^3 - x^2 + 1376*x - 130 over Rational Field2226sage: F.CPS_height_bound()22270.655515837697285222282229IMPLEMENTATION:2230Call the corresponding mwrank C++ library function. Note that2231the formula in the [CPS] paper is given for number fields. It's2232only the implementation in Sage that restricts to the rational2233field.2234"""2235if not self.is_minimal():2236raise RuntimeError, "curve must be minimal."2237return self.mwrank_curve().CPS_height_bound()223822392240def silverman_height_bound(self, algorithm='default'):2241r"""2242Return the Silverman height bound. This is a positive real2243(floating point) number B such that for all points `P` on the2244curve over any number field, `|h(P) - \hat{h}(P)| \leq B`,2245where `h(P)` is the naive logarithmic height of `P` and2246`\hat{h}(P)` is the canonical height.22472248INPUT:22492250- ``algorithm`` --22512252- 'default' (default) -- compute using a Python2253implementation in Sage22542255- 'mwrank' -- use a C++ implementation in the mwrank2256library22572258NOTES:22592260- The CPS_height_bound is often better (i.e. smaller) than2261the Silverman bound, but it only applies for points over2262the base field, whereas the Silverman bound works over2263all number fields.22642265- The Silverman bound is also fairly straightforward to2266compute over number fields, but isn't implemented here.22672268- Silverman's paper is 'The Difference Between the Weil2269Height and the Canonical Height on Elliptic Curves',2270Math. Comp., Volume 55, Number 192, pages 723-743. We2271use a correction by Bremner with 0.973 replaced by 0.961,2272as explained in the source code to mwrank (htconst.cc).22732274EXAMPLES::22752276sage: E=EllipticCurve('37a1')2277sage: E.silverman_height_bound()22784.8254007581809182279sage: E.silverman_height_bound(algorithm='mwrank')22804.8254007581809182281sage: E.CPS_height_bound()22820.163970761030469152283"""2284if algorithm == 'default':2285Delta = self.discriminant()2286j = self.j_invariant()2287b2 = self.b2()2288twostar = 2 if b2 else 12289from math import log2290def h(x):2291return log(max(abs(x.numerator()), abs(x.denominator())))2292def h_oo(x):2293return log(max(abs(x),1))2294mu = h(Delta)/12 + h_oo(j)/12 + h_oo(b2/12)/2 + log(twostar)/22295lower = 2*(-h(j)/24 - mu - 0.961)2296upper = 2*(mu + 1.07)2297return max(abs(lower), abs(upper))2298elif algorithm == 'mwrank':2299return self.mwrank_curve().silverman_bound()2300else:2301raise ValueError, "unknown algorithm '%s'"%algorithm2302230323042305def point_search(self, height_limit, verbose=False, rank_bound=None):2306"""2307Search for points on a curve up to an input bound on the naive2308logarithmic height.23092310INPUT:231123122313- ``height_limit (float)`` - bound on naive height23142315- ``verbose (bool)`` - (default: False)23162317If True, report on each point as found together with linear2318relations between the points found and the saturation process.23192320If False, just return the result.23212322- ``rank_bound (bool)`` - (default: None)23232324If provided, stop searching for points once we find this many2325independent nontorsion points.23262327OUTPUT: points (list) - list of independent points which generate2328the subgroup of the Mordell-Weil group generated by the points2329found and then saturated.23302331.. warning::23322333height_limit is logarithmic, so increasing by 1 will cause2334the running time to increase by a factor of approximately23354.5 (=exp(1.5)).23362337IMPLEMENTATION: Uses Michael Stoll's ratpoints library.23382339EXAMPLES::23402341sage: E=EllipticCurve('389a1')2342sage: E.point_search(5, verbose=False)2343[(-1 : 1 : 1), (-3/4 : 7/8 : 1)]23442345Increasing the height_limit takes longer, but finds no more2346points::23472348sage: E.point_search(10, verbose=False)2349[(-1 : 1 : 1), (-3/4 : 7/8 : 1)]23502351In fact this curve has rank 2 so no more than 2 points will ever be2352output, but we are not using this fact.23532354::23552356sage: E.saturation(_)2357([(-1 : 1 : 1), (-3/4 : 7/8 : 1)], 1, 0.152460177943144)23582359What this shows is that if the rank is 2 then the points listed do2360generate the Mordell-Weil group (mod torsion). Finally,23612362::23632364sage: E.rank()2365223662367If we only need one independent generator::23682369sage: E.point_search(5, verbose=False, rank_bound=1)2370[(-2 : 0 : 1)]23712372"""2373from sage.libs.ratpoints import ratpoints2374from sage.functions.all import exp2375from sage.rings.arith import GCD2376H = exp(float(height_limit)) # max(|p|,|q|) <= H, if x = p/q coprime2377coeffs = [16*self.b6(), 8*self.b4(), self.b2(), 1]2378points = []2379a1 = self.a1()2380a3 = self.a3()2381new_H = H*2 # since we change the x-coord by 2 below2382for X,Y,Z in ratpoints(coeffs, new_H, verbose):2383if Z == 0: continue2384z = 2*Z2385x = X/22386y = (Y/z - a1*x - a3*z)/22387d = GCD((x,y,z))2388x = x/d2389if max(x.numerator().abs(), x.denominator().abs()) <= H:2390y = y/d2391z = z/d2392points.append(self((x,y,z)))2393if rank_bound is not None:2394points = self.saturation(points, verbose=verbose)[0]2395if len(points) == rank_bound:2396break2397if rank_bound is None:2398points = self.saturation(points, verbose=verbose)[0]2399return points240024012402def selmer_rank(self):2403"""2404The rank of the 2-Selmer group of the curve.24052406EXAMPLE: The following is the curve 960D1, which has rank 0, but2407Sha of order 4.24082409::24102411sage: E = EllipticCurve([0, -1, 0, -900, -10098])2412sage: E.selmer_rank()2413324142415Here the Selmer rank is equal to the 2-torsion rank (=1) plus2416the 2-rank of Sha (=2), and the rank itself is zero::24172418sage: E.rank()2419024202421In contrast, for the curve 571A, also with rank 0 and Sha of2422order 4, we get a worse bound::24232424sage: E = EllipticCurve([0, -1, 1, -929, -10595])2425sage: E.selmer_rank()242622427sage: E.rank_bound()2428224292430To establish that the rank is in fact 0 in this case, we would2431need to carry out a higher descent::24322433sage: E.three_selmer_rank() # optional: magma2434024352436Or use the L-function to compute the analytic rank::24372438sage: E.rank(only_use_mwrank=False)2439024402441"""2442try:2443return self.__selmer_rank2444except AttributeError:2445C = self.mwrank_curve()2446self.__selmer_rank = C.selmer_rank()2447return self.__selmer_rank244824492450def rank_bound(self):2451"""2452Upper bound on the rank of the curve, computed using24532-descent. In many cases, this is the actual rank of the2454curve. If the curve has no 2-torsion it is the same as the24552-selmer rank.24562457EXAMPLE: The following is the curve 960D1, which has rank 0, but2458Sha of order 4.24592460::24612462sage: E = EllipticCurve([0, -1, 0, -900, -10098])2463sage: E.rank_bound()2464024652466It gives 0 instead of 2, because it knows Sha is nontrivial. In2467contrast, for the curve 571A, also with rank 0 and Sha of order 4,2468we get a worse bound::24692470sage: E = EllipticCurve([0, -1, 1, -929, -10595])2471sage: E.rank_bound()247222473sage: E.rank(only_use_mwrank=False) # uses L-function2474024752476"""2477try:2478return self.__rank_bound2479except AttributeError:2480C = self.mwrank_curve()2481self.__rank_bound = C.rank_bound()2482return self.__rank_bound248324842485def an(self, n):2486"""2487The n-th Fourier coefficient of the modular form corresponding to2488this elliptic curve, where n is a positive integer.24892490EXAMPLES::24912492sage: E=EllipticCurve('37a1')2493sage: [E.an(n) for n in range(20) if n>0]2494[1, -2, -3, 2, -2, 6, -1, 0, 6, 4, -5, -6, -2, 2, 6, -4, 0, -12, 0]2495"""2496return Integer(self.pari_mincurve().ellak(n))24972498def ap(self, p):2499"""2500The p-th Fourier coefficient of the modular form corresponding to2501this elliptic curve, where p is prime.25022503EXAMPLES::25042505sage: E=EllipticCurve('37a1')2506sage: [E.ap(p) for p in prime_range(50)]2507[-2, -3, -2, -1, -5, -2, 0, 0, 2, 6, -4, -1, -9, 2, -9]2508"""2509if not arith.is_prime(p):2510raise ArithmeticError, "p must be prime"2511return Integer(self.pari_mincurve().ellap(p))25122513def quadratic_twist(self, D):2514"""2515Return the quadratic twist of this elliptic curve by D.25162517D must be a nonzero rational number.25182519.. note::25202521This function overrides the generic ``quadratic_twist()``2522function for elliptic curves, returning a minimal model.25232524EXAMPLES::25252526sage: E=EllipticCurve('37a1')2527sage: E2=E.quadratic_twist(2); E22528Elliptic Curve defined by y^2 = x^3 - 4*x + 2 over Rational Field2529sage: E2.conductor()253023682531sage: E2.quadratic_twist(2) == E2532True2533"""2534return EllipticCurve_number_field.quadratic_twist(self, D).minimal_model()25352536def minimal_model(self):2537r"""2538Return the unique minimal Weierstrass equation for this elliptic2539curve. This is the model with minimal discriminant and2540`a_1,a_2,a_3 \in \{0,\pm 1\}`.25412542EXAMPLES::25432544sage: E=EllipticCurve([10,100,1000,10000,1000000])2545sage: E.minimal_model()2546Elliptic Curve defined by y^2 + x*y + y = x^3 + x^2 + x + 1 over Rational Field2547"""2548try:2549return self.__minimal_model2550except AttributeError:2551F = self.pari_mincurve()2552self.__minimal_model = EllipticCurve_rational_field([Q(F[i]) for i in range(5)])2553return self.__minimal_model25542555def is_minimal(self):2556r"""2557Return True iff this elliptic curve is a reduced minimal model.25582559The unique minimal Weierstrass equation for this elliptic curve.2560This is the model with minimal discriminant and2561`a_1,a_2,a_3 \in \{0,\pm 1\}`.25622563TO DO: This is not very efficient since it just computes the2564minimal model and compares. A better implementation using the Kraus2565conditions would be preferable.25662567EXAMPLES::25682569sage: E=EllipticCurve([10,100,1000,10000,1000000])2570sage: E.is_minimal()2571False2572sage: E=E.minimal_model()2573sage: E.is_minimal()2574True2575"""2576return self.ainvs() == self.minimal_model().ainvs()25772578def is_p_minimal(self, p):2579"""2580Tests if curve is p-minimal at a given prime p.25812582INPUT: p - a primeOUTPUT: True - if curve is p-minimal258325842585- ``False`` - if curve isn't p-minimal258625872588EXAMPLES::25892590sage: E = EllipticCurve('441a2')2591sage: E.is_p_minimal(7)2592True25932594::25952596sage: E = EllipticCurve([0,0,0,0,(2*5*11)**10])2597sage: [E.is_p_minimal(p) for p in prime_range(2,24)]2598[False, True, False, True, False, True, True, True, True]2599"""2600if not p.is_prime():2601raise ValueError,"p must be prime"2602if not self.is_p_integral(p):2603return False2604if p > 3:2605return ((self.discriminant().valuation(p) < 12) or (self.c4().valuation(p) < 4))2606# else p = 2,32607Emin = self.minimal_model()2608return self.discriminant().valuation(p) == Emin.discriminant().valuation(p)26092610# Duplicate!2611#2612# def is_integral(self):2613# for n in self.ainvs():2614# if n.denominator() != 1:2615# return False2616# return True26172618def kodaira_type(self, p):2619"""2620Local Kodaira type of the elliptic curve at `p`.26212622INPUT:26232624- p, an integral prime262526262627OUTPUT:262826292630- the Kodaira type of this elliptic curve at p,2631as a KodairaSymbol.263226332634EXAMPLES::26352636sage: E = EllipticCurve('124a')2637sage: E.kodaira_type(2)2638IV2639"""2640return self.local_data(p).kodaira_symbol()26412642kodaira_symbol = kodaira_type26432644def kodaira_type_old(self, p):2645"""2646Local Kodaira type of the elliptic curve at `p`.26472648INPUT:264926502651- p, an integral prime265226532654OUTPUT:26552656- the kodaira type of this elliptic curve at p,2657as a KodairaSymbol.26582659EXAMPLES::26602661sage: E = EllipticCurve('124a')2662sage: E.kodaira_type_old(2)2663IV2664"""2665if not arith.is_prime(p):2666raise ArithmeticError, "p must be prime"2667try:2668self.__kodaira_type2669except AttributeError:2670self.__kodaira_type = {}2671self.__tamagawa_number = {}2672if not self.__kodaira_type.has_key(p):2673v = self.pari_mincurve().elllocalred(p)2674from kodaira_symbol import KodairaSymbol2675self.__kodaira_type[p] = KodairaSymbol(v[1])2676self.__tamagawa_number[p] = Integer(v[3])2677return self.__kodaira_type[p]26782679def tamagawa_number(self, p):2680r"""2681The Tamagawa number of the elliptic curve at `p`.26822683This is the order of the component group2684`E(\QQ_p)/E^0(\QQ_p)`.26852686EXAMPLES::26872688sage: E = EllipticCurve('11a')2689sage: E.tamagawa_number(11)269052691sage: E = EllipticCurve('37b')2692sage: E.tamagawa_number(37)269332694"""2695return self.local_data(p).tamagawa_number()26962697def tamagawa_number_old(self, p):2698r"""2699The Tamagawa number of the elliptic curve at `p`.27002701This is the order of the component group2702`E(\QQ_p)/E^0(\QQ_p)`.27032704EXAMPLES::27052706sage: E = EllipticCurve('11a')2707sage: E.tamagawa_number_old(11)270852709sage: E = EllipticCurve('37b')2710sage: E.tamagawa_number_old(37)271132712"""2713if not arith.is_prime(p):2714raise ArithmeticError, "p must be prime"2715try:2716return self.__tamagawa_number[p]2717except (AttributeError, KeyError):2718self.kodaira_type_old(p)2719return self.__tamagawa_number[p]27202721def tamagawa_exponent(self, p):2722"""2723The Tamagawa index of the elliptic curve at `p`.27242725This is the index of the component group2726`E(\QQ_p)/E^0(\QQ_p)`. It equals the2727Tamagawa number (as the component group is cyclic) except for types2728`I_m^*` (`m` even) when the group can be2729`C_2 \times C_2`.27302731EXAMPLES::27322733sage: E = EllipticCurve('816a1')2734sage: E.tamagawa_number(2)273542736sage: E.tamagawa_exponent(2)273722738sage: E.kodaira_symbol(2)2739I2*27402741::27422743sage: E = EllipticCurve('200c4')2744sage: E.kodaira_symbol(5)2745I4*2746sage: E.tamagawa_number(5)274742748sage: E.tamagawa_exponent(5)2749227502751See #4715::27522753sage: E=EllipticCurve('117a3')2754sage: E.tamagawa_exponent(13)275542756"""2757if not arith.is_prime(p):2758raise ArithmeticError, "p must be prime"2759cp = self.tamagawa_number(p)2760if not cp==4:2761return cp2762ks = self.kodaira_type(p)2763if ks._roman==1 and ks._n%2==0 and ks._starred:2764return 22765return 427662767def tamagawa_product(self):2768"""2769Returns the product of the Tamagawa numbers.27702771EXAMPLES::27722773sage: E = EllipticCurve('54a')2774sage: E.tamagawa_product ()277532776"""2777try:2778return self.__tamagawa_product2779except AttributeError:2780self.__tamagawa_product = Integer(self.pari_mincurve().ellglobalred()[2].python())2781return self.__tamagawa_product27822783def real_components(self):2784"""2785Returns 1 if there is 1 real component and 2 if there are 2.27862787EXAMPLES::27882789sage: E = EllipticCurve('37a')2790sage: E.real_components ()279122792sage: E = EllipticCurve('37b')2793sage: E.real_components ()279422795sage: E = EllipticCurve('11a')2796sage: E.real_components ()279712798"""2799invs = self.short_weierstrass_model().ainvs()2800x = rings.polygen(self.base_ring())2801f = x**3 + invs[3]*x + invs[4]2802if f.discriminant() > 0:2803return 22804else:2805return 128062807def has_good_reduction_outside_S(self,S=[]):2808r"""2809Tests if this elliptic curve has good reduction outside `S`.28102811INPUT:28122813- S - list of primes (default: empty list).28142815.. note::28162817Primality of elements of S is not checked, and the output2818is undefined if S is not a list or contains non-primes.28192820This only tests the given model, so should only be applied to2821minimal models.28222823EXAMPLES::28242825sage: EllipticCurve('11a1').has_good_reduction_outside_S([11])2826True2827sage: EllipticCurve('11a1').has_good_reduction_outside_S([2])2828False2829sage: EllipticCurve('2310a1').has_good_reduction_outside_S([2,3,5,7])2830False2831sage: EllipticCurve('2310a1').has_good_reduction_outside_S([2,3,5,7,11])2832True2833"""2834return self.discriminant().is_S_unit(S)28352836def period_lattice(self, embedding=None):2837r"""2838Returns the period lattice of the elliptic curve with respect to2839the differential `dx/(2y + a_1x + a_3)`.28402841INPUT:28422843- ``embedding`` - ignored (for compatibility with the2844period_lattice function for elliptic_curve_number_field)28452846OUTPUT:28472848(period lattice) The PeriodLattice_ell object associated to2849this elliptic curve (with respect to the natural embedding of2850`\QQ` into `\RR`).28512852EXAMPLES::28532854sage: E = EllipticCurve('37a')2855sage: E.period_lattice()2856Period lattice associated to Elliptic Curve defined by y^2 + y = x^3 - x over Rational Field2857"""2858try:2859return self._period_lattice2860except AttributeError:2861from sage.schemes.elliptic_curves.period_lattice import PeriodLattice_ell2862self._period_lattice = PeriodLattice_ell(self)2863return self._period_lattice28642865def elliptic_exponential(self, z, embedding=None):2866r"""2867Computes the elliptic exponential of a complex number with respect to the elliptic curve.28682869INPUT:28702871- ``z`` (complex) -- a complex number28722873- ``embedding`` - ignored (for compatibility with the2874period_lattice function for elliptic_curve_number_field)28752876OUTPUT:28772878The image of `z` modulo `L` under the Weierstrass parametrization2879`\CC/L \to E(\CC)`.28802881.. note::28822883The precision is that of the input ``z``, or the default2884precision of 53 bits if ``z`` is exact.28852886EXAMPLES::28872888sage: E = EllipticCurve([1,1,1,-8,6])2889sage: P = E([1,-2])2890sage: z = P.elliptic_logarithm() # default precision is 100 here2891sage: E.elliptic_exponential(z)2892(1.0000000000000000000000000000 : -2.0000000000000000000000000000 : 1.0000000000000000000000000000)2893sage: z = E([1,-2]).elliptic_logarithm(precision=201)2894sage: E.elliptic_exponential(z)2895(1.00000000000000000000000000000000000000000000000000000000000 : -2.00000000000000000000000000000000000000000000000000000000000 : 1.00000000000000000000000000000000000000000000000000000000000)28962897::28982899sage: E = EllipticCurve('389a')2900sage: Q = E([3,5])2901sage: E.elliptic_exponential(Q.elliptic_logarithm())2902(3.0000000000000000000000000000 : 5.0000000000000000000000000000 : 1.0000000000000000000000000000)2903sage: P = E([-1,1])2904sage: P.elliptic_logarithm()29050.47934825019021931612953301006 + 0.98586885077582410221120384908*I2906sage: E.elliptic_exponential(P.elliptic_logarithm())2907(-1.0000000000000000000000000000 : 1.0000000000000000000000000000 : 1.0000000000000000000000000000)290829092910Some torsion examples::29112912sage: w1,w2 = E.period_lattice().basis()2913sage: E.two_division_polynomial().roots(CC,multiplicities=False)2914[-2.0403022002854..., 0.13540924022175..., 0.90489296006371...]2915sage: [E.elliptic_exponential((a*w1+b*w2)/2)[0] for a,b in [(0,1),(1,1),(1,0)]]2916[-2.0403022002854..., 0.13540924022175..., 0.90489296006371...]29172918sage: E.division_polynomial(3).roots(CC,multiplicities=False)2919[-2.88288879135...,29201.39292799513...,29210.078313731444316... - 0.492840991709...*I,29220.078313731444316... + 0.492840991709...*I]2923sage: [E.elliptic_exponential((a*w1+b*w2)/3)[0] for a,b in [(0,1),(1,0),(1,1),(2,1)]]2924[-2.8828887913533..., 1.39292799513138,29250.0783137314443... - 0.492840991709...*I,29260.0783137314443... + 0.492840991709...*I]29272928Observe that this is a group homomorphism (modulo rounding error)::29292930sage: z = CC.random_element()2931sage: 2 * E.elliptic_exponential(z)2932(-1.52184235874404 - 0.0581413944316544*I : 0.948655866506124 - 0.0381469928565030*I : 1.00000000000000)2933sage: E.elliptic_exponential(2 * z)2934(-1.52184235874404 - 0.0581413944316562*I : 0.948655866506128 - 0.0381469928565034*I : 1.00000000000000)2935"""2936return self.period_lattice().elliptic_exponential(z)29372938def lseries(self):2939"""2940Returns the L-series of this elliptic curve.29412942Further documentation is available for the functions which apply to2943the L-series.29442945EXAMPLES::29462947sage: E=EllipticCurve('37a1')2948sage: E.lseries()2949Complex L-series of the Elliptic Curve defined by y^2 + y = x^3 - x over Rational Field2950"""2951try:2952return self.__lseries2953except AttributeError:2954from lseries_ell import Lseries_ell2955self.__lseries = Lseries_ell(self)2956return self.__lseries29572958def Lambda(self, s, prec):2959r"""2960Returns the value of the Lambda-series of the elliptic curve E at2961s, where s can be any complex number.29622963IMPLEMENTATION: Fairly *slow* computation using the definitions2964and implemented in Python.29652966Uses prec terms of the power series.29672968EXAMPLES::29692970sage: E = EllipticCurve('389a')2971sage: E.Lambda(1.4+0.5*I, 50)2972-0.354172680517... + 0.874518681720...*I2973"""2974from sage.all import pi29752976s = C(s)2977N = self.conductor()2978pi = R(pi)2979a = self.anlist(prec)2980eps = self.root_number()2981sqrtN = float(N.sqrt())2982def _F(n, t):2983return gamma_inc(t+1, 2*pi*n/sqrtN) * C(sqrtN/(2*pi*n))**(t+1)2984return sum([a[n]*(_F(n,s-1) + eps*_F(n,1-s)) for n in xrange(1,prec+1)])29852986def is_local_integral_model(self,*p):2987r"""2988Tests if self is integral at the prime `p`, or at all the2989primes if `p` is a list or tuple of primes29902991EXAMPLES::29922993sage: E=EllipticCurve([1/2,1/5,1/5,1/5,1/5])2994sage: [E.is_local_integral_model(p) for p in (2,3,5)]2995[False, True, False]2996sage: E.is_local_integral_model(2,3,5)2997False2998sage: Eint2=E.local_integral_model(2)2999sage: Eint2.is_local_integral_model(2)3000True3001"""3002if len(p)==1: p=p[0]3003if isinstance(p,(tuple,list)):3004return misc.forall(p, lambda x : self.is_local_integral_model(x))[0]3005assert p.is_prime(), "p must be prime in is_local_integral_model()"3006return misc.forall(self.ainvs(), lambda x : x.valuation(p) >= 0)[0]30073008def local_integral_model(self,p):3009r"""3010Return a model of self which is integral at the prime `p`.30113012EXAMPLES::30133014sage: E=EllipticCurve([0, 0, 1/216, -7/1296, 1/7776])3015sage: E.local_integral_model(2)3016Elliptic Curve defined by y^2 + 1/27*y = x^3 - 7/81*x + 2/243 over Rational Field3017sage: E.local_integral_model(3)3018Elliptic Curve defined by y^2 + 1/8*y = x^3 - 7/16*x + 3/32 over Rational Field3019sage: E.local_integral_model(2).local_integral_model(3) == EllipticCurve('5077a1')3020True3021"""3022assert p.is_prime(), "p must be prime in local_integral_model()"3023ai = self.a_invariants()3024e = min([(ai[i].valuation(p)/[1,2,3,4,6][i]) for i in range(5)]).floor()3025return constructor.EllipticCurve([ai[i]/p**(e*[1,2,3,4,6][i]) for i in range(5)])30263027def is_global_integral_model(self):3028r"""3029Return true iff self is integral at all primes.30303031EXAMPLES::30323033sage: E=EllipticCurve([1/2,1/5,1/5,1/5,1/5])3034sage: E.is_global_integral_model()3035False3036sage: Emin=E.global_integral_model()3037sage: Emin.is_global_integral_model()3038True3039"""3040return self.is_integral()30413042def global_integral_model(self):3043r"""3044Return a model of self which is integral at all primes.30453046EXAMPLES::30473048sage: E = EllipticCurve([0, 0, 1/216, -7/1296, 1/7776])3049sage: F = E.global_integral_model(); F3050Elliptic Curve defined by y^2 + y = x^3 - 7*x + 6 over Rational Field3051sage: F == EllipticCurve('5077a1')3052True3053"""3054ai = self.a_invariants()3055for a in ai:3056if not a.is_integral():3057for p, _ in a.denom().factor():3058e = min([(ai[i].valuation(p)/[1,2,3,4,6][i]) for i in range(5)]).floor()3059ai = [ai[i]/p**(e*[1,2,3,4,6][i]) for i in range(5)]3060for z in ai:3061assert z.denominator() == 1, "bug in global_integral_model: %s" % ai3062return constructor.EllipticCurve(list(ai))30633064integral_model = global_integral_model30653066def integral_short_weierstrass_model(self):3067r"""3068Return a model of the form `y^2 = x^3 + ax + b` for this3069curve with `a,b\in\ZZ`.30703071EXAMPLES::30723073sage: E = EllipticCurve('17a1')3074sage: E.integral_short_weierstrass_model()3075Elliptic Curve defined by y^2 = x^3 - 11*x - 890 over Rational Field3076"""3077F = self.minimal_model().short_weierstrass_model()3078_,_,_,A,B = F.ainvs()3079for p in [2,3]:3080e=min(A.valuation(p)/4,B.valuation(p)/6).floor()3081A /= Integer(p**(4*e))3082B /= Integer(p**(6*e))3083return constructor.EllipticCurve([A,B])30843085# deprecated function replaced by integral_short_weierstrass_model, see trac 3974.3086def integral_weierstrass_model(self):3087r"""3088Return a model of the form `y^2 = x^3 + ax + b` for this3089curve with `a,b\in\ZZ`.30903091Note that this function is deprecated, and that you should use3092integral_short_weierstrass_model instead as this will be3093disappearing in the near future.30943095EXAMPLES::30963097sage: E = EllipticCurve('17a1')3098sage: E.integral_weierstrass_model() #random3099doctest:1: DeprecationWarning: integral_weierstrass_model is deprecated, use integral_short_weierstrass_model instead!3100Elliptic Curve defined by y^2 = x^3 - 11*x - 890 over Rational Field3101"""3102from sage.misc.misc import deprecation3103deprecation("integral_weierstrass_model is deprecated, use integral_short_weierstrass_model instead!")3104return self.integral_short_weierstrass_model()310531063107def modular_degree(self, algorithm='sympow'):3108r"""3109Return the modular degree of this elliptic curve.31103111The result is cached. Subsequent calls, even with a different3112algorithm, just returned the cached result.31133114INPUT:311531163117- ``algorithm`` - string:31183119- ``'sympow'`` - (default) use Mark Watkin's (newer) C3120program sympow31213122- ``'magma'`` - requires that MAGMA be installed (also3123implemented by Mark Watkins)312431253126.. note::31273128On 64-bit computers ec does not work, so Sage uses sympow3129even if ec is selected on a 64-bit computer.31303131The correctness of this function when called with algorithm "sympow"3132is subject to the following three hypothesis:313331343135- Manin's conjecture: the Manin constant is 131363137- Steven's conjecture: the `X_1(N)`-optimal quotient is3138the curve with minimal Faltings height. (This is proved in most3139cases.)31403141- The modular degree fits in a machine double, so it better be3142less than about 50-some bits. (If you use sympow this constraint3143does not apply.)314431453146Moreover for all algorithms, computing a certain value of an3147`L`-function 'uses a heuristic method that discerns when3148the real-number approximation to the modular degree is within3149epsilon [=0.01 for algorithm='sympow'] of the same integer for 33150consecutive trials (which occur maybe every 25000 coefficients or3151so). Probably it could just round at some point. For rigour, you3152would need to bound the tail by assuming (essentially) that all the3153`a_n` are as large as possible, but in practice they3154exhibit significant (square root) cancellation. One difficulty is3155that it doesn't do the sum in 1-2-3-4 order; it uses31561-2-4-8--3-6-12-24-9-18- (Euler product style) instead, and so you3157have to guess ahead of time at what point to curtail this3158expansion.' (Quote from an email of Mark Watkins.)31593160.. note::31613162If the curve is loaded from the large Cremona database,3163then the modular degree is taken from the database.31643165EXAMPLES::31663167sage: E = EllipticCurve([0, -1, 1, -10, -20])3168sage: E3169Elliptic Curve defined by y^2 + y = x^3 - x^2 - 10*x - 20 over Rational Field3170sage: E.modular_degree()317113172sage: E = EllipticCurve('5077a')3173sage: E.modular_degree()317419843175sage: factor(1984)31762^6 * 3131773178::31793180sage: EllipticCurve([0, 0, 1, -7, 6]).modular_degree()318119843182sage: EllipticCurve([0, 0, 1, -7, 6]).modular_degree(algorithm='sympow')318319843184sage: EllipticCurve([0, 0, 1, -7, 6]).modular_degree(algorithm='magma') # optional - magma3185198431863187We compute the modular degree of the curve with rank 4 having3188smallest (known) conductor::31893190sage: E = EllipticCurve([1, -1, 0, -79, 289])3191sage: factor(E.conductor()) # conductor is 23444631922 * 1172233193sage: factor(E.modular_degree())31942^7 * 26173195"""3196try:3197return self.__modular_degree31983199except AttributeError:3200if algorithm == 'sympow':3201from sage.lfunctions.all import sympow3202m = sympow.modular_degree(self)3203elif algorithm == 'magma':3204from sage.interfaces.all import magma3205m = rings.Integer(magma(self).ModularDegree())3206else:3207raise ValueError, "unknown algorithm %s"%algorithm3208self.__modular_degree = m3209return m32103211def modular_parametrization(self):3212r"""3213Returns the modular parametrization of this elliptic curve, which is3214a map from `X_0(N)` to self, where `N` is the conductor of self.32153216EXAMPLES::32173218sage: E = EllipticCurve('15a')3219sage: phi = E.modular_parametrization(); phi3220Modular parameterization from the upper half plane to Elliptic Curve defined by y^2 + x*y + y = x^3 + x^2 - 10*x - 10 over Rational Field3221sage: z = 0.1 + 0.2j3222sage: phi(z)3223(8.20822465478531 - 13.1562816054682*I : -8.79855099049364 + 69.4006129342200*I : 1.00000000000000)32243225This map is actually a map on `X_0(N)`, so equivalent representatives3226in the upper half plane map to the same point::32273228sage: phi((-7*z-1)/(15*z+2))3229(8.20822465478524 - 13.1562816054681*I : -8.79855099049... + 69.4006129342...*I : 1.00000000000000)32303231We can also get a series expansion of this modular parameterization::32323233sage: E=EllipticCurve('389a1')3234sage: X,Y=E.modular_parametrization().power_series()3235sage: X3236q^-2 + 2*q^-1 + 4 + 7*q + 13*q^2 + 18*q^3 + 31*q^4 + 49*q^5 + 74*q^6 + 111*q^7 + 173*q^8 + 251*q^9 + 379*q^10 + 560*q^11 + 824*q^12 + 1199*q^13 + 1773*q^14 + 2548*q^15 + 3722*q^16 + 5374*q^17 + O(q^18)3237sage: Y3238-q^-3 - 3*q^-2 - 8*q^-1 - 17 - 33*q - 61*q^2 - 110*q^3 - 186*q^4 - 320*q^5 - 528*q^6 - 861*q^7 - 1383*q^8 - 2218*q^9 - 3472*q^10 - 5451*q^11 - 8447*q^12 - 13020*q^13 - 19923*q^14 - 30403*q^15 - 46003*q^16 + O(q^17)32393240The following should give 0, but only approximately::32413242sage: q = X.parent().gen()3243sage: E.defining_polynomial()(X,Y,1) + O(q^11) == 03244True3245"""3246return ModularParameterization(self)32473248def congruence_number(self):3249r"""3250Let `X` be the subspace of `S_2(\Gamma_0(N))` spanned by the newform3251associated with this elliptic curve, and `Y` be orthogonal compliment3252of `X` under the Petersson inner product. Let `S_X` and `S_Y` be the3253intersections of `X` and `Y` with `S_2(\Gamma_0(N)m \ZZ)`. The congruence3254number is defined to be `[S_X \oplus S_Y : S_2(\Gamma_0(N),\ZZ)]`.3255It measures congruences between `f` and elements of `S_2(\Gamma_0(N),\ZZ)`3256orthogonal to `f`.32573258EXAMPLES::32593260sage: E = EllipticCurve('37a')3261sage: E.congruence_number()326223263sage: E.congruence_number()326423265sage: E = EllipticCurve('54b')3266sage: E.congruence_number()326763268sage: E.modular_degree()326923270sage: E = EllipticCurve('242a1')3271sage: E.modular_degree()3272163273sage: E.congruence_number() # long time (4s on sage.math, 2011)3274176327532763277It is a theorem of Ribet that the congruence number is equal to the3278modular degree in the case of square free conductor. It is a conjecture3279of Agashe, Ribet, and Stein that `ord_p(c_f/m_f) \le ord_p(N)/2`.32803281TESTS::32823283sage: E = EllipticCurve('11a')3284sage: E.congruence_number()328513286"""3287try:3288return self.__congruence_number3289except AttributeError:3290pass3291# Currently this is *much* faster to compute3292m = self.modular_degree()3293if self.conductor().is_squarefree():3294self.__congruence_number = m3295else:3296W = self.modular_symbol_space(sign=1)3297V = W.complement().cuspidal_subspace()3298self.__congruence_number = W.congruence_number(V)3299if not m.divides(self.__congruence_number):3300# We should never get here3301raise ValueError, "BUG in modular degree or congruence number computation of: %s" % self3302return self.__congruence_number33033304def cremona_label(self, space=False):3305"""3306Return the Cremona label associated to (the minimal model) of this3307curve, if it is known. If not, raise a RuntimeError exception.33083309EXAMPLES::33103311sage: E=EllipticCurve('389a1')3312sage: E.cremona_label()3313'389a1'33143315The default database only contains conductors up to 10000, so any3316curve with conductor greater than that will cause an error to be3317raised. The optional package 'database_cremona_ellcurve-20120606'3318contains more curves, with conductors up to 240000.33193320::33213322sage: E = EllipticCurve([1, -1, 0, -79, 289])3323sage: E.conductor()33242344463325sage: E.cremona_label() # optional - database_cremona_ellcurve3326'234446a1'3327sage: E = EllipticCurve((0, 0, 1, -79, 342))3328sage: E.conductor()3329190478513330sage: E.cremona_label()3331Traceback (most recent call last):3332...3333RuntimeError: Cremona label not known for Elliptic Curve defined by y^2 + y = x^3 - 79*x + 342 over Rational Field.3334"""3335try:3336if not space:3337return self.__cremona_label.replace(' ','')3338return self.__cremona_label3339except AttributeError:3340try:3341X = self.database_curve()3342except RuntimeError:3343raise RuntimeError, "Cremona label not known for %s."%self3344self.__cremona_label = X.__cremona_label3345return self.cremona_label(space)33463347label = cremona_label33483349def reduction(self,p):3350"""3351Return the reduction of the elliptic curve at a prime of good3352reduction.33533354.. note::33553356The actual reduction is done in ``self.change_ring(GF(p))``;3357the reduction is performed after changing to a model which3358is minimal at p.33593360INPUT:33613362- ``p`` - a (positive) prime number336333643365OUTPUT: an elliptic curve over the finite field GF(p)33663367EXAMPLES::33683369sage: E = EllipticCurve('389a1')3370sage: E.reduction(2)3371Elliptic Curve defined by y^2 + y = x^3 + x^2 over Finite Field of size 23372sage: E.reduction(3)3373Elliptic Curve defined by y^2 + y = x^3 + x^2 + x over Finite Field of size 33374sage: E.reduction(5)3375Elliptic Curve defined by y^2 + y = x^3 + x^2 + 3*x over Finite Field of size 53376sage: E.reduction(38)3377Traceback (most recent call last):3378...3379AttributeError: p must be prime.3380sage: E.reduction(389)3381Traceback (most recent call last):3382...3383AttributeError: The curve must have good reduction at p.3384sage: E=EllipticCurve([5^4,5^6])3385sage: E.reduction(5)3386Elliptic Curve defined by y^2 = x^3 + x + 1 over Finite Field of size 53387"""3388p = rings.Integer(p)3389if not p.is_prime():3390raise AttributeError, "p must be prime."3391disc = self.discriminant()3392if not disc.valuation(p) == 0:3393local_data=self.local_data(p)3394if local_data.has_good_reduction():3395return local_data.minimal_model().change_ring(rings.GF(p))3396raise AttributeError, "The curve must have good reduction at p."3397return self.change_ring(rings.GF(p))33983399def torsion_order(self):3400"""3401Return the order of the torsion subgroup.34023403EXAMPLES::34043405sage: e = EllipticCurve('11a')3406sage: e.torsion_order()340753408sage: type(e.torsion_order())3409<type 'sage.rings.integer.Integer'>3410sage: e = EllipticCurve([1,2,3,4,5])3411sage: e.torsion_order()341213413sage: type(e.torsion_order())3414<type 'sage.rings.integer.Integer'>3415"""3416try:3417return self.__torsion_order3418except AttributeError:3419self.__torsion_order = self.torsion_subgroup().order()3420return self.__torsion_order34213422def _torsion_bound(self,number_of_places = 20):3423r"""3424Computes an upper bound on the order of the torsion group of the3425elliptic curve by counting points modulo several primes of good3426reduction. Note that the upper bound returned by this function is a3427multiple of the order of the torsion group.34283429INPUT:343034313432- ``number_of_places (default = 20)`` - the number3433of places that will be used to find the bound343434353436OUTPUT:343734383439- ``integer`` - the upper bound344034413442EXAMPLES:3443"""3444E = self3445bound = Integer(0)3446k = 03447p = Integer(2) # will run through odd primes3448while k < number_of_places :3449p = p.next_prime()3450# check if the formal group at the place is torsion-free3451# if so the torsion injects into the reduction3452while not E.is_local_integral_model(p) or not E.is_good(p): p = p.next_prime()3453bound = arith.gcd(bound,E.reduction(p).cardinality())3454if bound == 1:3455return bound3456k += 13457return bound345834593460def torsion_subgroup(self, algorithm="pari"):3461"""3462Returns the torsion subgroup of this elliptic curve.34633464INPUT:346534663467- ``algorithm`` - string:34683469- ``"pari"`` - (default) use the PARI library34703471- ``"doud"`` - use Doud's algorithm34723473- ``"lutz_nagell"`` - use the Lutz-Nagell theorem347434753476OUTPUT: The EllipticCurveTorsionSubgroup instance associated to3477this elliptic curve.34783479.. note::34803481To see the torsion points as a list, use :meth:`.torsion_points`.34823483EXAMPLES::34843485sage: EllipticCurve('11a').torsion_subgroup()3486Torsion Subgroup isomorphic to Z/5 associated to the Elliptic Curve defined by y^2 + y = x^3 - x^2 - 10*x - 20 over Rational Field3487sage: EllipticCurve('37b').torsion_subgroup()3488Torsion Subgroup isomorphic to Z/3 associated to the Elliptic Curve defined by y^2 + y = x^3 + x^2 - 23*x - 50 over Rational Field34893490::34913492sage: e = EllipticCurve([-1386747,368636886]);e3493Elliptic Curve defined by y^2 = x^3 - 1386747*x + 368636886 over Rational Field3494sage: G = e.torsion_subgroup(); G3495Torsion Subgroup isomorphic to Z/2 + Z/8 associated to the Elliptic3496Curve defined by y^2 = x^3 - 1386747*x + 368636886 over3497Rational Field3498sage: G.03499(1227 : 22680 : 1)3500sage: G.13501(282 : 0 : 1)3502sage: list(G)3503[(0 : 1 : 0), (1227 : 22680 : 1), (2307 : -97200 : 1), (8787 : 816480 : 1), (1011 : 0 : 1), (8787 : -816480 : 1), (2307 : 97200 : 1), (1227 : -22680 : 1), (282 : 0 : 1), (-933 : 29160 : 1), (-285 : -27216 : 1), (147 : 12960 : 1), (-1293 : 0 : 1), (147 : -12960 : 1), (-285 : 27216 : 1), (-933 : -29160 : 1)]3504"""3505try:3506return self.__torsion_subgroup3507except AttributeError:3508self.__torsion_subgroup = ell_torsion.EllipticCurveTorsionSubgroup(self, algorithm)3509self.__torsion_order = self.__torsion_subgroup.order()3510return self.__torsion_subgroup35113512def torsion_points(self, algorithm="pari"):3513"""3514Returns the torsion points of this elliptic curve as a sorted3515list.35163517INPUT:351835193520- ``algorithm`` - string:35213522- "pari" - (default) use the PARI library35233524- "doud" - use Doud's algorithm35253526- "lutz_nagell" - use the Lutz-Nagell theorem352735283529OUTPUT: A list of all the torsion points on this elliptic curve.35303531EXAMPLES::35323533sage: EllipticCurve('11a').torsion_points()3534[(0 : 1 : 0), (5 : -6 : 1), (5 : 5 : 1), (16 : -61 : 1), (16 : 60 : 1)]3535sage: EllipticCurve('37b').torsion_points()3536[(0 : 1 : 0), (8 : -19 : 1), (8 : 18 : 1)]35373538::35393540sage: E=EllipticCurve([-1386747,368636886])3541sage: T=E.torsion_subgroup(); T3542Torsion Subgroup isomorphic to Z/2 + Z/8 associated to the Elliptic Curve defined by y^2 = x^3 - 1386747*x + 368636886 over Rational Field3543sage: T == E.torsion_subgroup(algorithm="doud")3544True3545sage: T == E.torsion_subgroup(algorithm="lutz_nagell")3546True3547sage: E.torsion_points()3548[(-1293 : 0 : 1),3549(-933 : -29160 : 1),3550(-933 : 29160 : 1),3551(-285 : -27216 : 1),3552(-285 : 27216 : 1),3553(0 : 1 : 0),3554(147 : -12960 : 1),3555(147 : 12960 : 1),3556(282 : 0 : 1),3557(1011 : 0 : 1),3558(1227 : -22680 : 1),3559(1227 : 22680 : 1),3560(2307 : -97200 : 1),3561(2307 : 97200 : 1),3562(8787 : -816480 : 1),3563(8787 : 816480 : 1)]3564"""3565return sorted(self.torsion_subgroup(algorithm).points())35663567## def newform_eval(self, z, prec):3568## """3569## The value of the newform attached to this elliptic curve at3570## the point z in the complex upper half plane, computed using3571## prec terms of the power series expansion. Note that the power3572## series need not converge well near the real axis.3573## """3574## raise NotImplementedError35753576@cached_method3577def root_number(self, p=None):3578"""3579Returns the root number of this elliptic curve.35803581This is 1 if the order of vanishing of the L-function L(E,s) at 13582is even, and -1 if it is odd.35833584INPUT::35853586- `p` -- optional, default (None); if given, return the local3587root number at `p`35883589EXAMPLES::35903591sage: EllipticCurve('11a1').root_number()359213593sage: EllipticCurve('37a1').root_number()3594-13595sage: EllipticCurve('389a1').root_number()359613597sage: type(EllipticCurve('389a1').root_number())3598<type 'sage.rings.integer.Integer'>35993600sage: E = EllipticCurve('100a1')3601sage: E.root_number(2)3602-13603sage: E.root_number(5)360413605sage: E.root_number(7)3606136073608The root number is cached::36093610sage: E.root_number(2) is E.root_number(2)3611True3612sage: E.root_number()361313614"""3615e = self.pari_mincurve()3616if p is None:3617return Integer(e.ellrootno())3618else:3619return Integer(e.ellrootno(p))36203621def has_cm(self):3622"""3623Returns True iff this elliptic curve has Complex Multiplication.36243625EXAMPLES::36263627sage: E=EllipticCurve('37a1')3628sage: E.has_cm()3629False3630sage: E=EllipticCurve('32a1')3631sage: E.has_cm()3632True3633sage: E.j_invariant()363417283635"""36363637return CMJ.has_key(self.j_invariant())36383639def cm_discriminant(self):3640"""3641Returns the associated quadratic discriminant if this elliptic3642curve has Complex Multiplication.36433644A ValueError is raised if the curve does not have CM (see the3645function has_cm()).36463647EXAMPLES::36483649sage: E=EllipticCurve('32a1')3650sage: E.cm_discriminant()3651-43652sage: E=EllipticCurve('121b1')3653sage: E.cm_discriminant()3654-113655sage: E=EllipticCurve('37a1')3656sage: E.cm_discriminant()3657Traceback (most recent call last):3658...3659ValueError: Elliptic Curve defined by y^2 + y = x^3 - x over Rational Field does not have CM3660"""36613662try:3663return CMJ[self.j_invariant()]3664except KeyError:3665raise ValueError, "%s does not have CM"%self366636673668def quadratic_twist(self, D):3669"""3670Return the global minimal model of the quadratic twist of this3671curve by D.36723673EXAMPLES::36743675sage: E=EllipticCurve('37a1')3676sage: E7=E.quadratic_twist(7); E73677Elliptic Curve defined by y^2 = x^3 - 784*x + 5488 over Rational Field3678sage: E7.conductor()3679290083680sage: E7.quadratic_twist(7) == E3681True3682"""3683return EllipticCurve_number_field.quadratic_twist(self, D).minimal_model()36843685def minimal_quadratic_twist(self):3686r"""3687Determines a quadratic twist with minimal conductor. Returns a3688global minimal model of the twist and the fundamental3689discriminant of the quadratic field over which they are3690isomorphic.36913692.. note::36933694If there is more than one curve with minimal conductor, the3695one returned is the one with smallest label (if in the3696database), or the one with minimal `a`-invariant list3697(otherwise).36983699EXAMPLES::37003701sage: E = EllipticCurve('121d1')3702sage: E.minimal_quadratic_twist()3703(Elliptic Curve defined by y^2 + y = x^3 - x^2 over Rational Field, -11)3704sage: Et, D = EllipticCurve('32a1').minimal_quadratic_twist()3705sage: D3706137073708sage: E = EllipticCurve('11a1')3709sage: Et, D = E.quadratic_twist(-24).minimal_quadratic_twist()3710sage: E == Et3711True3712sage: D3713-2437143715sage: E = EllipticCurve([0,0,0,0,1000])3716sage: E.minimal_quadratic_twist()3717(Elliptic Curve defined by y^2 = x^3 + 1 over Rational Field, 40)3718sage: E = EllipticCurve([0,0,0,1600,0])3719sage: E.minimal_quadratic_twist()3720(Elliptic Curve defined by y^2 = x^3 + 4*x over Rational Field, 5)372137223723"""3724j = self.j_invariant()3725if j!=0 and j!=1728:3726# the constructor from j will give the minimal twist3727Et = constructor.EllipticCurve_from_j(j)3728else:3729if j==0:3730c = -2*self.c6()3731for p in c.support():3732e = c.valuation(p)//33733c /= p**(3*e)3734E1 = constructor.EllipticCurve([0,0,0,0,c])3735elif j==1728:3736c = -3*self.c4()3737for p in c.support():3738e = c.valuation(p)//23739c /= p**(2*e)3740E1 = constructor.EllipticCurve([0,0,0,c,0])3741tw = [-1,2,-2,3,-3,6,-6]3742Elist = [E1] + [E1.quadratic_twist(t) for t in tw]3743crv_cmp = lambda E,F: cmp(E.conductor(),F.conductor())3744Elist.sort(cmp=crv_cmp)3745Et = Elist[0]37463747Et = Et.minimal_model()37483749D = self.is_quadratic_twist(Et) # 1 or square-free3750if D % 4 != 1:3751D *= 437523753return Et, D375437553756##########################################################3757# Isogeny class3758##########################################################3759def isogeny_class(self, algorithm="sage", verbose=False, fill_matrix=True, return_maps=False):3760r"""3761Returns all curves over `\QQ` isogenous to this elliptic curve.37623763INPUT:37643765- ``verbose`` -- bool (default: False): ignored unless3766``algorithm`` == "mwrank", in which case it is passed to the3767isogeny class function in mwrank.37683769- ``algorithm`` - string: one of the following:37703771- "mwrank" - (default) use the mwrank C++ library37723773- "database" - use the Cremona database (only works if3774curve is isomorphic to a curve in the database)37753776- "sage" - use the native Sage implementation.37773778- ``fill_matrix`` -- bool (default: True): See below.37793780- ``return_maps`` -- bool (default: False): Ignored unless3781``algorithm`` == "sage"; then if True, also returns a list of3782lists indexed by pairs of curves in the class such that the3783`(i,j)` entry is the isogeny from curve `i` to curve `j` if3784that isogeny has prime degree, else 0.37853786OUTPUT:37873788Tuple (list of curves, matrix of integers) or (list of curves,3789matrix of integers, matrix of isogenies). The sorted list of3790all curves isogenous to self is returned. If ``algorithm`` is3791not "database", the isogeny matrix is also returned, otherwise3792None is returned as the second return value. When fill_matrix3793is True (default) the `(i,j)` entry of the matrix is a3794positive integer giving the least degree of a cyclic isogeny3795from curve `i` to curve `j` (in particular, the diagonal3796entries are all `1`). When fill_matrix is False, the3797non-prime entries are replaced by `0` (used in the3798``isogeny_graph()`` function).37993800.. note::38013802The ordering depends on which algorithm is used.38033804.. note::38053806The curves returned are all standard minimal models.38073808.. warning::38093810With ``algorithm`` "mwrank", the result is *not*3811provably correct, in the sense that when the numbers are3812huge isogenies could be missed because of precision3813issues. Using ``algorithm`` "sage" avoids this problem,3814though is slower.38153816.. note::38173818TO DO: when composition of isogenies is implemented, the3819optional returned matrix of isogenies should be completed3820to include all the isogenies, not just those of prime3821degree.38223823EXAMPLES::38243825sage: I, A = EllipticCurve('37b').isogeny_class('mwrank')3826sage: I # randomly ordered3827[Elliptic Curve defined by y^2 + y = x^3 + x^2 - 23*x - 50 over Rational Field,3828Elliptic Curve defined by y^2 + y = x^3 + x^2 - 1873*x - 31833 over Rational Field,3829Elliptic Curve defined by y^2 + y = x^3 + x^2 - 3*x +1 over Rational Field]3830sage: A3831[1 3 3]3832[3 1 9]3833[3 9 1]38343835::38363837sage: I, _ = EllipticCurve('37b').isogeny_class('database'); I3838[Elliptic Curve defined by y^2 + y = x^3 + x^2 - 1873*x - 31833 over Rational Field,3839Elliptic Curve defined by y^2 + y = x^3 + x^2 - 23*x - 50 over Rational Field,3840Elliptic Curve defined by y^2 + y = x^3 + x^2 - 3*x + 1 over Rational Field]38413842This is an example of a curve with a `37`-isogeny::38433844sage: E = EllipticCurve([1,1,1,-8,6])3845sage: E.isogeny_class ()3846([Elliptic Curve defined by y^2 + x*y + y = x^3 + x^2 - 8*x + 6 over Rational Field, Elliptic Curve defined by y^2 + x*y + y = x^3 + x^2 - 208083*x - 36621194 over Rational Field], [ 1 37]3847[37 1])38483849This curve had numerous `2`-isogenies::38503851sage: e=EllipticCurve([1,0,0,-39,90])3852sage: e.isogeny_class ()3853([Elliptic Curve defined by y^2 + x*y = x^3 - 39*x + 90 over Rational Field, Elliptic Curve defined by y^2 + x*y = x^3 - 4*x - 1 over Rational Field, Elliptic Curve defined by y^2 + x*y = x^3 + x over Rational Field, Elliptic Curve defined by y^2 + x*y = x^3 - 49*x - 136 over Rational Field, Elliptic Curve defined by y^2 + x*y = x^3 - 34*x - 217 over Rational Field, Elliptic Curve defined by y^2 + x*y = x^3 - 784*x - 8515 over Rational Field], [1 2 4 4 8 8]3854[2 1 2 2 4 4]3855[4 2 1 4 8 8]3856[4 2 4 1 2 2]3857[8 4 8 2 1 4]3858[8 4 8 2 4 1])38593860See http://math.harvard.edu/~elkies/nature.html for more3861interesting examples of isogeny structures.38623863::38643865sage: E = EllipticCurve(j = -262537412640768000)3866sage: E.isogeny_class(algorithm="sage")3867([Elliptic Curve defined by y^2 + y = x^3 - 2174420*x + 1234136692 over Rational Field, Elliptic Curve defined by y^2 + y = x^3 - 57772164980*x - 5344733777551611 over Rational Field], [ 1 163]3868[163 1])38693870For large examples, the "mwrank" algorithm may fail to find3871some isogenies since it works in fixed precision::38723873sage: E1 = E.quadratic_twist(6584935282)3874sage: E1.isogeny_class(algorithm="mwrank")3875([Elliptic Curve defined by y^2 = x^3 - 94285835957031797981376080*x + 352385311612420041387338054224547830898 over Rational Field],3876[1])38773878Since the result is cached, this looks no different::38793880sage: E1.isogeny_class(algorithm="sage")3881([Elliptic Curve defined by y^2 = x^3 - 94285835957031797981376080*x + 352385311612420041387338054224547830898 over Rational Field],3882[1])38833884But resetting the curve shows that the native algorithm is better::38853886sage: E1 = E.quadratic_twist(6584935282)3887sage: E1.isogeny_class(algorithm="sage")3888([Elliptic Curve defined by y^2 = x^3 - 94285835957031797981376080*x + 352385311612420041387338054224547830898 over Rational Field,3889Elliptic Curve defined by y^2 = x^3 - 2505080375542377840567181069520*x - 1526091631109553256978090116318797845018020806 over Rational Field],3890[ 1 163]3891[163 1])3892sage: E1.conductor()38931843309296671206365333049638943895::38963897sage: E = EllipticCurve('14a1')3898sage: E.isogeny_class(algorithm="sage")3899([Elliptic Curve defined by y^2 + x*y + y = x^3 + 4*x - 6 over Rational Field, Elliptic Curve defined by y^2 + x*y + y = x^3 - 36*x - 70 over Rational Field, Elliptic Curve defined by y^2 + x*y + y = x^3 - x over Rational Field, Elliptic Curve defined by y^2 + x*y + y = x^3 - 171*x - 874 over Rational Field, Elliptic Curve defined by y^2 + x*y + y = x^3 - 11*x + 12 over Rational Field, Elliptic Curve defined by y^2 + x*y + y = x^3 - 2731*x - 55146 over Rational Field], [ 1 2 3 3 6 6]3900[ 2 1 6 6 3 3]3901[ 3 6 1 9 2 18]3902[ 3 6 9 1 18 2]3903[ 6 3 2 18 1 9]3904[ 6 3 18 2 9 1])39053906sage: E = EllipticCurve('11a1')3907sage: E.isogeny_class(algorithm="sage", return_maps=True)3908([Elliptic Curve defined by y^2 + y = x^3 - x^2 - 10*x - 20 over Rational Field, Elliptic Curve defined by y^2 + y = x^3 - x^2 over Rational Field, Elliptic Curve defined by y^2 + y = x^3 - x^2 - 7820*x - 263580 over Rational Field], [ 1 5 5]3909[ 5 1 25]3910[ 5 25 1], [[0, Isogeny of degree 5 from Elliptic Curve defined by y^2 + y = x^3 - x^2 - 10*x - 20 over Rational Field to Elliptic Curve defined by y^2 + y = x^3 - x^2 over Rational Field, Isogeny of degree 5 from Elliptic Curve defined by y^2 + y = x^3 - x^2 - 10*x - 20 over Rational Field to Elliptic Curve defined by y^2 + y = x^3 - x^2 - 7820*x - 263580 over Rational Field], [Isogeny of degree 5 from Elliptic Curve defined by y^2 + y = x^3 - x^2 over Rational Field to Elliptic Curve defined by y^2 + y = x^3 - x^2 - 10*x - 20 over Rational Field, 0, 0], [Isogeny of degree 5 from Elliptic Curve defined by y^2 + y = x^3 - x^2 - 7820*x - 263580 over Rational Field to Elliptic Curve defined by y^2 + y = x^3 - x^2 - 10*x - 20 over Rational Field, 0, 0]])39113912"""3913from sage.schemes.elliptic_curves.ell_curve_isogeny import fill_isogeny_matrix, unfill_isogeny_matrix3914from sage.matrix.all import MatrixSpace39153916try:3917curves, M = self.__isogeny_class3918if fill_matrix and M[0,0]==0:3919M = fill_isogeny_matrix(M)3920elif not fill_matrix and M[0,0]==1:3921M = unfill_isogeny_matrix(M)3922return curves, M3923except AttributeError:3924pass39253926if algorithm == "mwrank":3927try:3928E = self.mwrank_curve()3929except ValueError:3930E = self.minimal_model().mwrank_curve()3931I, A = E.isogeny_class(verbose=verbose)3932M = matrix.MatrixSpace(rings.IntegerRing(), len(A))(A)3933curves = [constructor.EllipticCurve(ainvs) for ainvs in I]39343935elif algorithm == "database":39363937try:3938label = self.cremona_label(space=False)3939except RuntimeError:3940raise RuntimeError, "unable to to find %s in the database"%self3941db = sage.databases.cremona.CremonaDatabase()3942curves = db.isogeny_class(label)3943if len(curves) == 0:3944raise RuntimeError, "unable to to find %s in the database"%self3945curves.sort()3946M = None39473948elif algorithm == "sage":39493950curves = [self.minimal_model()]3951ijl_triples = []3952l_list = None39533954i = 03955while i<len(curves):3956E = curves[i]3957isogs = E.isogenies_prime_degree(l_list)3958for phi in isogs:3959Edash = phi.codomain()3960l = phi.degree()3961# look to see if Edash is new. Note that the3962# curves returned by isogenies_prime_degree() are3963# standard minimal models, so it suffices to check3964# equality rather than isomorphism here.3965try:3966j = curves.index(Edash)3967except ValueError:3968j = len(curves)3969curves.append(Edash)3970ijl_triples.append((i,j,l,phi))3971if l_list is None:3972l_list = [l for l in Set([ZZ(f.degree()) for f in isogs])]3973i = i+139743975ncurves = len(curves)3976M = MatrixSpace(IntegerRing(),ncurves)(0)3977maps = [[0]*ncurves for i in range(ncurves)]3978for i,j,l,phi in ijl_triples:3979M[i,j] = l3980maps[i][j]=phi39813982else:3983raise ValueError, "unknown algorithm '%s'"%algorithm39843985if fill_matrix and not M is None:3986from sage.schemes.elliptic_curves.ell_curve_isogeny import fill_isogeny_matrix3987M = fill_isogeny_matrix(M)39883989if not algorithm=="database":3990self.__isogeny_class = (curves, M)3991if return_maps:3992return curves, M, maps3993return curves, M39943995def isogenies_prime_degree(self, l=None):3996r"""3997Returns a list of `\ell`-isogenies from self, where `\ell` is a3998prime.39994000INPUT:40014002- ``l`` -- either None or a prime or a list of primes.40034004OUTPUT:40054006(list) `\ell`-isogenies for the given `\ell` or if `\ell` is None, all4007`\ell`-isogenies.40084009.. note::40104011The codomains of the isogenies returned are standard4012minimal models. This is because the functions4013:meth:`isogenies_prime_degree_genus_0()` and4014:meth:`isogenies_sporadic_Q()` are implemented that way for4015curves defined over `\QQ`.40164017EXAMPLES::40184019sage: E = EllipticCurve([45,32])4020sage: E.isogenies_prime_degree()4021[]4022sage: E = EllipticCurve(j = -262537412640768000)4023sage: E.isogenies_prime_degree()4024[Isogeny of degree 163 from Elliptic Curve defined by y^2 + y = x^3 - 2174420*x + 1234136692 over Rational Field to Elliptic Curve defined by y^2 + y = x^3 - 57772164980*x - 5344733777551611 over Rational Field]4025sage: E1 = E.quadratic_twist(6584935282)4026sage: E1.isogenies_prime_degree()4027[Isogeny of degree 163 from Elliptic Curve defined by y^2 = x^3 - 94285835957031797981376080*x + 352385311612420041387338054224547830898 over Rational Field to Elliptic Curve defined by y^2 = x^3 - 2505080375542377840567181069520*x - 1526091631109553256978090116318797845018020806 over Rational Field]40284029sage: E = EllipticCurve('14a1')4030sage: E.isogenies_prime_degree(2)4031[Isogeny of degree 2 from Elliptic Curve defined by y^2 + x*y + y = x^3 + 4*x - 6 over Rational Field to Elliptic Curve defined by y^2 + x*y + y = x^3 - 36*x - 70 over Rational Field]4032sage: E.isogenies_prime_degree(3)4033[Isogeny of degree 3 from Elliptic Curve defined by y^2 + x*y + y = x^3 + 4*x - 6 over Rational Field to Elliptic Curve defined by y^2 + x*y + y = x^3 - x over Rational Field, Isogeny of degree 3 from Elliptic Curve defined by y^2 + x*y + y = x^3 + 4*x - 6 over Rational Field to Elliptic Curve defined by y^2 + x*y + y = x^3 - 171*x - 874 over Rational Field]4034sage: E.isogenies_prime_degree(5)4035[]4036sage: E.isogenies_prime_degree(11)4037[]4038sage: E.isogenies_prime_degree(29)4039[]4040sage: E.isogenies_prime_degree(4)4041Traceback (most recent call last):4042...4043ValueError: 4 is not prime.40444045"""4046from ell_curve_isogeny import isogenies_prime_degree_genus_0, isogenies_sporadic_Q40474048if l in [2, 3, 5, 7, 13]:4049return isogenies_prime_degree_genus_0(self, l)4050elif l != None and type(l) != list:4051return isogenies_sporadic_Q(self, l)4052if l == None:4053isogs = isogenies_prime_degree_genus_0(self)4054if isogs != []:4055return isogs4056else:4057return isogenies_sporadic_Q(self)4058if type(l) == list:4059isogs = []4060i = 04061while i<len(l):4062isogenies = [f for f in self.isogenies_prime_degree(l[i]) if not f in isogs]4063isogs.extend(isogenies)4064i = i+14065return isogs40664067def is_isogenous(self, other, proof=True, maxp=200):4068"""4069Returns whether or not self is isogenous to other.40704071INPUT:40724073- ``other`` -- another elliptic curve.40744075- ``proof`` (default True) -- If ``False``, the function will4076return ``True`` whenever the two curves have the same4077conductor and are isogenous modulo `p` for `p` up to ``maxp``.4078If ``True``, this test is followed by a rigorous test (which4079may be more time-consuming).40804081- ``maxp`` (int, default 200) -- The maximum prime `p` for4082which isogeny modulo `p` will be checked.40834084OUTPUT:40854086(bool) True if there is an isogeny from curve ``self`` to4087curve ``other``.40884089METHOD:40904091First the conductors are compared as well as the Traces of4092Frobenius for good primes up to ``maxp``. If any of these4093tests fail, ``False`` is returned. If they all pass and4094``proof`` is ``False`` then ``True`` is returned, otherwise a4095complete set of curves isogenous to ``self`` is computed and4096``other`` is checked for isomorphism with any of these,40974098EXAMPLES::40994100sage: E1 = EllipticCurve('14a1')4101sage: E6 = EllipticCurve('14a6')4102sage: E1.is_isogenous(E6)4103True4104sage: E1.is_isogenous(EllipticCurve('11a1'))4105False41064107::41084109sage: EllipticCurve('37a1').is_isogenous(EllipticCurve('37b1'))4110False41114112::41134114sage: E = EllipticCurve([2, 16])4115sage: EE = EllipticCurve([87, 45])4116sage: E.is_isogenous(EE)4117False4118"""4119if not is_EllipticCurve(other):4120raise ValueError, "Second argument is not an Elliptic Curve."4121if not other.base_field() is QQ:4122raise ValueError, "If first argument is an elliptic curve over QQ then the second argument must be also."41234124if self.is_isomorphic(other):4125return True41264127E1 = self.minimal_model()4128E2 = other.minimal_model()4129D1 = E1.discriminant()4130D2 = E2.discriminant()41314132if any([E1.change_ring(rings.GF(p)).cardinality() != E2.change_ring(rings.GF(p)).cardinality() for p in [p for p in rings.prime_range(2,maxp) if D1.valuation(p) == 0 and D2.valuation(p) == 0]]):4133return False41344135if E1.conductor() != E2.conductor():4136return False41374138if not proof:4139return True4140else:4141return E2 in E1.isogeny_class()[0]41424143def isogeny_degree(self, other):4144"""4145Returns the minimal degree of an isogeny between self and4146other.41474148INPUT:41494150- ``other`` -- another elliptic curve.41514152OUTPUT:41534154(int) The minimal degree of an isogeny from ``self`` to4155``other``, or 0 if the curves are not isogenous.41564157EXAMPLES::41584159sage: E = EllipticCurve([-1056, 13552])4160sage: E2 = EllipticCurve([-127776, -18037712])4161sage: E.isogeny_degree(E2)41621141634164::41654166sage: E1 = EllipticCurve('14a1')4167sage: E2 = EllipticCurve('14a2')4168sage: E3 = EllipticCurve('14a3')4169sage: E4 = EllipticCurve('14a4')4170sage: E5 = EllipticCurve('14a5')4171sage: E6 = EllipticCurve('14a6')4172sage: E3.isogeny_degree(E1)417334174sage: E3.isogeny_degree(E2)417564176sage: E3.isogeny_degree(E3)417714178sage: E3.isogeny_degree(E4)417994180sage: E3.isogeny_degree(E5)418124182sage: E3.isogeny_degree(E6)41831841844185::41864187sage: E1 = EllipticCurve('30a1')4188sage: E2 = EllipticCurve('30a2')4189sage: E3 = EllipticCurve('30a3')4190sage: E4 = EllipticCurve('30a4')4191sage: E5 = EllipticCurve('30a5')4192sage: E6 = EllipticCurve('30a6')4193sage: E7 = EllipticCurve('30a7')4194sage: E8 = EllipticCurve('30a8')4195sage: E1.isogeny_degree(E1)419614197sage: E1.isogeny_degree(E2)419824199sage: E1.isogeny_degree(E3)420034201sage: E1.isogeny_degree(E4)420244203sage: E1.isogeny_degree(E5)420444205sage: E1.isogeny_degree(E6)420664207sage: E1.isogeny_degree(E7)4208124209sage: E1.isogeny_degree(E8)42101242114212::42134214sage: E1 = EllipticCurve('15a1')4215sage: E2 = EllipticCurve('15a2')4216sage: E3 = EllipticCurve('15a3')4217sage: E4 = EllipticCurve('15a4')4218sage: E5 = EllipticCurve('15a5')4219sage: E6 = EllipticCurve('15a6')4220sage: E7 = EllipticCurve('15a7')4221sage: E8 = EllipticCurve('15a8')4222sage: E1.isogeny_degree(E1)422314224sage: E7.isogeny_degree(E2)422584226sage: E7.isogeny_degree(E3)422724228sage: E7.isogeny_degree(E4)422984230sage: E7.isogeny_degree(E5)4231164232sage: E7.isogeny_degree(E6)4233164234sage: E7.isogeny_degree(E8)42354423642370 is returned when the curves are not isogenous::42384239sage: A = EllipticCurve('37a1')4240sage: B = EllipticCurve('37b1')4241sage: A.isogeny_degree(B)424204243sage: A.is_isogenous(B)4244False4245"""4246E1 = self.minimal_model()4247E2 = other.minimal_model()42484249if not E1.is_isogenous(E2, proof=False):4250return Integer(0)42514252cl, mat = E1.isogeny_class()4253try:4254return mat[0,cl.index(E2)]4255except ValueError:4256return Integer(0)42574258#4259# The following function can be implemented once composition of4260# isogenies has been implemented.4261#4262# def contruct_isogeny(self, other):4263# """4264# Returns an isogeny from self to other if the two curves are in4265# the same isogeny class.4266# """426742684269def optimal_curve(self):4270"""4271Given an elliptic curve that is in the installed Cremona4272database, return the optimal curve isogenous to it.42734274EXAMPLES:42754276The following curve is not optimal::42774278sage: E = EllipticCurve('11a2'); E4279Elliptic Curve defined by y^2 + y = x^3 - x^2 - 7820*x - 263580 over Rational Field4280sage: E.optimal_curve()4281Elliptic Curve defined by y^2 + y = x^3 - x^2 - 10*x - 20 over Rational Field4282sage: E.optimal_curve().cremona_label()4283'11a1'42844285Note that 990h is the special case where the optimal curve4286isn't the first in the Cremona labeling::42874288sage: E = EllipticCurve('990h4'); E4289Elliptic Curve defined by y^2 + x*y + y = x^3 - x^2 + 6112*x - 41533 over Rational Field4290sage: F = E.optimal_curve(); F4291Elliptic Curve defined by y^2 + x*y + y = x^3 - x^2 - 1568*x - 4669 over Rational Field4292sage: F.cremona_label()4293'990h3'4294sage: EllipticCurve('990a1').optimal_curve().cremona_label() # a isn't h.4295'990a1'42964297If the input curve is optimal, this function returns that4298curve (not just a copy of it or a curve isomorphic to it!)::42994300sage: E = EllipticCurve('37a1')4301sage: E.optimal_curve() is E4302True43034304Also, if this curve is optimal but not given by a minimal4305model, this curve will still be returned, so this function4306need not return a minimal model in general.43074308::43094310sage: F = E.short_weierstrass_model(); F4311Elliptic Curve defined by y^2 = x^3 - 16*x + 16 over Rational Field4312sage: F.optimal_curve()4313Elliptic Curve defined by y^2 = x^3 - 16*x + 16 over Rational Field4314"""4315label = self.cremona_label()4316N, isogeny, number = sage.databases.cremona.parse_cremona_label(label)4317if N == 990 and isogeny == 'h':4318optimal_label = '990h3'4319else:4320optimal_label = '%s%s1'%(N,isogeny)4321if optimal_label == label: return self4322return constructor.EllipticCurve(optimal_label)43234324def isogeny_graph(self):4325r"""4326Returns a graph representing the isogeny class of this elliptic4327curve, where the vertices are isogenous curves over4328`\QQ` and the edges are prime degree isogenies43294330EXAMPLES::43314332sage: LL = []4333sage: for e in cremona_optimal_curves(range(1, 38)):4334... G = e.isogeny_graph()4335... already = False4336... for H in LL:4337... if G.is_isomorphic(H):4338... already = True4339... break4340... if not already:4341... LL.append(G)4342...4343sage: graphs_list.show_graphs(LL)43444345::43464347sage: E = EllipticCurve('195a')4348sage: G = E.isogeny_graph()4349sage: for v in G: print v, G.get_vertex(v)4350...43510 Elliptic Curve defined by y^2 + x*y = x^3 - 110*x + 435 over Rational Field43521 Elliptic Curve defined by y^2 + x*y = x^3 - 115*x + 392 over Rational Field43532 Elliptic Curve defined by y^2 + x*y = x^3 + 210*x + 2277 over Rational Field43543 Elliptic Curve defined by y^2 + x*y = x^3 - 520*x - 4225 over Rational Field43554 Elliptic Curve defined by y^2 + x*y = x^3 + 605*x - 19750 over Rational Field43565 Elliptic Curve defined by y^2 + x*y = x^3 - 8125*x - 282568 over Rational Field43576 Elliptic Curve defined by y^2 + x*y = x^3 - 7930*x - 296725 over Rational Field43587 Elliptic Curve defined by y^2 + x*y = x^3 - 130000*x - 18051943 over Rational Field4359sage: G.plot(edge_labels=True)4360"""4361from sage.graphs.graph import Graph4362L, M = self.isogeny_class(algorithm='mwrank', fill_matrix=False)4363G = Graph(M, format='weighted_adjacency_matrix')4364G.set_vertices(dict([(v,L[v]) for v in G.vertices()]))4365return G43664367def manin_constant(self):4368r"""4369Return the Manin constant of this elliptic curve. If `\phi: X_0(N) \to E` is the modular4370parametrization of minimal degree, then the Manin constant `c` is defined to be the rational4371number `c` such that `\phi^*(\omega_E) = c\cdot \omega_f` where `\omega_E` is a Neron differential and `\omega_f = f(q) dq/q` is the differential on `X_0(N)` corresponding to the4372newform `f` attached to the isogeny class of `E`.43734374It is known that the Manin constant is an integer. It is conjectured that in each class there is at least one, more precisely the so-called strong Weil curve or `X_0(N)`-optimal curve, that has Manin constant `1`.43754376OUTPUT:43774378an integer43794380This function only works if the curve is in the installed4381Cremona database. Sage includes by default a small databases;4382for the full database you have to install an optional package.43834384EXAMPLES::43854386sage: EllipticCurve('11a1').manin_constant()438714388sage: EllipticCurve('11a2').manin_constant()438914390sage: EllipticCurve('11a3').manin_constant()4391543924393Check that it works even if the curve is non-minimal::43944395sage: EllipticCurve('11a3').change_weierstrass_model([1/35,0,0,0]).manin_constant()4396543974398Rather complicated examples (see #12080) ::43994400sage: [ EllipticCurve('27a%s'%i).manin_constant() for i in [1,2,3,4]]4401[1, 1, 3, 3]4402sage: [ EllipticCurve('80b%s'%i).manin_constant() for i in [1,2,3,4]]4403[1, 2, 1, 2]44044405"""4406from sage.databases.cremona import CremonaDatabase44074408if self.conductor() > CremonaDatabase().largest_conductor():4409raise NotImplementedError, "The Manin constant can only be evaluated for curves in Cremona's tables. If you have not done so, you may wish to install the optional large database."44104411E = self.minimal_model()4412C = self.optimal_curve()4413_, m = C.isogeny_class()4414ma = max(max(x) for x in m)4415OmC = C.period_lattice().basis()4416OmE = E.period_lattice().basis()4417q_plus = QQ(gp.bestappr(OmE[0]/OmC[0],ma+1) )4418n_plus = q_plus.numerator()44194420cinf_E = E.real_components()4421cinf_C = C.real_components()4422OmC_minus = OmC[1].imag()4423if cinf_C == 1:4424OmC_minus *= 24425OmE_minus = OmE[1].imag()4426if cinf_E == 1:4427OmE_minus *= 24428q_minus = QQ(gp.bestappr(OmE_minus/OmC_minus, ma+1))4429n_minus = q_minus.numerator()4430n = ZZ(n_minus * n_plus)44314432if cinf_C == cinf_E:4433return n4434# otherwise they have different number of connected component and we have to adjust for this4435elif cinf_C > cinf_E:4436if ZZ(n_plus) % 2 == 0 and ZZ(n_minus) % 2 == 0:4437return n // 24438else:4439return n4440else: #if cinf_C < cinf_E:4441if q_plus.denominator() % 2 == 0 and q_minus.denominator() % 2 == 0:4442return n4443else:4444return n*244454446def _shortest_paths(self):4447r"""4448Technical internal function that returns the list of isogenies4449curves and corresponding dictionary of shortest isogeny paths4450from self to each other curve in the isogeny class.44514452.. warning::44534454The result is *not* provably correct, in the4455sense that when the numbers are huge isogenies could be4456missed because of precision issues.44574458OUTPUT:44594460list, dict44614462EXAMPLES::44634464sage: EllipticCurve('11a1')._shortest_paths()4465([Elliptic Curve defined by y^2 + y = x^3 - x^2 - 10*x - 20 over Rational Field,4466Elliptic Curve defined by y^2 + y = x^3 - x^2 - 7820*x - 263580 over Rational Field,4467Elliptic Curve defined by y^2 + y = x^3 - x^2 over Rational Field],4468{0: 0, 1: 5, 2: 5})4469sage: EllipticCurve('11a2')._shortest_paths()4470([Elliptic Curve defined by y^2 + y = x^3 - x^2 - 7820*x - 263580 over Rational Field,4471Elliptic Curve defined by y^2 + y = x^3 - x^2 - 10*x - 20 over Rational Field,4472Elliptic Curve defined by y^2 + y = x^3 - x^2 over Rational Field],4473{0: 0, 1: 5, 2: 25})4474"""4475from sage.graphs.graph import Graph4476L, M = self.isogeny_class(algorithm='mwrank')4477M = M.change_ring(rings.RR)4478# see trac #4889 for nebulous M.list() --> M.entries() change...4479# Take logs here since shortest path minimizes the *sum* of the weights -- not the product.4480M = M.parent()([a.log() if a else 0 for a in M.list()])4481G = Graph(M, format='weighted_adjacency_matrix')4482G.set_vertices(dict([(v,L[v]) for v in G.vertices()]))4483v = G.shortest_path_lengths(0, by_weight=True, weight_sums=True)4484# Now exponentiate and round to get degrees of isogenies4485v = dict([(i, j.exp().round() if j else 0) for i,j in v.iteritems()])4486return L, v44874488def _multiple_of_degree_of_isogeny_to_optimal_curve(self):4489r"""4490Internal function returning an integer m such that the degree of4491the isogeny between this curve and the optimal curve in its4492isogeny class is a divisor of m.44934494.. warning::44954496The result is *not* provably correct, in the4497sense that when the numbers are huge isogenies could be4498missed because of precision issues.44994500EXAMPLES::45014502sage: E = EllipticCurve('11a1')4503sage: E._multiple_of_degree_of_isogeny_to_optimal_curve()450454505sage: E = EllipticCurve('11a2')4506sage: E._multiple_of_degree_of_isogeny_to_optimal_curve()4507254508sage: E = EllipticCurve('11a3')4509sage: E._multiple_of_degree_of_isogeny_to_optimal_curve()4510254511"""4512_, v = self._shortest_paths()4513# Compute the degree of an isogeny from self to anything else4514# in the isogeny class of self. Assuming the isogeny4515# enumeration is complete (which need not be the case a priori!), the LCM4516# of these numbers is a multiple of the degree of the isogeny4517# to the optimal curve.4518v = [deg for num, deg in v.iteritems() if deg] # get just the degrees4519return arith.LCM(v)45204521##########################################################4522# Galois Representations4523##########################################################45244525def galois_representation(self):4526r"""4527The compatible family of the Galois representation4528attached to this elliptic curve.45294530Given an elliptic curve `E` over `\QQ`4531and a rational prime number `p`, the `p^n`-torsion4532`E[p^n]` points of `E` is a representation of the4533absolute Galois group of `\QQ`. As `n` varies4534we obtain the Tate module `T_p E` which is a4535a representation of `G_K` on a free `\ZZ_p`-module4536of rank `2`. As `p` varies the representations4537are compatible.45384539EXAMPLES::45404541sage: rho = EllipticCurve('11a1').galois_representation()4542sage: rho4543Compatible family of Galois representations associated to the Elliptic Curve defined by y^2 + y = x^3 - x^2 - 10*x - 20 over Rational Field4544sage: rho.is_irreducible(7)4545True4546sage: rho.is_irreducible(5)4547False4548sage: rho.is_surjective(11)4549True4550sage: rho.non_surjective()4551[5]4552sage: rho = EllipticCurve('37a1').galois_representation()4553sage: rho.non_surjective()4554[]4555sage: rho = EllipticCurve('27a1').galois_representation()4556sage: rho.is_irreducible(7)4557True4558sage: rho.non_surjective() # cm-curve4559[0]45604561"""4562try:4563return self.__rho4564except AttributeError:4565from gal_reps import GaloisRepresentation4566self.__rho = GaloisRepresentation(self)4567return self.__rho45684569# deprecated as it should be the is_reducible for a scheme (and hence return False always).4570def is_reducible(self, p):4571"""4572Return True if the mod-p representation attached to E is4573reducible.45744575Note that this function is deprecated, and that you should use4576galois_representation().is_reducible(p) instead as this will be4577disappearing in the near future.45784579EXAMPLES::45804581sage: EllipticCurve('20a1').is_reducible(3) #random4582doctest:1: DeprecationWarning: is_reducible is deprecated, use galois_representation().is_reducible(p) instead!4583True45844585"""4586from sage.misc.misc import deprecation4587deprecation("is_reducible is deprecated, use galois_representation().is_reducible(p) instead!")4588return self.galois_representation().is_reducible(p)45894590# deprecated as it should be the is_irreducible for a scheme (and hence return True always).4591def is_irreducible(self, p):4592"""4593Return True if the mod p representation is irreducible.45944595Note that this function is deprecated, and that you should use4596galois_representation().is_irreducible(p) instead as this will be4597disappearing in the near future.45984599EXAMPLES::46004601sage: EllipticCurve('20a1').is_irreducible(7) #random4602doctest:1: DeprecationWarning: is_irreducible is deprecated, use galois_representation().is_irreducible(p) instead!4603True46044605"""4606from sage.misc.misc import deprecation4607deprecation("is_irreducible is deprecated, use galois_representation().is_irreducible(p) instead!")4608return self.galois_representation().is_irreducible(p)46094610# deprecated4611def is_surjective(self, p, A=1000):4612r"""4613Returns true if the mod p representation is surjective46144615Note that this function is deprecated, and that you should use4616galois_representation().is_surjective(p) instead as this will be4617disappearing in the near future.46184619EXAMPLES::46204621sage: EllipticCurve('20a1').is_surjective(7) #random4622doctest:1: DeprecationWarning: is_surjective is deprecated, use galois_representation().is_surjective(p) instead!4623True46244625"""4626from sage.misc.misc import deprecation4627deprecation("is_surjective is deprecated, use galois_representation().is_surjective(p) instead!")4628return self.galois_representation().is_surjective(p,A)46294630# deprecated4631def reducible_primes(self):4632r"""4633Returns a list of reducible primes.46344635Note that this function is deprecated, and that you should use4636galois_representation().reducible_primes() instead as this will be4637disappearing in the near future.46384639EXAMPLES::46404641sage: EllipticCurve('20a1').reducible_primes() #random4642doctest:1: DeprecationWarning: reducible_primes is deprecated, use galois_representation().reducible_primes() instead!4643[2,3]46444645"""4646from sage.misc.misc import deprecation4647deprecation("reducible_primes is deprecated, use galois_representation().reducible_primes() instead!")4648return self.galois_representation().reducible_primes()46494650# deprecated4651def non_surjective(self, A=1000):4652r"""4653Returns a list of primes p for which the Galois representation mod p is not surjective.46544655Note that this function is deprecated, and that you should use4656galois_representation().non_surjective() instead as this will be4657disappearing in the near future.46584659EXAMPLES::46604661sage: EllipticCurve('20a1').non_surjective() #random4662doctest:1: DeprecationWarning: non_surjective is deprecated, use galois_representation().non_surjective() instead!4663[2,3]46644665"""4666from sage.misc.misc import deprecation4667deprecation("non_surjective is deprecated, use galois_representation().non_surjective() instead!")4668return self.galois_representation().non_surjective()46694670def is_semistable(self):4671"""4672Return True iff this elliptic curve is semi-stable at all primes.46734674EXAMPLES::46754676sage: E=EllipticCurve('37a1')4677sage: E.is_semistable()4678True4679sage: E=EllipticCurve('90a1')4680sage: E.is_semistable()4681False4682"""4683return self.conductor().is_squarefree()46844685def is_ordinary(self, p, ell=None):4686"""4687Return True precisely when the mod-p representation attached to4688this elliptic curve is ordinary at ell.46894690INPUT:46914692- ``p`` - a prime ell - a prime (default: p)46934694OUTPUT: bool46954696EXAMPLES::46974698sage: E=EllipticCurve('37a1')4699sage: E.is_ordinary(37)4700True4701sage: E=EllipticCurve('32a1')4702sage: E.is_ordinary(2)4703False4704sage: [p for p in prime_range(50) if E.is_ordinary(p)]4705[5, 13, 17, 29, 37, 41]47064707"""4708if ell is None:4709ell = p4710return self.ap(ell) % p != 047114712def is_good(self, p, check=True):4713"""4714Return True if `p` is a prime of good reduction for4715`E`.47164717INPUT:47184719- ``p`` - a prime47204721OUTPUT: bool47224723EXAMPLES::47244725sage: e = EllipticCurve('11a')4726sage: e.is_good(-8)4727Traceback (most recent call last):4728...4729ValueError: p must be prime4730sage: e.is_good(-8, check=False)4731True47324733"""4734if check:4735if not arith.is_prime(p):4736raise ValueError, "p must be prime"4737return self.conductor() % p != 0473847394740def is_supersingular(self, p, ell=None):4741"""4742Return True precisely when p is a prime of good reduction and the4743mod-p representation attached to this elliptic curve is4744supersingular at ell.47454746INPUT:47474748- ``p`` - a prime ell - a prime (default: p)47494750OUTPUT: bool47514752EXAMPLES::47534754sage: E=EllipticCurve('37a1')4755sage: E.is_supersingular(37)4756False4757sage: E=EllipticCurve('32a1')4758sage: E.is_supersingular(2)4759False4760sage: E.is_supersingular(7)4761True4762sage: [p for p in prime_range(50) if E.is_supersingular(p)]4763[3, 7, 11, 19, 23, 31, 43, 47]47644765"""4766if ell is None:4767ell = p4768return self.is_good(p) and not self.is_ordinary(p, ell)47694770def supersingular_primes(self, B):4771"""4772Return a list of all supersingular primes for this elliptic curve4773up to and possibly including B.47744775EXAMPLES::47764777sage: e = EllipticCurve('11a')4778sage: e.aplist(20)4779[-2, -1, 1, -2, 1, 4, -2, 0]4780sage: e.supersingular_primes(1000)4781[2, 19, 29, 199, 569, 809]47824783::47844785sage: e = EllipticCurve('27a')4786sage: e.aplist(20)4787[0, 0, 0, -1, 0, 5, 0, -7]4788sage: e.supersingular_primes(97)4789[2, 5, 11, 17, 23, 29, 41, 47, 53, 59, 71, 83, 89]4790sage: e.ordinary_primes(97)4791[7, 13, 19, 31, 37, 43, 61, 67, 73, 79, 97]4792sage: e.supersingular_primes(3)4793[2]4794sage: e.supersingular_primes(2)4795[2]4796sage: e.supersingular_primes(1)4797[]4798"""4799v = self.aplist(max(B, 3))4800P = rings.prime_range(max(B,3)+1)4801N = self.conductor()4802return [P[i] for i in [0,1] if P[i] <= B and v[i]%P[i]==0 and N%P[i] != 0] + \4803[P[i] for i in range(2,len(v)) if v[i] == 0 and N%P[i] != 0]48044805def ordinary_primes(self, B):4806"""4807Return a list of all ordinary primes for this elliptic curve up to4808and possibly including B.48094810EXAMPLES::48114812sage: e = EllipticCurve('11a')4813sage: e.aplist(20)4814[-2, -1, 1, -2, 1, 4, -2, 0]4815sage: e.ordinary_primes(97)4816[3, 5, 7, 11, 13, 17, 23, 31, 37, 41, 43, 47, 53, 59, 61, 67, 71, 73, 79, 83, 89, 97]4817sage: e = EllipticCurve('49a')4818sage: e.aplist(20)4819[1, 0, 0, 0, 4, 0, 0, 0]4820sage: e.supersingular_primes(97)4821[3, 5, 13, 17, 19, 31, 41, 47, 59, 61, 73, 83, 89, 97]4822sage: e.ordinary_primes(97)4823[2, 11, 23, 29, 37, 43, 53, 67, 71, 79]4824sage: e.ordinary_primes(3)4825[2]4826sage: e.ordinary_primes(2)4827[2]4828sage: e.ordinary_primes(1)4829[]4830"""4831v = self.aplist(max(B, 3) )4832P = rings.prime_range(max(B,3) +1)4833return [P[i] for i in [0,1] if P[i] <= B and v[i]%P[i]!=0] +\4834[P[i] for i in range(2,len(v)) if v[i] != 0]48354836def eval_modular_form(self, points, prec):4837"""4838Evaluate the modular form of this elliptic curve at points in CC48394840INPUT:484148424843- ``points`` - a list of points in the half-plane of4844convergence48454846- ``prec`` - precision484748484849OUTPUT: A list of values L(E,s) for s in points48504851.. note::48524853Better examples are welcome.48544855EXAMPLES::48564857sage: E=EllipticCurve('37a1')4858sage: E.eval_modular_form([1.5+I,2.0+I,2.5+I],0.000001)4859[0, 0, 0]4860"""4861if not isinstance(points, (list,xrange)):4862try:4863points = list(points)4864except TypeError:4865return self.eval_modular_form([points],prec)4866an = self.pari_mincurve().ellan(prec)4867s = 04868c = pari('2 * Pi * I')4869ans = []4870for z in points:4871s = pari(0)4872r0 = (c*z).exp()4873r = r04874for n in xrange(1,prec):4875s += an[n-1]*r4876r *= r04877ans.append(s.python())4878return ans487948804881########################################################################4882# The Tate-Shafarevich group4883########################################################################48844885def sha(self):4886"""4887Return an object of class4888'sage.schemes.elliptic_curves.sha_tate.Sha' attached to this4889elliptic curve.48904891This can be used in functions related to bounding the order of Sha4892(The Tate-Shafarevich group of the curve).48934894EXAMPLES::48954896sage: E=EllipticCurve('37a1')4897sage: S=E.sha()4898sage: S4899Tate-Shafarevich group for the Elliptic Curve defined by y^2 + y = x^3 - x over Rational Field4900sage: S.bound_kolyvagin()4901([2], 1)4902"""4903try:4904return self.__sha4905except AttributeError:4906from sha_tate import Sha4907self.__sha = Sha(self)4908return self.__sha49094910#################################################################################4911# Functions related to Heegner points#################################################################################4912heegner_point = heegner.ell_heegner_point4913kolyvagin_point = heegner.kolyvagin_point49144915heegner_discriminants = heegner.ell_heegner_discriminants4916heegner_discriminants_list = heegner.ell_heegner_discriminants_list4917satisfies_heegner_hypothesis = heegner.satisfies_heegner_hypothesis49184919heegner_point_height = heegner.heegner_point_height49204921heegner_index = heegner.heegner_index4922_adjust_heegner_index = heegner._adjust_heegner_index4923heegner_index_bound = heegner.heegner_index_bound4924_heegner_index_in_EK = heegner._heegner_index_in_EK49254926heegner_sha_an = heegner.heegner_sha_an49274928_heegner_forms_list = heegner._heegner_forms_list4929_heegner_best_tau = heegner._heegner_best_tau49304931#################################################################################4932# p-adic functions4933#################################################################################49344935padic_regulator = padics.padic_regulator49364937padic_height_pairing_matrix = padics.padic_height_pairing_matrix49384939padic_height = padics.padic_height4940padic_height_via_multiply = padics.padic_height_via_multiply49414942padic_sigma = padics.padic_sigma4943padic_sigma_truncated = padics.padic_sigma_truncated49444945padic_E2 = padics.padic_E249464947matrix_of_frobenius = padics.matrix_of_frobenius49484949# def weierstrass_p(self):4950# # TODO: add allowing negative valuations for power series4951# return 1/t**2 + a1/t + rings.frac(1,12)*(a1-8*a2) -a3*t \4952# - (a4+a1*a3)*t**2 + O(t**3)495349544955def mod5family(self):4956"""4957Return the family of all elliptic curves with the same mod-54958representation as self.49594960EXAMPLES::49614962sage: E=EllipticCurve('32a1')4963sage: E.mod5family()4964Elliptic Curve defined by y^2 = x^3 + 4*x over Fraction Field of Univariate Polynomial Ring in t over Rational Field4965"""4966E = self.short_weierstrass_model()4967a = E.a4()4968b = E.a6()4969return mod5family.mod5family(a,b)49704971def tate_curve(self, p):4972r"""4973Creates the Tate Curve over the `p`-adics associated to4974this elliptic curves.49754976This Tate curve a `p`-adic curve with split multiplicative4977reduction of the form `y^2+xy=x^3+s_4 x+s_6` which is4978isomorphic to the given curve over the algebraic closure of4979`\QQ_p`. Its points over `\QQ_p`4980are isomorphic to `\QQ_p^{\times}/q^{\ZZ}`4981for a certain parameter `q\in\ZZ_p`.49824983INPUT:49844985p - a prime where the curve has multiplicative reduction.49864987EXAMPLES::49884989sage: e = EllipticCurve('130a1')4990sage: e.tate_curve(2)49912-adic Tate curve associated to the Elliptic Curve defined by y^2 + x*y + y = x^3 - 33*x + 68 over Rational Field49924993The input curve must have multiplicative reduction at the prime.49944995::49964997sage: e.tate_curve(3)4998Traceback (most recent call last):4999...5000ValueError: The elliptic curve must have multiplicative reduction at 350015002We compute with `p=5`::50035004sage: T = e.tate_curve(5); T50055-adic Tate curve associated to the Elliptic Curve defined by y^2 + x*y + y = x^3 - 33*x + 68 over Rational Field50065007We find the Tate parameter `q`::50085009sage: T.parameter(prec=5)50103*5^3 + 3*5^4 + 2*5^5 + 2*5^6 + 3*5^7 + O(5^8)50115012We compute the `\mathcal{L}`-invariant of the curve::50135014sage: T.L_invariant(prec=10)50155^3 + 4*5^4 + 2*5^5 + 2*5^6 + 2*5^7 + 3*5^8 + 5^9 + O(5^10)5016"""5017try:5018return self._tate_curve[p]5019except AttributeError:5020self._tate_curve = {}5021except KeyError:5022pass50235024Eq = ell_tate_curve.TateCurve(self,p)5025self._tate_curve[p] = Eq5026return Eq50275028def height(self, precision=None):5029"""5030Returns the real height of this elliptic curve. This is used in5031integral_points()50325033INPUT:503450355036- ``precision`` - desired real precision of the result5037(default real precision if None)503850395040EXAMPLES::50415042sage: E=EllipticCurve('5077a1')5043sage: E.height()504417.45133347988965045sage: E.height(100)504617.4513334798896127025085793995047sage: E=EllipticCurve([0,0,0,0,1])5048sage: E.height()50491.386294361119895050sage: E=EllipticCurve([0,0,0,1,0])5051sage: E.height()50527.454719949364005053"""5054if precision is None:5055precision = RealField().precision()5056R = RealField(precision)5057c4 = self.c4()5058c6 = self.c6()5059j = self.j_invariant()5060log_g2 = R((c4/12)).abs().log()5061log_g3 = R((c6/216)).abs().log()50625063if j == 0:5064h_j = R(1)5065else:5066h_j = max(log(R(abs(j.numerator()))), log(R(abs(j.denominator()))))5067if (self.c4() != 0) and (self.c6() != 0):5068h_gs = max(1, log_g2, log_g3)5069elif c4 == 0:5070if c6 == 0:5071return max(1,h_j)5072h_gs = max(1, log_g3)5073else:5074h_gs = max(1, log_g2)5075return max(R(1),h_j, h_gs)50765077def lll_reduce(self, points, height_matrix=None):5078"""5079Returns an LLL-reduced basis from a given basis, with transform5080matrix.50815082INPUT:508350845085- ``points`` - a list of points on this elliptic5086curve, which should be independent.50875088- ``height_matrix`` - the height-pairing matrix of5089the points, or None. If None, it will be computed.509050915092OUTPUT: A tuple (newpoints,U) where U is a unimodular integer5093matrix, new_points is the transform of points by U, such that5094new_points has LLL-reduced height pairing matrix50955096.. note::50975098If the input points are not independent, the output depends5099on the undocumented behaviour of PARI's ``qflllgram()``5100function when applied to a gram matrix which is not5101positive definite.51025103EXAMPLE::51045105sage: E = EllipticCurve([0, 1, 1, -2, 42])5106sage: Pi = E.gens(); Pi5107[(-4 : 1 : 1), (-3 : 5 : 1), (-11/4 : 43/8 : 1), (-2 : 6 : 1)]5108sage: Qi, U = E.lll_reduce(Pi)5109sage: sorted(Qi)5110[(-4 : 1 : 1), (-3 : 5 : 1), (-2 : 6 : 1), (0 : 6 : 1)]5111sage: U.det()511215113sage: E.regulator_of_points(Pi)51144.590880369605735115sage: E.regulator_of_points(Qi)51164.5908803696057451175118::51195120sage: E = EllipticCurve([1,0,1,-120039822036992245303534619191166796374,504224992484910670010801799168082726759443756222911415116])5121sage: xi = [2005024558054813068,\5122-4690836759490453344,\51234700156326649806635,\51246785546256295273860,\51256823803569166584943,\51267788809602110240789,\512727385442304350994620556,\512854284682060285253719/4,\5129-94200235260395075139/25,\5130-3463661055331841724647/576,\5131-6684065934033506970637/676,\5132-956077386192640344198/2209,\5133-27067471797013364392578/2809,\5134-25538866857137199063309/3721,\5135-1026325011760259051894331/108241,\51369351361230729481250627334/1366561,\513710100878635879432897339615/1423249,\513811499655868211022625340735/17522596,\5139110352253665081002517811734/21353641,\5140414280096426033094143668538257/285204544,\514136101712290699828042930087436/4098432361,\514245442463408503524215460183165/5424617104,\5143983886013344700707678587482584/141566320009,\51441124614335716851053281176544216033/152487126016]5145sage: points = [E.lift_x(x) for x in xi]5146sage: newpoints, U = E.lll_reduce(points) # long time (36s on sage.math, 2011)5147sage: [P[0] for P in newpoints] # long time5148[6823803569166584943, 5949539878899294213, 2005024558054813068, 5864879778877955778, 23955263915878682727/4, 5922188321411938518, 5286988283823825378, 175620639884534615751/25, -11451575907286171572, 3502708072571012181, 1500143935183238709184/225, 27180522378120223419/4, -5811874164190604461581/625, 26807786527159569093, 7404442636649562303, 475656155255883588, 265757454726766017891/49, 7272142121019825303, 50628679173833693415/4, 6951643522366348968, 6842515151518070703, 111593750389650846885/16, 2607467890531740394315/9, -1829928525835506297]5149"""5150r = len(points)5151if height_matrix is None:5152height_matrix = self.height_pairing_matrix(points)5153U = pari(height_matrix).lllgram().python()5154new_points = [sum([U[j,i]*points[j] for j in range(r)]) for i in range(r)]5155return new_points, U51565157def antilogarithm(self, z, max_denominator=None):5158r"""5159Returns the rational point (if any) associated to this complex5160number; the inverse of the elliptic logarithm function.51615162INPUT:51635164- ``z`` -- a complex number representing an element of5165`\CC/L` where `L` is the period lattice of the elliptic curve51665167- ``max_denominator`` (int or None) -- parameter controlling5168the attempted conversion of real numbers to rationals. If5169None, ``simplest_rational()`` will be used; otherwise,5170``nearby_rational()`` will be used with this value of5171``max_denominator``.51725173OUTPUT:51745175- point on the curve: the rational point which is the5176image of `z` under the Weierstrass parametrization, if it5177exists and can be determined from `z` and the given value5178of max_denominator (if any); otherwise a ValueError exception5179is raised.51805181EXAMPLES::51825183sage: E = EllipticCurve('389a')5184sage: P = E(-1,1)5185sage: z = P.elliptic_logarithm()5186sage: E.antilogarithm(z)5187(-1 : 1 : 1)5188sage: Q = E(0,-1)5189sage: z = Q.elliptic_logarithm()5190sage: E.antilogarithm(z)5191Traceback (most recent call last):5192...5193ValueError: approximated point not on the curve5194sage: E.antilogarithm(z, max_denominator=10)5195(0 : -1 : 1)51965197sage: E = EllipticCurve('11a1')5198sage: w1,w2 = E.period_lattice().basis()5199sage: [E.antilogarithm(a*w1/5,1) for a in range(5)]5200[(0 : 1 : 0), (16 : -61 : 1), (5 : -6 : 1), (5 : 5 : 1), (16 : 60 : 1)]5201"""5202if z.is_zero():5203return self(0)5204expZ = self.elliptic_exponential(z)5205xy = [t.real() for t in expZ[:2]]5206if max_denominator is None:5207xy = [t.simplest_rational() for t in xy]5208else:5209xy = [t.nearby_rational(max_denominator=max_denominator) for t in xy]5210try:5211return self(xy)5212except TypeError:5213raise ValueError, "approximated point not on the curve"52145215def integral_x_coords_in_interval(self,xmin,xmax):5216r"""5217Returns the set of integers `x` with `xmin\le x\le xmax` which are5218`x`-coordinates of rational points on this curve.52195220INPUT:52215222- ``xmin``, ``xmax`` (integers) -- two integers.52235224OUTPUT:52255226(set) The set of integers `x` with `xmin\le x\le xmax` which5227are `x`-coordinates of rational points on the elliptic curve.52285229EXAMPLES::52305231sage: E = EllipticCurve([0, 0, 1, -7, 6])5232sage: xset = E.integral_x_coords_in_interval(-100,100)5233sage: xlist = list(xset); xlist.sort(); xlist5234[-3, -2, -1, 0, 1, 2, 3, 4, 8, 11, 14, 21, 37, 52, 93]52355236TODO: re-implement this using the much faster point searching5237implemented in Stoll's ``ratpoints`` program.52385239"""5240xmin=Integer(xmin)5241xmax=Integer(xmax)5242ans = set([])5243x = xmin5244while x<=xmax:5245if self.is_x_coord(x):5246ans.add(x)5247x+=15248return ans52495250prove_BSD = BSD.prove_BSD52515252def integral_points(self, mw_base='auto', both_signs=False, verbose=False):5253"""5254Computes all integral points (up to sign) on this elliptic curve.52555256INPUT:525752585259- ``mw_base`` - list of EllipticCurvePoint generating5260the Mordell-Weil group of E (default: 'auto' - calls self.gens())52615262- ``both_signs`` - True/False (default False): if5263True the output contains both P and -P, otherwise only one of each5264pair.52655266- ``verbose`` - True/False (default False): if True,5267some details of the computation are output526852695270OUTPUT: A sorted list of all the integral points on E (up to sign5271unless both_signs is True)52725273.. note::52745275The complexity increases exponentially in the rank of curve5276E. The computation time (but not the output!) depends on5277the Mordell-Weil basis. If mw_base is given but is not a5278basis for the Mordell-Weil group (modulo torsion), integral5279points which are not in the subgroup generated by the given5280points will almost certainly not be listed.52815282EXAMPLES: A curve of rank 3 with no torsion points52835284::52855286sage: E=EllipticCurve([0,0,1,-7,6])5287sage: P1=E.point((2,0)); P2=E.point((-1,3)); P3=E.point((4,6))5288sage: a=E.integral_points([P1,P2,P3]); a5289[(-3 : 0 : 1), (-2 : 3 : 1), (-1 : 3 : 1), (0 : 2 : 1), (1 : 0 : 1), (2 : 0 : 1), (3 : 3 : 1), (4 : 6 : 1), (8 : 21 : 1), (11 : 35 : 1), (14 : 51 : 1), (21 : 95 : 1), (37 : 224 : 1), (52 : 374 : 1), (93 : 896 : 1), (342 : 6324 : 1), (406 : 8180 : 1), (816 : 23309 : 1)]52905291::52925293sage: a = E.integral_points([P1,P2,P3], verbose=True)5294Using mw_basis [(2 : 0 : 1), (3 : -4 : 1), (8 : -22 : 1)]5295e1,e2,e3: -3.0124303725933... 1.0658205476962... 1.946609824897105296Minimal eigenvalue of height pairing matrix: 0.63792081458500...5297x-coords of points on compact component with -3 <=x<= 15298[-3, -2, -1, 0, 1]5299x-coords of points on non-compact component with 2 <=x<= 65300[2, 3, 4]5301starting search of remaining points using coefficient bound 55302x-coords of extra integral points:5303[2, 3, 4, 8, 11, 14, 21, 37, 52, 93, 342, 406, 816]5304Total number of integral points: 1853055306It is not necessary to specify mw_base; if it is not provided,5307then the Mordell-Weil basis must be computed, which may take5308much longer.53095310::53115312sage: E=EllipticCurve([0,0,1,-7,6])5313sage: a=E.integral_points(both_signs=True); a5314[(-3 : -1 : 1), (-3 : 0 : 1), (-2 : -4 : 1), (-2 : 3 : 1), (-1 : -4 : 1), (-1 : 3 : 1), (0 : -3 : 1), (0 : 2 : 1), (1 : -1 : 1), (1 : 0 : 1), (2 : -1 : 1), (2 : 0 : 1), (3 : -4 : 1), (3 : 3 : 1), (4 : -7 : 1), (4 : 6 : 1), (8 : -22 : 1), (8 : 21 : 1), (11 : -36 : 1), (11 : 35 : 1), (14 : -52 : 1), (14 : 51 : 1), (21 : -96 : 1), (21 : 95 : 1), (37 : -225 : 1), (37 : 224 : 1), (52 : -375 : 1), (52 : 374 : 1), (93 : -897 : 1), (93 : 896 : 1), (342 : -6325 : 1), (342 : 6324 : 1), (406 : -8181 : 1), (406 : 8180 : 1), (816 : -23310 : 1), (816 : 23309 : 1)]53155316An example with negative discriminant::53175318sage: EllipticCurve('900d1').integral_points()5319[(-11 : 27 : 1), (-4 : 34 : 1), (4 : 18 : 1), (16 : 54 : 1)]53205321Another example with rank 5 and no torsion points::53225323sage: E=EllipticCurve([-879984,319138704])5324sage: P1=E.point((540,1188)); P2=E.point((576,1836))5325sage: P3=E.point((468,3132)); P4=E.point((612,3132))5326sage: P5=E.point((432,4428))5327sage: a=E.integral_points([P1,P2,P3,P4,P5]); len(a) # long time (18s on sage.math, 2011)53285453295330TESTS:53315332The bug reported on trac #4525 is now fixed::53335334sage: EllipticCurve('91b1').integral_points()5335[(-1 : 3 : 1), (1 : 0 : 1), (3 : 4 : 1)]53365337::53385339sage: [len(e.integral_points(both_signs=False)) for e in cremona_curves([11..100])] # long time (15s on sage.math, 2011)5340[2, 0, 2, 3, 2, 1, 3, 0, 2, 4, 2, 4, 3, 0, 0, 1, 2, 1, 2, 0, 2, 1, 0, 1, 3, 3, 1, 1, 4, 2, 3, 2, 0, 0, 5, 3, 2, 2, 1, 1, 1, 0, 1, 3, 0, 1, 0, 1, 1, 3, 6, 1, 2, 2, 2, 0, 0, 2, 3, 1, 2, 2, 1, 1, 0, 3, 2, 1, 0, 1, 0, 1, 3, 3, 1, 1, 5, 1, 0, 1, 1, 0, 1, 2, 0, 2, 0, 1, 1, 3, 1, 2, 2, 4, 4, 2, 1, 0, 0, 5, 1, 0, 1, 2, 0, 2, 2, 0, 0, 0, 1, 0, 3, 1, 5, 1, 2, 4, 1, 0, 1, 0, 1, 0, 1, 0, 2, 2, 0, 0, 1, 0, 1, 1, 4, 1, 0, 1, 1, 0, 4, 2, 0, 1, 1, 2, 3, 1, 1, 1, 1, 6, 2, 1, 1, 0, 2, 0, 6, 2, 0, 4, 2, 2, 0, 0, 1, 2, 0, 2, 1, 0, 3, 1, 2, 1, 4, 6, 3, 2, 1, 0, 2, 2, 0, 0, 5, 4, 1, 0, 0, 1, 0, 2, 2, 0, 0, 2, 3, 1, 3, 1, 1, 0, 1, 0, 0, 1, 2, 2, 0, 2, 0, 0, 1, 2, 0, 0, 4, 1, 0, 1, 1, 0, 1, 2, 0, 1, 4, 3, 1, 2, 2, 1, 1, 1, 1, 6, 3, 3, 3, 3, 1, 1, 1, 1, 1, 0, 7, 3, 0, 1, 3, 2, 1, 0, 3, 2, 1, 0, 2, 2, 6, 0, 0, 6, 2, 2, 3, 3, 5, 5, 1, 0, 6, 1, 0, 3, 1, 1, 2, 3, 1, 2, 1, 1, 0, 1, 0, 1, 0, 5, 5, 2, 2, 0, 0, 1, 0, 0, 0, 0, 1, 1, 1, 1]53415342The bug reported at #4897 is now fixed::53435344sage: [P[0] for P in EllipticCurve([0,0,0,-468,2592]).integral_points()]5345[-24, -18, -14, -6, -3, 4, 6, 18, 21, 24, 36, 46, 102, 168, 186, 381, 1476, 2034, 67246]53465347.. note::53485349This function uses the algorithm given in [Co1].53505351REFERENCES:53525353- [Co1] Cohen H., Number Theory Vol I: Tools and Diophantine5354Equations GTM 239, Springer 200753555356AUTHORS:53575358- Michael Mardaus (2008-07)53595360- Tobias Nagel (2008-07)53615362- John Cremona (2008-07)5363"""5364#####################################################################5365# INPUT CHECK #######################################################5366if not self.is_integral():5367raise ValueError, "integral_points() can only be called on an integral model"53685369if mw_base=='auto':5370mw_base = self.gens()5371r = len(mw_base)5372else:5373try:5374r = len(mw_base)5375except TypeError:5376raise TypeError, 'mw_base must be a list'5377if not all([P.curve() is self for P in mw_base]):5378raise ValueError, "points are not on the correct curve"53795380tors_points = self.torsion_points()53815382# END INPUT-CHECK####################################################5383#####################################################################53845385#####################################################################5386# INTERNAL FUNCTIONS ################################################53875388############################## begin ################################5389def point_preprocessing(free,tor):5390r"""5391Transforms the mw_basis ``free`` into a `\ZZ`-basis for5392`E(\QQ)\cap E^0(`\RR)`. If there is a torsion point on the5393"egg" we add it to any of the gens on the egg; otherwise5394we replace the free generators with generators of a5395subgroup of index 2.5396"""5397r = len(free)5398newfree = [Q for Q in free] # copy5399tor_egg = [T for T in tor if not T.is_on_identity_component()]5400free_id = [P.is_on_identity_component() for P in free]5401if any(tor_egg):5402T = tor_egg[0]5403for i in range(r):5404if not free_id[i]:5405newfree[i] += T5406else:5407if not all(free_id):5408i0 = free_id.index(False)5409P = free[i0]5410for i in range(r):5411if not free_id[i]:5412if i==i0:5413newfree[i] = 2*newfree[i]5414else:5415newfree[i] += P5416return newfree5417############################## end ################################54185419# END Internal functions #############################################5420######################################################################54215422if (r == 0):5423int_points = [P for P in tors_points if not P.is_zero()]5424int_points = [P for P in int_points if P[0].is_integral()]5425if not both_signs:5426xlist = set([P[0] for P in int_points])5427int_points = [self.lift_x(x) for x in xlist]5428int_points.sort()5429if verbose:5430print 'Total number of integral points:',len(int_points)5431return int_points54325433if verbose:5434import sys # so we can flush stdout for debugging54355436g2 = self.c4()/125437g3 = self.c6()/2165438disc = self.discriminant()5439j = self.j_invariant()5440b2 = self.b2()54415442Qx = rings.PolynomialRing(RationalField(),'x')5443pol = Qx([-self.c6()/216,-self.c4()/12,0,4])5444if disc > 0: # two real component -> 3 roots in RR5445#on curve 897e4, only one root is found with default precision!5446RR = R5447prec = RR.precision()5448ei = pol.roots(RR,multiplicities=False)5449while len(ei)<3:5450prec*=25451RR=RealField(prec)5452ei = pol.roots(RR,multiplicities=False)5453e1,e2,e3 = ei5454if r >= 1: #preprocessing of mw_base only necessary if rank > 05455mw_base = point_preprocessing(mw_base, tors_points)5456#at most one point in E^{egg}54575458elif disc < 0: # one real component => 1 root in RR (=: e3),5459# 2 roots in C (e1,e2)5460roots = pol.roots(C,multiplicities=False)5461e3 = pol.roots(R,multiplicities=False)[0]5462roots.remove(e3)5463e1,e2 = roots54645465from sage.all import pi5466e = R(1).exp()5467pi = R(pi)54685469M = self.height_pairing_matrix(mw_base)5470mw_base, U = self.lll_reduce(mw_base,M)5471M = U.transpose()*M*U54725473if verbose:5474print "Using mw_basis ",mw_base5475print "e1,e2,e3: ",e1,e2,e35476sys.stdout.flush()54775478# Algorithm presented in [Co1]5479h_E = self.height()5480w1, w2 = self.period_lattice().basis()5481mu = R(disc).abs().log() / 65482if j!=0:5483mu += max(R(1),R(j).abs().log()) / 65484if b2!=0:5485mu += max(R(1),R(b2).abs().log())5486mu += log(R(2))5487else:5488mu += 154895490c1 = (mu + 2.14).exp()5491c2 = min(M.charpoly ().roots(multiplicities=False))5492if verbose:5493print "Minimal eigenvalue of height pairing matrix: ", c25494sys.stdout.flush()54955496c3 = (w1**2)*R(b2).abs()/48 + 85497c5 = (c1*c3).sqrt()5498c7 = abs((3*pi)/((w1**2) * (w1/w2).imag()))54995500mw_base_log = [] #contains \Phi(Q_i)5501mod_h_list = [] #contains h_m(Q_i)5502c9_help_list = []5503for i in range(0,r):5504mw_base_log.append(mw_base[i].elliptic_logarithm().abs())5505mod_h_list.append(max(mw_base[i].height(),h_E,c7*mw_base_log[i]**2))5506c9_help_list.append((mod_h_list[i]).sqrt()/mw_base_log[i])5507c8 = max(e*h_E,max(mod_h_list))5508c9 = e/c7.sqrt() * min(c9_help_list)5509n=r+15510c10 = R(2 * 10**(8+7*n) * R((2/e)**(2 * n**2)) * (n+1)**(4 * n**2 + 10 * n) * log(c9)**(-2*n - 1) * misc.prod(mod_h_list))55115512top = Z(128) #arbitrary first upper bound5513bottom = Z(0)5514log_c9=log(c9); log_c5=log(c5)5515log_r_top = log(R(r*(10**top)))5516# if verbose:5517# print "[bottom,top] = ",[bottom,top]55185519while R(c10*(log_r_top+log_c9)*(log(log_r_top)+h_E+log_c9)**(n+1)) > R(c2/2 * (10**top)**2 - log_c5):5520#initial bound 'top' too small, upshift of search interval5521bottom = top5522top = 2*top5523while top >= bottom: #binary-search like search for fitting exponent (bound)5524# if verbose:5525# print "[bottom,top] = ",[bottom,top]5526bound = (bottom + (top - bottom)/2).floor()5527log_r_bound = log(R(r*(10**bound)))5528if R(c10*(log_r_bound+log_c9)*(log(log_r_bound)+h_E+log_c9)**(n+1)) > R(c2/2 * (10**bound)**2 - log_c5):5529bottom = bound + 15530else:5531top = bound - 155325533H_q = R(10)**bound5534break_cond = 0 #at least one reduction step5535#reduction via LLL5536M = matrix.MatrixSpace(Z,n)5537while break_cond < 0.9: #as long as the improvement of the new bound in comparison to the old is greater than 10%5538c = R((H_q**n)*10) #c has to be greater than H_q^n5539m = copy(M.identity_matrix())5540for i in range(r):5541m[i, r] = R(c*mw_base_log[i]).round()5542m[r,r] = max(Z(1),R(c*w1).round()) #ensures that m isn't singular55435544#LLL - implemented in sage - operates on rows not on columns5545m_LLL = m.LLL()5546m_gram = m_LLL.gram_schmidt()[0]5547b1_norm = R(m_LLL.row(0).norm())55485549#compute constant c1 ~ c1_LLL of Corollary 2.3.17 and hence d(L,0)^2 ~ d_L_05550c1_LLL = -15551for i in range(n):5552tmp = R(b1_norm/(m_gram.row(i).norm()))5553if tmp > c1_LLL:5554c1_LLL = tmp55555556if c1_LLL < 0:5557raise RuntimeError, 'Unexpected intermediate result. Please try another Mordell-Weil base'55585559d_L_0 = R(b1_norm**2 / c1_LLL)55605561#Reducing of upper bound5562Q = r * H_q**25563T = (1 + (3/2*r*H_q))/25564if d_L_0 < R(T**2+Q):5565d_L_0 = 10*(T**2*Q)5566low_bound = R(((d_L_0 - Q).sqrt() - T)/c)55675568#new bound according to low_bound and upper bound5569#[c_5 exp((-c_2*H_q^2)/2)] provided by Corollary 8.7.35570if low_bound != 0:5571H_q_new = R((log(low_bound/c5)/(-c2/2))).sqrt()5572H_q_new = H_q_new.ceil()5573if H_q_new == 1:5574break_cond = 1 # stops reduction5575else:5576break_cond = R(H_q_new/H_q)5577H_q = H_q_new5578else:5579break_cond = 1 # stops reduction, so using last H_q > 05580#END LLL-Reduction loop55815582b2_12 = b2/125583if disc > 0:5584##Points in egg have X(P) between e1 and e2 [X(P)=x(P)+b2/12]:5585x_int_points = self.integral_x_coords_in_interval((e1-b2_12).ceil(), (e2-b2_12).floor())5586if verbose:5587print 'x-coords of points on compact component with ',(e1-b2_12).ceil(),'<=x<=',(e2-b2_12).floor()5588L = list(x_int_points) # to have the order5589L.sort() # deterministic for doctests!5590print L5591sys.stdout.flush()5592else:5593x_int_points = set()55945595##Points in noncompact component with X(P)< 2*max(|e1|,|e2|,|e3|) , espec. X(P)>=e35596x0 = (e3-b2_12).ceil()5597x1 = (2*max(abs(e1),abs(e2),abs(e3)) - b2_12).ceil()5598x_int_points2 = self.integral_x_coords_in_interval(x0, x1)5599x_int_points = x_int_points.union(x_int_points2)5600if verbose:5601print 'x-coords of points on non-compact component with ',x0,'<=x<=',x1-15602L = list(x_int_points2)5603L.sort()5604print L5605sys.stdout.flush()56065607if verbose:5608print 'starting search of remaining points using coefficient bound ',H_q5609sys.stdout.flush()5610x_int_points3 = integral_points_with_bounded_mw_coeffs(self,mw_base,H_q)5611x_int_points = x_int_points.union(x_int_points3)5612if verbose:5613print 'x-coords of extra integral points:'5614L = list(x_int_points3)5615L.sort()5616print L5617sys.stdout.flush()56185619if len(tors_points)>1:5620x_int_points_t = set()5621for x in x_int_points:5622P = self.lift_x(x)5623for T in tors_points:5624Q = P+T5625if not Q.is_zero() and Q[0].is_integral():5626x_int_points_t = x_int_points_t.union([Q[0]])5627x_int_points = x_int_points.union(x_int_points_t)56285629# Now we have all the x-coordinates of integral points, and we5630# construct the points, depending on the parameter both_signs:5631if both_signs:5632int_points = sum([self.lift_x(x,all=True) for x in x_int_points],[])5633else:5634int_points = [self.lift_x(x) for x in x_int_points]5635int_points.sort()5636if verbose:5637print 'Total number of integral points:',len(int_points)5638return int_points56395640def S_integral_points(self, S, mw_base='auto', both_signs=False, verbose=False, proof=None):5641"""5642Computes all S-integral points (up to sign) on this elliptic curve.56435644INPUT:56455646- ``S`` - list of primes56475648- ``mw_base`` - list of EllipticCurvePoint generating the5649Mordell-Weil group of E (default: 'auto' - calls5650:meth:`.gens`)56515652- ``both_signs`` - True/False (default False): if True the5653output contains both P and -P, otherwise only one of each5654pair.56555656- ``verbose`` - True/False (default False): if True, some5657details of the computation are output.56585659- ``proof`` - True/False (default True): if True ALL5660S-integral points will be returned. If False, the MW basis5661will be computed with the proof=False flag, and also the5662time-consuming final call to5663S_integral_x_coords_with_abs_bounded_by(abs_bound) is5664omitted. Use this only if the computation takes too long,5665but be warned that then it cannot be guaranteed that all5666S-integral points will be found.56675668OUTPUT:56695670A sorted list of all the S-integral points on E (up to sign5671unless both_signs is True)56725673.. note::56745675The complexity increases exponentially in the rank of curve5676E and in the length of S. The computation time (but not5677the output!) depends on the Mordell-Weil basis. If mw_base5678is given but is not a basis for the Mordell-Weil group5679(modulo torsion), S-integral points which are not in the5680subgroup generated by the given points will almost5681certainly not be listed.56825683EXAMPLES:56845685A curve of rank 3 with no torsion points::56865687sage: E=EllipticCurve([0,0,1,-7,6])5688sage: P1=E.point((2,0)); P2=E.point((-1,3)); P3=E.point((4,6))5689sage: a=E.S_integral_points(S=[2,3], mw_base=[P1,P2,P3], verbose=True);a5690max_S: 3 len_S: 3 len_tors: 15691lambda 0.485997517468...5692k1,k2,k3,k4 6.68597129142710e234 1.31952866480763 3.31908110593519e9 2.42767548272846e175693p= 2 : trying with p_prec = 305694mw_base_p_log_val = [2, 2, 1]5695min_psi = 2 + 2^3 + 2^6 + 2^7 + 2^8 + 2^9 + 2^11 + 2^12 + 2^13 + 2^16 + 2^17 + 2^19 + 2^20 + 2^21 + 2^23 + 2^24 + 2^28 + O(2^30)5696p= 3 : trying with p_prec = 305697mw_base_p_log_val = [1, 2, 1]5698min_psi = 3 + 3^2 + 2*3^3 + 3^6 + 2*3^7 + 2*3^8 + 3^9 + 2*3^11 + 2*3^12 + 2*3^13 + 3^15 + 2*3^16 + 3^18 + 2*3^19 + 2*3^22 + 2*3^23 + 2*3^24 + 2*3^27 + 3^28 + 3^29 + O(3^30)5699mw_base [(1 : -1 : 1), (2 : 0 : 1), (0 : -3 : 1)]5700mw_base_log [0.667789378224099, 0.552642660712417, 0.818477222895703]5701mp [5, 7]5702mw_base_p_log [[2^2 + 2^3 + 2^6 + 2^7 + 2^8 + 2^9 + 2^14 + 2^15 + 2^18 + 2^19 + 2^24 + 2^29 + O(2^30), 2^2 + 2^3 + 2^5 + 2^6 + 2^9 + 2^11 + 2^12 + 2^14 + 2^15 + 2^16 + 2^18 + 2^20 + 2^22 + 2^23 + 2^26 + 2^27 + 2^29 + O(2^30), 2 + 2^3 + 2^6 + 2^7 + 2^8 + 2^9 + 2^11 + 2^12 + 2^13 + 2^16 + 2^17 + 2^19 + 2^20 + 2^21 + 2^23 + 2^24 + 2^28 + O(2^30)], [2*3^2 + 2*3^5 + 2*3^6 + 2*3^7 + 3^8 + 3^9 + 2*3^10 + 3^12 + 2*3^14 + 3^15 + 3^17 + 2*3^19 + 2*3^23 + 3^25 + 3^28 + O(3^30), 2*3 + 2*3^2 + 2*3^3 + 2*3^4 + 2*3^6 + 2*3^7 + 2*3^8 + 3^10 + 2*3^12 + 3^13 + 2*3^14 + 3^15 + 3^18 + 3^22 + 3^25 + 2*3^26 + 3^27 + 3^28 + O(3^30), 3 + 3^2 + 2*3^3 + 3^6 + 2*3^7 + 2*3^8 + 3^9 + 2*3^11 + 2*3^12 + 2*3^13 + 3^15 + 2*3^16 + 3^18 + 2*3^19 + 2*3^22 + 2*3^23 + 2*3^24 + 2*3^27 + 3^28 + 3^29 + O(3^30)]]5703k5,k6,k7 0.321154513240... 1.55246328915... 0.161999172489...5704initial bound 2.6227097483365...e1175705bound_list [58, 58, 58]5706bound_list [8, 9, 9]5707bound_list [8, 7, 7]5708bound_list [8, 7, 7]5709starting search of points using coefficient bound 85710x-coords of S-integral points via linear combination of mw_base and torsion:5711[-3, -26/9, -8159/2916, -2759/1024, -151/64, -1343/576, -2, -7/4, -1, -47/256, 0, 1/4, 4/9, 9/16, 58/81, 7/9, 6169/6561, 1, 17/16, 2, 33/16, 172/81, 9/4, 25/9, 3, 31/9, 4, 25/4, 1793/256, 8, 625/64, 11, 14, 21, 37, 52, 6142/81, 93, 4537/36, 342, 406, 816, 207331217/4096]5712starting search of extra S-integer points with absolute value bounded by 3.893219649794205713x-coords of points with bounded absolute value5714[-3, -2, -1, 0, 1, 2]5715Total number of S-integral points: 435716[(-3 : 0 : 1), (-26/9 : 28/27 : 1), (-8159/2916 : 233461/157464 : 1), (-2759/1024 : 60819/32768 : 1), (-151/64 : 1333/512 : 1), (-1343/576 : 36575/13824 : 1), (-2 : 3 : 1), (-7/4 : 25/8 : 1), (-1 : 3 : 1), (-47/256 : 9191/4096 : 1), (0 : 2 : 1), (1/4 : 13/8 : 1), (4/9 : 35/27 : 1), (9/16 : 69/64 : 1), (58/81 : 559/729 : 1), (7/9 : 17/27 : 1), (6169/6561 : 109871/531441 : 1), (1 : 0 : 1), (17/16 : -25/64 : 1), (2 : 0 : 1), (33/16 : 17/64 : 1), (172/81 : 350/729 : 1), (9/4 : 7/8 : 1), (25/9 : 64/27 : 1), (3 : 3 : 1), (31/9 : 116/27 : 1), (4 : 6 : 1), (25/4 : 111/8 : 1), (1793/256 : 68991/4096 : 1), (8 : 21 : 1), (625/64 : 14839/512 : 1), (11 : 35 : 1), (14 : 51 : 1), (21 : 95 : 1), (37 : 224 : 1), (52 : 374 : 1), (6142/81 : 480700/729 : 1), (93 : 896 : 1), (4537/36 : 305425/216 : 1), (342 : 6324 : 1), (406 : 8180 : 1), (816 : 23309 : 1), (207331217/4096 : 2985362173625/262144 : 1)]57175718It is not necessary to specify mw_base; if it is not provided,5719then the Mordell-Weil basis must be computed, which may take5720much longer.57215722::57235724sage: a = E.S_integral_points([2,3])5725sage: len(a)57264357275728An example with negative discriminant::57295730sage: EllipticCurve('900d1').S_integral_points([17], both_signs=True)5731[(-11 : -27 : 1), (-11 : 27 : 1), (-4 : -34 : 1), (-4 : 34 : 1), (4 : -18 : 1), (4 : 18 : 1), (2636/289 : -98786/4913 : 1), (2636/289 : 98786/4913 : 1), (16 : -54 : 1), (16 : 54 : 1)]57325733Output checked with Magma (corrected in 3 cases)::57345735sage: [len(e.S_integral_points([2], both_signs=False)) for e in cremona_curves([11..100])] # long time (17s on sage.math, 2011)5736[2, 0, 2, 3, 3, 1, 3, 1, 3, 5, 3, 5, 4, 1, 1, 2, 2, 2, 3, 1, 2, 1, 0, 1, 3, 3, 1, 1, 5, 3, 4, 2, 1, 1, 5, 3, 2, 2, 1, 1, 1, 0, 1, 3, 0, 1, 0, 1, 1, 3, 7, 1, 3, 3, 3, 1, 1, 2, 3, 1, 2, 3, 1, 2, 1, 3, 3, 1, 1, 1, 0, 1, 3, 3, 1, 1, 7, 1, 0, 1, 1, 0, 1, 2, 0, 3, 1, 2, 1, 3, 1, 2, 2, 4, 5, 3, 2, 1, 1, 6, 1, 0, 1, 3, 1, 3, 3, 1, 1, 1, 1, 1, 3, 1, 5, 1, 2, 4, 1, 1, 1, 1, 1, 0, 1, 0, 2, 2, 0, 0, 1, 0, 1, 1, 6, 1, 0, 1, 1, 0, 4, 3, 1, 2, 1, 2, 3, 1, 1, 1, 1, 8, 3, 1, 2, 1, 2, 0, 8, 2, 0, 6, 2, 3, 1, 1, 1, 3, 1, 3, 2, 1, 3, 1, 2, 1, 6, 9, 3, 3, 1, 1, 2, 3, 1, 1, 5, 5, 1, 1, 0, 1, 1, 2, 3, 1, 1, 2, 3, 1, 3, 1, 1, 1, 1, 0, 0, 1, 3, 3, 1, 3, 1, 1, 2, 2, 0, 0, 6, 1, 0, 1, 1, 1, 1, 3, 1, 2, 6, 3, 1, 2, 2, 1, 1, 1, 1, 7, 5, 4, 3, 3, 1, 1, 1, 1, 1, 1, 8, 5, 1, 1, 3, 3, 1, 1, 3, 3, 1, 1, 2, 3, 6, 1, 1, 7, 3, 3, 4, 5, 9, 6, 1, 0, 7, 1, 1, 3, 1, 1, 2, 3, 1, 2, 1, 1, 1, 1, 1, 1, 1, 7, 8, 2, 3, 1, 1, 1, 1, 0, 0, 0, 1, 1, 1, 1]57375738An example from [PZGH]::57395740sage: E = EllipticCurve([0,0,0,-172,505])5741sage: E.rank(), len(E.S_integral_points([3,5,7])) # long time (5s on sage.math, 2011)5742(4, 72)57435744This is curve "7690e1" which failed until \#4805 was fixed::57455746sage: EllipticCurve([1,1,1,-301,-1821]).S_integral_points([13,2])5747[(-13 : 16 : 1),5748(-9 : 20 : 1),5749(-7 : 4 : 1),5750(21 : 30 : 1),5751(23 : 52 : 1),5752(63 : 452 : 1),5753(71 : 548 : 1),5754(87 : 756 : 1),5755(2711 : 139828 : 1),5756(7323 : 623052 : 1),5757(17687 : 2343476 : 1)]57585759REFERENCES:57605761- [PZGH] Petho A., Zimmer H.G., Gebel J. and Herrmann E.,5762Computing all S-integral points on elliptic curves5763Math. Proc. Camb. Phil. Soc. (1999), 127, 383-40257645765- Some parts of this implementation are partially based on the5766function integral_points()57675768AUTHORS:57695770- Tobias Nagel (2008-12)57715772- Michael Mardaus (2008-12)57735774- John Cremona (2008-12)5775"""5776# INPUT CHECK #######################################################57775778if proof is None:5779from sage.structure.proof.proof import get_flag5780proof = get_flag(proof, "elliptic_curve")5781else:5782proof = bool(proof)578357845785if not self.is_integral():5786raise ValueError, "S_integral_points() can only be called on an integral model"5787if not all([self.is_p_minimal(s) for s in S]):5788raise ValueError, "%s must be p-minimal for all primes in S"%self57895790try:5791len_S = len(S)5792if len_S == 0:5793return self.integral_points(mw_base, both_signs, verbose)5794if not all([s.is_prime() for s in S]):5795raise ValueError, "All elements of S must be prime"5796S.sort()5797except TypeError:5798raise TypeError, 'S must be a list of primes'5799except AttributeError:#catches: <tuple>.sort(), <!ZZ>.is_prime()5800raise AttributeError,'S must be a list of primes'58015802if mw_base=='auto':5803if verbose:5804print "Starting computation of MW basis"5805mw_base = self.gens(proof=proof)5806r = len(mw_base)5807if verbose:5808print "Finished computation of MW basis; rank is ",r5809else:5810try:5811r = len(mw_base)5812except TypeError:5813raise TypeError, 'mw_base must be a list'5814if not all([P.curve() is self for P in mw_base]):5815raise ValueError, "mw_base-points are not on the correct curve"58165817#End Input-Check ######################################################58185819#Internal functions ###################################################5820def reduction_at(p):5821r"""5822Reducing the bound `H_q` at the finite place p in S via LLL5823"""5824indexp = S.index(p)5825pc = Z(p**(R(c.log()/log(p,e)).ceil()))5826m = copy(M.identity_matrix())5827for i in range(r):5828try:5829m[i, r] = Z((beta[indexp][i])%pc)5830except ZeroDivisionError: #If Inverse doesn't exist, change denominator (which is only approx)5831val_nu = (beta[indexp][i]).numerator()5832val_de = (beta[indexp][i]).denominator()5833m[i, r] = Z((val_nu/(val_de+1))%pc)5834m[r,r] = max(Z(1), pc)58355836#LLL - implemented in sage - operates on rows not on columns5837m_LLL = m.LLL()5838m_gram = m_LLL.gram_schmidt()[0]5839b1_norm = R(m_LLL.row(0).norm())58405841c1_LLL = -15842for i in range(n):5843tmp = R(b1_norm/(m_gram.row(i).norm()))5844if tmp > c1_LLL:5845c1_LLL = tmp5846if c1_LLL < 0:5847raise RuntimeError, 'Unexpected intermediate result. Please try another Mordell-Weil base'5848d_L_0 = R(b1_norm**2 / c1_LLL)58495850#Reducing of upper bound5851Q = r * H_q**25852T = (1 + (3/2*r*H_q))/25853if d_L_0 < R(T**2+Q):5854d_L_0 = 10*(T**2*Q)5855low_bound = R(((d_L_0 - Q).sqrt() - T)/c)58565857##new bound according to low_bound and upper bound5858##[k5*k6 exp(-k7**H_q^2)]5859if low_bound != 0:5860H_q_infinity = R(((low_bound/(k6)).log()/(-k7)).sqrt())5861return (H_q_infinity.ceil())5862else:5863return (H_q)5864#<-------------------------------------------------------------------------5865#>-------------------------------------------------------------------------5866def S_integral_points_with_bounded_mw_coeffs():5867r"""5868Returns the set of S-integers x which are x-coordinates of5869points on the curve which are linear combinations of the5870generators (basis and torsion points) with coefficients5871bounded by `H_q`. The bound `H_q` will be computed at5872runtime.5873(Modified version of integral_points_with_bounded_mw_coeffs() in5874integral_points() )58755876TODO: Make this more efficient. In the case ``S=[]`` we5877worked over the reals and only computed a combination5878exactly if the real coordinates were approximately5879integral. We need a version of this which works for5880S-integral points, probably by finding a bound on the5881denominator.5882"""5883from sage.groups.generic import multiples5884xs=set()5885N=H_q58865887def test(P):5888"""5889Record x-coord of a point if S-integral.5890"""5891if not P.is_zero():5892xP = P[0]5893if xP.is_S_integral(S):5894xs.add(xP)58955896def test_with_T(R):5897"""5898Record x-coords of a 'point+torsion' if S-integral.5899"""5900for T in tors_points:5901test(R+T)59025903# For small rank and small H_q perform simple search5904if r==1 and N<=10:5905for P in multiples(mw_base[0],N+1):5906test_with_T(P)5907return xs59085909# explicit computation and testing linear combinations5910# ni loops through all tuples (n_1,...,n_r) with |n_i| <= N5911# stops when (0,0,...,0) is reached because after that, only inverse points of5912# previously tested points would be tested59135914E0=E(0)5915ni = [-N for i in range(r)]5916mw_baseN = [-N*P for P in mw_base]5917Pi = [0 for j in range(r)]5918Pi[0] = mw_baseN[0]5919for i in range(1,r):5920Pi[i] = Pi[i-1] + mw_baseN[i]59215922while True:5923if all([n==0 for n in ni]):5924test_with_T(E0)5925break59265927# test the ni-combination which is Pi[r-1]5928test_with_T(Pi[r-1])59295930# increment indices and stored points5931i0 = r-15932while ni[i0]==N:5933ni[i0] = -N5934i0 -= 15935ni[i0] += 15936if all([n==0 for n in ni[0:i0+1]]):5937Pi[i0] = E05938else:5939Pi[i0] += mw_base[i0]5940for i in range(i0+1,r):5941Pi[i] = Pi[i-1] + mw_baseN[i]59425943return xs5944#<-------------------------------------------------------------------------5945#>-------------------------------------------------------------------------5946def S_integral_x_coords_with_abs_bounded_by(abs_bound):5947r"""5948Extra search of points with `|x|< ` abs_bound, assuming5949that `x` is `S`-integral and `|x|\ge|x|_q` for all primes5950`q` in `S`. (Such points are not covered by the main part5951of the code). We know59525953.. math::59545955x=\frac{\xi}{\p_1^{\alpha_1} \cdot \dots \cdot \p_s^{\alpha_s}},\ (gcd(\xi,\p_i)=1),\ p_i \in S59565957so a bound of `\alpha_i` can be found in terms of5958abs_bound. Additionally each `\alpha` must be even, giving5959another restriction. This gives a finite list of5960denominators to test, and for each, a range of numerators.5961All candidates for `x` resulting from this theory are then5962tested, and a list of the ones which are `x`-coordinates5963of (`S`-integral) points is returned.59645965TODO: Make this more efficient. If we had an efficient5966function for searching for integral points (for example,5967by wrapping Stoll's ratpoint program) then it should be5968better to scale the equation by the maximum denominator5969and search for integral points on the scaled model.59705971"""5972x_min = min(self.two_division_polynomial().roots(R,multiplicities=False))5973x_min_neg = bool(x_min<0)5974x_min_pos = not x_min_neg5975log_ab = R(abs_bound.log())5976alpha = [(log_ab/R(log(p,e))).floor() for p in S]5977if all([alpha_i <= 1 for alpha_i in alpha]): # so alpha_i must be 0 to satisfy that denominator is a square5978return set([x for x in range(-abs_bound,abs_bound) if E.is_x_coord(x)])5979else:5980xs = []5981alpha_max_even = [y-y%2 for y in alpha]5982p_pow_alpha = []5983list_alpha = []5984for i in range(len_S-1):5985list_alpha.append(range(0,alpha_max_even[i]+2,2))5986p_pow_alpha.append([S[i]**list_alpha[i][j] for j in range(len(list_alpha[i]))])5987if verbose:5988print list_alpha, p_pow_alpha5989# denom_maxpa is a list of pairs (d,q) where d runs5990# through possible denominators, and q=p^a is the5991# maximum prime power divisor of d:5992denom_maxpa = [(misc.prod(tmp),max(tmp)) for tmp in cartesian_product_iterator(p_pow_alpha)]5993# The maximum denominator is this (not used):5994# denom = [misc.prod([pp[-1] for pp in p_pow_alpha],1)]5995for de,maxpa in denom_maxpa:5996n_max = (abs_bound*de).ceil()5997n_min = maxpa*de5998if x_min_pos:5999pos_n_only = True6000if x_min > maxpa:6001n_min = (x_min*de).floor()6002else:6003pos_n_only = False6004neg_n_max = (x_min.abs()*de).ceil()60056006# if verbose:6007# print "testing denominator ",de6008# print "numerator bounds = ",(n_min,n_max)60096010for n in misc.xsrange(n_min,n_max+1):6011tmp = n/de # to save time, do not check de is the exact denominator6012if E.is_x_coord(tmp):6013xs+=[tmp]6014if not pos_n_only:6015if n <= neg_n_max:6016if E.is_x_coord(-tmp):6017xs+=[-tmp]60186019return set(xs)6020#<-------------------------------------------------------------------------6021#End internal functions ###############################################6022from sage.misc.all import cartesian_product_iterator60236024E = self6025tors_points = E.torsion_points()60266027if (r==0):#only Torsionpoints to consider6028int_points = [P for P in tors_points if not P.is_zero()]6029int_points = [P for P in int_points if P[0].is_S_integral(S)]6030if not both_signs:6031xlist = set([P[0] for P in int_points])6032int_points = [E.lift_x(x) for x in xlist]6033int_points.sort()6034if verbose:6035print 'Total number of S-integral points:',len(int_points)6036return int_points60376038if verbose:6039import sys # so we can flush stdout for debugging60406041e = R(1).exp()6042a1, a2, a3, a4, a6 = E.a_invariants()6043b2, b4, b6, b8 = E.b_invariants()6044c4, c6 = E.c_invariants()6045disc = E.discriminant()6046#internal function is doing only a comparison of E and E.short_weierstass_model() so the following is easier6047if a1 == a2 == a3 == 0:6048is_short = True6049else:6050is_short = False60516052w1, w2 = E.period_lattice().basis()60536054Qx = rings.PolynomialRing(RationalField(),'x')6055pol = Qx([-54*c6,-27*c4,0,1])6056if disc > 0: # two real component -> 3 roots in RR6057# it is possible that only one root is found with default precision! (see integral_points())6058RR = R6059prec = RR.precision()6060ei = pol.roots(RR,multiplicities=False)6061while len(ei)<3:6062prec*=26063RR=RealField(prec)6064ei = pol.roots(RR,multiplicities=False)6065e1,e2,e3 = ei6066elif disc < 0: # one real component => 1 root in RR (=: e3),6067# 2 roots in C (e1,e2)6068roots = pol.roots(C,multiplicities=False)6069e3 = pol.roots(R,multiplicities=False)[0]6070roots.remove(e3)6071e1,e2 = roots60726073len_tors = len(tors_points)6074n = r + 160756076M = E.height_pairing_matrix(mw_base)6077mw_base, U = E.lll_reduce(mw_base,M)6078M = U.transpose()*M*U60796080# NB "lambda" is a reserved word in Python!6081lamda = min(M.charpoly(algorithm="hessenberg").roots(multiplicities = False))6082max_S = max(S)6083len_S += 1 #Counting infinity (always "included" in S)6084if verbose:6085print 'max_S:',max_S,'len_S:',len_S,'len_tors:',len_tors6086print 'lambda',lamda6087sys.stdout.flush()60886089if is_short:6090disc_0_abs = R((4*a4**3 + 27*a6**2).abs())6091k4 = R(10**4 * max(16*a4**2, 256*disc_0_abs.sqrt()**3))6092k3 = R(32/3 * disc_0_abs.sqrt() * (8 + 0.5*disc_0_abs.log())**4)6093else:6094disc_sh = R(E.short_weierstrass_model().discriminant()) #computes y^2=x^3 -27c4x -54c66095k4 = R(20**4 * max(3**6 * c4**2, 16*(disc_sh.abs().sqrt())**3))6096k3 = R(32/3 * disc_sh.abs().sqrt() * (8 + 0.5*disc_sh.abs().log())**4)609760986099k2 = max(R(b2.abs()), R(b4.abs().sqrt()), R(b6.abs()**(1/3)), R(b8.abs()**(1/4))).log()6100k1 = R(7 * 10**(38*len_S+49)) * R(len_S**(20*len_S+15)) * max_S**24 * R(max(1,log(max_S, e))**(4*len_S - 2)) * k3 * k3.log()**2 * ((20*len_S - 19)*k3 + (e*k4).log()) + 2*R(2*b2.abs()+6).log()61016102if verbose:6103print 'k1,k2,k3,k4',k1,k2,k3,k46104sys.stdout.flush()6105#H_q -> [PZGH]:N_0 (due to consistency to integral_points())6106H_q = R(((k1/2+k2)/lamda).sqrt())61076108#computation of logs6109mw_base_log = [(pts.elliptic_logarithm().abs())*(len_tors/w1) for pts in mw_base]6110mw_base_p_log = []6111beta = []6112mp=[]6113tmp = 06114for p in S:6115Np = E.Np(p)6116cp = E.tamagawa_exponent(p)6117mp_temp = Z(len_tors).lcm(cp*Np)6118mp.append(mp_temp) #only necessary because of verbose below6119p_prec=30+E.discriminant().valuation(p)6120p_prec_ok=False6121while not p_prec_ok:6122if verbose:6123print "p=",p,": trying with p_prec = ",p_prec6124try:6125mw_base_p_log.append([mp_temp*(pts.padic_elliptic_logarithm(p,absprec=p_prec)) for pts in mw_base])6126p_prec_ok=True6127except ValueError:6128p_prec *= 26129#reorder mw_base_p: last value has minimal valuation at p6130mw_base_p_log_val = [mw_base_p_log[tmp][i].valuation() for i in range(r)]6131if verbose:6132print "mw_base_p_log_val = ",mw_base_p_log_val6133min_index = mw_base_p_log_val.index(min(mw_base_p_log_val))6134min_psi = mw_base_p_log[tmp][min_index]6135if verbose:6136print "min_psi = ",min_psi6137mw_base_p_log[tmp].remove(min_psi)6138mw_base_p_log[tmp].append(min_psi)6139#beta needed for reduction at p later on6140try:6141beta.append([-mw_base_p_log[tmp][j]/min_psi for j in range(r)])6142except ValueError:6143# e.g. mw_base_p_log[tmp]==[0]: can occur e.g. [?]'172c6, S=[2]6144beta.append([0] for j in range(r))6145tmp +=161466147if verbose:6148print 'mw_base',mw_base6149print 'mw_base_log', mw_base_log6150print 'mp', mp6151print 'mw_base_p_log',mw_base_p_log6152#print 'beta', beta6153sys.stdout.flush()61546155#constants in reduction (not needed to be computed every reduction step)6156k5 = R((2*len_tors)/(3*w1))6157k6 = R((k2/len_S).exp())6158k7 = R(lamda/len_S)61596160if verbose:6161print 'k5,k6,k7',k5,k6,k76162sys.stdout.flush()61636164break_cond = 06165M = matrix.MatrixSpace(Z,n)6166#Reduction of initial bound6167if verbose:6168print 'initial bound',H_q6169sys.stdout.flush()61706171while break_cond < 0.9:6172#reduction at infinity6173bound_list=[]6174c = R((H_q**n)*100)6175m = copy(M.identity_matrix())6176for i in range(r):6177m[i, r] = R(c*mw_base_log[i]).round()6178m[r,r] = max(Z(1), R(c*w1).round())6179#LLL - implemented in sage - operates on rows not on columns6180m_LLL = m.LLL()6181m_gram = m_LLL.gram_schmidt()[0]6182b1_norm = R(m_LLL.row(0).norm())61836184#compute constant c1_LLL (cf. integral_points())6185c1_LLL = -16186for i in range(n):6187tmp = R(b1_norm/(m_gram.row(i).norm()))6188if tmp > c1_LLL:6189c1_LLL = tmp6190if c1_LLL < 0:6191raise RuntimeError, 'Unexpected intermediate result. Please try another Mordell-Weil base'6192d_L_0 = R(b1_norm**2 / c1_LLL)61936194#Reducing of upper bound6195Q = r * H_q**26196T = (1 + (3/2*r*H_q))/26197if d_L_0 < R(T**2+Q):6198d_L_0 = 10*(T**2*Q)6199low_bound = R(((d_L_0 - Q).sqrt() - T)/c)62006201##new bound according to low_bound and upper bound6202##[k5*k6 exp(-k7**H_q^2)]6203if low_bound != 0:6204H_q_infinity = R(((low_bound/(k5*k6)).log()/(-k7)).abs().sqrt())6205bound_list.append(H_q_infinity.ceil())6206else:6207bound_list.append(H_q)62086209##reduction for finite places in S6210for p in S:6211bound_list.append(reduction_at(p))62126213if verbose:6214print 'bound_list',bound_list6215sys.stdout.flush()62166217H_q_new = max(bound_list)6218if (H_q_new > H_q): #no improvement6219break_cond = 1 #stop reduction6220elif (H_q_new == 1): #best possible H_q6221H_q = H_q_new6222break_cond = 1 #stop6223else:6224break_cond = R(H_q_new/H_q)6225H_q = H_q_new6226#end of reductions62276228#search of S-integral points6229#step1: via linear combination and H_q6230x_S_int_points = set()6231if verbose:6232print 'starting search of points using coefficient bound ',H_q6233sys.stdout.flush()6234x_S_int_points1 = S_integral_points_with_bounded_mw_coeffs()6235x_S_int_points = x_S_int_points.union(x_S_int_points1)6236if verbose:6237print 'x-coords of S-integral points via linear combination of mw_base and torsion:'6238L = list(x_S_int_points1)6239L.sort()6240print L6241sys.stdout.flush()62426243#step 2: Extra search6244if e3 < 0:6245M = R( max((27*c4).abs().sqrt(), R((54*c6).abs()**(1/3)) / R(2**(1/3))-1) )6246else:6247M = R(0)6248e0 = max(e1+e2, 2*e3) + M6249abs_bound = R((max(0,e0)+6*b2.abs())/36)62506251if proof:6252if verbose:6253print 'starting search of extra S-integer points with absolute value bounded by',abs_bound6254sys.stdout.flush()6255if abs_bound != 0:6256x_S_int_points2 = S_integral_x_coords_with_abs_bounded_by(abs_bound)6257x_S_int_points = x_S_int_points.union(x_S_int_points2)6258if verbose:6259print 'x-coords of points with bounded absolute value'6260L = list(x_S_int_points2)6261L.sort()6262print L6263sys.stdout.flush()62646265if len(tors_points)>1:6266x_S_int_points_t = set()6267for x in x_S_int_points:6268P = E.lift_x(x)6269for T in tors_points:6270Q = P+T6271if not Q.is_zero() and Q[0].is_S_integral(S):6272x_S_int_points_t = x_S_int_points_t.union([Q[0]])6273x_S_int_points = x_S_int_points.union(x_S_int_points_t)62746275# All x values collected, now considering "both_signs"6276if both_signs:6277S_int_points = sum([self.lift_x(x,all=True) for x in x_S_int_points],[])6278else:6279S_int_points = [self.lift_x(x) for x in x_S_int_points]6280S_int_points.sort()6281if verbose:6282print 'Total number of S-integral points:',len(S_int_points)6283return S_int_points628462856286def cremona_curves(conductors):6287"""6288Return iterator over all known curves (in database) with conductor6289in the list of conductors.62906291EXAMPLES::62926293sage: [(E.label(), E.rank()) for E in cremona_curves(srange(35,40))]6294[('35a1', 0),6295('35a2', 0),6296('35a3', 0),6297('36a1', 0),6298('36a2', 0),6299('36a3', 0),6300('36a4', 0),6301('37a1', 1),6302('37b1', 0),6303('37b2', 0),6304('37b3', 0),6305('38a1', 0),6306('38a2', 0),6307('38a3', 0),6308('38b1', 0),6309('38b2', 0),6310('39a1', 0),6311('39a2', 0),6312('39a3', 0),6313('39a4', 0)]6314"""6315if isinstance(conductors, (int,long, rings.RingElement)):6316conductors = [conductors]6317return sage.databases.cremona.CremonaDatabase().iter(conductors)63186319def cremona_optimal_curves(conductors):6320"""6321Return iterator over all known optimal curves (in database) with6322conductor in the list of conductors.63236324EXAMPLES::63256326sage: [(E.label(), E.rank()) for E in cremona_optimal_curves(srange(35,40))]6327[('35a1', 0),6328('36a1', 0),6329('37a1', 1),6330('37b1', 0),6331('38a1', 0),6332('38b1', 0),6333('39a1', 0)]63346335There is one case -- 990h3 -- when the optimal curve isn't labeled with a 1::63366337sage: [e.cremona_label() for e in cremona_optimal_curves([990])]6338['990a1', '990b1', '990c1', '990d1', '990e1', '990f1', '990g1', '990h3', '990i1', '990j1', '990k1', '990l1']63396340"""6341if isinstance(conductors, (int,long,rings.RingElement)):6342conductors = [conductors]6343return sage.databases.cremona.CremonaDatabase().iter_optimal(conductors)63446345def integral_points_with_bounded_mw_coeffs(E, mw_base, N):6346r"""6347Returns the set of integers `x` which are6348`x`-coordinates of points on the curve `E` which6349are linear combinations of the generators (basis and torsion6350points) with coefficients bounded by `N`.6351"""6352from sage.groups.generic import multiples6353xs=set()6354tors_points = E.torsion_points()6355r = len(mw_base)63566357def use(P):6358"""6359Helper function to record x-coord of a point if integral.6360"""6361if not P.is_zero():6362xP = P[0]6363if xP.is_integral():6364xs.add(xP)63656366def use_t(R):6367"""6368Helper function to record x-coords of a point +torsion if6369integral.6370"""6371for T in tors_points:6372use(R+T)63736374# We use a naive method when the number of possibilities is small:63756376if r==1 and N<=10:6377for P in multiples(mw_base[0],N+1):6378use_t(P)6379return xs63806381# Otherwise it is very very much faster to first compute6382# the linear combinations over RR, and only compute them as6383# rational points if they are approximately integral.63846385# Note: making eps larger here will dramatically increase6386# the running time. If evidence arises that integral6387# points are being missed, it would be better to increase6388# the real precision than to increase eps.63896390def is_approx_integral(P):6391r"""6392Local function, returns True if the real point `P` is approximately integral.6393"""6394eps = 0.00016395return (abs(P[0]-P[0].round()))<eps and (abs(P[1]-P[1].round()))<eps63966397RR = RealField(100) #(100)6398ER = E.change_ring(RR)6399ER0 = ER(0)64006401# Note: doing [ER(P) for P in mw_base] sometimes fails. The6402# following way is harder, since we have to make sure we don't use6403# -P instead of P, but is safer.64046405Rgens = [ER.lift_x(P[0]) for P in mw_base]6406for i in range(r):6407if abs(Rgens[i][1]-mw_base[i][1])>abs((-Rgens[i])[1]-mw_base[i][1]):6408Rgens[i] = -Rgens[i]64096410# the ni loop through all tuples (a1,a2,...,ar) with6411# |ai|<=N, but we stop immediately after using the tuple6412# (0,0,...,0).64136414# Initialization:6415ni = [-N for i in range(r)]6416RgensN = [-N*P for P in Rgens]6417# RPi[i] = -N*(Rgens[0]+...+Rgens[i])6418RPi = [0 for j in range(r)]6419RPi[0] = RgensN[0]6420for i in range(1,r):6421RPi[i] = RPi[i-1] + RgensN[i]64226423tors_points_R = map(ER, tors_points)6424while True:6425if all([n==0 for n in ni]):6426use_t(E(0))6427break64286429# test the ni-combination which is RPi[r-1]6430RP = RPi[r-1]64316432for T, TR in zip(tors_points, tors_points_R):6433if is_approx_integral(RP + TR):6434P = sum([ni[i]*mw_base[i] for i in range(r)],T)6435use(P)64366437# increment indices and stored points6438i0 = r-16439while ni[i0]==N:6440ni[i0] = -N6441i0 -= 16442ni[i0] += 16443# The next lines are to prevent rounding error: (-P)+P behaves6444# badly for real points!6445if all([n==0 for n in ni[0:i0+1]]):6446RPi[i0] = ER06447else:6448RPi[i0] += Rgens[i0]6449for i in range(i0+1,r):6450RPi[i] = RPi[i-1] + RgensN[i]64516452return xs6453645464556456