Hi Alex
Thanks for the quick reply. By _ you mean a variable? I tried your
syntax but it does not work.
However, [2*x for x in [3,4]] does work.
> Hmmm. As far as I know you can use _ as a placeholder for a
> variable, and it's meant for this kind of use (where you don't
> really want to introduce a new variable name). It's strange that
> it doesn't work for you. Can you post the error message that you get?
Actually, _ is an actual variable, though personally I find it a bit
harder to read than a normal letter. The one special thing about it
(in ipython at least) is that it constantly gets reassigned to the
last returned value, e.g.
sage: 1+2
3
sage: _
3
- Robert
I get
sage: vector( [k for k in range(10)])
(0, 1, 2, 3, 4, 5, 6, 7, 8, 9)
Are you sure that's what you typed?
--
William Stein
Associate Professor of Mathematics
University of Washington
http://wstein.org
I bet that's the case. You should maybe upgrade. We'll be posting
binaries soon.
William
It seems like this error was fixed recently. Pong, what version of Sage
are you running?
Jason
Yep, this was taken care of in 3.1.2:
http://trac.sagemath.org/sage_trac/ticket/3847
Sorry for my other delayed reply. Apparently gmane has a big delay in
mirroring responses.
Jason
Also, instead of doing your own loops, you can use %timeit:
sage: %timeit [2*random() for j in range(10)]
100000 loops, best of 3: 6.87 µs per loop
sage: %timeit list(2*vector([random() for j in range(10)]))
10000 loops, best of 3: 112 µs per loop
Using list comprehensions is almost always a good choice in Sage/Python;
as I understand (and as we see above), they're very well-optimized.
Dan
--
--- Dan Drake <dr...@mathsci.kaist.ac.kr>
----- KAIST Department of Mathematical Sciences
------- http://mathsci.kaist.ac.kr/~drake
I also added a command called timeit, so you can do
sage: timeit(' [2*random() for j in range(10)]')
this has the advantage that the input is preparsed using
the Sage preparser, so might give a slightly more accurate
result, and work in some cases where %timeit doesn't work.
For example,
sage: %timeit R.<x> = QQ[]
------------------------------------------------------------
File "<magic-timeit>", line 6
R.<x> = QQ[]
^
SyntaxError: invalid syntax
sage: timeit('R.<x> = QQ[]')
625 loops, best of 3: 287 µs per loop
It would be reasonable to argue that the fact that %timeit doesn't
preparse its input is a bug in Sage (actually IPython), and that it
should. I've cc'd Fernando Perez (author of IPython) in case he has a
comment.
William
> Thanks to both Dan and William. However, Dan's result puzzled me.
> Aren't they suggested that the for loop is faster?
>
> Here is what I got:
>
> sage: timeit('list(2*vector([random() for j in range(10)]))')
> 625 loops, best of 3: 332 µs per loop
> sage: timeit('[2*random() for j in range(10)]')
> 125 loops, best of 3: 8.3 ms per loop
A more precise benchmark (ignoring vector/list creation) would
probably be:
sage: L = [random() for j in range(10)]
sage: v = vector(L)
sage: timeit("2*v")
625 loops, best of 3: 1.76 µs per loop
sage: timeit("[2*a for a in L]")
25 loops, best of 3: 29.2 ms per loop
To explain your timings, note
sage: parent(random())
<type 'float'>
sage: parent(vector([random() for j in range(10)]))
Vector space of dimension 10 over Real Double Field
sage: parent(2)
Integer Ring
In your first loop, it's creating a RDF vector and then multiplying
by 2 via
sage: cm = sage.structure.element.get_coercion_model()
sage: cm.explain(2, v)
Action discovered.
Left scalar multiplication by Integer Ring on Vector space of
dimension 10 over Real Double Field
Result lives in Vector space of dimension 10 over Real Double Field
Vector space of dimension 10 over Real Double Field
in other words, it turns "2" into an RDF, then multiplies every
element (in fast compiled code) of the RDF vector. In the second
case, it's having to re-discover the float-Integer operation each
time (as the result is a float) which happens to be the worst-case
scenario. Note with RDF rather than floats
sage: timeit("[2*a for a in v]")
625 loops, best of 3: 20.9 µs per loop
(still not the speed of a vector-element multiply, but much better).
There is a ticket or two related to improving this, e.g. #3938 and
#2898.
> which suggested otherwise. Also how does timeit determine how many
> loops to perform in a test?
In my experience (haven't looked at the code) it keeps timing until
it hits about a second, going by powers of 5.
>> Also, instead of doing your own loops, you can use %timeit:
>>
>> sage: %timeit [2*random() for j in range(10)]
>> 100000 loops, best of 3: 6.87 µs per loop
>> sage: %timeit list(2*vector([random() for j in range(10)]))
>> 10000 loops, best of 3: 112 µs per loop
Note that the 2 is not getting preparsed, and so one is doing python-
int * python-float. Also, in the second example, the bulk of the time
is in the conversion, not the multiply
sage: sage: %timeit list(2*vector([random() for j in range(10)]))
10000 loops, best of 3: 173 µs per loop
sage: %timeit list(vector([random() for j in range(10)]))
10000 loops, best of 3: 167 µs per loop
>> Using list comprehensions is almost always a good choice in Sage/
>> Python;
>> as I understand (and as we see above), they're very well-optimized.
Yes, though using vectors can be faster too, and if one's list really
is a vector than it can make much easier to read code than
manipulating lists.
- Robert