# HG changeset patch
# User John Cremona
# Date 1265299155 0
# Node ID da1d714ce6c643ada7230478729c24fd2ba373b8
# Parent bf84525b72903999beae77685f41a227396f87ad
#8184: patch interface for eclib/mwrank for eclib20080310.p9.spkg
diff r bf84525b7290 r da1d714ce6c6 sage/libs/mwrank/interface.py
 a/sage/libs/mwrank/interface.py Sun Jan 31 21:29:03 2010 0800
+++ b/sage/libs/mwrank/interface.py Thu Feb 04 15:59:15 2010 +0000
@@ 243,45 +243,127 @@
def rank(self):
"""
Returns the rank of this curve, computed using 2descent.
+
+ 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 2selmer
 group. This is the rank of the curve minus the rank of the
 2torsion, minus a number determined by whatever mwrank was
 able to determine related to $\Sha(E)[2]$ (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 2descent.
+
+ If the curve has no 2torsion, this is equal to the 2Selmer
+ rank. If the curve has 2torsion, the upper bound may be
+ smaller than the bound obtained from the 2Selmer rank minus
+ the 2rank of the torsion, since more information is gained
+ from the 2isogenous 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 2isogenous
+ 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 2Selmer group of the curve.
+
+ EXAMPLES:
+
+ The following is the curve 960D1, which has rank 0, but Sha of
+ order 4. The 2torsion 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
+ 2rank 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 2torsion, 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 2torsion, the rank upper bound is
+ always equal to the 2Selmer 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()
@@ 328,8 +410,12 @@
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$.
@@ 341,12 +427,15 @@
sage: E.rank()
0
 The rank of $E$is actually 0 (as one could see by computing
 the Lfunction), 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 Lfunction), 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())
diff r bf84525b7290 r da1d714ce6c6 sage/libs/mwrank/mwrank.pyx
 a/sage/libs/mwrank/mwrank.pyx Sun Jan 31 21:29:03 2010 0800
+++ b/sage/libs/mwrank/mwrank.pyx Thu Feb 04 15:59:15 2010 +0000
@@ 73,11 +73,12 @@
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)
@@ 296,13 +297,20 @@
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
@@ 310,7 +318,7 @@
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
@@ 319,7 +327,7 @@
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
diff r bf84525b7290 r da1d714ce6c6 sage/libs/mwrank/wrap.cc
 a/sage/libs/mwrank/wrap.cc Sun Jan 31 21:29:03 2010 0800
+++ b/sage/libs/mwrank/wrap.cc Thu Feb 04 15:59:15 2010 +0000
@@ 244,17 +244,22 @@
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());
}
@@ 264,7 +269,7 @@
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();
}
diff r bf84525b7290 r da1d714ce6c6 sage/libs/mwrank/wrap.h
 a/sage/libs/mwrank/wrap.h Sun Jan 31 21:29:03 2010 0800
+++ b/sage/libs/mwrank/wrap.h Thu Feb 04 15:59:15 2010 +0000
@@ 104,15 +104,17 @@
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
diff r bf84525b7290 r da1d714ce6c6 sage/schemes/elliptic_curves/ell_rational_field.py
 a/sage/schemes/elliptic_curves/ell_rational_field.py Sun Jan 31 21:29:03 2010 0800
+++ b/sage/schemes/elliptic_curves/ell_rational_field.py Thu Feb 04 15:59:15 2010 +0000
@@ 2446,13 +2446,9 @@
else:
return rings.Integer(0)
 def selmer_rank_bound(self):
 """
 Bound on the rank of the curve, computed using the 2selmer group.
 This is the rank of the curve minus the rank of the 2torsion,
 minus a number determined by whatever mwrank was able to determine
 related to Sha[2]. Thus in many cases, this is the actual rank of
 the curve.
+ def selmer_rank(self):
+ """
+ The rank of the 2Selmer group of the curve.
EXAMPLE: The following is the curve 960D1, which has rank 0, but
Sha of order 4.
@@ 2460,7 +2456,57 @@
::
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 2torsion rank (=1) plus
+ the 2rank 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 Lfunction 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
+ 2descent. In many cases, this is the actual rank of the
+ curve. If the curve has no 2torsion it is the same as the
+ 2selmer 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
@@ 2468,17 +2514,17 @@
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 Lfunction
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):
@@ 5555,7 +5601,7 @@
A curve for which 3 divides the order of the ShafarevichTate 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[2] computed by MWrank
True for p not in {2, 3} by Kolyvagin.
ALERT: p = 3 left in Kolyvagin bound
@@ 5580,14 +5626,14 @@
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[2] computed by MWrank
True for p not in {2} by Kolyvagin.
[2]
::
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[2] computed by MWrank
Timeout stopped Heegner index computation...
Proceeding to use heegner_index_bound instead.
@@ 5612,7 +5658,7 @@
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
@@ 5637,7 +5683,7 @@
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[2]:
two_proven = False
diff r bf84525b7290 r da1d714ce6c6 sage/schemes/elliptic_curves/sha_tate.py
 a/sage/schemes/elliptic_curves/sha_tate.py Sun Jan 31 21:29:03 2010 0800
+++ b/sage/schemes/elliptic_curves/sha_tate.py Thu Feb 04 15:59:15 2010 +0000
@@ 640,14 +640,9 @@
def two_selmer_bound(self):
r"""
 This returns a lower bound on the `\mathbb{F}_2`dimension
+ This returns the 2rank, i.e. the `\mathbb{F}_2`dimension
of the 2torsion 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[2], or if we can not find sufficiently many points
 it should give a lower bound.

+ rank of `E`.
EXAMPLE::
sage: sh = EllipticCurve('571a1').sha()
@@ 664,19 +659,14 @@
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 twoisogeny, 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