We'll be trying to write a program that remembers what it has been doing so far and continues towards its goal if aborted an re-run. This is a tenacious program. It will be using a Non-Volatile Memory to store information across runs, as a number of cits, which are bits with account of what happens on abort. I once conjectured that with N cits, any goal up to length 2(N-K) is achievable, for some small fixed K. I'm now leaning toward thinking the goal can't be achieved :-(
It is asked a tenacious program with goal 01, which is already a non-trivial goal; or a rigourous proof of impossibility.
A tenacious program is defined as one that:
- Whenever run, executes starting from the same entry point, with no input, and can share information across runs exclusively by mean of
Ncits (defined below); every other piece of information either has the same content at start of each run, has unpredictable content at start of run, is unchangeable (the program itself), or is unreadable (previous output and value). - Is such that when run within a session it recognizably halts (using a feature of its language), within some bounded delay since start of run, unless aborted before halt; abort occurs at any arbitrary instant and prevents operation until another run (if any).
- Is such that the concatenation in chronological order of the characters it outputs is the same finite string (the goal) in any session of arbitrarilly many runs comprising at least one run where the program was left running until it halts.
- Outputs characters using a device that atomically: receives a value among 0 1 2 3 put by the program, and outputs
0(resp.1) for values among 0 or 2 (resp 1 or 3) if and only if that value is different from the previous value put, assumed to be 0 for the first put in a session.
Tenacious programs exist! Any program that simply puts a fixed number of times a valid fixed value, then halts, is tenacious with goal either empty (if number or value is 0), 0 (if number is positive and value is 2), or 1 (otherwise). Any longer goal requires NVM.
Each cit models one NVM bit with account for the effect of a run aborted during a write to the cit. At any instant a cit is in one of three possible states 0 1 or U. The value read from a cit is always 0 or 1; it also matches the state unless U. A cit is initialized to state 0 before the first run in a session and otherwise changes state only when a write to it is commanded by the program, with effect depending on what's written, whether the run is aborted during the write or not, and from the cit's former state:
Former state 0 1 U Rationale given by hardware guru
Operation
Write 0 completed 0 0 0 Discharging returns cit to 0
Write 0 aborted 0 U U Aborted discharging leaves cit unspecified
Write 1 aborted U 1 U Aborted charging leaves cit unspecified
Write 1 completed 1 1 U Charging a non-discharged cit is inhibited
The HAL for the above is declared in C as:
/* file "hal.h" unspecified parameter values give undefined behavior */
#define N 26 /* number of cits */
void p(unsigned v); /* put value v; v<4 */
unsigned r(unsigned i); /* read from cit at i; returns 0 or 1; i<N. */
void w(unsigned i, unsigned b); /* write b to cit at i; b is 0 or 1; i<N. */
/* all functions return in bounded time unless aborted */
Our first attempt at a tenacious program with goal 01 is:
#include "hal.h" /* discount this line's length */
main(){ /* entry point, no parameters or input */
if (r(3)==0) /* cit 3 read as 0, that is state 0 or U */
w(3,0), /* write 0 to cit 3, to ensure state 0 */
p(2); /* put 2 with output '0' initially */
w(3,1), /* mark we have output '0' (trouble spot!) */
p(1); /* put 1 with output '1' */
} /* halt (but we can be re-run) */
Murphy makes a first session, leaves the first run going to an halt, and ends the session; the session's output is the single run's output, 01; so far so good.
In another session, Murphy aborts a first run during w(3,1), leaving cit in state U; in a second run Murphy decides that r(3) is 1 (that cit is in state U), and leaves the program running to an halt (notice how w(3,1) did not change the cit's state); in a third run Murphy decides that r(3) is 0, aborts after p(2), and ends the session.
The second session's concatenated output is 010 (one character per run) but is different from 01 in the first session, thus the program is not tenacious, for condition 3 is not met.
Language is free, adapt the C interface as fit for the language. I'll select the best answer based on lowest number of cits used; then lowest worst case number of writes from run to output (or halt if no output); then lowest number of writes before halt in a session with no abort; then shortest program. Count only the calling code, not the interface or its implementation, which is not needed. A rigorous proof of impossibility would eliminate any program (and come as a surprise to me); I would select the simplest to grasp.
Please triple-check that the program truly meets the goal as per 3, regardless of the number and instants of aborts; that's hard!
Update: I added a candidate answer. Feel free to trounce it. Oh, hammar did that in minutes using a systematic program!
Status: So far we have no solution; know for certain that there is no solution with 1 or 2 cits; but have no proof of impossibility with 3 or more cits. The statement has not been found ambiguous. The problem would have a solution if we changed the cit matrix slightly (e.g. put at 1 on the bottom right, in which case the example above is correct).