3
$\begingroup$

I have two functions as follows,

Multifactorial[n_, k_] := Abs[Apply[Times, Range[-n, -1, k]]]
For[i = 1, i < 11, i++, Print[N[Sum[1/Multifactorial[n, i], {n, 0, 150}], 20]]]

and

ClosedFormRMFC[n_] := 1 + 1/n Exp[1/n] Sum[n^(k/n) Gamma[k/n, 0, 1/n], {k, n}]
For[i = 1, i < 11, i++, Print[N[ClosedFormRMFC[i], 20]]]

Both the functions have an identical output, they both output 10 numerical constants with a 20 decimal accuracy.

I am not sure how to compare the efficiency in executing both these functions.

The first function is an infinite series and as such needs arbitrarily large partial sums to get higher accuracy. While the second gives a closed form formula that just needs to be converted to a numerical form.

For higher values of accuracy I assume the second function must be computationally more efficient.

My question is how can I test this in Mathematica? How do I determine which is more efficient asymptotically? Is there some way to plot a graph showing the time taken in executing both functions for various levels of accuracy (in output)?

$\endgroup$
5
$\begingroup$

If I understand correctly what you want to do the following should work.

We start by

Multifactorial[n_, k_] := Abs[Apply[Times, Range[-n, -1, k]]]

Then we define a function that does the computation but does not show any output. This function also computes the absolute time that mathematica needs. This is done as follows

test1[xx_] := (For[i = 1, i < xx, i++, 
     Print[N[Sum[1/Multifactorial[n, i], {n, 0, 150}], 20]] // 
      Inactive] // AbsoluteTiming)[[1]]

To make a long story short, we do the same for the other function you provided

ClosedFormRMFC[n_] := 
 1 + 1/n Exp[1/n] Sum[n^(k/n) Gamma[k/n, 0, 1/n], {k, n}]

test2[xx_] := (For[i = 1, i < xx, i++, 
     Print[N[ClosedFormRMFC[i], 20]] // Inactive] // 
    AbsoluteTiming)[[1]]

And now it is relatively straightforward. We can create two lists that enumerate how many points we are taking each time and how much time each function needs. At the very end, ListPlot is our friend

list1 = ListPlot[Table[{xx, test1[xx]}, {xx, 1, 25}], 
   PlotRange -> All, PlotLegends -> "Expressions", 
   AxesLabel -> {"points", "time in sec"}, 
   PlotStyle -> {Red, Thick}];
list2 = ListPlot[Table[{xx, test2[xx]}, {xx, 1, 25}], 
   PlotRange -> All, PlotLegends -> "Expressions", 
   AxesLabel -> {"points", "time in sec"}, 
   PlotStyle -> {Blue, Thick}];

And we gather everything

Show[list1, list2]

enter image description here

If this is not what you were looking for, please leave a comment and I will either modify this or delete altogeher.

$\endgroup$
7
  • 1
    $\begingroup$ Thanks this is very nice solution indeed. You can even switch around the test variable xx to be in place of decimal accuracy, I'll try playing around a little with this. $\endgroup$ – Bhoris Dhanjal May 17 at 9:14
  • $\begingroup$ Glad I was able to help :) $\endgroup$ – DiSp0sablE_H3r0 May 17 at 9:48
  • 1
    $\begingroup$ +1 Although slower, RepeatedTiming gives more stable results. $\endgroup$ – Bob Hanlon May 17 at 13:28
  • 1
    $\begingroup$ "RepeatedTiming always evaluates expr at least four times. It gives a trimmed mean of the timings obtained, discarding lower and upper quartiles." $\endgroup$ – Bob Hanlon May 17 at 13:45
  • 1
    $\begingroup$ No, I don't think that it is necessary. It would literally just replace AbsoluteTiming with RepeatedTiming $\endgroup$ – Bob Hanlon May 17 at 13:51

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.