Hi, people say that for-next loops are the worst way to apply repeated operations (why?). Assume i have the list
L:=[1,3,5,6];
and the command line that does some stuff in it :
for i from 1 to nops(L)-1 do
sqrt(5*L[i]-L[i+1]);
end do;
Whats a better way to do this? I guess map is useful here, but i cant get it to work.
seq
The command seq is more efficient than a for loop. Try this:
restart;
L:=[1,3,5,6];
seq( sqrt(5*L[i]- L[i+1]),i=1..nops(L)-1);
Hope this helps.
J. Tarr
Not this example
map and seq can be a lot faster that doing a for-do loop, but not in this case:
> L:=[seq](2*i+1, i=10000..100000): > time(seq( sqrt(5*L[i]- L[i+1]),i=1..nops(L)-1) ); 2.316 > restart; > L:=[seq](2*i+1, i=10000..100000): > t:=time(): for i from 1 to nops(L)-1 do > sqrt(5*L[i]-L[i+1]): > end do: time() - t; 1.880seq and map are best in the case when you are creating a list as output. So, the following is extremely slow (I stopped it at 400 seconds)
But that is mostly due to the bad list construction technique, not the for loop. The following isn't too bad:
> restart; > L:=[seq](2*i+1, i=10000..100000): > M := Array(1..(100000-10000), 0); > t:=time(): for i from 1 to nops(L)-1 do > M[i]:=sqrt(5*L[i]-L[i+1]): > end do: M := convert(M, list): time() - t; 2.792John
zip
time(zip((x,y)->5*x+y,L[1..-2],L[2..-1])); 0.140Alec
with sqrt
> L:=[seq](2*i+1, i=10000..100000): > time(zip((x,y)->sqrt(5*x+y),L[1..-2],L[2..-1])); 2.632 > restart > L:=[seq](2*i+1, i=10000..100000): > time(seq( sqrt(5*L[i]- L[i+1]),i=1..nops(L)-1) ); 1.676 (timings from a different machine than my earlier post)John
I will keep those examples in
I will keep those examples in mind, thanks.
@alec: yes, another good and
@alec: yes, another good and compact solution, altough you left out the square root operation, so runtimes aren't comparable.
map[evalhf,inline]
Yes, zip is usually not very efficient in Maple, and sqrt, certainly, adds some time. Another problem with time comparision is that the answers are different - seq, map, and zip construct a list, or a sequence, and the loop doesn't.
By the way, without the square root, one of the fastest ways is
time(5*L[1..-2]+L[2..-1]); 0.Something similar can be achieved with square roots, too:
L:=Array(L,datatype=float[8]): L1:=ArrayTools:-Alias(L,[1..90000]): L2:=ArrayTools:-Alias(L,1,[1..90000]): time(map[evalhf,inline](sqrt,5*L1+L2)); 0.Alec
Pineapples and Bananas
That a a great example of how to do the numerical computation very fast, but I should point out that it is not really a fair comparison.
For the exact operation this is about the same speed:
L:=[seq](2*i+1, i=10000..100000): L:=Array(L): L1:=ArrayTools:-Alias(L,[1..90000]): L2:=ArrayTools:-Alias(L,1,[1..90000]): time(map[inline](sqrt,5*L1+L2)); 2.708John
datatype=float[8] and evalhf
datatype=float[8] and evalhf option in map make the difference. Why is it not fair?
Alec
Different Computation
It is doing a completely different computation:
sqrt(5*L[47]-L[48]): lprint(%); 3*8930^(1/2) evalf(sqrt(5*L[47]-L[48])); 283.4960317John
enhancements were made to zip
As stated in ?updates,Maple12,efficiency:
Which are these "certain routines"? Apparently 'sqrt' is not one of those.
2-parameter routines
That paragraph is in the section covering the zip() function. It's not surprising that sqrt() may not be one of the affected routines. The zip() routine "zips" an action across two parameters, while sqrt() takes the square root of a single parameter.
About the only way I can see to even make zip(sqrt,A,B) valid is for B to be merely an option such as 'symbolic'. But that wouldn't be particularly apt here and would likely not help much in the hardware datatype rtable case, which is also central (but left out, above) to that quoted paragraph covering zip's enhancements..
acer
May be not surprising
and may be that you are right, but it is not obvious and could be otherwise. You have to make an interpretation of the meaning of this paragraph: "certain routines" may be binary unary or whatever routines. It would be very simple for the writer of this help page to be explicit. And I do not find any clear reference to this issue in ?zip either.
zip's help page
The first line of the help-page ?zip says, " zip together two lists, matrices, or vectors."
The first line of zip's help-page's Description says, "The function zip applies the binary function f to the components of two data sets..."
How could it be more clear?
acer
Yes
This paragraph can be written much more clearly.
If that were the case, in that paragraph it should say "this and such binary routines", ie listing them, it is not much work, instead of something so vague as "certain routines". That paragraph does not exclude other interpretations.
inline?
Where is "inline" documented as an option for map? The help page only has evalhf and inplace. Or did you mean inplace?
inplace
Yes, I meant inplace. In these examples it doesn't seem to make much of a difference though.
Perhaps, the sqrt code for integers could be improved?
Alec
Well i see there are some
Well i see there are some effective ways to accelerate things, although i don't like the idea to specify low level things like datatype=float[8] or similar. Maple should do this for me (probably not possible). Also, thanks for poining out that forNext loops are not generally bad in terms of processing time. Moreover, you can easily specify stepsize->more flexibility.
Of course seq, zip and map allow a more compact notation, as there is no embracing do..end do term.
original data was exact
The original data was exact, so it would not be appropriate if Maple were automatically to convert the data to floating-point and then give a corresponding floating-point result (which is what those super fast methods above do).
acer