3
$\begingroup$

I have the following code:

f0[x_]:=0.1Exp[-x]+1.3;
f1[x_]:=f0[x](1+Sqrt[1/(10000f0[x])]);
f2[x_]:=f1[x](1+Sqrt[1/(10000f1[x])]);
f3[x_]:=f2[x](1+Sqrt[1/(10000f2[x])]);
f4[x_]:=f3[x](1+Sqrt[1/(10000f3[x])]);
f5[x_]:=f4[x](1+Sqrt[1/(10000f4[x])]);
f6[x_]:=f5[x](1+Sqrt[1/(10000f5[x])]);
Plot[{f0[x],f1[x],f2[x],f3[x],f4[x],f5[x],f6[x]},{x,0,2}]

Note that the $f_n$ are calculated iteratively, with $f_{n-1}$ being used to calculate $f_n$. This produces the following graph:

enter image description here

However, it's a pretty inefficient way to write code, especially when your functions are more complicated than this. So I figured I could do an actual iteration:

f0[x_]:=0.1Exp[-x]+1.3;
For[iter=1,iter<=6,iter++,
    f1[x_]:=f0[x](1+Sqrt[1/(10000f0[x])]);
    f0[x_]:=f1[x];
];
Plot[{f0[x],f1[x]},{x,0,2}]

However, this causes Mathematica to get stuck in a recursion loop because of the SetDelayed:

enter image description here

As a rule, I avoid using Set for functions because SetDelayed behaves better. Should I just use Set in this case to avoid this problem? Or is there a smarter way to code the iteration that I haven't thought about?

I suppose I could define an array of functions:

f=ConstantArray[0,7];
f[[1]][x_]:=0.1Exp[-x]+1.3;
For[iter=1,iter<=6,iter++,
    f[[iter+1]][x_]:=f[[iter]][x](1+Sqrt[1/(10000f[[iter]][x])]);
];
Plot[{f[[1]][x],f[[2]][x],f[[3]][x],f[[4]][x],f[[5]][x],f[[6]][x],f[[7]][x]},{x,0,2}]

I don't even know whether that would work (haven't tried it). Again, though, even if it does work, it's a pretty inefficient way to code; Mathematica would save seven functions in its memory instead of two.

$\endgroup$
2
  • $\begingroup$ You say: "As a rule, I avoid using Set for functions because SetDelayed behaves better. " What do you mean with 'behaves better'? I know, many user here disagree, but general rule should be: Avoid SetDelayed whereever you can! The best solution for your problem is as @bills shows in his answer. But if you want to do it the way you tried, this (with Set instead SetDelayed) also works well f[1][x_] = 0.1 Exp[-x] + 1.3; For[iter = 1, iter <= 6, iter++, f[iter + 1][x_] = f[iter][x] (1 + Sqrt[1/(10000 f[iter][x])])]; Plot[Evaluate[Table[f[i][x], {i, 1, 7}]], {x, 0, 2}] $\endgroup$
    – Akku14
    Commented Feb 9, 2022 at 6:23
  • $\begingroup$ It's just been my experience that, since Set causes things to evaluate instantly rather than later (when first invoked in a calculation), occasionally functions do silly things which are not always easy to debug, especially when you use loops. I couldn't give you an example right now, since it's a fairly uncommon thing and I can't remember any specific case in which it's happened to me, but ita has happened a few times, whereas this is the first real problem I've had with SetDelayed. $\endgroup$
    – Rain
    Commented Feb 9, 2022 at 6:35

4 Answers 4

7
$\begingroup$

You can define the function(s) recursively:

f0[0, x_] = 0.1 Exp[-x] + 1.3;
f0[n_, x_] := f0[n, x] = f0[n - 1, x] (1 + Sqrt[1/(10000 f0[n - 1, x])]);
Plot[f0[#, x] & /@ Range[6], {x, 0, 2}]
$\endgroup$
4
  • $\begingroup$ This will lead to memoization of each and every function evaluation of the final function. If that function gets used often this could seriously eat through memory. $\endgroup$
    – TimRias
    Commented Feb 9, 2022 at 8:29
  • $\begingroup$ @mmeent Would this work to avoid memoizing x: f[n_, xx_] := (f[n, x_] := ..... ; f[n, xx])? $\endgroup$ Commented Feb 9, 2022 at 15:45
  • $\begingroup$ @2012rcampion Probably. Have you tried? $\endgroup$
    – TimRias
    Commented Feb 9, 2022 at 16:44
  • $\begingroup$ It's easy to remove the unnecessary functions from memory once your iteration cycle has ended, though, and this is the answer with the most legible (to me) code I've received, which is why I accepted it. On some of the other answers I wouldn't know how the intermediate functions are stored and thus how to delete them and free up memory. $\endgroup$
    – Rain
    Commented Feb 11, 2022 at 3:01
4
$\begingroup$
Clear["Global`*"]

f[0][x_] := (Exp[-x] + 13)/10;
f[n_Integer?Positive][x_] := f[n][x] =
   f[n - 1][x] (1 + Sqrt[1/(10000 f[n - 1][x])]) // Simplify;

Format[f[n_][x_]] := Subscript[f, n][x];

Plotting,

Plot[
 Evaluate[Tooltip[f[#][x], #] & /@ Range[6, 0, -1]],
 {x, 0, 2},
 PlotLegends -> LineLegend[Range[6, 0, -1],
   LegendLabel -> Style["n", 14]],
 AxesLabel -> (Style[#, 14] & /@ {x, HoldForm[f[n][x]]})]

enter image description here

$\endgroup$
3
  • $\begingroup$ Thanks for your answer. What do Evaluate[Tooltip[...]] and HoldForm[...] do? Also, is there a difference (in evaluation time or in Mathematica encountering problems with particularly nasty code) between f[n,x] and f[n][x] or is it a matter of taste? $\endgroup$
    – Rain
    Commented Feb 9, 2022 at 0:08
  • 1
    $\begingroup$ The Evaluate causes the enclosed expression to be evaluated prior to x being given numeric values. This ensures that the all of the f[n] are defined and that the curves each have separate colors. The Tooltip adds the appropriate Tooltip to each curve. The HoldForm stops the f[n][x] from trying to evaluate and causes the label to be displayed in TraditionalForm. $\endgroup$
    – Bob Hanlon
    Commented Feb 9, 2022 at 1:05
  • $\begingroup$ I see. Thanks for taking the time to explain! :) $\endgroup$
    – Rain
    Commented Feb 9, 2022 at 6:30
2
$\begingroup$

You can use NestList with a pure function construct:

theList = NestList[# (1 + Sqrt[1/(10000 #)]) &, 0.1 Exp[-x] + 1.3, 6];
Plot[theList, {x, 0, 2}]
$\endgroup$
1
  • 1
    $\begingroup$ Again, though, this creates an array of functions and consumes way more memory than I'd like. $\endgroup$
    – Rain
    Commented Feb 8, 2022 at 23:59
0
$\begingroup$

To avoid unnecessarily storing function evaluations in memory. You can take the following approach using Function

f0[0] = Function[x, 0.1 Exp[-x] + 1.3];
f0[n_] := Function[x, f0[n - 1][x] (1 + Sqrt[1/(10000 f0[n - 1][x])])];
Plot[Evaluate[Table[f0[n][x], {n, 6}]], {x, 0, 2}]
$\endgroup$

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.