1

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.

meneken17
  • 500
  • 2
  • 8
  • Table[myStuff[i], {i, 0, Dialog[]}]? – Michael E2 Oct 23 '16 at 21:07
  • 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. – corey979 Oct 23 '16 at 21:36

2 Answers2

1

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

dan7geo
  • 1,410
  • 8
  • 14
  • No need to Flatten: s = s~Join~{myStuff[i]}. – corey979 Oct 23 '16 at 21:51
  • 2
    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 – dan7geo Oct 23 '16 at 21:53
  • 1
    see http://www.mathprogramming-intro.org/book/node525.html – dan7geo Oct 23 '16 at 21:57
  • 1
    Similar with Reap and Sow that avoids the pitfall @dan7geo points out: http://mathematica.stackexchange.com/questions/313/how-to-collect-result-continuously-interruptible-calculation-when-running-para/329#329 – evanb Oct 23 '16 at 22:02
1

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}.

evanb
  • 6,026
  • 18
  • 30
  • I added CheckAbort 33 seconds before your answer :) – dan7geo Oct 23 '16 at 22:06
  • 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? – evanb Oct 23 '16 at 22:09
  • 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. – dan7geo Oct 23 '16 at 22:16
  • 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[%] – evanb Oct 23 '16 at 22:33
  • see benchmark plot in my answer – dan7geo Oct 24 '16 at 05:24