11
$\begingroup$

I like using memoization (i.e. the construct myFunction[x_]:=myFunction[x]=...) when I have a heavy function that I need to re-evaluate on the same arguments. However, I find it frustrating that each time I quit the kernel(s), all the advantage goes lost.

Is there a way of saving the results? I can think of a very cumbersome way of doing it, such as this block upon defining our function

memo = If[FileExistsQ[FileNameJoin[{Directory[], "memo.mx"}]], Import["memo.mx"], {}];
myFunction[x_] := Module[{value = ...},
AppendTo[memo, "myFunction[" <> ToString[x] <> "]=" <> ToString[value]]; 
Export["memo.mx", Union@memo];
myFunction[x] = value]
Evaluate[ToExpression/@memo];

Is this okay, or is there a better (or even designated) way of doing this?

$\endgroup$
5
  • 3
    $\begingroup$ And DumpSave? $\endgroup$
    – unlikely
    Feb 19, 2015 at 17:16
  • $\begingroup$ I guess that does it! (I'm checking) $\endgroup$
    – Ziofil
    Feb 19, 2015 at 17:17
  • $\begingroup$ Yes! Thank you :D $\endgroup$
    – Ziofil
    Feb 19, 2015 at 17:22
  • 2
    $\begingroup$ @unlikely Can you post an answer? $\endgroup$
    – Szabolcs
    Feb 19, 2015 at 17:43
  • $\begingroup$ Here's a solution using Once to construct persistent memoization. $\endgroup$
    – Roman
    Mar 19, 2021 at 7:59

2 Answers 2

14
$\begingroup$

Not much different from your approach and maybe not the best/safest approach, but DumpSave helps a bit because at least you don't have to works with strings:

cacheFile = FileNameJoin[{$TemporaryDirectory, "fibonacciCache" <> ".mx"}];
If[FileExistsQ[cacheFile],
 Get[cacheFile],
 fibonacci[1] = 1;
 fibonacci[2] = 1;
 fibonacci[n_Integer] := Module[{},
   fibonacci[n] = fibonacci[n - 1] + fibonacci[n - 2];
   DumpSave[cacheFile, fibonacci];
   fibonacci[n]
   ]
 ]

For example

In[3]:= fibonacci[500] // Timing

Out[3]= {0.562500, \ 1394232245616978801397243828704072839500702565876973072641089629483255\ 71622863290691557658876222521294125}

Now Quit[]-ing and reevaluating the previous cell:

In[3]:= fibonacci[500] // Timing

Out[3]= {0., \ 1394232245616978801397243828704072839500702565876973072641089629483255\ 71622863290691557658876222521294125}

$\endgroup$
1
$\begingroup$

Here is another approach with LocalSymbol:

PersistentMemoize[key_, expr_] := Module[{name, value},
  name = "PersistentMemoize/" <> ToString[key // Hold // InputForm];
  value = LocalSymbol[name];
  If[Head[value] === LocalSymbol,
    value = LocalSymbol[name] = expr;
  ];
  value
];
SetAttributes[PersistentMemoize, HoldAll];

ClearPersistentMemoization[] := DeleteObject[LocalObjects["LocalSymbols/PersistentMemoize"]];

(* example *)

fib[n_] := fib[n] = PersistentMemoize[fib[n],
  Print["computing fib[" <> ToString[n] <> "]..."];
  fib[n - 1] + fib[n - 2]
];
fib[1] = 1;
fib[2] = 2;
```
$\endgroup$
1
  • $\begingroup$ Actually, after writing this answer, a further search leads me to an answer that looks nicer. $\endgroup$
    – tueda
    Mar 19, 2021 at 8:17

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.