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