interruptedWhile (useful for monitoring a computation non-interactively)
- To: mathgroup at smc.vnet.net
- Subject: [mg24595] interruptedWhile (useful for monitoring a computation non-interactively)
- From: Daniel Reeves <dreeves at eecs.umich.edu>
- Date: Tue, 25 Jul 2000 00:56:26 -0400 (EDT)
- Sender: owner-wri-mathgroup at wolfram.com
MathGroupies, I think the following may be generally useful so I thought I'd share it: (PS: I've noticed that the AbortProtect slows this down a bit; can anyone think of a better way of doing this?) (* Like a While loop except for the 1st 2 args, which say: every so many seconds pause and execute some code, presumably with the purpose of announcing some partial results or the status of the computation. *) SetAttributes[interruptedWhile, HoldRest]; interruptedWhile[interruptFreq_, interruptBody_, whileTest_, whileBody_] := Module[{compLoop, goComp}, compLoop := While[whileTest, AbortProtect[whileBody]]; goComp := TimeConstrained[compLoop, interruptFreq, Evaluate[interruptBody]; goComp]; goComp; ] Here's an example of using it: i = 1; numFound = 0; interruptedWhile[3, Print["Checked 1 thru ", i - 1, " and found ", numFound, " primes (expected ", PrimePi[i - 1], ")..."], i <= 1000000, If[PrimeQ[i], numFound++]; i++; ] Of course, you can manually interrupt and check on a computation from the front-end, so this is most useful for a really long computation that you have running in the background. In those cases, I often like to have the program send periodic emails. So while I'm at it, I'll paste in code to do that (of course this only works on Unix/Linux): SYSTEMINFO::usage = "A string with things like machine and user name and process IDs."; ENV::usage = "A string showing all operating system environment variables."; mail::usage = "mail[ to -> {list of addresses}, \n from -> \"Some Name <some at email.address>\", (* or just email address *) \n subject -> \"string\", \n body -> \"string\", (* see SYSTEMINFO and BODY *)\n headers -> {list of \"Header: stuff\" strings} (* additional headers *)]. Use Options[mail] to see default options."; SYSTEMINFO := StringJoin @@ ToString /@ {"$MachineName: ", $MachineName, "\n$MachineDomain: ", $MachineDomain, "\n$UserName: ", $UserName, "\n$ProcessID: ", $ProcessID, "\n$ParentProcessID: ", $ParentProcessID, "\n$CommandLine: ", $CommandLine, "\nARGV: ", Global`ARGV, "\n"}; ENV = Read["!/usr/bin/env", Record, RecordSeparators -> {}]; Close["!/usr/bin/env"]; (* Default options for mail. *) Options[mail] := { to -> {"dreeves at eecs.umich.edu"}, from -> "MY-MMA-AGENT <dreeves at maria.physics.lsa.umich.edu>", subject -> StringJoin @@ ToString /@ {"OUTPUT from process ", $ProcessID, " on ", $MachineName}, body -> SYSTEMINFO <> "\nEnvironment:\n\n" <> ENV, headers -> {} }; (*like perl's join function*) intersperse[delim_String, l_List] := Module[{pair}, StringJoin @@ Drop[pair[#, delim] & /@ l /. pair -> Sequence, -1]] mail[opts___] := Module[{opt, allHeaders, stream}, opt[x_] := x /. {opts} /. Options[mail]; allHeaders = Join[opt[headers], { "Subject: [mg24595] " <> opt[subject], "From: " <> opt[from], To: mathgroup at smc.vnet.net "To: " <> intersperse[", ", opt[to]]}]; stream = OpenWrite["!/usr/lib/sendmail -oi -t"]; WriteString[stream, intersperse["\n", allHeaders], "\n\n", opt[body]]; Close[stream];] -- -- -- -- -- -- -- -- -- -- -- -- Daniel Reeves http://ai.eecs.umich.edu/people/dreeves/ "Jesus is coming, everyone look busy."