MathGroup Archive 1998

[Date Index] [Thread Index] [Author Index]

Search the Archive

Re: Why doesn't this work ?



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



  • Prev by Date: RE: howto interrupt with mathlink
  • Next by Date: RE: Re: Rotate3D bug solution
  • Prev by thread: RE: Why doesn't this work ?
  • Next by thread: Re: Why doesn't this work ?