2
$\begingroup$

I use functions that memorize their values like this one:

bva2N[(k_)?IntegerQ, (bv_)?NumericQ, (p_)?NumericQ] := 
    bva2N[k, bv, p] = NIntegrate[bva2sub[bv, p*(1 - \[Psi]^k)], 
      {\[Psi], 0, 1}, Method -> {"LocalAdaptive", "SymbolicProcessing" -> 
         False}]

They produce hundreds of thousands of DownValues which I don't want to Save together with my results. Of course, I can delete these DownValues using such a script:

clearCache[f_] := 
  DownValues[f] = 
   DeleteCases[DownValues[f], _?(FreeQ[First[#], Pattern] &)];

funcs = {b, a2N, a2D1N, a2D2N, bva2N, bva2D1N, bva2D2N, P1N, P1D1N, A1N, A1D1N, B1N, B1D1N};

ParallelEvaluate[clearCache[#] & /@ funcs];
Evaluate[clearCache[#] & /@ funcs];

However I'd like to keep these DownValues for further use in current session. I guess that it is possible to save somehow these values in temporal arrays and then restore after saving my results. But it takes some appreciable time and many dozens megabites of memory.

Is there a better way to reach my goal?

$\endgroup$

2 Answers 2

2
$\begingroup$

Okay, something like this might work.

g[][x_] := x^2;
g[x_] := memo`g[x];
memo`g[x_] := memo`g[x] = g[][x]

When you save, exclude the memo context:

Save[filename, g, ExcludedContexts -> "memo`"]

This is a bit like defining a template first and then an implementation that defers to a memoizer which can extract the template.

Update

You could refine this for polymorphic cases (and just a more general abstraction):

g[][x_] := x^2;
g[][x_, y_] := x^y
g[args__] := memo`g[args];
memo`g[args__] := memo`g[args] = g[][args]
$\endgroup$
3
  • $\begingroup$ Thank you very much for this answer. I'll choose the best of two solutions after testing for speed which is most important in my case. $\endgroup$ Nov 13, 2023 at 0:38
  • $\begingroup$ I have lot of functions defined like this: a2N[(k_)?IntegerQ, (bv_)?NumericQ, (p_)?NumericQ] := a2N[k, bv, p] = NIntegrate[Re[a2sub2[bv, p*(1 - \[Psi]^k)]], {\[Psi], 0, 1}, Method -> "LocalAdaptive", AccuracyGoal -> 10] Is there a way to automatically transform this definition to your definition? E.g.: Do[....{fun,{a2N,a2D1N,a2D2N....] $\endgroup$ Nov 30, 2023 at 4:27
  • $\begingroup$ Yes, I think so, but I think it would involve directly manipulating DownValues and SubValues for each symbol. If that's really worth your time and you need help with it, then I think it warrants a separate question. But if you do add a new question, please simplify it. Use dummy definitions rather than NIntegrate and remove dependencies on extraneous symbols. $\endgroup$
    – lericr
    Nov 30, 2023 at 16:31
2
$\begingroup$

One way would be to use a separate symbol for the memoization. Here is a toy example:

ClearAll[f, fmemo]

f[0] = 1;
f[n_] := fmemo[n] /. m_fmemo :> (m = n * f[n-1])

Now, after we evaluate an expression using f:

f[5]
(* 120 *)

the definition of f is unchanged:

??f

definition of f

but the memoized values have been stored under fmemo:

??fmemo

definition of fmemo

If desired, the values of fmemo can be cleared using Clear[fmemo] without impacting the definition of f.

$\endgroup$
1
  • $\begingroup$ Thank you very much for this answer. I'll choose the best of the two solutions after testing for speed which is most important in my case. $\endgroup$ Nov 13, 2023 at 0:38

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.