Re: Why doesn't this work ?
- To: mathgroup@smc.vnet.net
- Subject: [mg10447] Re: Why doesn't this work ?
- From: Hein Hundal <hundalhm@vicon.net>
- Date: Tue, 13 Jan 1998 02:07:42 -0500
- References: <69cole$ep5@smc.vnet.net>
Andreas Keese wrote: > > Look at this: > > This works: > Clear[S1]; > S1=Sin[x]; > Plot[S1, {x, 0, 3}] > > But why doesn't it work with more than one functions ? > > Clear[S2]; > S2={Sin[x],Cos[x]}; > Plot[S2, {x, 0, Pi}] > > gives an error - Mathematica complains that S2 is not a machine-size > number. > > BTW: I don't want S2 to be pattern cause I want to use this as follows: > > Clear[S,dx,S3,x]; > S[x_]:={Sin[x/dx], Cos[x/dx], Sin[2*x/dx]}; > S3=Evaluate[S[x] /. dx -> 2]; > Plot[S3, {x, 0, Pi}]; > > Bye, > Andreas Andreas, First let me say that the following works. S2={Sin[x], Cos[x]}; Plot[Evaluate[S2], {x, 0, Pi}] and Clear[S,dx,S3,x]; S[x_] := {Sin[x/dx], Cos[x/dx], Sin[2*x/dx]}; S3 = Evaluate[S[x] /. dx -> 2]; Plot[Evaluate[S3], {x, 0, Pi}]; In General, you want to evaluate the first argument passed to Plot whenever it a symbol that evaluates to the expression that you want to plot. Sometimes you can get away without Evaluate, as in your first example, but Evaluate would speed it up. On My Computer I get the following results for 10 Plots, In[15]:= Block[{$DisplayFunction = Identity}, Sum[ S2=Sin[x]; First[Timing[Plot[Evaluate[S2], {x, 0, Pi}]]], {10}]] Out[15]= 0.06 Second In[16]:= Block[{$DisplayFunction = Identity}, Sum[ S2=Sin[x]; First[Timing[Plot[S2, {x, 0, Pi}]]], {10}]] Out[16]= 0.27 Second Evaluating S2 improves the speed 4.5 fold. If you used the default display function, there is only a minor improvement in speed. The hard questions are why does this work and why is it faster. I will try to give an explanation, but maybe someone else can improve or correct my conception of the situation. 1) Why does Evaluating work? Plot[] has the HoldAll attribute. I think Plot will first check to see if the first argument is a list. When you type Plot[S2, {x,0,Pi}], it sees that the first argument is a symbol, not a list, and then decides the plot is only a single function plot. Later it evaluates S2 with x set to specific Real numbers and finds that the result is of type List, not Real. So that results in an error message. When you type Plot[Evaluate[S2], {x,0,Pi}], the Evaluate function overrides the HoldAll atrribute. So S2 then evaluates to {Sin[x], Cos[x]} before the Plot function gets to see it. When the Plot function checks the first argument it now sees that it is a list, so it sets up correctly for a multifunction plot. 2) Why is it faster? I think a number of things are slowing down the evaluation of Plot[S2, {x,0, Pi}]. I found 3 reasons why the Evaluation step increases the speed. There may be more reasons, but I couldn't find them. 2a) I think Plot[] tries to compile the expression S2 and fails. This takes some time. On my machine, setting the compiled option to False, speeds up the evaluation. In[32]:= Block[{$DisplayFunction = Identity}, Sum[ S2=Sin[x]; First[Timing[Plot[S2, {x, 0, Pi}]]], {100}]] Out[32]= 2.74 Second In[33]:= Block[{$DisplayFunction = Identity}, Sum[ S2=Sin[x]; First[Timing[Plot[S2, {x, 0, Pi}, Compiled->False]]], {100}]] Out[33]= 1.37 Second 2b) Another reason that Plot[S2, {x,0,Pi}] is slower than Plot[Evaluate[S2], {x,0,Pi}] is that in the first expression, S2 is looked up several times, whereas the second expression converts S2 to Sin[x] only once. This is demonstrated by the following code. In[38]:= evals = 0; S2:= (Print["Evaluation "<>ToString[evals++]]; Sin[x]); Plot[Evaluate[S2], {x,0,Pi}, DisplayFunction->Identity]; "Evaluation 0" In[39]:= Plot[S2, {x,0,Pi}, DisplayFunction->Identity] "Evaluation 1" "Evaluation 2" "Evaluation 3" "Evaluation 4" "Evaluation 5" "Evaluation 6" "Evaluation 7" "Evaluation 8" "Evaluation 9" "Evaluation 10" "Evaluation 11" "Evaluation 12" "Evaluation 13" "Evaluation 14" "Evaluation 15" "Evaluation 16" "Evaluation 17" "Evaluation 18" "Evaluation 19" "Evaluation 20" "Evaluation 21" "Evaluation 22" "Evaluation 23" "Evaluation 24" "Evaluation 25" "Evaluation 26" "Evaluation 27" "Evaluation 28" "Evaluation 29" "Evaluation 30" "Evaluation 31" "Evaluation 32" "Evaluation 33" "Evaluation 34" "Evaluation 35" "Evaluation 36" "Evaluation 37" "Evaluation 38" "Evaluation 39" "Evaluation 40" "Evaluation 41" "Evaluation 42" "Evaluation 43" "Evaluation 44" "Evaluation 45" "Evaluation 46" "Evaluation 47" "Evaluation 48" "Evaluation 49" "Evaluation 50" "Evaluation 51" "Evaluation 52" "Evaluation 53" "Evaluation 54" "Evaluation 55" "Evaluation 56" 2c) The last reason that Plot[Evaluate[S2], {x,0,Pi}] is slower is that once S2 is evaluated, it is successfully compiled. This is demonstrated by the code below. In[31]:= Block[{$DisplayFunction = Identity}, Sum[ S2=Sin[x]; First[Timing[Plot[Evaluate[S2], {x, 0, Pi}]]], {100}]] Out[31]= 0.76 Second In[30]:= Block[{$DisplayFunction = Identity}, Sum[ S2=Sin[x]; First[Timing[Plot[Evaluate[S2], {x, 0, Pi}, Compiled->False]]], {100}]] Out[30]= 1.16 Second Thanks for the question. I learned a lot while trying to figure out the answer. Hein Hundal