# Ticket #8184: trac_8184-eclib.patch

File trac_8184-eclib.patch, 17.4 KB (added by John Cremona, 13 years ago)

Applies to 4.3.2.alpha1

• ## sage/libs/mwrank/interface.py

```# HG changeset patch
# User John Cremona <john.cremona@gmail.com>
# Date 1265299155 0
# Node ID da1d714ce6c643ada7230478729c24fd2ba373b8
#8184: patch interface for eclib/mwrank for eclib-20080310.p9.spkg

diff -r bf84525b7290 -r da1d714ce6c6 sage/libs/mwrank/interface.py```
 a def rank(self): """ Returns the rank of this curve, computed using 2-descent. In general this may only be a lower bound for the rank; an upper bound may be obtained using the function rank_bound(). To test whether the value has been proved to be correct, use the method \method{certain}. EXAMPLES:: sage: E = mwrank_EllipticCurve([0, -1, 0, -900, -10098]) sage: E.rank() 0 sage: E.certain() True :: sage: E = mwrank_EllipticCurve([0, -1, 1, -929, -10595]) sage: E.rank() 0 sage: E.certain() False """ return self.__two_descent_data().getrank() def selmer_rank_bound(self): r""" Bound on the rank of the curve, computed using the 2-selmer group.  This is the rank of the curve minus the rank of the 2-torsion, minus a number determined by whatever mwrank was able to determine related to \$\Sha(E)\$ (e.g., using a second descent or if there is a rational \$2\$-torsion point, then there may be an isogeny to a curve with trivial \$\Sha(E)\$).  In many cases, this is the actual rank of the curve, but in general it is just \$\geq\$ the true rank. def rank_bound(self): """ Returns an upper bound for the rank of this curve, computed using 2-descent. If the curve has no 2-torsion, this is equal to the 2-Selmer rank.  If the curve has 2-torsion, the upper bound may be smaller than the bound obtained from the 2-Selmer rank minus the 2-rank of the torsion, since more information is gained from the 2-isogenous curve or curves. EXAMPLES: The following is the curve 960D1, which has rank 0, but Sha of order 4. but Sha of order 4:: sage: E = mwrank_EllipticCurve([0, -1, 0, -900, -10098]) sage: E.selmer_rank_bound() sage: E.rank_bound() 0 sage: E.rank() 0 In this case this was resolved using a second descent. In this case the rank was computed using a second descent, which is able to determine (by considering a 2-isogenous curve) that Sha is nontrivial.  If we deliberately stop the second descent, the rank bound is larger:: sage: E = mwrank_EllipticCurve([0, -1, 0, -900, -10098]) sage: E.two_descent(second_descent = False, verbose=False) sage: E.selmer_rank_bound() sage: E.rank_bound() 2 Above, the \method{selmer_rank_bound} gives 0 instead of 2, because it knows Sha is nontrivial.  In contrast, for the curve 571A, also with rank 0 and \$\Sha\$ of order 4, we obtain a worse bound: In contrast, for the curve 571A, also with rank 0 and Sha of order 4, we only obtain an upper bound of 2: sage: E = mwrank_EllipticCurve([0, -1, 1, -929, -10595]) sage: E.selmer_rank_bound() sage: E.rank_bound() 2 In this case the value returned by \method{rank} is only a lower bound in general (though in this is correct):: sage: E.rank() 0 sage: E.certain() False """ return self.__two_descent_data().getrankbound() def selmer_rank(self): r""" Returns the rank of the 2-Selmer group of the curve. EXAMPLES: The following is the curve 960D1, which has rank 0, but Sha of order 4.  The 2-torsion has rank 2, and the Selmer rank is 3:: sage: E = mwrank_EllipticCurve([0, -1, 0, -900, -10098]) sage: E.selmer_rank() 3 Nevertheless, we can obtain a tight upper bound on the rank since a second descent is performed which establishes the 2-rank of Sha:: sage: E.rank_bound() 0 To show that this was resolved using a second descent, we do the computation again but turn off the second descent:: sage: E = mwrank_EllipticCurve([0, -1, 0, -900, -10098]) sage: E.two_descent(second_descent = False, verbose=False) sage: E.rank_bound() 2 For the curve 571A, also with rank 0 and \$\Sha\$ of order 4, but with no 2-torsion, the selmer rank is strictly greater than the rank:: sage: E = mwrank_EllipticCurve([0, -1, 1, -929, -10595]) sage: E.selmer_rank() 2 sage: E.rank_bound() 2 In cases like this with no 2-torsion, the rank upper bound is always equal to the 2-Selmer rank.  If we ask for the rank, all we get is a lower bound:: sage: E.rank() 0 sage: E.certain() False """ return self.__two_descent_data().getselmer() computed the rank.  If \method{two_descent} hasn't been called, then it is first called by \method{certain} using the default parameters. The result is true if and only if the results of the methods \method{rank} and \method{rank_bound} are equal. EXAMPLES: A \$2\$-descent does not determine \$E(\Q)\$ with certainty for the curve \$y^2 + y = x^3 - x^2 - 120x - 2183\$. sage: E.rank() 0 The rank of \$E\$is actually 0 (as one could see by computing the L-function), but \$\Sha\$ has order 4 and the \$2\$-torsion is trivial, so mwrank does not conclusively determine the rank. The previous value is only a lower bound; the upper bound is greater:: sage: E.selmer_rank_bound() sage: E.rank_bound() 2 In fact the rank of \$E\$is actually 0 (as one could see by computing the L-function), but \$\Sha\$ has order 4 and the \$2\$-torsion is trivial, so mwrank cannot conclusively determine the rank in this case. """ return bool(self.__two_descent_data().getcertain())
• ## sage/libs/mwrank/mwrank.pyx

`diff -r bf84525b7290 -r da1d714ce6c6 sage/libs/mwrank/mwrank.pyx`
 a void two_descent_del(two_descent* t) int two_descent_ok(two_descent* t) long two_descent_getcertain(two_descent* t) char* two_descent_getbasis(two_descent* t) long two_descent_get_certain(two_descent* t) char* two_descent_get_basis(two_descent* t) char* two_descent_regulator(two_descent* t) long two_descent_getrank(two_descent* t) long two_descent_getselmer(two_descent* t) long two_descent_get_rank(two_descent* t) long two_descent_get_rank_bound(two_descent* t) long two_descent_get_selmer_rank(two_descent* t) void two_descent_saturate(two_descent* t, long sat_bd) def getrank(self): cdef int r _sig_on r = two_descent_getrank(self.x) r = two_descent_get_rank(self.x) _sig_off return r def getrankbound(self): cdef int r _sig_on r = two_descent_get_rank_bound(self.x) _sig_off return r def getselmer(self): _sig_on r = two_descent_getselmer(self.x) r = two_descent_get_selmer_rank(self.x) _sig_off return r return two_descent_ok(self.x) def getcertain(self): return two_descent_getcertain(self.x) return two_descent_get_certain(self.x) def saturate(self, saturation_bound=0): _sig_on def getbasis(self): _sig_on return string_sigoff(two_descent_getbasis(self.x)) return string_sigoff(two_descent_get_basis(self.x)) def regulator(self): _sig_on
• ## sage/libs/mwrank/wrap.cc

`diff -r bf84525b7290 -r da1d714ce6c6 sage/libs/mwrank/wrap.cc`
 a delete t; } long two_descent_getrank(struct two_descent* t) long two_descent_get_rank(struct two_descent* t) { return t->getrank(); } long two_descent_getselmer(struct two_descent* t) long two_descent_get_rank_bound(struct two_descent* t) { return t->getrankbound(); } long two_descent_get_selmer_rank(struct two_descent* t) { return t->getselmer(); } char* two_descent_getbasis(struct two_descent* t) char* two_descent_get_basis(struct two_descent* t) { return p2point_vector_to_str(t->getbasis()); } return t->ok(); } long two_descent_getcertain(const struct two_descent* t) long two_descent_get_certain(const struct two_descent* t) { return t->getcertain(); }
• ## sage/libs/mwrank/wrap.h

`diff -r bf84525b7290 -r da1d714ce6c6 sage/libs/mwrank/wrap.h`
 a EXTERN void two_descent_del(struct two_descent* t); EXTERN long two_descent_getrank(struct two_descent* t); EXTERN long two_descent_get_rank(struct two_descent* t); EXTERN long two_descent_getselmer(struct two_descent* t); EXTERN long two_descent_get_rank_bound(struct two_descent* t); EXTERN char* two_descent_getbasis(struct two_descent* t); EXTERN long two_descent_get_selmer_rank(struct two_descent* t); EXTERN char* two_descent_get_basis(struct two_descent* t); EXTERN int two_descent_ok(const struct two_descent* t); EXTERN long two_descent_getcertain(const struct two_descent* t); EXTERN long two_descent_get_certain(const struct two_descent* t); EXTERN void two_descent_saturate(struct two_descent* t, long sat_bd); // = 0 for unbounded
• ## sage/schemes/elliptic_curves/ell_rational_field.py

`diff -r bf84525b7290 -r da1d714ce6c6 sage/schemes/elliptic_curves/ell_rational_field.py`
 a else: return rings.Integer(0) def selmer_rank_bound(self): """ Bound on the rank of the curve, computed using the 2-selmer group. This is the rank of the curve minus the rank of the 2-torsion, minus a number determined by whatever mwrank was able to determine related to Sha. Thus in many cases, this is the actual rank of the curve. def selmer_rank(self): """ The rank of the 2-Selmer group of the curve. EXAMPLE: The following is the curve 960D1, which has rank 0, but Sha of order 4. :: sage: E = EllipticCurve([0, -1, 0, -900, -10098]) sage: E.selmer_rank_bound() sage: E.selmer_rank() 3 Here the Selmer rank is equal to the 2-torsion rank (=1) plus the 2-rank of Sha (=2), and the rank itself is zero:: sage: E.rank() 0 In contrast, for the curve 571A, also with rank 0 and Sha of order 4, we get a worse bound:: sage: E = EllipticCurve([0, -1, 1, -929, -10595]) sage: E.selmer_rank() 2 sage: E.rank_bound() 2 To establish that the rank is in fact 0 in this case, we would need to carry out a higher descent:: sage: E.three_selmer_rank() # optional: magma 0 Or use the L-function to compute the analytic rank:: sage: E.rank(only_use_mwrank=False) 0 """ try: return self.__selmer_rank except AttributeError: C = self.mwrank_curve() self.__selmer_rank = C.selmer_rank() return self.__selmer_rank def rank_bound(self): """ Upper bound on the rank of the curve, computed using 2-descent.  In many cases, this is the actual rank of the curve.  If the curve has no 2-torsion it is the same as the 2-selmer rank. EXAMPLE: The following is the curve 960D1, which has rank 0, but Sha of order 4. :: sage: E = EllipticCurve([0, -1, 0, -900, -10098]) sage: E.rank_bound() 0 It gives 0 instead of 2, because it knows Sha is nontrivial. In we get a worse bound:: sage: E = EllipticCurve([0, -1, 1, -929, -10595]) sage: E.selmer_rank_bound() sage: E.rank_bound() 2 sage: E.rank(only_use_mwrank=False)   # uses L-function 0 """ try: return self.__selmer_rank_bound return self.__rank_bound except AttributeError: C = self.mwrank_curve() self.__selmer_rank_bound = C.selmer_rank_bound() return self.__selmer_rank_bound self.__rank_bound = C.rank_bound() return self.__rank_bound def an(self, n): A curve for which 3 divides the order of the Shafarevich-Tate group:: sage: E = EllipticCurve('681b') sage: E.prove_BSD(verbosity=2)               # long time sage: E.prove_BSD(verbosity=2) p = 2: Unverified since it is difficult to access the rank bound for Sha computed by MWrank True for p not in {2, 3} by Kolyvagin. ALERT: p = 3 left in Kolyvagin bound sage: E = EllipticCurve('438e1') sage: E.prove_BSD(verbosity=1) p = 2: mwrank did not achieve a tight bound on the Selmer rank. p = 2: Unverified since it is difficult to access the rank bound for Sha computed by MWrank True for p not in {2} by Kolyvagin.  :: sage: E = EllipticCurve('960d1') sage: E.prove_BSD(verbosity=1) sage: E.prove_BSD(verbosity=1) # long time p = 2: Unverified since it is difficult to access the rank bound for Sha computed by MWrank Timeout stopped Heegner index computation... Proceeding to use heegner_index_bound instead. else: raise RuntimeError("Rank can't be computed precisely using Simon's program.") else: two_sel_rk_bd = self.mwrank_curve().selmer_rank_bound() two_sel_rk_bd = self.rank_bound() rank = self.rank() if rank > 1: # We do not know BSD(E,p) for even a single p, since it's print 'p = 2: mwrank did not achieve a tight bound on the Selmer rank.' two_proven = False elif two_sel_rk_bd < rank: raise RuntimeError("MWrank seems to have computed an incorrect lower bound of %d on the rank."%two_sel_rk_bd) raise RuntimeError("MWrank seems to have computed an incorrect upper bound of %d on the rank."%two_sel_rk_bd) else: # until we can easily access the computed rank of Sha: two_proven = False
• ## sage/schemes/elliptic_curves/sha_tate.py

`diff -r bf84525b7290 -r da1d714ce6c6 sage/schemes/elliptic_curves/sha_tate.py`
 a def two_selmer_bound(self): r""" This returns a lower bound on the `\mathbb{F}_2`-dimension This returns the 2-rank, i.e. the `\mathbb{F}_2`-dimension of the 2-torsion part of Sha, provided we can determine the rank of `E`. But it is not the best possible bound. TO DO: This should be rewritten, to give the exact order of Sha, or if we can not find sufficiently many points it should give a lower bound. rank of `E`. EXAMPLE:: sage: sh = EllipticCurve('571a1').sha() sage: sh = EllipticCurve('960d1').sha() sage: sh.two_selmer_bound() 0 2 sage: sh.an() 4 """ S = self.E.selmer_rank_bound() S = self.E.selmer_rank() r = self.E.rank() t = self.E.two_torsion_rank() b = S - r - t # the following is not true, selmer_rank_bound also # uses descent by two-isogeny, so b need not be even. # e.g. for 66a1, we find b = -1. #if b % 2 != 0: #    raise ArithmeticError, "There is a bug in two_selmer_bound since it's %s, but it must be even."%b if  b < 0 : b = 0 return b