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