1
$\begingroup$

Lets say I have a calculation in a form of

Table[myStuff[i],{i,0,k}]

Is there a way to avoid a fixed k but instead end the loop after an abitrary amount of time with an user input.

Such that I can start the calculation in the evening and just stop it in the morning without having to estimate a k.

$\endgroup$
  • $\begingroup$ Table[myStuff[i], {i, 0, Dialog[]}]? $\endgroup$ – Michael E2 Oct 23 '16 at 21:07
  • $\begingroup$ I'd propose: i = 0; While[i < Infinity, myStuff[i]; i++]; after aborting you can get i. You'd have to figure out how do you want to store the values of myStuff[i] (I don't know in detail what are you doing so this is just a hint), but it might turn out to be inefficient. $\endgroup$ – corey979 Oct 23 '16 at 21:36
1
$\begingroup$

Let's say myStuff is the following function:

myStuff[i_] := (Pause[1]; i^2)

Then run this:

result = 
 Module[{i = 1, s = {}},
  CheckAbort[
   While[True, s = {s, myStuff[i]}; i++], Flatten@s]]

(*{1, 4, 9, 16, 25, 36, 49}*)

This is the required table when aborted after 7 seconds.

See this for details on why using s = {s, myStuff[i]} is very efficient.

The below plot shows how this method, the Sow/Reap method in the other answer, and the method using Join scales with the size of the table:

BenchmarkPlot

$\endgroup$
  • $\begingroup$ No need to Flatten: s = s~Join~{myStuff[i]}. $\endgroup$ – corey979 Oct 23 '16 at 21:51
  • 2
    $\begingroup$ I bet that's slower for large lists, since you are copying the entire list. Whereas I am creating a linked list, which has much more efficient insertions $\endgroup$ – dan7geo Oct 23 '16 at 21:53
  • 1
    $\begingroup$ see mathprogramming-intro.org/book/node525.html $\endgroup$ – dan7geo Oct 23 '16 at 21:57
  • 1
    $\begingroup$ Similar with Reap and Sow that avoids the pitfall @dan7geo points out: mathematica.stackexchange.com/questions/313/… $\endgroup$ – evanb Oct 23 '16 at 22:02
1
$\begingroup$

To expound on my comment, drawing inspiration from How to collect result continuously (interruptible calculation) when running parallel calculations? you could do, for example,

myStuff[i_] := (Pause[1]; i^2)
Module[{i = 1},
    Last[Last[Reap[
        CheckAbort[
            While[True, Sow[myStuff[i]]; i++], 
            ignored
            ]
    ]]]
]

Interrupting after ~5 seconds gives {1, 4, 9, 16, 25}.

$\endgroup$
  • $\begingroup$ I added CheckAbort 33 seconds before your answer :) $\endgroup$ – dan7geo Oct 23 '16 at 22:06
  • $\begingroup$ Ha. I'd still be concerned about the speed of s={s, myStuff[i]}---doesn't it evaluate s when the list on the RHS gets constructed? $\endgroup$ – evanb Oct 23 '16 at 22:09
  • $\begingroup$ Not really. It's a call by reference thing which doesn't copy the list. Just uses a pointer to the list or something. I forgot the actual details of it. $\endgroup$ – dan7geo Oct 23 '16 at 22:16
  • $\begingroup$ Hm. You seem to be right. Map[ Module[{s}, s = {}; {#, Timing[For[i = 0, i < #, i++, s = {s, i}]][[1]]}] &, 2^ Range[1, 20]]; ListPlot[%] $\endgroup$ – evanb Oct 23 '16 at 22:33
  • $\begingroup$ see benchmark plot in my answer $\endgroup$ – dan7geo Oct 24 '16 at 5:24

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.