2
$\begingroup$

How does one efficiently produce a plot of {f[x], f[x]+1}? Assume that f[x] is a long computation, which I would like to avoid doing twice.

For example:

f = (Pause[.01]; #)&
Plot[f[x], {x, 0, 1}]
Plot[{f[x], f[x]+1}, {x, 0, 1}]

The second plot takes twice as long as the first plot to render, whereas it could be done in about the same amount of time if f[x] was memoized appropriately.

$\endgroup$
  • $\begingroup$ I remember a duplicate but I can't find it :/ $\endgroup$ – Kuba Feb 1 '15 at 19:36
  • $\begingroup$ Would you like the solution to handle discontinuous functions f (just like Plot does)? (ListLinePlot/ListPlot+Joined -> True does not do that.) $\endgroup$ – Michael E2 Feb 1 '15 at 20:47
  • $\begingroup$ Consider making your memoized remark into a complete answer. I think that's interesting and one is allowed to answer one's own question. (Unless your question is how to memoize it?) $\endgroup$ – Michael E2 Feb 1 '15 at 20:54
  • $\begingroup$ @Kuba Yeah, this has been asked before. I'll start looking. $\endgroup$ – Mr.Wizard Feb 2 '15 at 1:00
  • $\begingroup$ Okay, the one I found is not an exact duplicate but I propose closing anyway, unless the trivial solution of Plot[{#, #+1}& @ f[x], {x, 0, 1}] is accepted here. That however doesn't style lines separately. Therefore... $\endgroup$ – Mr.Wizard Feb 2 '15 at 1:11
2
$\begingroup$

Well, since Plot just samples the function to plot it, then it is really the same thing as when you sample it yourself using Table command. So why not sample the function once, then use ListLinePlot to plot the data. Adding 1 to the computed data is now no longer expensive since the computation of f[x] is already done.

f[x_] := Sin[x];
data = Table[f[x], {x, -2 Pi, 2 Pi, Pi/20}];
ListLinePlot[{data, data + 1}, DataRange -> {-2 Pi, 2 Pi}]

Mathematica graphics

The above is the same as if one did this, but now f[x] is sampled once

f[x_] := Sin[x];
Plot[{f[x], f[x] + 1}, {x, -2 Pi, 2 Pi}]

Mathematica graphics

$\endgroup$
2
$\begingroup$

As an example "expensive computation", let

f[x_] := (Pause[.01]; Sin[x]);

It's pretty easy to memoize f:

F[x_] := F[x] = f[x];

Then just plot the result:

Plot[F[x] + Range[5], {x, 0, 2}]

This takes 4.65 seconds. In contrast, replacing F with f takes 22.8 seconds, indicating that the computation is only performed once with memoization, rather than five times.

$\endgroup$
1
$\begingroup$

Consider

ft=Table[f...];
ListPlot[{ft,ft+1},Joined->True]

I have used that very successfully with extremely slow plots in the past. Just choose your table points carefully based on your f.

If you just cannot resist the compulsion to desktop publish each plot separately then you could do multiple ListPlot, each appropriately rendered, and combine all them with Show.

$\endgroup$

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.