7

I want to implement the recursive function

 v[n_] := v[n] = v[n-1] + f[n-1] + Random[NormalDistribution[0,s]] 

to get vel = {v[0], v[1],..., v[N]}.

I want to compute $M$ replicates of vel. How do I clear the memory of $v$ after each replicate of vel? If I don't I get the same vel repeated $M$ times.

Mike Honeychurch
  • 37,541
  • 3
  • 85
  • 158

2 Answers2

15

Suggested solution

If I understood the question right, then the simplest solution here would probably be to define a helper function like the following:

vv[n_] := Internal`InheritedBlock[{v}, v /@ Range[n]];

Then, you get

vel = vv[m]

and every run of vv would result in different set of values, while the values in the set will all come from the same memoization "run".

The presence of Internal`InheritedBlock guarantees that whatever values were remembered inside of it, will be cleared automatically when the execution leaves the block.

Example

For example:

ClearAll[f, v, s, vv];
s = 1;
f[x_] := x;
v[0] := 0;
v[n_] := v[n] = v[n - 1] + f[n - 1] + Random[NormalDistribution[0, s]];
vv[n_] := Internal`InheritedBlock[{v}, v /@ Range[n]];

Test:

vv[10]

(* {-0.0712327, 1.67558, 4.93819, 9.21973, 13.7199, 17.3607, 22.7843, 31.0941, 37.9027, 47.6244} *)

vv[10]

(* {-3.29625, -2.51668, -0.464889, 1.71271, 4.70297, 9.78192, 15.8081, 22.5965, 29.3856, 38.323} *)

Links

Closely related questions:

Leonid Shifrin
  • 114,335
  • 15
  • 329
  • 420
  • 1
    Array[v, n] could be used, too. Is there any reason why Internal`InheritedBlock[] is necessary here? – J. M.'s missing motivation Nov 09 '15 at 18:44
  • 3
    @J.M. I added the explanation to the post. The reason is to clear the memoized values, after each run. – Leonid Shifrin Nov 09 '15 at 18:49
  • I didn't see this answer before I wrote this one where I automate the process of storing and clearing cached values with a wrapper function. – Sjoerd Smit Oct 04 '20 at 11:25
  • 1
    @SjoerdSmit Sure thing (it is hard to know about all the answers, probably impossible). I wouldn't vote it up if I didn't think it had novel parts, too :). I don't think there is an exact answer like yours anywhere on the site (although as I said, there are bits and pieces scattered), and I think your answer is valuable. – Leonid Shifrin Oct 04 '20 at 11:37
0

You really want to define the collection of vs when you produce a realization of vel, so I'd replace this with

vel[n_] := Module[{},
  Table[
    v[k] = v[k - 1] + f[k - 1] + Random[NormalDistribution[0, s]],
  {k, 0, n}]
]

This generates a new set of vs every time you call vel[]. (The bulk of this could be replaced by NestList[], but I'm not convinced it buys much to do so.) You don't give any hints about the base case of your recursion, about s, or about what f does, so

Block[{s = 1},
  Print[vel[3]];
  Print[v[2]];
  Print[v[2]];
  Print[vel[3]];
]
v[2]
(*  {-1.39483+f[-1]+v[-1],-1.17269+f[-1]+f[0]+v[-1],-0.19439+f[-1]+f[0]+f[1]+v[-1],0.863082 +f[-1]+f[0]+f[1]+f[2]+v[-1]}  *)
(*  -0.19439+f[-1]+f[0]+f[1]+v[-1]  *)
(*  -0.19439+f[-1]+f[0]+f[1]+v[-1]  *)
(*  {-0.811165+f[-1]+v[-1],-0.959559+f[-1]+f[0]+v[-1],-2.25842+f[-1]+f[0]+f[1]+v[-1],-1.75508+f[-1]+f[0]+f[1]+f[2]+v[-1]}  *)
(*  -2.25842 + f[-1] + f[0] + f[1] + v[-1]  *)

The vs keep their values between calls to vel[] and change on each call to vel[]. If you want to reuse a vel without changing the vs, store it.

Eric Towers
  • 3,040
  • 12
  • 14