date-created: 2024-06-20 10:30:26 date-modified: 2024-06-20 06:03:57

Turing Äquivalenz | Vollständigkeit

anchored to 112.00_anchor_overview


Overview

Wir möchten den Sprung von Turingmaschinen als Konzept, zu tatsächlichen Systemen - Computern etc - ziehen. Denn wir wissen, dass moderne Computer kein Band und Schreibköpfe hat / aufweist, wir also dahingehend das Konzept von Speicher etc bisschen anders verstehen und beschreiben.

[!Tip]

Wie kann man etwa eine Programmiersprache passend und formal definieren, sodass sie genauso mächtig ist, wie eine Turing-Maschine?!

Können wir mächtigere Programmiersprachen konstruieren?

Turing-Vollständigkeit / Äquivalenz

Um folglich den Sprung zwischen Programmiersprachen und Architekturen bilden zu können, möchten wir eine Vergleichbarkeit zwischen diesen Konstrukten finden / bauen können.

dabei definieren wir zuerst die Turing-Vollständigkeit (also, dass es etwas alles, was turing–berechenbare-Funktionen sind, berechnen kann) (Wichtig, das ist eine Teilmenge von den Dingen, die eine TM kann!)

Und ferner werden wir noch Turing-Äquivalenz beschreiben und definieren!:

  • Das trifft ein, wenn wir genau die gleichen Funtionen, wie eine TM, berechnen können! (Also das Modell ist äquivalent zu Turing-Maschinen (siehe die Dominosteine oder Wang-Tiles 112.19_unentscheidbare_probleme))

Turing-Vollständigkeit

[!Definition] Berechnungsmodell

Wir möchten dafür das Konzept einer partiellen Funktion betrachten: Sei eine partielle Funktion von gegeben, wobei sie hier eine Abbildung von einer Teilmenge abbildet (also sie ist nicht auf jede Eingabe definiert!)

Wie können wir das Prinzip jetzt für ein Berechnungsmodell anwenden, wobei wir versuchen beliebige berechenbare Funktionen von ihrem Code zu einer Funktion umzuwandeln? Wann ist ein Programm dann berchnet von dem Modell? #card

Sei jetzt die Menge aller partiellen Funktionen (Also wir schauen uns wieder Kodierungen an, die auf andere abbilden können)

Wir wollen jetzt ein Berechnungsmodell definieren: Es handelt sich um folgende Abbildung: -> Es kann aber auch ein anderer Code sein, etwa wenn wir unseren Programmcode in Binärsprache translatieren (etwa Python-Compilieren oder so) dann lässt sich das Ganze auch decoded in eine Funktion, die damit umgesetzt wird.

Damit haben wir also von einer beliebigen Codierung eine Abbildung zur korrespondierenden Funktion (die dadurch umgesetzt wird) gezogen. und können jetzt vergleichen.

Ein Programm -berechnet dann eine Funkion (also dem Ziel-Raum der Abbildung), wenn folgend durch die Abbildung folgt:

Aus der Betrachtung können wir nun auch die Turing-Vollständigkeit bestimmen und definieren:

[!Req] Turing-Vollständigkeit

Angenommen wir haben jetzt also ein Berechnungsmodell Dann möchten wir jetzt vergleichen können, ob das Berechnungsmodell turing-vollständig ist (sein kann).

Was müssen wir dafür tun, um das zu beweisen? #card

Wir können uns jetzt vorstellen, dass wir versuchen werden die Funktionen, die in dem Berechnungsmodell auftreten, auch durch eine TM umgesetzt werden können.Also:

Ein Berechnungsmodell heißt jetzt Turing-vollständig, wenn es eine Turing berechenbare Abbildung gibt, sodass folgende Funktion identisch zu einer von einer TM berechneten Funktion ist:

Das heißt wir können die Funktion (welche von einem Programm umgesetzt wird, anschließend durch die Codierung einer Turing-Maschine, die das gleiche macht, umsetzen)

(Wir können uns das Ganze einfach so vorstellen, dass man den Programmcode, der eine bestimmte Funktion hat, garantiert in einer TM mit bestimmten Code ebenfalls umgesetzt werden kann.)

Das können wir jetzt noch erweitern, damit die Beschreibung nicht mehr partiell ist!

Turing-Äquivalenz

[!Beweis] Turing-Äquivalenz

Wir setzen jetzt zwei Attribute dafür, dass ein bestimmtes Berechnungsmodell als Turing-Äquivalent eingestuft wird:

welche beiden Attribute müssen für das Modell gelten? #card

Folgend muss gelten:

  • es ist Turing-vollständig
  • es gibt zusätzlich eine berechenbare Abbildung , beschrieben mit : , sodass (in dem Modell) gilt:, wobei dann eine Gödelnummer einer TM ist, welche die gleiche Funktion, wie berechnet!

–> Das bedeutet also ferner auch, dass jedes Programm eine TM simuliert. –> Damit ist jedes Programm in dem Modell garantiert eine Turing-Maschine (im Konzept zumindest)

While-Berechnungsmodelle

Vorsicht: Wir wollen uns hier von dem While-loop, wie wir ihn kennen, abtrennen, und uns losgelöst von expliziten Programmiersprachen, um die mathematische Definition beschäftigen. –> Wir werden hierbei syntactig sugar herausnehmen, damit wir die Grundlage verstehen und Anwenden können!

Definition

[!Definition]

Wir betrachten nun Strings über einem Alphabet, das aus folgenden Objekten besteht:

  1. Abzählar viele Variablen
  2. abzählbar viele Konstanten
  3. genau drei Keywords
  4. genau sieben Symbole

Ferner haben wir einfache Befehle, dabei gibt es drei verschiedene, die wir betrachten :

  • Wertzuweisung
  • Addition
  • Subtraktion

Unter Betrachtung dieser Voraussetzung möchten wir jetzt rekursiv While-Programme beschreiben:

Wie beschreiben wir jetzt ein while-Programm? #card

Ein While-Programm ist jetzt entweder ein einfacher Befehl oder hat die folgende Form:

  1. einer Schleife, also
  2. einer Verkettung wobei hier selbst while Programm sind ( sein (eventuell elementar oder halt wieder Ketten!))

Wir haben damit die Syntax von while Programmen definiert. Das heißt, wir haben festgelegt, welche Strings wir als while Programm bezeichnen wollen.

Natürlich ist intuitiv klar, welche Operationen wir damit meinen. Das haben wir aber bislang noch nicht definiert. Wie die Definition der Berechnung einer TM. I Deshalb folgt jetzt die Definition der Semantik, also “was ein while Programm bedeutet”. Die Semantik ist eine partielle Funktion, welche eine Eingabe auf eine Ausgabe abbildet

Semantik | While

[!Req] Semantik | While-Programme

Eingabe: Die Eingabe eines while Programms besteht aus s ∈ N natürlichen Zahlen und wird in den Variablen gespeichert.

Wie können wir dann die Ausgabe beschreiben, wie werden die Variablen belegt? #card

Ausgabe! Falls das Programm anhält, dann ist die Ausgabe der Inhalt der Variable x0 bei Beendigung des Programms. (Wenn das Programm nicht hält, dann ist die Ausgabe nicht definiert)

Ferner beschreiben wir, wie wir speicher hier definieren und beschreiben: Variablenbelegung: Jedes Programm darf hier beliebig viele, jedoch nur endlich viele Variablen benutzen. Sei dabei jetzt die maximale Zahl an benutzten Variablen. Dann können wir die Variablenbelegung zu jedem Zeitpunkt als einen Vektor schreiben -> Habne wir etwa folgende Startbelegung: (die Nullen, weil der Speicher da noch frei ist!)

[!Tip] Programmbeschreibung

Sei die Startbelegung der Variablen. Wir definieren dann rekursiv eine partielle Funktion , welche die Ausgabe von bei Eingabe produziert. Das ist länglich, geht aber nicht anders.

(Das heißt wir können mit dieser partiellen Funktion dann einfach eine While-Schleife “)

Wie können wir diese Funktion jetzt für unsere beiden Optionen von While-Programmen umsetzen? Wir haben: und zu Auswahl #card

Wenn jetzt , dann beschreiben wir die Funktion folgend: und wir haben damit quasi gezählt, bis wir den Index an der Stelle des Speichers gefunden haben und diesen dann beschrieben mit –> agiert hier als unser Speichermodell!

Wenn jetzt , dann beschreiben wir die Funktion folgend:

Also wir haben hier auch einfach die Werte aus bestimmten Indices genommen und dann durch eine Addition an die gewählte Stelle gesetzt –> damit also auch wieder belegt!

Da ist die Operation über die Axiome der natürlichen Zahlen definiert und somit möglich!. Wir definieren also die Semantik durch Rückführung auf die natürlichen Zahlen!

Ferner ist die Subtraktion analog: ist folglich

Wir wollen uns auch noch die Verkettung anschauen und werden sehen, dass das auch funktioniert.

[!Req] Verkettung bei While-Schleifen

Angenommen wir haben ein While-Programm: . Wir wollen das jetzt folgend definieren.

Wie definieren wir es entsprechend? welche zwei Zustände können jetzt auftreten? #card

Falls dieses Programme jetzt also als Kette vorliegt, dann beschreiben wir die Ausführung des Programmes folgend: -> Wir schreiben hier und meinen also die -fache Verkettung von auf ! Ferner gilt somit auch ! (Also die Identität!)

Falls jetzt ferner noch , dann sei die kleinste Zahl, sodass entweder nicht terminiert oder so, dass die -te Variable in . dann ist folglich:

Also wir können sagen, dass unser Programm eventuell terminieren wird, wenn an der -ten Stelle (im Speicher, also ) eine steht, sodass die While-Condition dann erfüllt wird!

–> wenn das nicht passiert, dann wird sie ewig laufen –> somist ist ihr Ergebnis auch undefined!

Wir haben damit nun die Syntax, als auch die Semantik von While-Programmen definiert.

-> Mann kan dann jetzt formal zeigen, dass für jedes -Programm das unsere Definition der Syntax erfüllt, die wir zuvor beschrieben haben, garantiert wohldefiniert sein wird.

[!Attention] While beschreibt Programmiersprachen

Was wir jetzt hier erkennen können: While-Programme beschreiben Programmiersprachen! (Jedoch eine sehr einfache (ohne weitere Definitionen und Syntactic sugar!))

Wir wollen dann jetzt die gängigen Konstrukte von Programmiersprachen in While-Programme überführen, und damit zeigen, dass sie entsprechend alles abdecken kann!


Synctactic Sugar | für While

Anhand mancher Beispiele wollen wir zeigen, dass wir diverse Konstrukte / Operationen umsetzen können: –> Wir wollen also etwa Arithmetiche Operationen und ferner auch Case-Statements explizit übersetzen ( das geht auch für alle anderen Operationen (weil while turing-complete ist!))

Multiplikation

\begin{algorithm} 
\begin{algorithmic} 

\Procedure{product}{$x_j,x_k$}
\State $x_{j} \longleftarrow 0$
\State $c \longleftarrow x_j$
\While{$c \not = 0$}
\State $x_{j}\longleftarrow x_{i}+ x_{k}$
\State $c \longleftarrow c-1$
\EndWhile
\EndProcedure

\end{algorithmic}
\end{algorithm}

und wir sehen, dass sie die Multiplikation relativ elemntar umsetzen kann!

Ferner noch Case-Statements:

\begin{algorithm} 

\begin{algorithmic}  

\Procedure{iftest}{}
\If{$x = 0$} 
\State P
\EndIf

\EndProcedure

\Procedure{asWhileLoop}{}
\State $y=1$
\While{$ x \not = 0$}
\State $y  =0 $
\State $x = 0$
\EndWhile
\While{$y \not = 0$}
\State $y = 0$
\State P
\EndWhile

\EndProcedure

\end{algorithmic}
\end{algorithm}

und damit haben wir passend übersetzen können!

Wir bemerken - später nochmal wichtig! - , dass diese -Ausdrück keine echten Schleifen sind, weil ihr Inneres höchstens einmal ausgewertet wird. Frage ist dabei dann.

[!Attention]

Wir wollen jetzt herausfinden, ob wir andere Paradigmen finden können, die eventuell mächtiger sind, als die soeben definierte While-Schleife


Dafür schauen wir uns ferner ein weiteres bekanntes Paradigma, die For-Schleife an!

For-Programme:

[!Definition]

Wir betrachten dasselbe Alphabet, wie bei den -programmen, wobei das Keyword while durch for ersetzt wird. Ein for-Programm ist dann auch eines von drei Fällen: (Es ist somit beinahe äquivalent zu der Definition des while-Programmes) Dennoch müssen wir wieder 3 Fälle der Definition betrachten!

welche drei Fälle betrachten wir? #card

  1. entweder ein einfacher Befehl - oder eine Addition/Subtraktion (wie bei der while-Schleife) (das können wir dann einfach umsetzen)
  2. Es tritt eine Schleife auf! mit folgender Struktur
\begin{algorithm} 
\begin{algorithmic} 
\For{$x_j$} 
\State $P_{1}$
\EndFor
\end{algorithmic}
\end{algorithm}
  1. Es kann auch hier eine Verkettung auftreten: , wobei auch hier jeweils beide Programme for-Programme sind!

Wir möchten auch hier wieder die Semantik besprechen und definieren:

[!Req] Semantik von For-Programmen

Betrachten wir For-Programme, so ist ihre Semantik ähnlich - aber nicht gleich - zu while-Programmen.

Wie translatieren wir hier dann ein For-Programm? Spezifisch für das Programm #card

  • Wir werden einfache Programme - also die Zuweisung eines Wertes o.a., wie bei der Semantik von While betrachten.
  • Ein Programm schreiben wir folgende Struktur auf

Wichtig Was wir durch diese Notation forcieren:

  • der Wert von wird nur einmal eingelesen und damit festgelegt, wie oft die Schleife läuft. Das heißt wir können keine Programme formulieren, die innerhalb ihres Codes wieder den Index verändern und somit eventuell endlos lang laufen können / werden.

Wir wollen ferner etablieren / herausfinden, dass alle For-Programme auch durch while-Schleifen umsetzbar sind (so, wie wir schon vorherigen syntactic sugar damit umsetzen konnten)

Alle -Programme sind -Programme

[!Satz] Alle -Programme sind -Programme

Wir wollen folgend beweisen, warum wir eine jede For-Schleife auch als while Programm darstellen können.

Wie gehen wir vor, um entsprechend zu übersetzen / es zu beweisen? #card

Für einfache Befehle und Verkettungen ist die Semantik gleich und daher müssen wir hier nichts beweisen (also Zuweisung etc ist kein Problem)

Jedoch die For-Schleife müssen wir uns anschauen, also “for do end, wobei ein -Programm mit einem bekannten und äquivalenten -programm sein wird. Es gilt jetzt: und wir sehen, dass das äquivalent zu folgendem -Programm sein wird (also

\begin{algorithm} 
\begin{algorithmic} 
\State $y = x_{i}$ 
\Comment{als neue Variable, die wir nach und nach verringern}
\While{$y \neq 0$}
\State $y = y-1$
\State $P_{1}'$ \Comment{wir führen also die Funktion durch} 
\EndWhile
\end{algorithmic}
\end{algorithm}

Wir haben also eine neue Zählvariable eingeführt, die genau -mal die Funktion in der While-Schleife ausfuhren / anwenden wird!

Alle -Programme terminieren immer

[!Feedback] Behauptung

Wir wollen noch behaupten, dass mit unserer Definition! -Programme immer terminieren:

wie können wir das beweisen? #card

(Als Vorüberlegung: Wenn wir eine maximale Zahl der Iterationen setzen, dann werden wir folgend garantiert immer terminieren, weil wir die Schritte eben genau mal ausführen ( und wir verbieten, dass sie diesen Indice verändern!))

Möglich ist das durch eine strukturelle Induktion

IA: ein einfacher Befehl terminiert immer

IS: Sei ein -Programm das terminiert.

  • Sei for do end”. Dann terminiert nach genau Schritten, weil immer terminiert
  • Sei (eine Verkettung), dann terminiert nach endlich vielen Schritten, weil ebenfalls terminieren müssen!

Damit haben wir genau gezeigt, dass sie terminieren müssen

[!Question]

Was ist, wenn wir eine Schleife konstruieren, die im letzten Schritt, also etwa mit if x-1 = 0 then createNewLoop(), immer wieder eine neue Schleife aufrufen würde - oder vielleicht auch sich selbst?

–> Dann würde sie hier ja eigentlich nicht terminieren, weil sie ja technisch immer und immer wieder rekursiv sich selbst aufruft

GOTO-Programme

Neben While ist auch Goto sehr mächtig - auch wenn es niemand nutzt!(zum Glück xd) - was wir folgend belegen möchten.

[!Definition] -Programme

Wir betrachten das selbe Alphabet, wie bei while-Programmen, jedoch ersetzen wir ‘while’ mit ‘goto’ und ‘end’ mit ‘halt’.

Damit beschreiben wir jetzt ein -Programm.

Wie ist es aufgebaut, woraus besteht es? Spezifisch, welche Formen haben die Operationen, und wie beenden wir? #card

Ein -Programm besteht aus einer endlichen Folge von Tupeln (wobei: (Zeilennr, Befehl)) wobei dann jeder Befehl eines der folgenden Formate hat:

  • if goto
  • halt

Offensichtlich kann ein solches -Programm auch wieder in eine Schleife verfallen!:

  • (1, )
  • (2, )
  • (3, )

Nach Schöning (Die Semantik solcher Programme sollte klar sein (sie ist ähnlich / gleich, wie bei programmen))

Aber denken Sie mal drüber nach, wie man sie sauber definiert. (Wichtig, Wenn eine Zeile kein goto enthält, wird danach einfach die nächste folgende Zeile verarbeitet!) –> Variablen können mit Zeilennummern belegt werden!

While | For | Goto | - Berechenbarkeit

Wie auch schon mit 112.12_turing_maschinen können wir Funktion als term-berechenbar einstufen, wobei

[!Definition]

Wir wollen ferner eine partielle Funktion while-berechenbar nennen (oder eben auch for/goto-berechenbar)

was muss gelten? #card

Wir können diese partielle Funktion so beschreiben, wenn es ein while-Programm gibt, welches die Funktion berechnet!

for-berechenbar -> while-berechenbar

Wir wissen schon, dass [Alle -Programme sind -Programme](#Alle%20-Programme%20sind%20-Programme) und ferner können wir daraus auch einen Umkehrschluss finden:

[!Feedback] Mächtigkeit von While gegenüber for

Es gilt jetzt: Es gibt -Programme, welche nicht durch -Programme simuliert werden können.

welche, wie können wir das beweisen? #card

kann man mit einem einfachen Gegenbeispiel zeigen: -> Wir wissen ja schon, das Programm immer terminieren, also wenn wir dann ein while-Programm konzipieren, was nicht anhält, haben wir schon ein Gegenbeispiel!

\begin{algorithm} 
\begin{algorithmic} 
\State $x_{1} =1$
\State $x_{2} = 0$
\While{$x_{1} \neq 0$}
\State $x_{2} = x_{2}+1$
\EndWhile
\end{algorithmic}
\end{algorithm}

Wir sehen offensichtlich, dass man das nicht als For-Programm schreiben kann!

(Es gibt noch ein besseres Beispiel, was wir uns anschauen wollen: Die Ackermann-Funktion!)

-Berechenbar -> -Berechenbar

Beide scheinen sich ja ähnlich - können nicht terminieren und loopen und laufen irgendwie im Kreis - also wollen wir noch die Äquivalenz beider betrachten:

[!Satz]

Es gilt: Jedes -Programm kann durch ein goto-Programm simuliert werden! Also jede -berechenbare Funktion ist auch -berechenbar!

wie können wir das beweisen? #card

Dafür möchten wir eine Struktur etablieren, die dabei hilft einfach immer eine -Schleife in ein -Programm umzuschreiben:

\begin{algorithm} 
\begin{algorithmic} 
\While{$x_{1} \neq 0$}
\State $P$
\EndWhile
\end{algorithmic}
\end{algorithm}

kann man dann etwa folgend mit goto simulieren:

\begin{algorithm} 
\begin{algorithmic} 
\State $M_{1} :~ if~x_{i} = 0 ~ goto M_{2}: P; ~goto`(else)~ M_{1}$
\State $M_{2}: \dots$
\end{algorithmic}
\end{algorithm}

Das geht aber auch in die andere Richtung gut:

[!Req] jedes goto - in while umwandeln (können)

Es gilt: Jedes -Programm kann durch ein -Programm mit nur einer Schleife simuliert werden! (Also jede -berechenbare Funktion ist auch berechenbar)

Wie können wir das folglich beweisen, was wäre der Ansatz zur Übersetzung? #card

Wir können das Programm folgend übersetzen. (Vorab, wir wissen, dass man mit while-schleifen darstellen kann!)

Wir translatieren also folgende Struktur:

\begin{algorithm} 
\begin{algorithmic} 
\State $1: A_{1}$
\State $2: A_{2}$
\State $3: A_{3}$
\State $\vdots$
\State $k: A_{k}$
\end{algorithmic}
\end{algorithm}

In folgende Schleife:

\begin{algorithm} 
\begin{algorithmic} 
\State $Zeile~ = 1$ 
\Comment{Gibt den Start an!}
\While{$Zeile \neq 0$}
\If{$Zeile = 1$}
\State $\hat{A_{1}}$
\EndIf
\If{$Zeile = 2$}
\State $\hat{A_{2}}$
\EndIf
\State $\vdots$
\If{$Zeile =l$}
\State $\hat{A_{k}}$
\EndIf

\EndWhile

\end{algorithmic}
\end{algorithm}

Also wir prüfen konstant auf welcher Zeile wir nun sind, um dann die richtige Funktionalität auszuführen und verpacken das in einem Loop!

Ferner beschreiben wir hier noch , weil wir da nicht einfach den Code übernehmen können (etwa wenn wir springen, was machen wir dann?)

Wir definiere es demnach folgend:

Und somit haben wir also immer entsprechend die aktuelle Zeile aktualisiert (passen also auf, dass wir u.U. richtig springen!)

-> bei einfachen Operationen (Arithmetik etwa) werden wir einfach Ausführen und dann auf die nächste Zeile springen (wie beim goto!) Bei einem -Befehl verändern wir die entsprechend die aktuelle Zeile (welche dann mit den -Conditions abgedeckt werden!) die while-Schleife wird beendet, wenn wir halt im finden!


Es lässt sich aus der Äquivalenz noch ein Korollar aufstellen:

[!Korollar] Kleensche Normalform für -Programme

Es gilt für -Programme:

Jede -Berechenbare Funktion kann durch ein -Programm mit nur einer Schleife berechnet werden

Wie können wir das beweisen? #card

Wir haben ja gesehen, dass man jedes -Programm in ein -Programm übersetzen kann. Anschließend kann man jedes -Programm aber auch wieder in ein -Programm mit einer einzigen Schleife übersetzen, wie wir bei [-Berechenbar -> -Berechenbar](#-Berechenbar%20->%20-Berechenbar) gesehen haben!

(Tatsächlich stimmt das nur so halb, weil wir ja etc auch als while-Schleife darstellen müssen und obig nur als syntaktischen Zucker implementiert haben)

While ist Turing-Äquivalent!

[!Attention]

Es gilt auch: ist Turing-Äquivalent!

(War ja irgendwie klar, als wir gesehen haben, dass -Schleifen manchmal einfach nicht halten)

Turing-Äquivalenz

Beweis

[!Beweis] Strukturelle Induktion

Wir können das durch eine Reduktion von umsetzen (also wir können while-Programme in Turing-Maschinen übersetzen!)

Machen wir dafür eine strukturelle Induktion (wir haben ja auch schon -Programme induktiv definiert!)

Wir führen den Beweis zunächst für den Induktionsanfang der Definition durch, und zeigen dann, wie die TM Konstruktion durch diesen Schritt hindurch funktioniert (also nicht verletzt wird!)

Gegeben sei ein -Programm mit Variablen.

Wir konstruieren jetzt eine TM mit Bändern , so dass der Inhalt einer Variable dann auf dem ten Band liegt!

Induktionsanfang:

Ein einfacher Befehl ist eine der folgenden drei Anweisungen (nach Definition), wobei :

  • Zuweisung
  • Addition
  • Subtraktion

(Intuitiv ist es klar, dass wir arithmetische Operationen mit einer TM darstellen können (haben wir schon in einer Übung gemacht Aufgabe-1))

Induktionsschritt:

ein -Programm ist entweder ein einfacher Befehl oder hat folgende Form:

  • Schleife: “while do
  • eine Verkettung

Wir wollen diese jetzt noch passend umformen, sodass sie von einer TM dargestellt werden können.

  1. Sei eine TM, die berechnet / simuliert.

Wir bauen jetzt eine TM indem wir - sofern nicht schon existiert - um ein Band erweitern, auf dem dann stehen kann. –> Nach jedem Lauf von liest dann aus und ruft ggf dann wieder auf ( wenn die While-Condition noch nicht erfüllt wurde!)

  1. Die Verkettung von zwei s ist auch eine TM!

Sei die TM für das Programm . Dann lassen wir jetzt zuerst laufen. Wenn diese TM terminiert dann starten wir auf dem Output von (also Verkettung ist simpel!)

Damit haben wir alle wichtigen Aspekte übersetzt und somit in TMs übersetzt!

Übersicht | Turing-Maschine als PseudoCode

Folgender PseudoCode ist cool, weil man hier ganz gut die Idee und Funktionsweise einer TM erkennen kann! (Man sieht die einzelnen Bereiche (Initialisierung, Übergänge, wann man einen Endzustand erhält etc) sehr klar)

[!bsp] Turing-Maschine als While-Programm

Sei eine Turingmaschine.

Mit folgendem -Programm können wir die Berechnung simulieren!

\begin{algorithm} 
\begin{algorithmic} 
\Procedure{M}{w} 
\State $q = q_{0}$ \Comment{speichert aktuellen Zustand, ist jetzt der erste}
\State $l=1$ \Comment{l speichert die Position auf dem Band}
\For{$\mid w\mid$}
\state $x_{l} = w_{l}$  \Comment{Lese aktuellen Buchstaben ein}
\state $l = l+1$ 
\Comment{inkrementiere Position}

\EndFor
\state $l=1$ \Comment{resete head}
\While{$T \neq 0$}
\state $(q,x_{l},D) = \delta(q,x_{l})$
\state \Comment{Wir ziehen also die neuen Zustände und Inhalt aus der Übergangsfunktion!}
\state $l = l +D$ \Comment{bewege Kopf}
\If{$q = q_{accept} \lor q  = q_{reject}$}
\Comment{found end condition!}
\state $T = 0$
\EndIf

\EndWhile
\EndProcedure
\end{algorithmic}
\end{algorithm}