# Factor out invariant code from Plot

Given a simple Gaussian kernel

UnscaledKernel[a_, b_, sigma_] :=
Exp[-(((a - b)/sigma).((a - b)/sigma))/2]


and un-normalized smoothing function

Smooth[valCountLst_, val_, sigma_] :=
Sum[valCountLst[[i]][[2]]*
UnscaledKernel[{valCountLst[[i]][[1]]}, {val}, sigma], {i, 1,
Length[valCountLst]}];


and a normalization constant so that the integral on the defined domain is 1:

ScalingFactor[valCountLst_, sigma_, lower_, upper_] :=
Integrate[
Smooth[valCountLst, everyVal, sigma], {everyVal, lower, upper}]


From this unsmoothed data (that is, 1000 items at value 0 and 10 items at value 1):

testList = {{0, 1000}, {1, 10}};


I'm plotting smoothed (un-normalized) data takes 0.024 seconds:

Plot[N[Log[Smooth[testList, x, 0.2]]], {x, 0, 1.0}] // Timing


(output is {0.024, THEFIGURE}).

When plotting the smoothed, normalized data, it takes much longer, 13.09 seconds:

Plot[N[Log[
Smooth[testList, x, 0.2]/ScalingFactor[testList, 0.2]]], {x, 0,
1.0}] // Timing


This seems strange since the scaling factor takes only 0.044 seconds to compute.

My conclusion is that Mathematica is computing the scaling factor for every point, even though it does not depend on the point value x.

Is there a way to help Mathematica compute this expression once and factor it out (or memoize it)?

Thanks a lot.

-

You could also use the Evaluated -> True undocumented option:

Plot[N[Log[Smooth[testList, x, 0.2]/ScalingFactor[testList, 0.2]]],
{x, 0, 1.0}, Evaluated -> True]


Please note that I had modified your definition of ScalingFactor to

ScalingFactor[valCountLst_, sigma_] := Integrate[ Smooth[valCountLst, x, sigma], {x, 0, 1}]


because you're calling it with the wrong number of parameters in your question

-

Is there a way to help Mathematica compute this expression once and factor it out (or memoize it)?

I'd use With[], like so:

With[{sc = ScalingFactor[testList, 0.2]},
Plot[Log[Smooth[testList, x, 0.2]/sc], {x, 0, 1}]

-
+1 Thanks, I used that elsewhere. – user Oct 9 '12 at 8:20