Mitschrift BFS WS 13/14 Stand: 4. Juni 2014 Dieses Skript zum Teil Primitive und µ-rekursion der Vorlesung Berechenbarkeit und Formale Sprachen im Wintersemester 2013/14 bei Prof. Wanka wurde von untenstehenden Studenten erarbeitet. Es ist somit offensichtlich inoffiziell und erhebt weder einen Anspruch auf Korrektheit noch auf Vollständigkeit. Burkhard Ringlein burkhard.ringlein@studium.fau.de Benedikt Lorch benedikt.lorch@studium.fau.de
Inhaltsverzeichnis 4 Primitive und µ-rekursion 1 4.1 LOOP-, WHILE- und die GOTO-Berechenbarkeit...................... 1 4.2 Definition primitiv rekursiver und µ-rekursiver Funktionen.................. 4 4.3 Die Ackermann-Funktion.................................... 8 5 Zusammenfassung 11 5.1 Berechenbarkeit.......................................... 11 5.1.1 Halteproblem....................................... 11 5.1.2 universelle Turing-Maschine............................... 11 5.1.3 NP-Vollständigkeit.................................... 11 5.1.4 Nichtdeterminisus.................................... 11 5.2 Formale Sprachen......................................... 11 0
4 Primitive und µ-rekursion 4.1 LOOP-, WHILE- und die GOTO-Berechenbarkeit Variablen: x 1, x 2, x 3,... Konstanten: 0, 1, 2,... Trennsymbole: ;, := Operationszeichen: +, 1 Schlüsselwörter: LOOP, DO, END Induktive Definition von LOOP-Programmen: Wertzuweisungen: x j := x j + c c ist eine (bel.) Konstante aus N = 0, 1, 2... x j := x j c Also sind auch: x i := x j [+0] 2 und x i := c[+x j ] 2 mögliche Wertzuweisungen. Sind P 1 und P 2 LOOP-Programme, so ist auch P 1 ; P 2 ein LOOP-Programm. Ist P ein LOOP Programm, ist auch LOOP x i DO P END ein LOOP-Programm. Bei Eingabe n 1,..., n k N stehen diese Zahlen in x 1,..., x k, alle anderen Variablen x i sind mit 0 initialisiert. Am Ende der Rechnung steht die Ausgabe in x 1. Bedeutung von + und ist klar. P 1 ; P 2 : führe erst P 1 aus, dann P 2 LOOP x i DO P END : Führe P sooft hintereinander aus, wie der Wert von x i zu Beginn 2 der LOOP-Schleife ist. Definition 4.1 Eine Funktion f: N k N heisst LOOP-berechenbar, falls es ein LOOP-Programm P gibt, das f berechnet, so dass zu Beginn n 1,...n k inx 1,..., x k stehen und zum Schluss f(n 1,...n k ) in x 1 steht. LOOP-berechenbare Funktionen sind total. Frage: Sind alle total berechenbare Funktionen LOOP-berechenbar? 3 ein paar Programmiertricks: IF x i = 0 T HEN P END kann durch ein LOOP-Programm simuliert werden. 1 modifiziertes minus : [max(a b, 0) =: a b] 2 für Formale Korrektheit: x j := 0undx j wird nie wieder benutzt 2 Wie richtige for-schleifen (vor C) 3 Antwort vorweg: NEIN! siehe Ackermann-Funktion 1
1 y:=1; LOOP x_i DO y:= 0 END; 3 LOOP y DO P END; x 3 := x 1 + x 2 ebenso: 1 x_3 := x_1 [ + 0]; LOOP x_2 DO x_3 := x_3 +1 END; 4 Somit können wir auch mehrere Variablen addieren. z.b.: Multiplikation: x 3 := x 1 x 2 x_3 := 0; 2 LOOP x_2 DO x_3 := x_3 + x_1 END; MOD, DIV gehen entsprechend. WHILE-Programme sind LOOP-Programme mit dem zusätzlichen Konstrukt WHILE x j 0 DO P END; P wird solange wiederholt, wie x i nicht 0 ist. LOOP x DO P END: 2 y:= x; WHILE y 0 DO y := y 1; P END Definition 4.2 Eine Funktion f : N k heist WHILE-berechenbar, wenn es ein WHILE-Programm gibt, das f berechnet im Sinne wie bei Def. 4.1. 5 Satz 4.3 Jede WHILE-berechenbare Funktion kann von einer det. 1-Band-TM berechnet werden. 6 GOTO-Programme: Anweisungen: A i, Marken M i M 1 : A 1 ; M 2 : A 2 ;...; M k : A k Wertzuweisungen: x j := x j + c x i = x j c unbedingter Sprung: goto M i bedingter Sprung: IF x j = c T HEN GOT O M j Ende: HALT WHILE x j 0DO P END; entspricht: 4 [ + 0] formal wieder ganz korrekt 5 Vorweg: Wobei WHILE ist mächtiger als LOOP: jede LOOP kann in ein WHILE überführt werden, umgekehrt jedoch nicht immer. 6 Beweis ist mit unserem Wissen kein Problem: z.b.: Funktion gleich auf TM simulieren oder Funktion in ein C-Programm schreiben, da schon bewiesen, dass c-programme auf TMs simuliert werden können. 2
1 M 1 : IF x i = 0 THEN GOTO M 2 ; P; 3 GOTO M 1 ; M 2 : HALT; Jedes WHILE-Programm kann in ein GOTO-Programm umgewandelt werden. Nun: GOTO-Programme in WHILE Programme verwandeln. GOTO-Programm: M 1 : A 1 ; M 2 : A 2 ;...; M k : A k count:=1; 2 WHILE count 0 DO IF count = 1 THEN A 1 END; 4 IF count = 2 THEN A 2 END;... 6 IF count = k THEN A k END; END; x j := x l ± c; count := count + 1 falls A i = (x j := x l ± c) count := j fallsa A i = (GOT O M j ) i = ( ) falls A i = (IF x j = c T HEN GOT O M j ) count := falls A i = (HALT ) ( ): 1 IF x_j = c THEN count :=j 3 ELSE count := count +1 5 END; Satz 4.4 Jedes GOTO-Programm kann durch ein WHILE-Programm mit nur einer WHILE-Schleife simuliert werden. Satz 4.5 (Kleensche Normalform für WHILE-Programme) Jede WHILE-berechenbare Funktion kann durch ein WHILE-Programm mit maximal einem WHILE- Konstrukt berechnet werden. Beweis: Beliebiges WHILE-Programm GOTO-Programm WHILE-Programm. 7 7 T M RAM GOT O W HILE LOOP 3
4.2 Definition primitiv rekursiver und µ-rekursiver Funktionen Definition 4.6 Die Klasse der primitiv rekursiven Funktionen ist induktiv definiert: 1. Die konstanten Funktionen sind primitiv rekursiv f(x) = 7 f(x, y, z, a, b) = 7 f() = 7 8 2. Die Projektionen sind primitiv Rekursiv π2(x, 3 y, z) = y 3. Die Nachfolge-Funktion s(n) = n + 1 ist primitiv rekursiv 4. Jede Funktion, die durch Einsetzten von primitiv rekursiven Funktionen entsteht, ist primitiv rekursiv h(a, b, x, y, d) = f(a, b, g(x, y), d) 5. Jede Funktion, die durch primitive Rekursion aus primitiv rekursiven Funktionen entsteht, ist primitiv rekursiv f(0,,, ) = g(,, ) f(n + 1,,, ) = h(f(n,...),...,..) einige Beispiele: 1 add(x,y) = x + y add : N 2 N add(0,x) = π1 1(x) 3 add(n+1,x) = s(add(n,x)) 5 mult(0,x) = 0 mult(n+1,x) = add(mult(n,x),x) 7 u(n) = max(n-1, 0) 9 u(0) = 0 u(n+1) = n 11 sub ist unser modifiziertes Minus : 13 sub(x,0) = x sub(x,y+1) = u(sub(x,y)) a b 15 auch Kodierungsfunktion: c(x,y) = ( x+y+1) 2 + x = 1 (x + y + 1)(x + y) + x 2 17 ist primitiv rekursiv. 8 1.-3. sind die Basisfunktionen 4
c(x, y) ist eine bijektive Abbildung von N 2 nach N 9 < z, x, y >= c(z, c(x, y)) < n 0, n 1,..., n k >= c(n 0, c(n 1,..., c(n k, 0))...) f(c(x, y)) = y e(c(x, y)) = x z.b. : f(18) = 2 e(18) = 3 d 0 (n) = e(n) (= n 0 ) d 1 (n) = e(f(n) (= n 1 ) d k (n) = e(f(f(f(n))) ) k mal. Wenn e und f primitiv rekursiv sind, sind es auch d i. Ein Prädikat P(x) ist primitiv rekursiv, falls die charakteristische Funktion primitiv rekursiv ist. q(n) = max{x x n, P (x) = 1} beschränkte Maximumsbildung existiert das Maximum nicht, so ist q(n) = 0 q(0) = 0 { n + 1 falls P (n + 1) = 1 q(n + 1) == q(n) sonst 9 N ist hier wieder N {0} 5
= q(n) + P (n + 1)(n + 1 q(n)) Ist P(x) primitiv rekursiv, so ist es auch q(n). Beschränkter Existenzquantor: Q(n) es gibt ein xin0,..., n : P(x) = 1 Q(0) = P (0) Q(n + 1) = P (n + 1) + Q(n) (P n + 1) Q(n) e (n, m, k) = max{x x n, y k : e(n) = e (n, n, n) c(x, y) = m} ist primitiv rekursiv f (n, m, k) = max{y y n, y k : c(x, y) = m} f(n) = f (n, n, n) Satz 4.7 Die Klasse der primitiv rekursiven Funktionen ist genau die Klasse der LOOP-berechenbaren Funktionen. Beweis: f: N r N sei LOOP-berechenbar, mitttels LOOP-Programm P x 1,..., x r enthalten die Eingabe x 0 soll f(x 1,...x n ) enthalten Ziel: g P (< a 0, a 1,..., a r > ) =< b 0, b 1,..., b k > n g p ist eine primitiv rekursiv, wobei b 0,..., b k die Inhalte der Register x 0,...x k sind nach Ausführung von P. Falls F von der Form ist: x i := x j ± c g p (n) = < d 0 (n),..., d i 1 (n), d i (n) ± c, d i+1 (n),..., d k (n) > Falls P von der Form ist: P 1 ; P 2 : g p (n) = g P2 (g P1 (n)) Falls P von der Form ist: LOOP x i DO Q END Hilfsfunktion: h(0, x) = x. h(n, x) = g Q (...g Q (g Q (g Q ( x)))) n mal h(n + 1, x) = g Q (h(g Q (h(n, x)), x)) g P (n) = h(d i (n), n) f(n 1,...n r ) = d 0 (g p (< 0, n 1,..., n r, 0,...0 >)) k r Gegeben sei eine primitiv rekursive Funktion f ; 6
Ziel: Angabe eines Loop-Programms, das f berechnet 10. Sei f durch primitive Rekursion gegeben, d.h. f(0, x) = g(x) [Rekursionsende] f(n + 1, x) = h(f(n, x), n, x) 1 x 1 := n; z := 0; 3 x 0 := g(x); LOOP n DO 5 z := z+1; x 0 := h(x 0, z, x) 7 END //in x 0 steht f(n, x)// Der µ-operator macht aus einer (k + 1)-stelligen Fkt. f eine k-stellige wie folgt: µf(x 1,..., x k ) = min{n f(n, x 1,...x k ) = 0 und m < n ist f(m, x 1,..., x k )definiert}. 11 Definition 4.8 Die Klasse der µ-rekursiven Funktionen ist die Klasse von (eventuell partiellen) Funktionen, welche die Basisfunktionen enthält, abgeschlossen unter Einsetzung, primitiver Rekursion und Anwendung des µ- Operators ist. Satz 4.9 Die Klasse der µ-rekursiven Funktionen ist genau die Klasse der berechenbaren Funktionen (d.h. Turingberechenbaren Funktionen). Beweis: Sei f berechenbar durch ein WHILE 12 -Programm P. Falls P von der Form WHILE x i 0 DO Q END h(0, x) = x, h(n + 1, x) = g Q (h(n, x)) 13 g p (x) = h(µ(d i h)(x), x) besagt, wie oft die WHILE-Schleife durchlaufen wird, bis x i = 0 ist. Sei f durch µ-operator definiert. WHILE-Programm angeben, das f berechnet: x 0 := 0; 2 y := f(0,x) WHILE y 0 DO 4 x 0 := x 0 + 1; y := h(x 0, x) 10 reine Programmieraufgabe ; An dieser Stelle ist in Schönig s Buch ein Fehler 11 Konvention: min ist undefiniert 12 wie schon gezeigt: ist ja äquivalent einer Turing-Maschine 13 ggf. partiell 7
6 END //in x 0 steht f(n, x)// 14 Satz 4.10 (Normalformsatz von Kleene) Berechenbare Funktionen benötigen den µ-operator maximal einmal. 4.3 Die Ackermann-Funktion Definition 4.11 (Ackermann-Funktion) Kopie der Folie von der Vorlesungsseite 15 : ack(1, y) = y + 2 ack(2, y) = 2 y + 3 ack(x,y) ist Turing-berechenbar 16 und damit auch µ-rekursiv. ack(x,y) ist total. ack(x,y) ist nicht primitiv rekursiv. 14 was ist jetzt das besondere am µ-operator: µ-operator sucht die erste Stelle, sodass das Abbruch-Kriterium der rekursiven-funktion erfüllt ist. ( Mathematische Beschreibung von WHILE ) 15 http://www12.informatik.uni-erlangen.de/edu/bfs/ws1314/ack.pdf 16 Zur Erinnerung: Berechenbar heißt nicht, dass das Ergebnis auch erlebbar ist (siehe P-NP) 8
Zu einem LOOP-Programm P sei : f p (n) = max{ i 0 n i n i n } i 0 Die n i sind die konkreten Eingaben für P. Die n i sind die Inhalte der Variablen, nachdem P mit den n i gestartet worden und fertig ist 17. Lemma 4.12 Für jedes LOOP-Programm P gibt es eine Zahl k P, so dass für alle n gilt: f P (n) ack(k P, n) P k p n N 0 : f P (n) ack(k p, n) Beweis: Induktiv über den Aufbau von LOOP-Programmen. Falls P von der Form x i := x j ± c ist: OBdA ist c {0, 1} 18 f P (n) 2 n + 1 ack( 2 k P, n) Falls P von der Form P 1 ; P 2 ist: Per Induktionsannahme gibt es k P1 und k P2 mit f P1 ack(k P1, n) f P2 ack(k P2, n) Mit k 3 := max{k P1 1, k P2 } f P (n) f P2 (f P1 (n)) 19 ack(k P2, ack(k P1, n)) ack(k P3, ack(k P3 + 1, n)) = ack(k P3 + 1, n + 1) ack(k P3 + 2, n) k p := max{k P1 1, k P2 } + 2 Falls P von der Form LOOP x i DO Q END ist. Sei k Q die zahl mit f q (n) ack(k q, n) OBdA: x i kommt in Q nicht vor. 20 Sei m (m n) die Zahl, so dass m Schleifendurchläufe die größte Summe i 0 n i erzeugt. m = 0 : f P (n) = n < ack(0, n) = n + 1 m = 1 : f P (n) f Q (n) ack(k Q, n) m 2 : f P (n) f Q (...f Q (f Q (n m))...) + m m Mal ack(k Q, f Q (f Q (...f Q (n m)...))) + m m 1 Mal 17 Somit: Was auch immer P mit den Eingaben n i ausrechnet, kann nicht größer als f p(n) sein. 18 ersetze x i := x j + 3 durch x i := x j + 1; x i := x j + 1; x i := x j + 1; usw. 19 Die Laufzeit ist natürlich transitiv: O(n 2 ) O(n 3 ) = O(n 6 ) 20 D.h. wie richtige for-schleifen: Es steht am Anfang fest, wie oft die Schleife läuft. 9
ack(k Q, ack(k Q,...ack(k Q, n m)...)) + m m f P (n) ack(k Q, ack(k Q,...ack(k Q, n m)...)) m Mal ack(k Q,...ack(k Q, ack(k Q + 1, n m))) = ack(k Q + 1, n 1) ack(k Q + 1, n) k P Satz 4.13 ack(x,y) ist nicht LOOP-berechenbar, und somit auch nicht primitiv rekursiv. Beweis: Diagonalisierung Annahme: ack(x,y) ist LOOP-berechenbar durch P. Dann ist auch g(n) = ack(n, m) duch P LOOPberechenbar. g(n) f P (n) ack(k P, n) 21 Für n = k P g(k P ) f P (k P ) ack(k P, k P ) = g(k P ) 21 aus Lemma 4.11 10
5 Zusammenfassung viel Energie für die Klausur reinstecken 5.1 Berechenbarkeit Turing-Maschine normaler Computer 1 Church-Turing-These Typ-0-Sprachen µ-rekursion (primitiv Rekursiv/LOOP-Programme, Ackermann-Funktion) 2 5.1.1 Halteproblem Zentral, es gibt Probleme, die nicht entschieden werden können. [Reduktionen ] Die ganzen Bauer bauen immer neue Maschinen, Computer gibt es immer nur einmal 5.1.2 universelle Turing-Maschine. z.b.: die Ackermann-Funktion ist berechenbar, aber nicht für Menschen-berechenbar 5.1.3 NP-Vollständigkeit 5.1.4 Nichtdeterminisus Quintessenz für den Alltag: wenn man ein NP-Problem lösen will, sollte man von exakten Lösungen Abstand nehmen. 5.2 Formale Sprachen Grammatiken: Typ-0,..., Typ-3 Typ-2-Grammatiken: kontextfreie Sprachen, als Grundlage für Programmiersprachen Chomsky-NF CYK-Algorithmus Kellerautomaten 1 Eigentlich kann die Turingmaschiene mit ihrem unendlichen Speicher mehr 2 Die Ackermann-Funktion ist der BusyBeaver der primitiv-rekursiven Funktionen 11
Pumping-Lemma für kontextfreie-sprachen 3 Typ-3-Sprachen: reguläre-sprachen, als Grundlage der lexikalischen Analyse z.b.: {a n b n n 0} / L 3 : Das sind die Grundlagen auf denen wir 4 stehen... 3 hauptsächlich als Indikator für nicht-kontextfreiheit 4 als wissenschaftlich ausgebildete Informatiker 12