Ticket #3674: sage-trac3674c.2.patch
| File sage-trac3674c.2.patch, 19.2 kB (added by cremona, 4 months ago) |
|---|
-
a/sage/schemes/elliptic_curves/ell_point.py
old new 54 54 # http://www.gnu.org/licenses/ 55 55 #***************************************************************************** 56 56 57 from math import ceil, floor, sqrt58 57 from sage.structure.element import AdditiveGroupElement, RingElement 59 58 60 59 import sage.plot.all as plot … … 867 866 y = lam*(x-x3)-y-a1*x3-a3 868 867 x = x3 869 868 c = (x - e3).sqrt() 870 while (a -b)/a > 0.5**precision:869 while (a - b)/a > 0.5**(precision-1): 871 870 a,b,c = (a + b)/2, (a*b).sqrt(), (c + (c**2 + b**2 - a**2).sqrt())/2 872 871 873 872 z = (a/c).arcsin()/a -
a/sage/schemes/elliptic_curves/ell_rational_field.py
old new 12 12 -- David Roe (2007-9): moved sha, l-series and p-adic functionality to separate files. 13 13 -- John Cremona (2008-01) 14 14 -- Tobias Nagel & Michael Mardaus (2008-07): added integral_points 15 -- John Cremona (2008-07): further work on integral_points 15 16 """ 16 17 17 18 #***************************************************************************** … … 56 57 import sage.databases.cremona 57 58 from sage.libs.pari.all import pari 58 59 import sage.functions.transcendental as transcendental 59 import math 60 from sage.calculus.calculus import sqrt, arcsin, floor, ceil 60 from sage.calculus.calculus import sqrt, floor, ceil 61 61 import sage.libs.mwrank.all as mwrank 62 62 import constructor 63 63 from sage.interfaces.all import gp … … 86 86 import ell_tate_curve 87 87 88 88 factor = arith.factor 89 exp = math.exp90 89 mul = misc.mul 91 90 next_prime = arith.next_prime 92 91 kronecker_symbol = arith.kronecker_symbol … … 2352 2351 self.__torsion_order = self.torsion_subgroup().order() 2353 2352 return self.__torsion_order 2354 2353 2355 def torsion_subgroup(self, flag=0):2354 def torsion_subgroup(self, algorithm="pari"): 2356 2355 """ 2357 2356 Returns the torsion subgroup of this elliptic curve. 2358 2357 2359 2358 INPUT: 2360 flag -- (default: 0) chooses PARI algorithm: 2361 flag = 0: uses Doud algorithm 2362 flag = 1: uses Lutz-Nagell algorithm 2359 algorithm -- string: 2360 "pari" -- (default) use the pari library 2361 "doud" -- use Doud's algorithm 2362 "lutz_nagell" -- use the Lutz-Nagell theorem 2363 2363 2364 2364 OUTPUT: 2365 2365 The EllipticCurveTorsionSubgroup instance associated to this elliptic curve. … … 2390 2390 try: 2391 2391 return self.__torsion_subgroup 2392 2392 except AttributeError: 2393 self.__torsion_subgroup = rational_torsion.EllipticCurveTorsionSubgroup(self, flag)2393 self.__torsion_subgroup = rational_torsion.EllipticCurveTorsionSubgroup(self, algorithm) 2394 2394 self.__torsion_order = self.__torsion_subgroup.order() 2395 2395 return self.__torsion_subgroup 2396 2396 2397 def torsion_points(self, flag=0):2397 def torsion_points(self, algorithm="pari"): 2398 2398 """ 2399 2399 Returns the torsion points of this elliptic curve as a sorted list. 2400 2400 2401 2401 INPUT: 2402 flag -- (default: 0) chooses PARI algorithm: 2403 flag = 0: uses Doud algorithm 2404 flag = 1: uses Lutz-Nagell algorithm 2402 algorithm -- string: 2403 "pari" -- (default) use the pari library 2404 "doud" -- use Doud's algorithm 2405 "lutz_nagell" -- use the Lutz-Nagell theorem 2405 2406 2406 2407 OUTPUT: 2407 2408 A list of all the torsion points on this elliptic curve. … … 2413 2414 [(0 : 1 : 0), (8 : -19 : 1), (8 : 18 : 1)] 2414 2415 2415 2416 sage: E=EllipticCurve([-1386747,368636886]) 2416 sage: E.torsion_subgroup()2417 sage: T=E.torsion_subgroup(); T 2417 2418 Torsion Subgroup isomorphic to Multiplicative Abelian Group isomorphic to C8 x C2 associated to the Elliptic Curve defined by y^2 = x^3 - 1386747*x + 368636886 over Rational Field 2419 sage: T == E.torsion_subgroup(algorithm="doud") 2420 True 2421 sage: T == E.torsion_subgroup(algorithm="lutz_nagell") 2422 True 2418 2423 sage: E.torsion_points() 2419 2424 [(-1293 : 0 : 1), 2420 2425 (-933 : -29160 : 1), … … 2434 2439 (8787 : 816480 : 1)] 2435 2440 """ 2436 2441 multiples = sage.groups.generic.multiples 2437 gens = self.torsion_subgroup( flag).gens()2442 gens = self.torsion_subgroup(algorithm).gens() 2438 2443 ngens = len(gens) 2439 2444 if ngens == 0: 2440 2445 return [self(0)] … … 3478 3483 we return v = -1. 3479 3484 3480 3485 INPUT: 3481 D (int) -- (de ault: 0) Heegner discriminant; if 0, use the3486 D (int) -- (default: 0) Heegner discriminant; if 0, use the 3482 3487 first discriminant < -4 that satisfies the Heegner 3483 3488 hypothesis 3484 3489 verbose (bool) -- (default: True) … … 3660 3665 return Eq 3661 3666 3662 3667 def height(self, precision=53): 3663 """Returns real height of this elliptic curve 3668 """ 3669 Returns the real height of this elliptic curve. 3664 3670 This is used in integral_points() 3665 3671 3666 3672 3667 INPUT: precision (integer) bit precision of the field of real 3668 numbers in which the result will lie (default: 53 as in 3669 RealField()) 3673 INPUT: 3674 3675 precision -- (integer: default 53) bit precision of the 3676 field of real numbers in which the result will lie 3670 3677 3671 3678 EXAMPLES: 3672 3679 sage: E=EllipticCurve('5077a1') … … 3682 3689 7.45471994936400 3683 3690 3684 3691 """ 3685 #Computes height of curve 'self' according to Co13686 3692 R = RealField(precision) 3687 3693 c4 = self.c4() 3688 3694 c6 = self.c6() … … 3704 3710 h_gs = max(1, log_g2) 3705 3711 return max(R(1),h_j, h_gs) 3706 3712 3707 def integral_points(self, mw_base='auto', both_signs=False): 3708 """ 3709 Computes all integral points (up to sign) on the elliptic 3710 curve E which has Mordell-Weil basis mw_base. 3711 3712 INPUT: 3713 self -- EllipticCurve_Rational_Field 3713 def antilogarithm(self, z, precision=100): 3714 """ 3715 Returns the rational point (if any) associated to this complex 3716 number; the inverse of the elliptic logarithm function. 3717 3718 INPUT: 3719 z -- a complex number representing an element of 3720 CC/L where L is the period lattice of the elliptic 3721 curve 3722 3723 precision -- an integer specifying the precision (in bits) which 3724 will be used for the computation 3725 3726 OUTPUT: The rational point which is the image of z under 3727 the Weierstrass parametrization, if it exists and can 3728 be determined from z with default precision. 3729 3730 NOTE: This uses the function ellztopoint from the pari library 3731 3732 TODO: Extend the wrapping of ellztopoint() to allow passing of 3733 the precision parameter. 3734 3735 """ 3736 3737 E_pari = self.pari_curve(prec) 3738 try: 3739 coords = E_pari.ellztopoint(z) 3740 if len(coords) == 1: 3741 return self(0) 3742 return self([CC(xy).real().simplest_rational() for xy in coords]) 3743 except TypeError: 3744 raise ValueError, "No rational point computable from z" 3745 3746 def integral_points(self, mw_base='auto', both_signs=False, verbose=False): 3747 """ 3748 Computes all integral points (up to sign) on this elliptic curve. 3749 3750 INPUT: 3714 3751 mw_base -- list of EllipticCurvePoint generating the 3715 3752 Mordell-Weil group of E 3716 3753 (default: 'auto' - calls self.gens()) 3717 3718 3754 both_signs -- True/False (default False): if True the 3719 3755 output contains both P and -P, otherwise only 3720 one of ecah pair. 3721 3722 OUTPUT: 3723 set of all integral points on E 3756 one of each pair. 3757 verbose -- True/False (default False): if True, some 3758 details of the computation are output 3759 3760 OUTPUT: 3761 A sorted list of all the integral points on E 3724 3762 (up to sign unless both_signs is True) 3725 3763 3726 HINTS: 3727 - The complexity increases exponentially in the rank of curve E. 3728 - It can help if you try another Mordell-Weil base, because the 3729 computation time depends on this, too. 3764 NOTES: The complexity increases exponentially in the rank of 3765 curve E. The computation time (but not the output!) 3766 depends on the Mordell-Weil basis. If mw_base is given 3767 but it not a basis for the Mordell-Weil group (modulo 3768 torsion), integral points which are not in the subgroup 3769 generated by the given points will almost certainly not be 3770 listed. 3730 3771 3731 3772 EXAMPLES: 3732 3773 A curve of rank 3 with no torsion points … … 3736 3777 sage: a=E.integral_points([P1,P2,P3]); a 3737 3778 [(-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)] 3738 3779 3739 It is also possible to not specify mw_base and tors_base but 3740 then the Mordell-Weil basis must be found by other functions 3741 which will takes longer 3780 sage: a = E.integral_points([P1,P2,P3], verbose=True) 3781 Points on compact component: 3782 [(-3 : -1 : 1), (-2 : -4 : 1), (-1 : -4 : 1), (0 : -3 : 1), (1 : -1 : 1)] 3783 Points on non-compact component with x<= 7 3784 [(2 : -1 : 1), (3 : -4 : 1), (4 : -7 : 1)] 3785 starting search of remaining points using coefficient bound 9 3786 Extra integral points: 3787 [(342 : 6324 : 1), (37 : -225 : 1), (8 : 21 : 1), (52 : 374 : 1), (406 : -8181 : 1), (14 : -52 : 1), (816 : 23309 : 1), (93 : 896 : 1), (11 : -36 : 1), (3 : 3 : 1), (4 : -7 : 1), (21 : 95 : 1), (2 : -1 : 1)] 3788 Total number of integral points: 18 3789 3790 It is also possible to not specify mw_base, but then the 3791 Mordell-Weil basis must be computed; this may take much longer 3742 3792 3743 3793 sage: E=EllipticCurve([0,0,1,-7,6]) 3744 3794 sage: a=E.integral_points(both_signs=True); a … … 3771 3821 """ 3772 3822 ##################################################################### 3773 3823 # INPUT CHECK ####################################################### 3774 try: 3775 assert self.is_integral() 3776 except: 3824 if not self.is_integral(): 3777 3825 raise ValueError, "integral_points() can only be called on an integral model" 3778 3826 3779 3827 if mw_base=='auto': … … 3784 3832 r = len(mw_base) 3785 3833 except TypeError: 3786 3834 raise TypeError, 'mw_base must be a list' 3787 for P in mw_base: 3788 try: 3789 assert P.curve() is self 3790 except: 3791 raise ValueError, "points are not on the correct curve" 3835 if not all([P.curve() is self for P in mw_base]): 3836 raise ValueError, "points are not on the correct curve" 3792 3837 3793 3838 tors_base = self.torsion_subgroup().gens() 3794 3839 len_tors = len(tors_base) … … 3834 3879 ############################## end ################################ 3835 3880 ############################## begin ################################ 3836 3881 def search_remaining_points(): 3837 """Returns list of integral points on curve E written as 3838 linear combination of n times the mordell-weil base 3839 points and torsion points (n is bounded by H_q, which 3840 will be computed at runtime) 3882 r""" 3883 Returns a list of integral points on the curve which are 3884 linear combinations of the generators (basis and torsion 3885 points) with coefficients bounded by $H_q$. The bound 3886 $H_q$ will be computed at runtime. 3841 3887 """ 3842 OP=self(0)3843 3888 pts=[] 3844 3889 for i in range(1,((2*H_q+1)**r)/2): 3845 3890 koeffs = Z(i).digits(base=2*H_q+1) … … 3849 3894 P = P + (koeffs[index]-H_q)*mw_base[index] 3850 3895 for Q in tors_points: # P + torsion points (includes 0) 3851 3896 P = P + Q 3852 if P!=OPand P[0].is_integral():3897 if not P.is_zero() and P[0].is_integral(): 3853 3898 pts.append(P) 3854 3899 if both_signs: 3855 3900 Q = -P … … 3868 3913 pts.sort() 3869 3914 return pts 3870 3915 3871 e = exp(R(1))3916 e = R(1).exp() 3872 3917 pi = R(constants.pi) 3873 3918 3874 3919 g2 = self.c4()/12 … … 3889 3934 e3 = pol.roots(R,multiplicities=False)[0] 3890 3935 roots.remove(e3) 3891 3936 e1,e2 = roots 3892 3937 3938 if verbose: 3939 print "Using mw_basis ",mw_base 3940 print "e1,e2,e3: ",e1,e2,e3 3941 3893 3942 # Algorithm presented in [Co1] 3894 3943 h_E = self.height() 3895 3944 w1, w2 = self.period_lattice().basis() … … 3900 3949 mu += max(R(1),R(b2).abs().log()) 3901 3950 mu += log(R(2)) 3902 3951 3903 c1 = exp(mu + 2.14)3952 c1 = (mu + 2.14).exp() 3904 3953 M = self.height_pairing_matrix(mw_base) 3905 3954 c2 = min(M.charpoly ().roots(multiplicities=False)) 3955 if verbose: 3956 print "Minimal eigenvalue of height pairing matrix: ", c2 3957 3906 3958 c3 = (w1**2)*R(b2).abs()/48 + 8 3907 3959 c5 = (c1*c3).sqrt() 3908 3960 c7 = abs((3*pi)/((w1**2) * (w1/w2).imag())) … … 3924 3976 bottom = 0 3925 3977 log_c9=log(c9); log_c5=log(c5) 3926 3978 log_r_top = log(R(r*(10**top))) 3927 3979 if verbose: 3980 print "[bottom,top] = ",[bottom,top] 3981 3928 3982 while 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): 3929 3983 #initial bound 'top' too small, upshift of search interval 3930 3984 bottom = top 3931 3985 top = 2*top 3932 3986 while top >= bottom: #binary-search like search for fitting exponent (bound) 3987 if verbose: 3988 print "[bottom,top] = ",[bottom,top] 3933 3989 bound = floor(bottom + (top - bottom)/2) 3934 3990 log_r_bound = log(R(r*(10**bound))) 3935 3991 if 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): … … 3972 4028 d_L_0 = 10*(T**2*Q) 3973 4029 low_bound = R((sqrt(d_L_0 - Q) - T)/c) 3974 4030 3975 #new bound according to low_bound and upper bound [c_5 exp((-c_2*H_q^2)/2)] provided by Corollary 8.7.3 4031 #new bound according to low_bound and upper bound 4032 #[c_5 exp((-c_2*H_q^2)/2)] provided by Corollary 8.7.3 3976 4033 H_q_new = R(sqrt(log(low_bound/c5)/(-c2/2))) 3977 4034 H_q_new = ceil(H_q_new) 3978 4035 break_cond = R(H_q_new/H_q) … … 3980 4037 #END LLL-Reduction loop 3981 4038 3982 4039 3983 int_points = []3984 ##for a more detailed view how the function works uncomment3985 ##all print - statements below3986 4040 if disc > 0: 3987 ##Points in egg have e2>=x>=e1 3988 int_points += search_points(ceil(e1), floor(e2)+1) 3989 #print 'Points on compact component \n',list(int_points) 4041 ##Points in egg have x between e1 and e2: 4042 int_points = search_points(ceil(e1), floor(e2)+1) 4043 if verbose: 4044 print 'Points on compact component:' 4045 print int_points 4046 else: 4047 int_points = [] 3990 4048 3991 4049 ##Points in noncompact component with x(P)< 2*max(|e1|,|e2|,|e3|) , espec. x(P)>=e3 3992 int_points += search_points(ceil(e3), ceil(2*max(abs(e1),abs(e2),abs(e3)))) 3993 #print 'Points on compact component and non-compact component part 1 \n', list(int_points) 3994 3995 #print 'starting search of remainig points using bound ',H_q 3996 int_points += search_remaining_points() 3997 #print 'Integral points:\n',list(int_points) 3998 #print 'Total amount of points:',len(int_points) 4050 x0 = ceil(e3) 4051 x1 = ceil(2*max(abs(e1),abs(e2),abs(e3))) 4052 int_points2 = search_points(x0, x1) 4053 int_points += int_points2 4054 if verbose: 4055 print 'Points on non-compact component with x<=',x1 4056 print int_points2 4057 4058 if verbose: 4059 print 'starting search of remaining points using coefficient bound ',H_q 4060 int_points3 = search_remaining_points() 4061 int_points += int_points3 4062 if verbose: 4063 print 'Extra integral points:' 4064 print int_points3 3999 4065 if both_signs: 4000 4066 int_points = list(set(int_points)) # remove duplicates 4001 4067 else: 4002 4068 xlist = set([P[0] for P in int_points]) 4003 4069 int_points = [self.lift_x(x) for x in xlist] 4004 4070 int_points.sort() 4071 if verbose: 4072 print 'Total number of integral points:',len(int_points) 4005 4073 return int_points 4006 4074 4007 4075 -
a/sage/schemes/elliptic_curves/rational_torsion.py
old new 48 48 49 49 AUTHOR: Nick Alexander 50 50 """ 51 def __init__(self, E, flag=0):51 def __init__(self, E, algorithm="pari"): 52 52 self.__E = E 53 53 54 flag = 0 55 if algorithm=="doud": 56 flag = 1 57 if algorithm=="lutz_nagell": 58 flag = 2 54 59 G = None 55 60 loop = 0 56 61 while G is None and loop < 3: