2
$\begingroup$

This came up in the context of plotting solutions to NDSolve, but I've reduced it to the following issue. This really has me scratching my head.

points = {{0, 0}, {1, 1}, {2, 3}, {3, 4}, {4, 3}, {5, 0}};
ifun = Interpolation[points]

ifun is now an InterpolatingFunction. I cannot plot ifun, but I can plot ifun[t] thus:

Plot[ifun[t], {t,0.,1.0}]

If I make the following assignment, I cannot plot ifun2[t]:

ifun2[t] = ifun[t]

In other words, the following statement will not plot anything:

Plot[ifun2[t], {t,0.0,1.0}]

However, if I do this:

ifun3[t_] = ifun[t]

I can plot ifun3[t]. Now, if I ask: is ifun2[t] identical to ifun[t]

ifun2[t] == ifun[t]

The answer is "True". Similarly for ifun3[t], it is identical to ifun[t]. However, ifun3[t] plots, and ifun2[t] does not! How can ifun2[t] and ifun3[t] both be identical to ifun[t] if one plots and the other doesn't?

$\endgroup$
  • $\begingroup$ ifun2[t] plots for me v 12.0. Did you clear the kernel? $\endgroup$ – Bill Watts May 23 at 6:31
  • $\begingroup$ Could you send your code, and I'll try it? I am also using 12.0 and I've cleared the kernel multiple times. Another perspective: evaluating ifun2[1.0] returns "ifun2[1.0]", but evaluating ifun3[1.0] returns the number "1.". $\endgroup$ – Anthony Mannucci May 23 at 6:39
  • 2
    $\begingroup$ Plot has HoldAll attribute, when you try to plot ifun2[t], t is first replaced by some number and then rules are checked for ifun[some number], but only exact pattern ifun2[t] is defined for ifun2. ifun3 is defined for ifun3[any argument]. Check Downvalues[] of ifun2 and ifun3. See also reference.wolfram.com/language/tutorial/… $\endgroup$ – I.M. May 23 at 6:59
  • $\begingroup$ ifun is a pure function. To set ifun2 equal to ifun use ifun2 = ifun. Then test with (ifun /@ Range[0, 5, 0.1]) === (ifun2 /@ Range[0, 5, 0.1]). It will evaluate to True $\endgroup$ – Bob Hanlon May 23 at 15:14
2
$\begingroup$

This has to do with how Plot evaluates its arguments and the difference in how the arguments evaluate.

Clearly the OP knows there is a difference between a pattern t_ and a literal symbol t.

ifun2[t]  = ifun[t]
ifun3[t_] = ifun[t]

The two codes below show the difference in evaluation. On the one hand ifun2[t] is defined only when the argument is literally a t; ifun2[0.] is undefined, if t has the value 0.. On the other hand, ifun3[t] is defined whatever expression is substituted for t; it operates like a function.

Block[{t = 0.}, ifun2[t]]
(*  ifun2[0.]  *)

Block[{t = 0.}, ifun3[t]]
(*  0.  *)

Now Plot holds its arguments (it has the attribute HoldAll). The expression to be plotted is not evaluated until t is given a value like 0.. So the first plot below is blank because Plot gets ifun2[0.] instead of a number. The second code evaluates ifun2[t] before passing the value to Plot. It evaluates to ifun[t] and then to InterpolatingFunction[...][t]; when Plot evaluates, it has a numeric function and generates the plot.

Plot[ifun2[t], {t, 0.0, 1.0}]
Plot[Evaluate@ifun2[t], {t, 0.0, 1.0}]

In the code below, ifun3[t] will evaluate to the value of the interpolating function even when t is replaced by a different value. Hence, you get the desired plot.

Plot[ifun3[t], {t, 0.0, 1.0}]

In short, the definition of ifun3[] is to be the preferred method of defining functions.

Hmm, didn't read the comments: This is essentially what @I.M. said below the OP.

| improve this answer | |
$\endgroup$
0
$\begingroup$

My code is identical to yours. I just copied and pasted it. The plot works, but ifun2[1.0] does not work and it should not work because it is not of the form ifun2[t]. You need the underscore to use an argument that changes. What does work for ifun2 is

points = {{0, 0}, {1, 1}, {2, 3}, {3, 4}, {4, 3}, {5, 0}};
ifun = Interpolation[points]

ifun2[t]=ifun[t]

ifun2[1.0]
ifun2[1.]

does not work because you are missing the underscore with the t so only ifun2[t] works. This is all in the documentation. Notice this, however.

ifun2[t] /. t -> 1.0
(*1.*)

works and

Plot[ifun2[t], {t, 0., 1.0}]

works for me. I don't know why it doesn't work for you. Your ifun3 works fully because you are using the underscore with the argument in your function.

| improve this answer | |
$\endgroup$
  • 1
    $\begingroup$ Thanks. I see I was not thinking in the appropriate "Mathematica" way. The equivalence was not an equivalence between ifun2 and ifun3, but an equivalence between the specific cases ifun2[t] and ifun3[t]. If I use something other than t, they are no longer equivalent. I was (once again) thinking like a human who knows math, and mapping the incorrect concepts to what was going on. $\endgroup$ – Anthony Mannucci May 23 at 7:23

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.