Wir werden versuchen, ein Programm zu schreiben, das sich daran erinnert, was es bisher getan hat, und das seinem Ziel näher kommt, wenn eine Wiederholung abgebrochen wird. Dies ist ein hartnäckiges Programm. Es wird ein nichtflüchtiger Speicher verwendet , um Informationen über Läufe hinweg als eine Anzahl von Cits zu speichern , die Bits sind, die berücksichtigen, was beim Abbruch passiert. Ich habe einmal vermutet, dass mit N Cits jedes Ziel bis zur Länge 2 (NK) für ein kleines festes K erreichbar ist. Ich neige jetzt dazu zu denken, dass das Ziel nicht erreicht werden kann :-(
Es wird um ein hartnäckiges Programm mit Ziel gebeten 01
, das bereits ein nicht triviales Ziel ist ; oder ein strenger Beweis der Unmöglichkeit.
Ein hartnäckiges Programm ist definiert als eines, das:
- Wird bei jeder Ausführung ab demselben Einstiegspunkt ohne Eingabe ausgeführt und kann Informationen über Läufe ausschließlich über
N
Cits (unten definiert) austauschen . Jede andere Information hat entweder zu Beginn jedes Laufs denselben Inhalt, zu Beginn des Laufs unvorhersehbaren Inhalt, ist unveränderlich (das Programm selbst) oder nicht lesbar (vorherige Ausgabe und Wert ). - Ist so, dass es beim Ausführen innerhalb einer Sitzung erkennbar anhält (unter Verwendung einer Funktion seiner Sprache), innerhalb einer begrenzten Verzögerung seit dem Start des Laufs, sofern es nicht vor dem Anhalten abgebrochen wird ; Der Abbruch erfolgt zu einem beliebigen Zeitpunkt und verhindert den Betrieb bis zu einem weiteren Lauf (falls vorhanden).
- Ist so , dass die Verkettung in chronologischer Reihenfolge der Zeichen es gibt ist die gleiche endliche Zeichenfolge (das Ziel ) in jeder Sitzung von arbitrarilly viele Läufe mindestens einen Lauf aufweist , wo das Programm ausgeführt wurde , nach links , bis er anhält.
- Gibt Zeichen mit einem Gerät aus, das atomar : einenvom Programm gesetzten Wert unter 0 1 2 3empfängt, und gibt(bzw.) Werte zwischen 0 oder 2 (bzw. 1 oder 3) aus, wenn sich dieser Wert vom vorherigen unterscheidet Wert put, angenommen 0 für den ersten Put in einer Sitzung.
0
1
Hartnäckige Programme existieren! Jedes Programm, das einfach eine feste Anzahl von Malen eines gültigen festen Werts setzt und dann anhält, ist hartnäckig, wobei das Ziel entweder leer ist (wenn Zahl oder Wert 0 ist) 0
(wenn Zahl positiv ist und Wert 2 ist) oder 1
(anderweitig). Jedes längere Ziel erfordert NVM.
Jeder Cit modelliert ein NVM-Bit unter Berücksichtigung der Auswirkung eines Laufs, der während eines Schreibvorgangs in den Cit abgebrochen wird . Zu jedem Zeitpunkt befindet sich eine Stadt in einem von drei möglichen Zuständen 0
1
oder U
. Der aus einer Cit gelesene Wert ist immer 0 oder 1; es entspricht auch dem Zustand, es sei denn U
. Ein cit wird so initialisiert, dass es 0
vor dem ersten Durchlauf in einer Sitzung angezeigt wird, und ändert ansonsten den Status nur, wenn das Programm einen Schreibvorgang anordnet. Dies hängt davon ab, was geschrieben wurde, ob der Lauf während des Schreibvorgangs abgebrochen wird oder nicht, und von der Cit's ehemaliger Staat:
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
Die HAL für das oben Genannte wird in C wie folgt deklariert:
/* 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 */
Unser erster Versuch eines hartnäckigen Programms mit Ziel 01
ist:
#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 macht eine erste Sitzung, beendet den ersten Lauf und beendet die Sitzung. Die Ausgabe der Sitzung ist die Ausgabe des einzelnen Laufs 01
. So weit, ist es gut.
In einer anderen Sitzung bricht Murphy einen ersten Lauf ab w(3,1)
und lässt cit im Zustand U
; In einem zweiten Durchlauf entscheidet Murphy, dass r(3)
1 ist (dass sich cit im Status befindet U
), und lässt das laufende Programm stehen (beachten Sie, dass w(3,1)
der Status des cit nicht geändert wurde). In einem dritten Lauf entscheidet Murphy, dass r(3)
es 0 ist, bricht ab p(2)
und beendet die Sitzung.
Die verkettete Ausgabe der zweiten Sitzung ist 010
(ein Zeichen pro Lauf), unterscheidet sich jedoch von 01
der ersten Sitzung, sodass das Programm nicht hartnäckig ist, da Bedingung 3 nicht erfüllt ist.
Die Sprache ist kostenlos. Passen Sie die C-Oberfläche an die Sprache an. Ich werde die beste Antwort basierend auf der niedrigsten Anzahl der verwendeten Cits auswählen. dann niedrigste Anzahl von Schreibvorgängen im ungünstigsten Fall vom Lauf zur Ausgabe (oder anhalten, wenn keine Ausgabe erfolgt); dann niedrigste Anzahl von Schreibvorgängen vor dem Anhalten in einer Sitzung ohne Abbruch; dann kürzestes Programm. Zählen Sie nur den aufrufenden Code, nicht die Schnittstelle oder deren Implementierung, die nicht benötigt wird. Ein strenger Beweis der Unmöglichkeit würde jedes Programm eliminieren (und mich überraschen) ; Ich würde das am einfachsten zu erfassende auswählen.
Bitte überprüfen Sie dreimal, ob das Programm das Ziel gemäß 3 wirklich erreicht, unabhängig von der Anzahl und dem Zeitpunkt der Abbrüche. das ist schwierig!
Update: Ich habe eine Kandidaten Antwort . Fühlen Sie sich frei, es zu trounzen. Oh, Hammar hat das in wenigen Minuten mit einem systematischen Programm gemacht!
Status : Bisher haben wir keine Lösung; sicher wissen, dass es keine Lösung mit 1 oder 2 Cits gibt; habe aber keinen Beweis der Unmöglichkeit mit 3 oder mehr Cits. Die Aussage wurde nicht als mehrdeutig befunden. Das Problem hätte eine Lösung, wenn wir die Cit-Matrix geringfügig ändern würden (z. B. rechts unten auf 1 setzen. In diesem Fall ist das obige Beispiel korrekt).
quelle
Antworten:
Ich habe zwar weder eine Lösung noch einen Beweis für die Unmöglichkeit, aber ich dachte, ich würde mein Testgeschirr für jeden veröffentlichen, der damit herumspielen möchte, da ich zu diesem Zeitpunkt so ziemlich aufgegeben habe.
Es ist eine Implementierung der HAL-Modellierungsprogramme als Haskell-Monade. Es prüft die Hartnäckigkeit, indem es eine Breitensuche über die möglichen Sitzungen durchführt, um nach Sitzungen zu suchen, die entweder 1. einmal angehalten wurden, ohne die richtige Ausgabe zu erzeugen, oder 2. eine Ausgabe erzeugt haben, die kein Präfix der gewünschten ist (dies fängt auch Programme ab, die eine unendliche Ausgabe erzeugen).
Hier ist das Beispielprogramm des OP, das in Haskell konvertiert wurde.
Und hier ist die entsprechende Ausgabe, die zeigt, dass das Programm nicht hartnäckig ist.
quelle
Es sei denn, jemand kann einen Fehler in diesem Programm finden. Ich denke, es überprüft und lehnt jedes relevante Zwei-Cit-Programm ab.
Ich behaupte, dass es ausreicht, Programme zu betrachten, die alle Cits lesen und eine durch die Menge gebildete Zahl einschalten. Jeder Zweig des Schalters besteht aus einer Reihe von Schreib- und Put-Vorgängen. Es macht nie Sinn, dieselbe Zahl mehr als einmal in einen Zweig zu setzen oder die zweite Ausgangsziffer vor die erste zu setzen. (Ich bin moralisch sicher, dass es keinen Sinn macht, die erste Ziffer anders als am Anfang eines Zweigs oder die zweite Ziffer anders als am Ende auszugeben, aber im Moment vermeide ich diese Vereinfachung).
Dann hat jeder Zweig einen Zielsatz von Cits, die er setzen möchte, und bewegt sich darauf zu, indem er die Bits, die 0 sein sollen, auf 0 und die Bits, die 1 sein sollen, auf 0 und dann auf 1 setzt; Diese Schreibvorgänge können auf verschiedene Arten angeordnet werden. Es macht keinen Sinn, ein Bit auf 1 zu setzen, es sei denn, Sie haben es in diesem Lauf bereits auf 0 gesetzt, oder es ist wahrscheinlich ein Nein.
Es werden 13680577296 mögliche Programme berücksichtigt. Eine 4-Kern-Maschine benötigte knapp 7 Stunden, um alle zu überprüfen, ohne eine einzige Lösung zu finden.
quelle
Das
heißtwar mein bester Versuch auf meine Frage zu beantworten.Ich bin mir nicht sicher, ob es die Anforderung 3 erfüllt, und bin offen für Widerlegungen.Es ist nicht hartnäckig :-(quelle
01
, Cits :110
. 2. Abbruch während # 15. Cits :10U
. 3. Lesen Siec = 1
, brechen Sie während # 12 ab. Cits :U0U
. 4. Lesen Siec = 0
,d = 0
und das Programm wird01
erneut gedruckt .