Registermaschinen: Unterschied zwischen den Versionen

Aus Einführung in die Theoretische Informatik und in die Mathematische Logik
Wechseln zu: Navigation, Suche
(Beispiele)
 
Zeile 47: Zeile 47:
  
 
Wir können nun die Kurzschreibweisen <code>R[i]+=R[j]</code> und <code>R[i]-=R[j]</code> einführen, um vom Register <code>R[i]</code> den Wert von <code>R[j]</code> abzuziehen. Damit können wir zum Beispiel Multiplikation definieren
 
Wir können nun die Kurzschreibweisen <code>R[i]+=R[j]</code> und <code>R[i]-=R[j]</code> einführen, um vom Register <code>R[i]</code> den Wert von <code>R[j]</code> abzuziehen. Damit können wir zum Beispiel Multiplikation definieren
 +
 +
'''TODO''' Das ist falsch, weil R[1] immer dekrementiert wird. Man will R[1] kopieren und dann den kopierten Wert immer addieren. Selbes für Division.
  
 
     Start: if R[1] == 0 then goto Done
 
     Start: if R[1] == 0 then goto Done

Aktuelle Version vom 13. Dezember 2018, 14:08 Uhr

Ein Maschinenmodell das näher an dem ist, was moderne Computer tun, sind Registermaschinen.

Statt einem Speicherband hat man mehrere Register, das sind Zahlenvariablen, die natürliche Zahlen beinhalten können, und es gibt Befehle zum Inkrementieren, Dekrementieren, auf null prüfen, und Sprunganweisungen.

Wir nennen diese Register $R_0, R_1, \ldots$. Üblicherweise nutzen wir ein Register als Eingabe und ein Register als Ausgabe, der Übersichtlichkeit nennen wir sie manchmal $R_{\mbox{in}}$ und $R_{\mbox{out}}$ oder Ähnliches (wie genau man die Register bezeichnet ist ja auch nicht so wichtig).

Wir werden sie als Programmcode – ähnlich zu Programmiersprachen – mit Sprunganweisungen darstellen.

Es gibt für jedes Register R[i] die Programmbefehle R[i]++ und R[i]--. R[i]++ erhöht das Register 1, R[i]-- senkt es um $1$ ab falls es $>0$ ist, und lässt es gleich, falls es $0$ ist. Weiterhin gibt es Anweisungen if R[i]==0 then goto A, wobei A eine Sprungmarke ist. Die Anweisung springt zur betreffenden Sprungmarke, je nach dem, ob das angegebene Register $0$ ist, oder nicht. Sprungmarken notiert man vor dem Befehl, mit einem Doppelpunkt dahinter. Weiterhin gibt es den befehl End, der das Programm beendet (natürlich könnte man diesen Befehl auch weglassen, und einfach vereinbaren, dass das Programm endet, sobald es hinter die letzte Programmzeile läuft, alles äquivalente Definitionen), und ein unconditionalles goto, das immer springt.

Beispiele

Die folgenden Beispiele brauchen wir auch für später.

Der folgende Code überprüft, ob $R_0 \ge R_1$, und falls ja, setzt er $R_2$ auf $1$:

   Start: if R[1]==0 then goto Yes
   if R[0] == 0 then goto No
   R[1]--
   R[0]--
   goto Start
   
   No: End
   
   Yes: R[2]++
   End

Ähnlich kann man prüfen, ob $R_i > R_j$. Wir können also die Kurzschreibweise if R_i > R_j then goto A einführen, ohne dass das resultierende Maschinenmodell stärker würde.

Addition geht durch wiederholte Inkrementierung

   Start: if R[1] == 0 then goto Done
   R[0]++
   R[1]--
   goto Start
   
   Done: End

Subtraktion analog, wobei man definiert, dass $a-b=0$ für $a<b$

   Start: if R[1] == 0 then goto Done
   R[0]--
   R[1]--
   goto Start
   
   Done: End

Wir können nun die Kurzschreibweisen R[i]+=R[j] und R[i]-=R[j] einführen, um vom Register R[i] den Wert von R[j] abzuziehen. Damit können wir zum Beispiel Multiplikation definieren

TODO Das ist falsch, weil R[1] immer dekrementiert wird. Man will R[1] kopieren und dann den kopierten Wert immer addieren. Selbes für Division.

   Start: if R[1] == 0 then goto Done
   R[1]--
   R[2]+=R[1]
   goto Start
   
   Done: End

Division die den Rest verwirft können wir analog definieren mittels wiederholter Subtraktion

   Start: if R[1] > R[0] then goto Done
   R[0] -= R[1]
   R[2]++
   goto Start
   
   Done: End

Damit können wir auch den Rest der Division berechnen, da dieser einfach a - b * a/b ist, wobei / die Division ohne Rest ist.

Turingmaschinen sind Register-Mächtig

Dass man jede Registermaschine auch als Turingmaschine umbauen kann, sieht man leicht: Haben wir $n$ Register, so können wir diese einfach eine $n$-Band-Turingmaschine ersetzen, auf der wir die Zahlen unal speichern, und ein bisschen Logik einbauen für den Nullfall.

Registermaschinen sind Turing-Mächtig

Wir zeigen, dass Registermaschinen äquivalent zu Zweikellerautomaten sind. Damit ist auch gezeigt, dass sie Turingmächtig sind.

Sei ein Alphabet ${\cal L}=\{a_1,\ldots,a_n\}$ gegeben, und sei $g(a_i):=i$. Dem Wort $a_{k_1}\ldots a_{k_q}$ ordnen wir eineindeutig die Zahl $\sum\limits_{i=0}^{q-1} n^i \cdot g(a_{k_i})$ zu, dem Wort $\varepsilon$ die Zahl $0$, und nennen diese Funktion auch $g$. Offensichtlich ist damit $g(a_j v) = j + n\cdot g(v)$.

Das heißt, das erste Zeichen unseres codierten Wortes kriegen wir heraus, indem wir den Modulus des Codes bezüglich $n$ berechnen. Ein weiteres Zeichen anhängen können wir, indem wir den code mit $n$ multiplizieren und das Zeichen aufaddieren. Beide Operationen sind, wie man an obigen Beispielen sieht, in polynomieller Zeit mit Registermaschinen möglich.

Vergleiche sind ebenfalls möglich. Damit ist es offensichtlich möglich, einen Zweikellerautomaten zu simulieren.