1
$\begingroup$

Consider a recursive piecewise function K[t]:

   K[t_] := If[t <= 1, g[0, 0, t],
       If[t <= 2, g[K[1], 1, t],
        If[t <= 3, g[K[2], 2, t],
         If[t <= 4, g[K[3], 3, t],
          If[t <= 5, g[K[4], 4, t],
           0]]]]];

here g[x,y,z] is another function.

It can also be defined in a better way:

Block[{t}, 
  K[t_] = Piecewise[
    Table[{If[i > 1, g[K[i - 1], i - 1, t], g[0, 0, t]], t <= i}, {i, 
      5}]]];

However when we set 5 to a larger number such as 15, plotting K[t] becomes very slow. What will be the most efficient way to solve this? Thank you.

$\endgroup$
  • $\begingroup$ Hi and welcome! To make the most of Mma.SE start by taking the tour now. It will help us to help you if you write an excellent question. Edit if improvable, show due diligence, give brief context, include minimal working example of code and data in formatted form**. As you receive give back, vote and answer questions, keep the site useful, be kind, correct mistakes and share what you have learned. $\endgroup$ – rhermans May 30 '17 at 13:37
1
$\begingroup$

Firstly, lets check the output of your function. For t = 3.1, your function returns g[g[g[g[0, 0, 1], 1, 2], 2, 3], 3, 3.1]. It can be seen that every time you change the input even a little bit, say t = 3.11, the function calculates the whole thing again i.e., g[g[g[g[0, 0, 1], 1, 2], 2, 3], 3, 3.11]. You can make it faster by memoizing the part g[g[g[0, 0, 1], 1, 2], 2, 3] which constitutes to f[3].

Following is the memoized version of your function:

f[t_] := If[t <= 1, g[0, 0, t], g[f[Ceiling[t - 1]] = f[Ceiling[t - 1]],
Ceiling[t - 1], t]]

Note the memoization part: f[Ceiling[t - 1]] = f[Ceiling[t - 1]]

$\endgroup$
  • $\begingroup$ @Serendipity doesn't this answer give you what you want? $\endgroup$ – Anjan Kumar May 30 '17 at 23:50
  • $\begingroup$ Yes and it's very fast. Thank you. $\endgroup$ – Serendipity May 31 '17 at 17:54
1
$\begingroup$

One feature you can use to solve this problem is Mathematica's native multiple-dispatch. Your function can be defined as a set of separate functions, and the Mathematica engine will do the hard work of figuring out which one you've called:

K[t_Integer /; t <= 1] := g[0, 0, t];
K[t_Integer /; 1 < t <= 5] := g[K[t-1], t-1, t];
K[t_Integer /; t > 5] := 0;

(Here I'm assuming that your function K should only take integers.)

Here is some documentation on the patterns used to define these functions:

You could alternatively use a Which statement, which is like cond in lisps, or like if-else statements in C:

K[t_Integer] := Which[
  t <= 1, g[0,0,t],
  1 < t <= 5, g[K[t-1], t-1, t],
  True, 0];

Closing Note:

The slowness you're experiencing is probably due to the recursion and not due to the Piecewise specifically. You can likely get around this by memoizing your recursive results:

K[t_Integer /; 1 < t <= 5] := K[t] = g[K[t-1], t-1, t];

When that function (e.g., K[4]) is called, it calculates the result once then memoizes it so that future calls will just return the pre-calculated result. See here for details: Memoizing in Mathematica

$\endgroup$
  • $\begingroup$ Thanks. The K takes Real values... So it seems to be a bit more difficult. $\endgroup$ – Serendipity May 30 '17 at 14:23
  • $\begingroup$ You can replace the _Integer with _Real to accept real values (or with _?NumericQ to accept either. $\endgroup$ – nben May 30 '17 at 23:10

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.