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 -~----------~----~----~----~------~----~------~--~---