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$
    – ybeltukov
    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$
    – ybeltukov
    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$
    – george2079
    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$
    – lucian
    Commented Oct 18, 2014 at 13:36

Your Answer

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

Not the answer you're looking for? Browse other questions tagged or ask your own question.