Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

How to avoid repeated recalculation of the same function

93 views
Skip to first unread message

pgei...@gmail.com

unread,
May 2, 2014, 2:18:56 AM5/2/14
to
Hi,

I'm doing a calculaton that's purly symbolic (no graphing, numerical integration, etc.).

Suppose I have a function f[x_]:=... that's very complex to build. In fact, f[x] ends up being a manageable expression (about 30 characters) but it takes Mathematica about 30 min to build that expression.

Another function g[] uses the function f[x] and references it many times. I've discovered that g[] actually builds f[x] every time it's referenced which takes 30 minutes each time. Theoretically, Mathematica could build it once and then use the resulting expression every time it's referenced.

So how do I accomplish that? That is, how do I make it build f[x] once and then use the resulting expression when it's needed?

Thanks,


Pavel

Sseziwa Mukasa

unread,
May 3, 2014, 3:39:32 AM5/3/14
to
If g is calling f with the same arguments all the time, memoize f: f[x_]:=f[x]=<expression>. Otherwise if the result of f is a simple symbolic expression, evaluate f once for x, then use the result to create another function h which g can call eg. simpleExpression = f[x]; h[y_]:= simpleExpression /. x->y; and call h from g instead of f.

Richard Fateman

unread,
May 3, 2014, 3:39:52 AM5/3/14
to
On 5/1/2014 11:18 PM, pgei...@gmail.com wrote:


Instead of f[x_]:= stuff, write

f[x_]:= (f[x]= stuff).

Then it remembers.


Bill Rowe

unread,
May 3, 2014, 3:40:12 AM5/3/14
to
On 5/2/14 at 2:18 AM, pgei...@gmail.com wrote:

>I'm doing a calculaton that's purly symbolic (no graphing, numerical
>integration, etc.).

>Suppose I have a function f[x_]:=... that's very complex to build.
>In fact, f[x] ends up being a manageable expression (about 30
>characters) but it takes Mathematica about 30 min to build that
>expression.

>Another function g[] uses the function f[x] and references it many
>times. I've discovered that g[] actually builds f[x] every time it's
>referenced which takes 30 minutes each time. Theoretically,
>Mathematica could build it once and then use the resulting
>expression every time it's referenced.

>So how do I accomplish that? That is, how do I make it build f[x]
>once and then use the resulting expression when it's needed?

Use Set rather than SetDelayed in the definition of f[x]. For
example, consider

In[1]:= f[x_] := Integrate[2 z + 3, {z, 0, x}];
g[x_] = Integrate[2 z + 3, {z, 0, x}];

Both accomplish the same thing as verified by

In[3]:= f[y] === g[y]
Out[3]= True

But notice the difference below

In[4]:= DownValues[g]
Out[4]= {HoldPattern[g[x_]] :> x^2 + 3*x}

In[5]:= DownValues[f]
Out[5]= {HoldPattern[f[x_]] :> Integrate[2*z + 3, {z, 0, x}]}

The integration step is done once with g but repeated every f is
called. And you can clearly see the difference this makes by
plotting both, i.e.,

In[6]:= Timing[Plot[f[x], {x, 0, 2}];]

Out[6]= {4.232786,Null}

In[7]:= Timing[Plot[g[x], {x, 0, 2}];]

Out[7]= {0.004068,Null}


Murray Eisenberg

unread,
May 3, 2014, 3:41:34 AM5/3/14
to
Did you try using Set ( = ) instead of SetDelayed ( := ) when defining f? That is, try:

f[x_] = expression


On May 2, 2014, at 2:18 AM, pgei...@gmail.com wrote:

> Hi,
>
> I'm doing a calculaton that's purly symbolic (no graphing, numerical integration, etc.).
>
> Suppose I have a function f[x_]:=... that's very complex to build. In fact, f[x] ends up being a manageable expression (about 30 characters) but it takes Mathematica about 30 min to build that expression.
>
> Another function g[] uses the function f[x] and references it many times. I've discovered that g[] actually builds f[x] every time it's referenced which takes 30 minutes each time. Theoretically, Mathematica could build it once and then use the resulting expression every time it's referenced.
>
> So how do I accomplish that? That is, how do I make it build f[x] once and then use the resulting expression when it's needed?
>
> Thanks,
>
>
> Pavel
>

Murray Eisenberg mur...@math.umass.edu
Mathematics & Statistics Dept.
Lederle Graduate Research Tower phone 240 246-7240 (H)
University of Massachusetts
710 North Pleasant Street
Amherst, MA 01003-9305







Bob Hanlon

unread,
May 3, 2014, 3:40:33 AM5/3/14
to

If the calculation can be done symbolicly use f[x_] = calc rather than
f[x_] := calc

You may also want to [Full]Simplify the expression, i.e., f[x_] = Simplify[
calc, assumptions ] to speed up subsequent use as well as improve numerical
precision.


Bob Hanlon

Joe Gwinn

unread,
May 3, 2014, 3:40:53 AM5/3/14
to
That bit me a few times as well.

Instead write f[x_]= ..., dropping the colon.

If you write only =, the ... is evaluated once and the result saved
under f[x_].

If you write :=, the whole ... is saved under f[x_], and evaluated
every time f[x] is invoked.

Joe Gwinn

Alex Krasnov

unread,
May 3, 2014, 3:41:54 AM5/3/14
to
Mathematica makes memoization easy. You can store the result directly in
the function definition using the idiom f[x_] := f[x] = (...). You can
then examine the stored results using Information[f].

Alex


On Fri, 2 May 2014, pgei...@gmail.com wrote:

> Hi,
>
> I'm doing a calculaton that's purly symbolic (no graphing, numerical integration, etc.).
>
> Suppose I have a function f[x_]:=... that's very complex to build. In fact, f[x] ends up being a manageable expression (about 30 characters) but it takes Mathematica about 30 min to build that expression.
>
> Another function g[] uses the function f[x] and references it many times. I've discovered that g[] actually builds f[x] every time it's referenced which takes 30 minutes each time. Theoretically, Mathematica could build it once and then use the resulting expression every time it's referenced.
>
> So how do I accomplish that? That is, how do I make it build f[x] once and then use the resulting expression when it's needed?
>
> Thanks,
>
>
> Pavel
>

psycho_dad

unread,
May 4, 2014, 2:27:12 AM5/4/14
to
Hey!

Consider the behavior of the two functions f and f1 (I have added the Pause[2] to give the impression of a long calculation):

f[x_]:=(Pause[2];x^2)
f1[x_]:= f1[x]=(Pause[2];x^2)

(Notice the f1[x_]:= f1[x] "trick" used above...)

Now evaluate both of them:
f[x]
f1[x]

both take a long time to evaluate the first time. Now repeat:
f[x]
f1[x]

you will notice that f1[x] was done instantaneously! The reason is that Mathematica has included the value as part of the definition due to the f1[x_]:= f1[x] "trick", so it remembers it after it evaluates it once.

There are also other ways to do what you want, eg hardcoding by hand the result for f[x] after you evaluate it once (assuming it it always the same) etc.

Cheers


Roland Franzius

unread,
May 4, 2014, 2:28:34 AM5/4/14
to
Mostly its enough to set (=) which evaluates the right hand side before
writing the definition

f[x_]=Integrate[1/(1+x^2),x]

?f

ArtTan[x]

The standard SetDelayed[ a,b ] - definitions don't evaluate b.

You can always write

SetDelayed@@{a, FullSimplify[b] }

to force b to be reduced to the simplest explicit form before making the
definition with :=.

But sometimes one wants to evaluate an expression but define the
expression with free patterns not to be evaluated.

For this case the best method is to use Evaluate, a function that
overides the Hold-Attribute and forces Hold-arguments in functions to
evaluated during input time

g[x_,a_ ]:= Integrate[1/(a + x^2),x]
h[x_,a_] := Evaluate[Integrate[1/(a + x^2),x]]

Unfortunately Mathematica lacks the input Attribute "Immediate", so
useful in the language FORTH.

This makes it very complicated to force the parser to evaluate certain
functions always regardless of Hold Attributes of function expression
are fed to.

The only workaround I see is to use the mouse selecting and
Shift+Contol+Enter replacement shortcut that Evaluates an expression in
the input line already and replaces it there with its current value,
text-symbolically

j[x_,a_]:= Shift+Ctr+Enter("FullSimplify[Integrate[1/(a + x^2),x]]")

--

Roland Franzius

0 new messages