Hi Nils,

Yep, I think there are ways of making this nicer.

> I was interested in elliptic curves with possible 9-torsion in Sha, so
> I figured querying Cremona's database would get me some examples.
> After some experimenting, I finally created a query that had the
> desired result:
>
> sage: DB = CremonaDatabase()
> sage: L = [ N.str()+c[0] for N in (lambda l: xrange(l[0],l[1]))
> (DB.conductor_range()) for c in DB.allbsd(N).items() if
>                 round(RDF(c[1][4]))%81 == 0]
>
> Two things made me feel uncomfortable with this expression:
>
>  - the whole lambda expression to make the pair output by
> DB.conductor_range() into an iterable. Is there a syntactically more
> pleasing construct in python for that?

So in this case, you're trying to call xrange with arguments given by
the entries of DB.conductor_range() -- the lambda works, but python
has a nicer syntax for this. (I don't know a better name than the
"*args" syntax.) You can do:

sage: t = (0,10)
sage: xrange(*t)
xrange(10)
sage: range(*t)
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]

and that will just insert the entries of t as sequential arguments to
xrange. (You can also use ** with a dictionary, and it will insert the
key:value pairs as keyword arguments to your function.)

> (for instance variables local to expressions. In Magma speak: "[a..b]
> where (a,b)=DB.conductor_range()")

The [1..5] syntax works just fine here, and returns Sage Integer
objects (i.e. sage.rings.integer.Integer), just like srange. Here's
what really happens:

sage: [1..5]
[1, 2, 3, 4, 5]
sage: preparse('[1..5]')
'(ellipsis_range(Integer(1),Ellipsis,Integer(5)))'

Sadly, the ellipsis argument needs to go in the middle -- so I can't
quickly do it only evaluating the function once and not using a
lambda. You can just use srange, though:

sage: t = (0,10)
sage: srange(*t)
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
sage: type(srange(*t)[0])
<type 'sage.rings.integer.Integer'>

>  - the round(RDF(c[1][4])) to make the "analytic sha" into an integer.
>

This one is a little more trouble: the Integer constructor just passes
strings off to MPIR's mpz_set_str, which isn't willing to accept
strings like '1.0'. On top of that, some of the strings (such as the
one for 389) aren't just of the form '1.0000000000' (i.e. an integer
with a bunch of zeros following). So probably the easiest way is to
use round, as you do above. However, you can make it maybe a bit more
readable:

sage: DB = CremonaDatabase()
sage: n = 81
sage: %time L = [ str(N)+label for N in srange(*DB.conductor_range())
for label,data in DB.allbsd(N).items() if
n.divides(RDF(data[4]).round()) ]
CPU times: user 90.17 s, sys: 1.57 s, total: 91.74 s
Wall time: 91.75 s
sage: len(L)
86

Does that seem better?

-cc

--~--~---------~--~----~------------~-------~--~----~
To post to this group, send email to sage-support@googlegroups.com
To unsubscribe from this group, send email to 
sage-support-unsubscr...@googlegroups.com
For more options, visit this group at 
http://groups.google.com/group/sage-support
URLs: http://www.sagemath.org
-~----------~----~----~----~------~----~------~--~---

Reply via email to