32
$\begingroup$

I was just evaluating a couple of expressions and started to get errors like this:

General::ivar: -1.49994 is not a valid variable. >>
General::ivar: -1.43871 is not a valid variable. >>
General::ivar: -1.37749 is not a valid variable. >>
General::stop: Further output of General::ivar will be 
               suppressed during this calculation. >>

I'm doing nothing complicated - currently, I simply did this:

f[x_]:=x^2 + 2x + 1
Plot[f[x], {x, -4, 4}]
Solve[f[x] == 4]
g[x_]:=D[f[x], x]
Plot[g[x], {x, -2, 2}]
// ^ errors caused by this

Actually, this isn't the exact quadratic I am investigating, but it is a quadratic and I expected this to work. I googled, as you'd expect, and found this Stack Overflow question which suggested:

Plot[Evaluate[g[x]], {x, -2, 2}]

As a workaround.

It works - my question is, why doesn't that set of instructions generate that error (I can see it is something to do with replacing, but why is one plot different from the other?) and how can I avoid it? Is there something I should specifically have done in forming g?

$\endgroup$
4
  • 2
    $\begingroup$ Or you could do g[x_] = D[f[x], x] (note that I changed SetDelayed to Set) before plotting... $\endgroup$ Commented Feb 4, 2012 at 14:01
  • $\begingroup$ @J.M. that works - got an explanation as to why? Would make a nice answer :) $\endgroup$
    – user236
    Commented Feb 4, 2012 at 14:07
  • 2
    $\begingroup$ Related question: stackoverflow.com/questions/5320330/… $\endgroup$ Commented Feb 4, 2012 at 15:02
  • $\begingroup$ Use Unset or Clear $\endgroup$ Commented Oct 29, 2023 at 14:39

3 Answers 3

49
$\begingroup$

The problem lies in g[x_] := D[f[x], x]; remember that what SetDelayed (that is, :=) does is to replace stuff on the right corresponding to patterns on the left before evaluating. Thus, when one does something like g[2] (and something like this happens within Plot[]), you are in fact evaluating D[f[2], 2], and since one cannot differentiate with respect to a constant ;), you get the General::ivar error message.

If you use Set instead (that is, g[x_] = D[f[x], x]), f[x] is differentiated first before the result of D[] is assigned to g[x_]. Since what's on the right of g[x_] is now an actual function, Plot[] no longer has a reason to complain.

$\endgroup$
24
$\begingroup$

J. M. has already given you a good answer to your question on the General::ivar error and how to avoid it. I wanted to demonstrate another example in the same spirit, where the difference between Set and SetDelayed is important, but you don't have the luxury of getting an error message like you did in this case, because it isn't semantically/syntactically incorrect. This is a common pitfall to watch out for, and is often the cause of "slow" plotting.

Consider a function that's the result of an expensive (however slight) calculation defined using Set and SetDelayed, as:

f[x_] := (Pause[0.05]; Integrate[y^2, {y, 0, 1}] x)
g[x_] = (Pause[0.05]; Integrate[y^2, {y, 0, 1}] x);

Now let's monitor the time taken in plotting the two functions and the points plotted in each case with:

Module[{i = 0, t},
  t = (Plot[f[x], {x, 0, 1}, EvaluationMonitor :> i++]; // AbsoluteTiming // First);
  Print["Timing = ", t, ", Points = ", i, ", Time/Point = ",  t/i]
]

and replace f[x] with g[x] for the latter. I get the following for f[x] and g[x] respectively:

(*
f[x] — Timing = 4.289333, Points = 77, Time/Point = 0.05570562
g[x] — Timing = 0.001735, Points = 77, Time/Point = 0.00002253
*)

What's happening here is that Plot is evaluating f[x] for each plot point (time/point ≈ 0.05), which can result in a tremendous slow down in cases where the evaluation takes considerable time. On the other hand, if you use Set as in g[x], the expensive calculation is computed only once and only the result is stored as the definition for g[x], and hence Plot doesn't have to re-evaluate it. The alternative is to force evaluation of f[x] and pass the result to Plot and this can also be done by wrapping an Evaluate around f[x].

$\endgroup$
2
  • 3
    $\begingroup$ I like this example. :) $\endgroup$ Commented Feb 4, 2012 at 15:21
  • $\begingroup$ How come plotting Evaluate[f[x]] is still much slower then plotting g[x] (for a factor of six on my system)? $\endgroup$
    – BoLe
    Commented Jul 5, 2016 at 4:49
15
$\begingroup$

As has already been explained by J. M., you need to evaluate the derivative.

When using the format g[x_] = D[f[x], x] I highly recommend either localizing x or using \[FormalX] (enter with Esc $x Esc) in its place:

Module[{x},
  g[x_] = D[f[x], x]
]

Or:

Mathematica graphics

$\endgroup$
2
  • $\begingroup$ Could you elaborate a bit on this? specifically, 1) Why localize x? x_ is a pattern so it takes whatever we input in g, yes? unless one is worried that x might be defined elsewhere. 2) also, x is local here but g is not? (sorry, I am unsure). $\endgroup$
    – majmun
    Commented Feb 8, 2020 at 6:02
  • 2
    $\begingroup$ @majmun I am happy to answer this kind of question. Yes, my concern was an external value on x that would interfere with proper evaluation, e.g. (6664). I don't think there was anything more to it than that. $\endgroup$
    – Mr.Wizard
    Commented Feb 9, 2020 at 11:14

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.