0

I have a system of recursive equations

x[t+1]:=f[x[t],p[t-1],a[t],a[t-1]];
p[t+1]:=g[p[t],x[t-1],a[t],a[t-1]];
a[t+1]:=h[x[t],p[t],a[t],a[t-1]];

I want to evaluate them for $t \in [0,10]$ with some initial conditions on all variables. I tried several possibilities like,

Table[{x[t+1],p[t+1],a[t+1]}, {t, 0, 10}]

or

{x[#+1],p[#+1],a[#+1]}&/@Range[0,10]

but all of them are extremely slow. The MWE of the above might be given as

x[0] := 1; x[1] := 1; p[0] := 2; p[1] := 2; a[0] := 3; a[1] := 3; x[t_] := 2 p[t - 1] a[t - 1] - x[t - 1] a[t - 2]; p[t_] := 5 x[t - 1] a[t - 1] - p[t - 1] a[t - 2]; a[t_] := 10 x[t - 1] p[t - 1] + a[t - 1] a[t - 2];

So commands

Table[{t + 1, x[t + 1], p[t + 1], a[t + 1]}, {t, 0, 10}]

and

{# + 1, x[# + 1], p[# + 1], a[# + 1]} & /@ Range[0, 10]

generate output

{{1, 1, 2, 3}, {2, 0.00336319, -0.00719693, 0.010203}, {3, 0.0677008, -0.0172979, 0.010203}, {4, 2.38052, -0.0540507, 0.00932697}, {5, 66.8197, 11.1562, 0.00471539}, {6, -0.518014, 1.47135, 7454.52}, {7, 21936.5, -19307.7, 27.5292}, {8, -1.64589*10^8, 1.46949*10^8, -4.23523*10^9}, {9, -1.24473*10^18, 3.48536*10^18, -2.41863*10^17}, {10, -1.68596*10^36, 1.50527*10^36, -4.33833*10^37}, {11, -1.30607*10^74, 3.65712*10^74, -2.53782*10^73}}

but very slowly. I noticed that if I calculate values for $t \in [0,2]$ and then put values as initial conditions for x[2], p[2], a[2] manually and then redo the code for $t \in [0,3]$ and repeat, it works much much faster. Is there a way to automatize it?

wlq
  • 75
  • 4
  • Is that all there is, because using what you've posted results in instantaneous results, on a netbook...Incomplete or scantily defined questions, where readers can't cut-n-paste the example to work with it are much less likely to get useful responses. – ciao Mar 05 '14 at 08:48
  • Well, the functions are very long so I cannot really paste them here. I used a shorthand notation in describing them. – wlq Mar 05 '14 at 08:50
  • 1
    then compose some minimal working example of "the problem"... – ciao Mar 05 '14 at 08:51

1 Answers1

3

I'm going to step out on the limb and answer re: what is almost certainly the "problem" - you are repeatedly evaluating to the same result, an aspect of recursive functions, so you're creating excess work.

By example of Fibonacci numbers:

fib[1] = 1;
fib[2] = 1;
fib[n_] := fib[n - 1] + fib[n - 2];

fib[5] // Timing
fib[30] // Timing

(* 
{0., 5}
{9.984064,832040}
*}

Note how the time gets huge quickly (keep in mind, this is a netbook I'm on right now).

With a simple change:

fib[n_] := fib[n] = fib[n - 1] + fib[n - 2]

fib[30] // Timing

{* {0., 832040} *}

By "remembering" past results, evaluation time is drastically reduced.

Assuming your system of functions is referentially transparent, just using this kind of construct will likely address your speed issues.

Edit: Seeing your update, this is precisely what will help you , e.g., change to:

x[t_] := x[t] = 2 p[t - 1] a[t - 1] - x[t - 1] a[t - 2];
p[t_] := p[t] = 5 x[t - 1] a[t - 1] - p[t - 1] a[t - 2];
a[t_] := a[t] = 10 x[t - 1] p[t - 1] + a[t - 1] a[t - 2];

on my netbook the time is below clock resolution. Nonetheless, in the future include in your questions what you're trying to accomplish, there may well be a smarter way to do things.

ciao
  • 25,774
  • 2
  • 58
  • 139
  • 1
    I suggest also reading this one here: http://mathematica.stackexchange.com/questions/2639/what-does-the-construct-fx-fx-mean – Pinguin Dirk Mar 05 '14 at 09:07
  • Wow, this solves everything, thank you! – wlq Mar 05 '14 at 09:07
  • @wlq: good to hear. Remember to Clear your definitions when finished with them or when you change definitions, else the "old" ones may get used. – ciao Mar 05 '14 at 09:09