9
$\begingroup$

I would like some advice about the use of memoization in conjunction with conditional statements. Let me try to explain my problem:

I am constructing a function depending on a number of parameters. Given a set of values I first need to check if they meet certain conditions and then calculate the value of the function like so:

myfunction[V_,a_,b_,c_]:=Block[
                          {v1},
                          If[TrueQ[a<b]&&TrueQ[b>c],Abort[]];
                          a*V^2+b*V+c
                          ]

The reason why I am constructing the function this way is because I need to study the variation of myfunction with V for different values of the parameters a, b and c and eventually plot some dependencies. So what I would like to have is to stop the evaluation of the function if the set of parameters a, b and c does not meet the conditions and if they do to plot the variation with V (this case is the easy part).

In its current form myfunction evaluates without a problem, but is quite slow. Having the If evaluated for every value of V when plotting the function, is very time consuming, considering that it only needs to be evaluated once.

So I thought I found the solution when I read about memoization. I have tried to rewrite the function like this:

myfunction[V_,a_,b_,c_]:=Block[
                          {v1,memo},
                          memo:=memo=If[TrueQ[a<b]&&TrueQ[b>c],Abort[],0.];
                          a*V^2+b*V+c
                          ]

But it is not working. The Abort[] is never evaluated, only when TrueQ is False memo becomes 0 and that's all.

Is there a way to accomplish this?

Let me know if you need more details.

Update:

Thank you very much for your comments. Following ybeltukov's suggestion I have tried the following:

created a function

ExistCond[a_,b_,c_]=Block[
                     {some parameters},
                     definitions;
                     TrueQ[a<b]&&TrueQ[b>c](*main conditions to be satisfied*)
                    ];

then use it as follows with myfunction:

myfunction[V_,a_,b_,c_]/;ExistCond[a,b,c]:=myfunction[V,a,b,c]=Block[
                                                                {extra parameters},
                                                                definitions;
                                                                a*V^2+b*V+c
                                                                ];

Unfortunately when I plot myfunction it takes a long time first time I evaluate the plot and alas, the second time is very fast. But this is not what I intended. I was expecting that If the conditions in ExistCond evaluate to True then for the rest of the values of V, ExistCond is not evaluated again. I have a feeling I am confusing how memoization works.

$\endgroup$
6
  • 1
    $\begingroup$ myfunction[V_, a_, b_, c_] /; a < b && b > c := myfunction[V, a, b, c] = a*V^2 + b*V + c;? $\endgroup$ Commented Oct 18, 2014 at 12:17
  • $\begingroup$ /; is more convenient for conditions. For example, see my recent answer with conditions and memoization . $\endgroup$ Commented Oct 18, 2014 at 12:18
  • $\begingroup$ @belisarius or a bit more compact: mem : myfunction[V_, a_, b_, c_] /; a < b && b > c := mem = a*V^2 + b*V + c; $\endgroup$ Commented Oct 18, 2014 at 12:20
  • $\begingroup$ note for this simple example it may not be apparent if a solution has successfully avoided reevaluating the function definition for each V. For testing purpose you might want to use a fuction like (Pause[10];a V^2+b V+c) $\endgroup$ Commented Oct 18, 2014 at 12:42
  • $\begingroup$ Based on your last update, perhaps you need to memoize ExistCond[] instead $\endgroup$ Commented Oct 18, 2014 at 13:46

2 Answers 2

4
$\begingroup$

I'd do something like this:

myfunction[V_, a_, b_, c_] :=
  Block[{v1},
    If[TrueQ[a < b] && TrueQ[b > c], 
    Abort[],
    (* else *)
    myFunction[v1_, a, b, c] = a*v1^2 + b*v1 + c;
    myFunction[V, a, b, c]
  ]];

It is similar to my answer here. Basically, you memoize on some of the arguments.

$\endgroup$
3
$\begingroup$

Edit: revision - for this to work properly you need to evaluate the expression inside the function:

 myfun[a_,b_,c_]/; a < b && b > c:=
     myfun[a,b,c]=Function[{V}, Evaluate[ function code ] ]

usage is then for example:

 Plot[myfun[a,b,c][V],{V,0,1}]

if you need the Abort you can simply do

  myfun[a_,b_,c_]:=Abort[]

which will naturally catch anything missed by the conditional definition

Specific example:

Suppose we have a function with an expensive part that depends only on some of the parameters:

 f[a_, x_] /; a>0  := NIntegrate[ Cos[a  t ]^2 , {t, 0, Pi }]  ( x + a );
 Table[ Table[ f[a, x] , {x, 100}] , {a, 50}] // Timing // First

82.321728

now memorize the function for each different a:

 Clear[f];
 f[a_] /; a > 0 := f[a] = Function[{x}, 
    Evaluate[  NIntegrate[ Cos[a  t ]^2 , {t, 0, Pi }]  ( x + a ) ]];
 f[a_] := Abort[];
 Table[ Table[ f[a][ x] , {x, 100}] , {a, 50}] // Timing // First

0.015600

 f[0]

$Abort

@LeonidShifrin's approach of course works as well. Mine is a smidge faster, i suspect because because the /; pattern test beats the explicit If[].

$\endgroup$
1
  • $\begingroup$ I have tried that, after seeing your and ybeltukov's answer (how do you reference a name?) but it doesn't seem to be what I am looking for (see the updated post!) $\endgroup$ Commented Oct 18, 2014 at 13:36

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.