MathGroup Archive 2004

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

Search the Archive

Re: Re: Compile

  • To: mathgroup at smc.vnet.net
  • Subject: [mg45337] Re: [mg45333] Re: Compile
  • From: Andrzej Kozlowski <akoz at mimuw.edu.pl>
  • Date: Thu, 1 Jan 2004 05:54:30 -0500 (EST)
  • References: <200312310823.DAA08660@smc.vnet.net>
  • Sender: owner-wri-mathgroup at wolfram.com

First, I have to admit that my early, not carefully considered response 
to Maxim's examples was quite wrong. I failed to see that a lot more is 
going on under the hood than I at first suppose. I still stand by the 
assertion that all this is quite irrelevant. Maxim loves pathological 
examples because he thinks they prove some point he is trying to make 
(I am not even really sure what it is). In fact none of these examples 
would ever arise in practice: any moderately knowledgeable user of 
Mathematica knows that if you want to use the compiled->True (default) 
option setting in Plot your function has to be written out in-line or 
you have to use Evaluate. Moreover, his second example makes no sense 
at all except as an attempt to produce something mystifying, that will 
than allow him to suggest that something is badly wrong.
But any way, once the  reservation that all this has no relevance 
whatever to any practical usage of Mathematica has been made, we can 
try to play a little detective game, that may be perhaps even 
interesting as "art for art's sake".
So first of all, let's not that Maxim's first example

Module[{subs = x -> x^2},
   Plot[x /. subs, {x, 0, 1}, Compiled -> True]
]
Module[{subs = x -> x^2},
   Plot[x /. subs, {x, 0, 1}, Compiled -> False]
]


was in a way an exception, and that mislead me. The two examples 
produce different answers, and the second one gives the same output as 
when you use Evaluate in Plot, but it actually need not always be so 
and in fact is a rather special case. Just change it a little:

Module[{subs = x -> x^(1/3)},
   Plot[x^3 /. subs, {x, 0, 1}, Compiled -> True]
]
Module[{subs = x -> x^(1/3)},
   Plot[x^3 /. subs, {x, 0, 1}, Compiled -> False]
]

and you see no difference, both cases giving the cubic curve, while the 
correct approach, which any competent Mathematica user (except of 
course Maxim) would use:


Module[{subs = x -> x^(1/3)},
   Plot[Evaluate[x^3 /. subs], {x, 0, 1}, Compiled -> True]

gives a straight line. In fact, even in case when you do not Compile 
but when your function is not defined "in line" you should generally 
use Evaluate, for obvious reasons which have nothing to do with 
compilation. (This demonstrates the practical uselesness of both of 
Maxim's examples).
Secondly, you can see exactly what happens in all these cases if you use

Trace[  , TraceInternal->True]


And when you examine this you come to the following conclusion: that 
with the setting Compiled->False everything is predictable and there is 
no difficulty in explaining it. With the setting Compiled->True 
(without Evaluate), behaviour is more difficult to predict. But that is 
not actually surprising, because using the setting Compile->True in 
such cases without Evaluate is simply bad or incompetent Mathematica 
programming, contrary to the documentation and when you do that you 
can't complain that funny things happen (not that this sort of argument 
will ever stop Maxim).

Now let's quickly look at the output of Trace[ ,TraceInternal->True] in 
Maxim's examples. I won't include the output here for it is very long 
but just comment on some obvious aspects.

In the first example:

Module[{subs = x -> x^2}, Plot[x /. subs,
     {x, 0, 1}, Compiled -> False]]

The function to be plotted is first turned to x/x->x^2 which is not 
evaluated but numeric values of x are substituted in turn, thus giving 
things like:


4.16667 10^-8 /. 4.16667 10^-8   -> 1.73611 10^-15

and then the Plot is created. This has the same effect as using 
Evaluate, as I originally wrongly  claimed, but this this is just an 
accident because when we change the example to

Module[{subs = x -> x^(1/3)}, Plot[x^3 /. subs,
     {x, 0, 1}, Compiled -> False]]

we see different behaviour. Now the substitutions take the form:

0.0000667603 /. 0.040567 -> 0.343604

which now of course also has no effect.

In the case

Module[{subs = x -> x^2}, Plot[x /. subs,
     {x, 0, 1}, Compiled -> True]]

The values of x are computed but unlike in Compiled->False case  not 
substituted into the rule subs. In other words the points to be plotted 
are


4.16667 10^-8   /. x ->x ^2

etc, which means that the rule has no effect and we get a straight line.

But in the modified example

Module[{subs = x -> x^(1/3)}, Plot[x^3 /. subs,
     {x, 0, 1}, Compiled -> True]]

we see a different behaviour. CompiledFunction makes an appearance 
(although clearly compilation fails) and also the substitution rules 
fail to substitute but in a different way (similar to the 
Compiled->False setting).

In the the case

Module[{y := If[NumericQ[x], x, 1]}, Plot[x y, {x, 0, 1}, Compiled -> 
False]]

analogously to the first case above, the test If[NumericQ[x], x, 1] is 
applied to numeric values in pointwise way, but, in the case

Module[{y := If[NumericQ[x], x, 1]}, Plot[x y, {x, 0, 1}, Compiled -> 
True
     ]]

the test is applied with symbolic x resulting in the answer 1.

In both cases, when the Compiled->False is used, the "external" 
condition or definition is applied "pointwise".  This behaviour is 
predictable and agrees with the documentation.  In the case of 
Compile->True the explanation is essentially the one given by Bill 
Rowe, except that one should add that once compilation fails 
Mathematica proceeds to make a (wrong) plot, in a way which seems to 
depend on the character of the function that is being plotted and the 
external rules using to define it (you sometimes see  CompiledFunciton 
in the output of Trace and sometimes don't). But as many people have 
already pointed out, when you are doing what you should not be doing, 
you can't complain that you are getting unpredictable results.

Andrzej Kozlowski

On 31 Dec 2003, at 17:23, Bill Rowe wrote:

> On 12/30/03 at 4:14 AM, dontsendhere@. (Maxim) wrote:
>
>> I don't see any problem with Plot[Random[],{x,0,1},Compiled->True] 
>> either, it was just an
>> illustration (if you don't like Random[], you can insert A Very
>> Complicated Expression instead). But you have to read the thread from 
>> the beginning, the problem is
>> with
>>
>> Module[{y := If[NumericQ[x], x, 1]},
>>   Plot[x y, {x, 0, 1}, Compiled -> True]
>> ]
>
> But this too works as should be expected from the documentation. In 
> order for the expression x y to be Compiled it must be evaluated and 
> this must happen before Plot assigns values to any portion of the 
> expression. Consequently, when it is evaluated x is not numeric so y 
> evaluates to 1 and the product evaluates to x. Hence, with 
> Compiled->True a line with slope = 1 results.
>
> OTOH, with Compiled->False, Plot supplies a numeric value to x then 
> evaluates the expression. Since x is now numeric, y evalutes to x and 
> the product evaluates to x^2. The resulting plot is a parabola.
>
> --
> To reply via email subtract one hundred and four
>
>
>
Andrzej Kozlowski
Chiba, Japan
http://www.mimuw.edu.pl/~akoz/


  • Prev by Date: Re: Printing "Alias" Definitions
  • Next by Date: Mathematica exports curves in pieces to Illustrator
  • Previous by thread: Re: Compile
  • Next by thread: Re: Compile