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/