Datenverarbeitende Systeme
Kapitel 6: Touring-Automaten und kontextsensitive Sprachen

6.1 Kontextsensitive Sprachen – Typ 1-Grammatiken

Als letztes betrachten wir Sprachen, die nicht einmal kontextfrei sind. Wir haben im Moment keine Methode zur Hand, um eine Sprache in Typ 1 oder Typ 0 einzuordnen. Wir können nur mit dem Pumpig-Theorem aussagen, dass L eben nicht Typ 2 ist und damit 1 oder 0 sein muss. Wir können aber wieder einen Automaten angeben, der eine Sprache von beiden Typen erkennt. Später können wir diesen Automaten so klassifizieren, dass er nur Sprachen vom Typ 1 erkennt (siehe linear beschränkte Automaten) . Zunächst möchte ich aber allgemein den entsprechenden Automat vorstellen:


6.2 Der Touring-Automat

Ein Touring-Automat kommt mit einem einzigen Band aus, auf dem er die Eingabe erhält und auch die Ausgabe erledigt. Das Band dient zusätzlich als Zwischenspeicher. Das Band ist unendlich lang und alle unbeschriebenen Stellen enthalten zunächst Platzhalter (#). Die Ausgabe ist entweder ein Ausgabesymbol oder ein Steuerzeichen, um den Schreib-Lesekopf um eine Position nach links oder rechts zu verschieben.

TA = (X, B, S, s0, d, sf ):

X: Eingabealphabet
B: Bandalphabet, X ist Teilmenge von B, # ist aus X, # heißt Leerzeichen
S: endliche Zustandsmenge
s0: Startzustand
d: Zustandsübergangsfunktion
sf: Haltezustand

Zu Beginn steht der Schreib-Lesekopf über dem obersten Symbol der Eingabe. Der Automat terminiert, wenn sf erreicht wurde oder es keine Kante mehr für das Symbol gibt, das sich im aktuellen Zustand gerade unter dem Bandkopf steht. Die Steuerzeichen L und R sind Element von B und bewegen den Kopf nach links oder rechts. Kanten beschriften wir mit a/b, wobei a das Eingabesymbol und b das Ausgabesymbol ist. Ich will wieder auf unser beliebtes Sprachmodell L={ anbncn | n>0} zurückgreifen (wir haben es schon fast vermisst). Entwickeln wir zunächst einen Lösungsansatz:

  1. Lösche das erste a (überschreibe es mit #)
  2. gehe zum letzten b (zum ersten c und eins zurück, read-ahead nicht möglich)
  3. überschreibe dieses b durch ein c (jetzt haben wir ein a und ein b weniger, ein c mehr)
  4. gehe zum letzten c (ans Bandende und eins zurück, siehe 2)
  5. lösche dieses c mit # (das c aus 3 ist jetzt wieder entfernt)
  6. gehe um eins nach links und lösche auch dieses c
  7. gehe um eins nach links
  8. haben wir ein # erreicht, ist das Band leer und das Wort erkannt!
  9. Ansonsten gehe an den Bandanfang und um eins nach rechts auf das vorderste a
  10. wiederhole 1 – 9 solange, bis in 8 terminiert werden kann
     

Wir gewinnen folgenden Automaten:

Man könnte diesen Automaten noch optimieren, indem man S3 und S4 zusammenfasst.


6.3 Touringberechenbare Funktionen

Eine Funktion gilt als von einem Touring-Automat berechenbar, wenn es einen TA gibt, der genau dann für ein eingegebenes Wort w aus X* terminiert, wenn w im Definitionsbereich der Funktion liegt. Dann steht nach der Terminierung der Funktionswert f(w) auf dem Band.

Ein Touring-Automat ist durch eine Programmiersprache simulierbar, wenn wir einen Speicher finden, der nach beiden Seiten hin offen ist (Touring-Band). Dazu splitten wir das Band in zwei Hälften, einen Teil links vom Bandkopf und einen Teil rechts davon. Das Zeichen unter dem Bandkopf steht im rechten Speicher. Als Speicher legen wir zwei Stacks an und nennen sie LS (left Stack) und RS (right Stack). Eine Linksbewegung des Kopfes schiebt das oberste Zeichen von RS in LS, eine Rechtsbewegung macht das umgekehrte. Wenn wir ein Zeichen überschreiben, löschen wir zunächst das oberste Zeichen von RS und schieben das neue Zeichen auf den RS. Um diesen Algorithmus herum legen wir eine Schleife, die Zustandsübergangsfunktionen liegen in einer Tabelle im Speicher. Die Implementierung bleibt jedem selbst überlassen.

Umgekehrt wollen wir versuchen, eine Programmiersprache durch einen TA zu simulieren. Wenn uns das gelingt, können wir in Kombination mit dem obigen Algorithmus eine beliebige Sprache in eine beliebige andere übersetzen, in dem wir einen TA dazwischenbauen. Ob das der einfachste Weg ist, sei dahingestellt.

Um uns das Leben einfach zu machen, zeigen wir erst einmal, das jede Programmiersprache aus einfachen Grundbestandteilen besteht, die Operationen auf ganzen Zahlen n >= 0 erlauben. Schließlich besteht jede Zahl aus eine Folge von Bits, deren Interpretation als Ganzzahl oder Fließkommazahl mit oder ohne Vorzeichen am Ende dem Prozessor überlassen ist (na ja, wir müssen es ihm schon sagen). Alles, was unsere Sprache können muss, ist, eine Variable nullen (x=0), eins addieren (x++) oder eins subtrahieren (x--). Letztlich brauchen wir noch eine while-Schleife. Wir codieren Zahlen auf dem Band in unärer Darstellung. Null entspricht einem Strich, eins zwei Strichen und so weiter. Wollen wir eine Funktion mit mehreren Variablen realisieren (Vektoren, Schleifen, etc. ), so trennen wir die Variablen auf dem Band mit einem $-Zeichen. Die Implementierung der einzelnen Automaten überlasse ich dem geneigten Leser ebenso, wie den Aufbau von komplexeren Funktionen wie Summen oder if-then-else-Verzweigungen.

Damit ist gezeigt: Programmiersprachen sind von Touring-Automaten berechenbar und umgekehrt. Sprachen, die von Touring-Automaten akzeptiert werden heißen Regelsprachen.

6.3.1 Das Problem mit der Terminierung

Wir kennen drei Möglichkeiten der Arbeitsweise eines Touring-Automaten: Er kann in einem Haltezustand enden, irgendwann abbrechen, wenn es keine Kante für die aktuelle Eingabe gibt oder seine Arbeit bis in alle Ewigkeit fortsetzten ohne zu terminieren. Dabei haben wir das Problem, dass wir nie sagen können, ob der Automat nicht doch 5 Sekunden vor der Ewigkeit terminiert oder nicht. Nur weil eine Funktion nach 10 Millionen Jahren noch nicht fertigberechnet ist, heißt das noch nicht, das sie nie berechnet werden kann. Denken wir an die Faktorisierung langer Primzahlen oder die Zerlegung eines menschlichen Körpers in seine Einzelbestandteile wie es beim beamen a la Star-Trek nötig wäre.

Folgende Tabelle soll Aufschluss geben, wie ein Automat reagiert, der L(TA) erkennt (2 Fälle: L nichtverkürzend oder L rekursiv - siehe unten) oder Funktionen berechnet:

    TA erkennt L(TA) TA berechnet Funktion TA erkennt L(rekursiv)
TA terminiert erreicht Haltezustand Eingabe lag in der Sprache Eingabe lag in der Sprache, f(w) steht auf dem Band Eingabe lag in der Sprache
  bricht ab Eingabe lag nicht in der Sprache Kommt nicht vor Eingabe lag nicht in der Sprache
TA terminiert nicht   Eingabe lag nicht in der Sprache Eingabe lag nicht in der Sprache Kommt nicht vor

Eine Sprache heißt rekursiv, wenn es einen Automaten gibt, der für jedes Eingabewort x terminiert. Ein solcher Automat heißt terminierend.

6.3.2 Linear beschränkte Automaten

Ein Automat heißt linear beschränkt, wenn er mit einem endlichen Band auskommt. Solche Automaten sind in der Praxis von Bedeutung, da Computer im allgemeinen nur über endlich viel Speicher verfügen. Das Band dieser Automaten ist links und rechts jeweils durch zwei unterschiedliche Steuerzeichen begrenzt, die nicht überfahren und auch nicht überschrieben werden können. Linear beschränkte Automaten akzeptieren Sprachen, die mindestens vom Typ 1 sind. Damit haben wir eine Möglichkeit nachzuweisen, dass eine Sprache genau Typ 1 ist: Zeige mit Pumping-Theorem, dass L nicht Typ 2 und gib einen linear beschränkten Touring-Automaten dazu an.



© Gerhard Zapf
Kellerautomaten
Sitemap
www.tutorialpage.de
Klausurhilfen
Diese Seite wurde seit dem 12.07.01 genau 594 mal abgerufen.
Letzte Änderung: 11.09.2003