Theoretische Informatik SS 03 Übung 5 Aufgabe 1 Im Buch von Schöning ist auf S. 106-108 beschrieben, wie eine Turing-Maschine durch ein GOTO-Programm simuliert werden kann. Zeigen Sie, wie dabei die Anweisungen δ(z i , aj ) = 0 0 0 0 (zi , aj , R) und δ(zi , aj ) = (zi , aj , N ) mit DIV und MOD - Operationen simuliert werden können. Lösung: Wie dem Beweis bei Schöning zu entnehmen ist, wird für eine Turingmaschine mit Zustandsmenge Z = {z1 , . . . , zk } und Bandaphabet Γ = {a1 , . . . , am } eine Turingmaschinenkonfiguration in der Form a i1 . . . a ip z l a j 1 . . . a j q durch drei Programmvariablen x, y, z repräsentiert, die entsprechende Werte x = (i1 . . . ip )b y = (jq . . . j1 )b z=l annehmen. Es handelt sich dabei um Zahlen in b-närer Darstellung, wobei b > |Γ|: x= p X iµ · bp−µ µ=1 x repräsentiert die Bandinschriften links des Schreib-/Lesekopfes, y die rechts des Schreib/Lesekopfes, wobei hier die Ziffern in umgekehrter Reihenfolge stehen. 0 0 δ(zi , aj ) = (zi , aj , R): 0 0 Es muss ein Zustandswechsel in den Zustand i erfolgen, an x j angehängt und von y die erste Stelle entfernt werden: z = i 0 x = b∗x+j y = y DIV b 1 0 δ(zi , aj ) = (zi0 , aj 0 , N ): 0 Es muss ein Zustandswechsel in den Zustand i erfolgen und von y die erste Stelle durch j ersetzt werden: z = i 0 0 y = y DIV b y = b∗y+j 0 Aufgabe 2 Erinnert sei an die Definition der Ackermann-Funktion a a(0, y) = y + 1 a(x, 0) = a(x − 1, 1), x > 0 a(x, y) = a(x − 1, a(x, y − 1)), x, y > 0 Weisen Sie folgende Eigenschaften nach: a) a(1, y) = y + 2 Beweis: Wir führen Induktion über y: Induktionsanfang: ! a(1, 0) = y + 2 = 0+2 = 2 a(1, 0) = a(0, 1) = 2X Induktionsvoraussetzung: a(1, y) = y + 2 Induktionsbehauptung: a(1, y + 1) = (y + 1) + 2 Induktionsschluss: a(1, y + 1) = a(0, a(1, y)) IV = a(0, y + 2) = (y + 1) + 2 X 2 2 b) a(2, y) = 2y + 3 Beweis: Induktionsanfang: ! a(2, 0) = 2y + 3 = 0+3 = 3 a(2, 0) = a(1, 1) a) = 1+2 = 3X Induktionsvoraussetzung: a(2, y) = 2y + 3 Induktionsbehauptung: a(2, y + 1) = 2(y + 1) + 3 Induktionsschluss: a(2, y + 1) = a(1, a(2, y)) IV a(1, 2y + 3) = a) = 2y + 3 + 2 = 2(y + 1) + 3 X c) a(3, y) = 2y+3 − 3 Beweis: Induktionsanfang: ! a(3, 0) = 2y+3 − 3 = 20+3 − 3 = 8−3 = 5 a(3, 0) = a(2, 1) b) = 2·1+3 = 5X 3 2 Induktionsvoraussetzung: a(3, y) = 2y+3 − 3 Induktionsbehauptung: a(3, y + 1) = 2(y+1)+3 − 3 Induktionsschluss: a(3, y + 1) = a(2, a(3, y)) IV = a(2, 2y+3 − 3) = b) 2 · (2y+3 − 3) + 3 = 2(y+1)+3 − 3 X 2 d) Wie lautet die Formel für a(4, y)? Lösung: . 22 .. 2 a(4, y) = 2| {z } − 3 (y+3) oft Dieser Sachverhalt ist auch sehr gut an der Wertetafel der Ackermannfunktion a (Aufgabe 3) zu erkennen. Beweis: Induktionsanfang: ! a(4, 0) = . 22 .. 2 2| {z } − 3 (y+3) oft 2 = 22 − 3 = 16 − 3 = 13 a(4, 0) = a(3, 1) c) = 21+3 − 3 = 13 X 4 Induktionsvoraussetzung: 22 .. .2 a(4, y) = 2| {z } − 3 (y+3) oft Induktionsbehauptung: 22 a(4, y + 1) = .. .2 2| {z } −3 ((y+1)+3) oft Induktionsschluss: a(4, y + 1) = IV = a(3, a(4, y)) 22 c) (y+3) oft 2 .. 2 2. 2 | {z 2 22 2 | {z 2 2 } 2| 2{z } = −3 2 (y+3) oft . .. } −3+3 2(y+3) oft . .. = .2 a(3, 2| {z } − 3) = .. −3 −3X 2 ((y+1)+3) oft Aufgabe 3 Welche Funktionen können mit WHILE-Programmen aber nicht mit LOOP-Programmen berechnet werden: a) totale oder partielle Funktionen? Lösung: Partielle Funktionen sind nicht LOOP-berechenbar. Da LOOP-Programme nach endlicher Zeit stoppen, liefern sie immer ein Ergebnis, was falsch sein muss, wenn die zu berechnende Funktion an eben dieser Stelle nicht definiert ist. b) sehr schnell oder sehr langsam wachsende Funktionen? Lösung: 5 Sehr schnell wachsende Funktionen sind u.U. nicht LOOP-berechenbar. Die AckermannFunktion ist ein Beispiel für eine solche Funktion. Jedem LOOP-Programm P kann eine Funktion f P : −→ zugeordnet werden. Für die in P vorkommenden Variablen x0 , x1 , . . . , xk bezeichnet in der folgenden Definition n i den 0 Startwert der Variablen xi und ni den zugehörigen Endwert nach Ablauf des Programms P : fP (n) = max{ k X i=0 0 ni | k X ni ≤ n} i=1 fP (n) gibt also die größtmögliche Summe aller Variablenendwerte an, wenn P mit Anfangswerten gestartet wird, die in der Summe n nicht übersteigen. Man kann zeigen, dass für jedes LOOP-Programm P eine Konstante k existiert, so dass für alle n gilt: f P (n) < a(k, n) (vgl. Schöning S. 118). Damit folgt, dass die ACKERMANNFUNKTION a nicht LOOP-berechenbar ist. Beweis: Ann. a ist LOOP-berechenbar. =⇒ g(n) = a(n, n) ist LOOP-berechenbar. Sei P ein LOOP-Programm für g. =⇒ fP (n) < a(k, n) k sei eine Konstante, so dass fP (n) < a(k, n) gilt und wir wählen n := k. =⇒ g(k) ≤ fP (k) < a(k, k) = g(k), Widerspruch, a ist nicht LOOP-berechenbar. 2 In Schöning auf S. 113 ist nachzulesen, dass die Klasse der LOOP-berechenbaren Funktionen genau mit der Klasse der primitiv rekursiven Funktionen übereinstimmt. Daher kann man obigen Sachverhalt auch beweisen, indem man zeigt, dass die ACKERMANNFUNKTION a schneller wächst als alle primitiv rekursiven Funktionen. Aufgabe 4 a) Bekanntlich kann die Funktion c(x, y) = x+y+1 + x benutzt werden, um Paare von na2 türlichen Zahlen in eine einzelne Zahl zu codieren. Die Umkehrfunktionen e und f von c sind dann definiert durch e(c(x, y)) = x, f (c(x, y)) = y, c(e(n)), f (n)) = n. Geben Sie jeweils e(n) und f (n) an für n = 17, 25 und 31. Lösung: n = 17: (2 + 3 + 1) · (2 + 3) 6·5 (x + y + 1)(x + y) +x= +2= + 2 = 17 2 2 2 =⇒ e(c(x, y)) = e(17) =x = 2 =⇒ f (c(x, y)) = f (17) =y = 3 6 n = 25: (4 + 2 + 1) · (4 + 2) 7·6 (x + y + 1)(x + y) +x= +4= + 4 = 25 2 2 2 =⇒ e(c(x, y)) = e(25) =x = 4 =⇒ f (c(x, y)) = f (25) =y = 2 n = 31: (3 + 4 + 1) · (3 + 4) 8·7 (x + y + 1)(x + y) +2= +3= + 3 = 31 2 2 2 =⇒ e(c(x, y)) = e(31) =x = 3 =⇒ f (c(x, y)) = f (31) =y = 4 Allgemein gilt: e(n) = max{x ≤ n | ∃y ≤ n : c(x, y) = n} f (n) = max{y ≤ n | ∃x ≤ n : c(x, y) = n} b) Überzeugen Sie sich, dass das WHILE-Programm auf S. 120-21 im Buch von Schöning die Ackermann-Funktion für alle Eingaben (x, y) berechnet. Lösung: INPUT(x, y); INIT(stack); PUSH(x, stack); PUSH(y, stack); WHILE size(stack) 6= 1 DO y :=POP(stack); x :=POP(stack); IF x = 0 THEN PUSH(y + 1, stack); ELSIF y = 0 THEN PUSH(x − 1, stack);PUSH(1, stack); ELSE PUSH(x − 1, stack);PUSH(x, stack);PUSH(y − 1, stack); END{IF}; END{WHILE}; result :=POP(stack); OUTPUT(result); In den ersten vier Zeilen des Programms wird die Eingabeinstanz auf den Stack gelegt (zunächst x, dann y). Während der Schleifenabarbeitung gilt, dass immer die in der Rekursion zuletzt aufgerufene Instanz oben auf dem Stack liegt, so dass diese weiter bearbeitet wird - dies ist anfänglich die zu lösende Ursprungsinstanz. 7 Eine solche Verarbeitung erfolgt derart, dass entweder rekursiv (nach Definition von a) eine neue Instanz erzeugt und auf dem Stack abgelegt wird, oder bei x = 0 gerade y + 1. Dies entspricht ebenfalls genau der Definition der Ackermannfunktion a. Die Schleife kann erst stoppen, wenn der Stack nur noch ein Element enthält. Dabei muss es sich um das Resultat der ursprünglichen Instanz von a handeln. 8