Proseminar Theoretische Informatik - WS07/08 - Prof. Helmut Alt. I. Einleitung Berechnungsmodelle LOOP, WHILE, GOTO, rekursive Funktionen

Ähnliche Dokumente
Mächtigkeit von WHILE-Programmen

Zusammenfassung Grundzüge der Informatik 4

Theoretische Grundlagen der Informatik

Theorie der Informatik (CS206) Fortsetzung LOOP-Programme, primitiv-rekursive Funktionen

SOI Die Schweizer Informatikolympiade

GTI. Hannes Diener. 6. Juni Juni. ENC B-0123, diener@math.uni-siegen.de

Einfache Ausdrücke Datentypen Rekursive funktionale Sprache Franz Wotawa Institut für Softwaretechnologie

Kontrollstrukturen, Pseudocode und Modulo-Rechnung

Einführung in die Theoretische Informatik

Einführung. Vorlesungen zur Komplexitätstheorie: Reduktion und Vollständigkeit (3) Vorlesungen zur Komplexitätstheorie. K-Vollständigkeit (1/5)

Vorlesung. Funktionen/Abbildungen 1

Algorithmen und Programmierung

4 Greedy-Algorithmen (gierige Algorithmen)

Erwin Grüner

Deterministische Turing-Maschinen (DTM) F3 03/04 p.46/395

Technische Informatik 1 Übung 2 Assembler (Rechenübung) Georgia Giannopoulou (ggeorgia@tik.ee.ethz.ch) 22./23. Oktober 2015

5. Varianten des Turingmaschinen-Konzeptes I: Varianten der Programmstruktur

Entscheidungsbäume. Definition Entscheidungsbaum. Frage: Gibt es einen Sortieralgorithmus mit o(n log n) Vergleichen?

Universität Koblenz-Landau, Abteilung Koblenz FB 4 Informatik. Seminar Entscheidungsverfahren für logische Theorien. Endliche Modelle.

1 Syntax von Programmiersprachen

Programmieren in C. Rekursive Funktionen. Prof. Dr. Nikolaus Wulff

Das Briefträgerproblem

TECHNISCHE UNIVERSITÄT MÜNCHEN. Abzählbarkeit, Injektivität, Sürjektivität und Bijektivität

Programmieren. 10. Tutorium 4./ 5. Übungsblatt Referenzen

Zur Vereinfachung betrachten wir nun nur noch Funktionen f, die einen Funktionswert f nµberechnen. Sie werden alle in einer Tabelle dargestellt:

2: Zahlentheorie / Restklassen 2.1: Modulare Arithmetik

Sin-Funktion vgl. Cos-Funktion

Fallunterscheidung: if-statement

Entwurf von Algorithmen - Kontrollstrukturen

Zusammenfassung. 1 Wir betrachten die folgende Signatur F = {+,,, 0, 1} sodass. 3 Wir betrachten die Gleichungen E. 4 Dann gilt E 1 + x 1

SWE1 / Übung 2 ( )

NP-Vollständigkeit. Krautgartner Martin ( ) Markgraf Waldomir ( ) Rattensberger Martin ( ) Rieder Caroline ( )

, WS2012 Übungsgruppen: Mo.,

Lenstras Algorithmus für Faktorisierung

Diskrete Strukturen und Logik WiSe 2007/08 in Trier. Henning Fernau Universität Trier

Grundlagen der Theoretischen Informatik / Einführung in die Theoretische Informatik I. Ulrich Furbach. Sommersemester 2014

5.2 Das All-Pairs-Shortest-Paths-Problem (APSP-Problem) Kürzeste Wege zwischen allen Knoten. Eingabe: Gerichteter Graph G =(V, E, c)

VBA-Programmierung: Zusammenfassung

Übersicht. Schleifen. Schleifeninvarianten. Referenztypen, Wrapperklassen und API. 9. November 2009 CoMa I WS 08/09 1/15

Mathematische Maschinen

Einführung in die Informatik I

Gibt es verschiedene Arten unendlich? Dieter Wolke

Sprachen/Grammatiken eine Wiederholung

PHP 5.4 ISBN Stephan Heller, Andreas Dittfurth 1. Ausgabe, September Grundlagen zur Erstellung dynamischer Webseiten GPHP54

Die Gleichung A x = a hat für A 0 die eindeutig bestimmte Lösung. Für A=0 und a 0 existiert keine Lösung.

Bestimmung einer ersten

Modul 122 VBA Scribt.docx

Theoretische Informatik

Lua Grundlagen Einführung in die Lua Programmiersprache

Theoretische Grundlagen des Software Engineering

Grundlagen Theoretischer Informatik I SoSe 2011 in Trier. Henning Fernau Universität Trier fernau@uni-trier.de

I. Aussagenlogik. Aussagenlogik untersucht Verknüpfungen wie "und", "oder", "nicht", "wenn... dann" zwischen atomaren und komplexen Sätzen.

Elemente der Analysis II

Grundlagen der Informatik. Prof. Dr. Stefan Enderle NTA Isny

Ausarbeitung des Interpreter Referats

3. Turingmaschinen FORMALISIERUNG VON ALGORITHMEN. Turingmaschinen Registermaschinen Rekursive Funktionen UNTERSCHEIDUNGSMERKMALE DER ANSÄTZE:

11. Primfaktorzerlegungen

Grammatiken. Einführung

Theoretische Informatik

Wortproblem für kontextfreie Grammatiken

Stephan Brumme, SST, 2.FS, Matrikelnr

Softwareentwicklung 1. Übungsaufgabe 4 Kontrollstrukturen

Dynamische Optimierung. Kapitel 4. Dynamische Optimierung. Peter Becker (H-BRS) Operations Research II Wintersemester 2014/ / 206

ARBEITSBLATT ZU FORMALEN SPRACHEN

Programmierung in Python

SWP Prüfungsvorbereitung

Literatur. Dominating Set (DS) Dominating Sets in Sensornetzen. Problem Minimum Dominating Set (MDS)

Programmierkurs Java

Rekursion. Annabelle Klarl. Einführung in die Informatik Programmierung und Softwareentwicklung

Gliederung. Tutorium zur Vorlesung. Gliederung. Gliederung. 1. Gliederung der Informatik. 1. Gliederung der Informatik. 1. Gliederung der Informatik

1 Vom Problem zum Programm

Entscheidungsprobleme. Berechenbarkeit und Komplexität Entscheidbarkeit und Unentscheidbarkeit. Die Entscheidbarkeit von Problemen

Abschnitt: Algorithmendesign und Laufzeitanalyse

8 Diskrete Optimierung

Einführung in die Programmierung

Einführung in die Informatik für Hörer aller Fakultäten II. Andreas Podelski Stephan Diehl Uwe Waldmann

Java Einführung VARIABLEN und DATENTYPEN Kapitel 2

2. Universelle Algebra

Nichtlineare Optimierung ohne Nebenbedingungen

Autor: Michael Spahn Version: 1.0 1/10 Vertraulichkeit: öffentlich Status: Final Metaways Infosystems GmbH

II. Grundlagen der Programmierung. 9. Datenstrukturen. Daten zusammenfassen. In Java (Forts.): In Java:

1 Vom Problem zum Programm

Spezifikation der zulässigen Parameter. Bemerkungen: Bemerkungen: (2) Design by Contract:

Erweiterung der Aufgabe. Die Notenberechnung soll nicht nur für einen Schüler, sondern für bis zu 35 Schüler gehen:

Theoretische Informatik 1

Zweite Möglichkeit: Ausgabe direkt auf dem Bildschirm durchführen:

Codierung. Auszug aus dem Skript von Maciej Liśkiewicz und Henning Fernau

Konfiguration einer TM als String schreiben: Bandinschrift zwischen den Blank-Zeichen Links von der Kopfposition Zustand einfügen.

Brainfuck. 1 Brainfuck. 1.1 Brainfuck Geschichte und Umfeld. 1.2 Esoterische Programmiersprachen

Programmieren I. Kontrollstrukturen. Heusch 8 Ratz Institut für Angewandte Informatik

Einführung in die Informatik Grammars & Parsers

Rekursionsanfang, Rekursionsschritt oder äquivalente Antworten. (z.b.: Abbruchbedingung (= Basisfall), eigentliche Rekursion (= Selbstaufruf))

Übersicht Programmablaufsteuerung

Programmierung 2. Übersetzer: Code-Erzeugung. Sebastian Hack. Klaas Boesche. Sommersemester

Übung zur Vorlesung Einführung in die Computerlinguistik und Sprachtechnologie

Funktionale Programmierung Teil 2 Methodik: Spezifikation, Implementierung, Verifikation

22. Algorithmus der Woche Partnerschaftsvermittlung Drum prüfe, wer sich ewig bindet

Einführung in die Java- Programmierung

Computer und Software 1

Algorithmische Kernsprache. Zuweisung, einfache und bedingte Anweisung, Blöcke, Schleifen, return, debugging.

Transkript:

Proseminar Theoretische Informatik - WS07/08 - Prof. Helmut Alt I. Einleitung Berechnungsmodelle LOOP, WHILE, GOTO, rekursive Funktionen Berechenbarkeitsmodelle Welchen Sinn haben diese? Wie kann man effizient etwas nachweisen? - ndet Turingmaschine,... Modell / Reduktion mit berechenbaren Problemen Hilfsmittel - natürliche Zahlen, einfache Konzepte darauf (Wiederholung, Schachtelung, Variablen, Wertemanipulation) -> einfache Beweise für Machbarkeit Problem -> Lösung findbar? Existiert überhaupt? -> Einfacher Nachweis, wenn Lösung gefunden oder bewiesen dass es eine gibt. Kann man wissen, ob es eine Lösung gibt? Usw.

Proseminar Theoretische Informatik - WS07/08 - Prof. Helmut Alt II. LOOP, WHILE, GOTO Definition der LOOP Sprache Variablen: x 0, x 1, x 2,... Konstanten: 0, 1, 2,... Trennsymbole: ( ; ), ( := ) Operationszeichen: + - Schlüsselwörter: LOOP, DO, END induktive Definition der Syntax: 1. Eine Wertzuweisung der Form x i := x j ± c, wobei c eine Konstante ist, ist ein LOOP-Programm. 2. Falls P 1 und P 2 LOOP-Programme sind, so ist auch P 1 ; P 2 ein LOOP-Programm. 3. LOOP x i DO P END, wobei P ein LOOP-Programm ist und x i eine Variable, ist ein LOOP-Programm. Semantik: Das Programm startet mit Eingabevariablen n 1,..., n k aus N in den Variablen x 1,... x k, während alle anderen Variablen des Programms mit Null starten. Das Ergebnis der Berechnungen steht am Ende in x 0. Die Wirkweise der Semantik erschließt sich weitgehend intuitiv, die Loop-Schleife allerdings benutzt den Wert von x i vor dem Ausführen von P und führt das Programm so oft aus, d.h. Es gibt keine Kontrollmöglichkeit dynamischer Natur, die Zahl der Wiederholungen kann nicht aus der Schleife selbst heraus beeinflußt werden. Definition (LOOP-berechenbar): Eine Funktion f : N k -> N heißt LOOP-berechenbar, wenn es ein LOOP-Programm P gibt, dass für alle x aus N k als Eingabewert(e) mit f(x) in x 0 stoppt. Feststellungen: Alle LOOP-berechenbaren Funktionen sind total. Es gibt totale intuitiv berechenbare Funktionen, die nicht LOOP-berechenbar sind. ( vgl. Ackermannfunktion, letzter Vortrag )

Die WHILE Sprache Die WHILE-Sprache erweitert die LOOP-Sprache um das Konzept der WHILE- Schleife : WHILE x i 0 DO P END ( Das WHILE-Programm P wird sooft ausgeführt, wie der Variablen-Wert x i nicht Null ist. ) Ansonsten sind alle Konzepte aus LOOP in WHILE übertragen. ( Die Folgerungen allerdings ändern sich, LOOP... END wird eigentlich hinfällig. ) Definition ( WHILE-berechenbar ): Eine Funktion f : N k -> N heißt WHILE-berechenbar, falls es ein WHILE- Programm P gibt, dass für alle x aus N k als Eingabewert(e), für die f definiert ist, mit f(x) in x 0 hält, und nicht hält für alle x, für die f nicht definiert ist. Endlosschleifen sind mit dem WHILE-Konstrukt offensichtlich möglich. Satz: Turingmaschinen können WHILE-Programme simulieren, also ist jede WHILE-berechenbare Funktion auch Turing-berechenbar. [ Beweis / eher nicht, keine Zeit dafür ] Die GOTO Sprache Ein GOTO-Programm besteht aus einer Folge von Anweisungen, die jeweils einer eigenen Marke zugeordnet sind: M 1 : A 1 ; M 2 : A 2 ;... ; M k : A k Für A 1..k sind folgende Anweisungen möglich: Wertzuweisungen: x i := x j ± c ( c ist Konstante ) unbedingter Sprung: GOTO M i bedingter Sprung: IF x i = c THEN GOTO M j Stopanweisung: HALT Die Semantik erschließt sich intuitiv, das Programm startet mit A 1, bei einem Sprung wird an der entsprechenden Marke fortgefahren, ohne Sprung an der nächsten. HALT beendet das Programm. Endlosschleifen sind offensichtlich möglich.

Definition ( GOTO-berechenbar ): [ analog zu WHILE-berechenbar ] Eine Funktion f : N k -> N heißt GOTO-berechenbar, falls es ein GOTO-Programm P gibt, dass für alle x aus N k als Eingabewert(e), für die f definiert ist, mit f(x) in x 0 hält, und nicht hält für alle x, für die f nicht definiert ist. Satz: Jedes WHILE-Programm kann durch ein GOTO-Programm simuliert werden. D.h., Jede WHILE-berechenbare Funktion ist auch GOTO-berechenbar. [ Beweis, eher Skizze, einfacher] Satz: Jedes GOTO-Programm kann durch ein WHILE-Programm simuliert werden. D.h., Jede GOTO-berechenbare Funktion ist auch WHILE-berechenbar. ( Anmerkung: Das geht mit nur einer WHILE-Schleife ) [ Beweis, geht mit einer WHILE-Schleife ] Satz ( Kleenesche Normalform für WHILE-Programme ): Jede WHILE-berechenbare Funktion kann durch ein WHILE-Programm mit nur einer WHILE-Schleife berechnet werden. [ Beweis, nach vorherigem Beweis WHILE->GOTO->WHILE] Satz: GOTO-Programme können Turingmaschinen simulieren. Damit ist jede Turing-berechenbare Funktion auch GOTO-berechenbar. Beweis (mit 2-Zähler Maschine, siehe Vortrag 2 Zähler sind universell ): Problem: Wir brauchen Funktion c( x, y ) zur bijektiven Codierung zweier natürlicher Zahlen in eine und ihre Umkehrfunktionen e( n ) und f( n ) aus dem Teil rekursive Funktionen, sowie die Darstellung < x 1, x 2,..., x k > = c( x 1, c( x 2,..., c( x k, 0 )... ) ), und dessen Umkehrfunktionen d i, welche dort ausführlicher beschrieben sind. Die Funktionen c, e, f sind LOOP-berechenbar, wie später gezeigt wird. Wir drücken die Funktionalität der Maschine durch GOTO-Ausdrücke aus. Das Eingabeband wird über eine Eingabevariable x = < x 1, x 2,..., x k > simuliert, wobei x i die Zeichen des Eingabealphabets sind. Die beiden Zähler sind durch zwei Variablen p 1, p 2 repräsentiert. Es gibt eine Variable q um den Zustand anzugeben (Zahl, 0 = Start). Es gibt eine Variable c, die das zuletzt gelesene (aktuelles) Zeichen enthält. Eine Variable a, die angibt, ob der Zustand akzeptierend ist. Dazu eine gewisse Menge an Hilfsvariablen. Die d Zustände q i des Automaten und ihre Übergänge werden als codiertes verschachteltes Tupel in der Eingabevariable z mitgeliefert:

z = < cq 1, cq 2,..., cq d >, wobei cq i jetzt wieder ein Tupel ist, dass die nötigen Informationen enthält: ( Akzeptierend 0 1, ( u 1, u 2,..., u m ) ) u i geben die Übergänge an, also wieder ein Tupel mit: ( ( Eingabezeichen, p 1 = 0, p 2 = 0 ), Ziel-Zustand, Δ p 1, Δ p 2 ). Das Programm simuliert jetzt die 2-Zählermaschine, die als codiertes Tupel eingegeben wurde. Der Startzustand muss am Anfang stehen, daher ist q auf 0 gesetzt ( aktueller Zustand ). a wird gesetzt über e( d 0 ( z ) ). Skizze: Das Programm wird initialisiert mit q = 0 und geht dann in eine Hauptschleife: Hilfsvariable(Übergangsfunktionen) wird gesetzt: f( d q ( z ) ) a wird gesetzt mit e( d q ( z ) ) Gibt es ein Eingabezeichen so wird c = e( x ) und x = f( x ) gesetzt. Gibt es keins ( x = 0 ): Die Ausgabe wird gesetzt ( nach Wunsch, auf a oder auf < p 1, p 2 > ), wenn das Programm bei nicht-akzeptieren nicht halten soll, dann gehe in Endlosschleife. ( c, p 1 = 0, p 2 = 0 ) wird codiert und der Reihe nach mit den Übergangsfunktionen d.h. e( Übergangsfunktion[ Schleifenvariable ] ) verglichen, bei Übereinstimmung werden Δ p 1, Δ p 2 ausgelesen d 2,3 ( f( Ü...) ) und angewendet. Q wird auf den Zielzustand gesetzt d 1 ( f( Ü...) ). Fazit: Die Klassen der GOTO- / WHILE- / Turing-berechenbaren Funktionen sind gleich. Die Klasse der (totalen) WHILE-berechenbaren Funktionen enthält die Klasse der LOOP-berechenbaren Funktionen als echte Teilmenge.

Proseminar Theoretische Informatik - WS07/08 - Prof. Helmut Alt III.Rekursive Funktionen Induktive Definition der Klasse der primitiv rekursiven Funktionen: (1) Alle Konstanten Funktionen sind primitiv Rekursiv. (2) Alle identischen Abbildungen (Projektionen) sind primitiv rekursiv. (3) Die Nachfolgerfunktion s(n) = n + 1 auf den natürlichen Zahlen ist primitiv rekursiv. (4) Funktionen, die durch Einsetzung (Komposition) von primitiv rekursiven Funktionen entstehen, sind primitiv rekursiv. (5) Funktionen die durch primitive Rekursion aus primitiv rekursiven Funktionen entstehen, sind primitiv rekursiv. D.h. So eine Funktion f erfüllt das Gleichungssystem: f( 0,... ) = g (... ) f( n + 1,... ) = h( f( n,... ),... ) Mit primitiv rekursiven Funktionen g und h. Hier geht also generell um Funktionen von N k nach N. Die Funktionen unter 1. bis 3. werden Basisfunktionen genannt. Feststellungen: Addition, Multiplikation und modifizierte Subtraktion sind primitiv rekursiv (siehe Vorlesung). Primitiv rekursive Funktionen sind total. Satz: Die Klasse der primitiv rekursiven Funktion stimmt genau mit der Klasse der LOOPberechenbaren Funktion überein. [ Beweis weiter unten ] Natürliche Zahlen (Hilfsmittel für Beweis): Wir benutzen eine Funktion, die zwei natürliche Zahlen bijektiv auf eine abbildet. Diese geht auf Cantor zurück ( Abzählen von N 2 über die Diagonalen ) und wird auch Cantorsche Paarungsfunktion genannt (Wikipedia). c( x, y ) = ( x + y + 1 ) * ( x + y ) / 2 + x [ Folie / Tafel zur Veranschaulichung] [Beweis der Bijektivität hier nicht ] c ist primitiv rekursiv ( Addition, Multiplikation ).

Dieses ermöglicht uns sofort beliebig viele natürliche Zahlen in einer zu kodieren, und zwar durch Mehrfachanwendung von C, für ein k+1-tupel: < n 0, n 1,..., n k > := c( n 0, c( n 1,..., c( n k, 0 )... ) ) Also immer c( Argument, Kodierung des Rests durch c ). Da c bijektiv ist, können wir unter der Bedingung, dass c(x,y) = n gelte, die Umkehrfunktionen e und f zu c benutzen: e( n ) = x und f( n ) = y, also c( e(n), f(n) ) = n. Und damit auch die Umkehrfunktionen d 0,..., d k für ein n = < n 0, n 1,..., n k > angeben, die uns die Komponenten liefern: d 0 (n) = e( n ) = n 0 d 1 (n) = e( f(n) ) = n 1... d k (n) = e( f k (n) ) = n k [ f wird k-mal angewendet auf n ] Vorsicht mit d k+1 (n), das liefert wieder Null, es ist also eine Prüfung [f(n)=0] nötig, wenn man nicht weiß, wie lang das Tupel ist, welches in der Zahl n kodiert ist. (!) Diese Kodierung hat die Folge, dass man k-stellige Funktionen als einstellige Funktion darstellen kann, so dass es überhaupt erst sinnvoll ist Berechenbarkeit allgemein mit Funktionen auf den Natürlichen Zahlen beschreiben zu wollen. Wichtige Feststellung: Die Umkehrfunktionen von c ist auch primitiv rekursiv! Daraus folgt auch schnell, dass d i primitiv rekursiv sind, und wir haben ein gutes Hilfsmittel für folgende Beweise. Begriff der primitiven Rekursivität auf Prädikate erweitern (zunächst einstellig, mehrstellig ist aber plausibel), eigentlich über die charakteristische Funktion ( schreiben Prädikat stattdessen). Für ein einstelliges Prädikat P( x ) definieren wir den beschränkten max-operator, q( n ) := max{ x n P( x ) } Falls das Maximum nicht existiert soll q(n) einfach Null liefern, damit q total ist. q( 0 ) = 0 q( n + 1 ) = q( n ) + P( n + 1 ) * ( n + 1 q( n ) ) [Dieses entspricht: falls P(n + 1 ) : q( n + 1 ) = n+1, sonst: q( n + 1 ) = q( n ) ] Analog: beschränkter Existenzquantor... Für ein gegebenes Prädikat P( x ) soll Q( n ) wahr sein ( Q(n)=1 ), genau dann wenn es ein x n gibt, mit P( x ) : Q( 0 ) = P( 0 ) Q( n + 1 ) = P( n + 1 ) + Q( n ) - P( n + 1 ) * Q( n ) Q und q sind primitiv rekursiv, wenn die verwendeten Prädikate P auch primitiv rekursiv sind. Erweiterung auf mehrstellige Prädikate ist denkbar, wenn die weiteren Argumente auch in q/q dann vorkommen. Umkehrfunktionen zu e und f angeben: e ( n, m, k ) = max( x n y k : c( x, y ) = m } e( n ) = e ( n, n, n )

f ( n, m, k ) = max( y n x k : c( x, y ) = m } f( n ) = f ( n, n, n ) Damit sind e und f primitiv rekursiv. Beweis zum Satz ( primitiv rekursiv <-> LOOP-berechenbar ): <- : Sei f : N r -> N LOOP-berechenbar. P sei ein LOOP-Programm, das f berechnet. Die Programmvariablen von P seien x 0, x 1,..., x k (k r). Wir zeigen, dass es eine primitiv rekursive Funktion g P : N -> N gibt, die die Wirkung von P auf die Werte der Programmvariablen beschreibt, wie folgt: Wenn a 0, a 1,..., a k die Werte der Programmvariablen vor Ausführung sind, und b 0, b 1,..., b k deren Werte nach Ausführung des Programms, so gilt: g P ( < a 0, a 1,..., a k > ) = < b 0, b 1,..., b k > Das ganze induktiv über den Aufbau von P: Falls P die Form x i := x j ± c, so ist g P ( n ) = < d 0 ( n ),..., d i-1 ( n ), d j ( n ) ± c, d i+1 ( n ),..., d k ( n ) > Falls P die Form hat Q ; R, so ist g P ( n ) = g R ( g Q ( n ) ). g Q und g R gibt es nach Induktionsvoraussetzung, daher ist das eine Komposition von primitiv rekursiven Funktionen. Falls P die Form LOOP x i DO Q END hat: Nach I.V. Gibt es eine Funktion g Q, die Q berechnet. Wir definieren eine Hilfsfunktion h: h( 0, x ) = x h( n + 1, x ) = g Q ( h( n, x ) ) h gibt den Zustand der Programmvariablen x = < x 0, x 1,..., x k > nach n Anwendungen von Q wieder, damit ist g P wie folgt gefunden: g P ( n ) = h( d i ( n ), n ) Damit können wir f ausdrücken: f( n 1,..., n r ) = d 0 ( g P ( < 0, n 1,..., n r, 0,..., 0 > ) ). (Am Ende stehen k-r Nullen.) -> : Induktiv über den Aufbau der primitiv rekursiven Funktionen: Basisfunktionen: einfach, fast nach Definition. Einsetzung: durch Hintereinanderausführung von LOOP Programmen für die anderen primitiv rekursiven Funktionen, die ja nach Induktionsvoraussetzung existieren. Dabei werden die Zwischenergebnisse jeweils in separaten Variablen gespeichert ( Adapter -Programm ). f entstand durch primitive Rekursion und hat die Form: f( 0, x 1,..., x r ) = g( x 1,..., x r ) f( n + 1, x 1,..., x r ) = h( f( n, x 1,..., x r ), n, x 1,..., x r ) f kann durch ein LOOP-Programm mit einer Schleife berechnet werden: y := g( x 1,..., x r ) ; k := n ; LOOP n DO k := k 1 ; y := h( y, k, x 1,..., x r ) END ( Hier verkürzt: für g und h existieren bereits LOOP-Programme, nach I.V. )

Der μ-operator und die Klasse der μ-rekursiven Funktionen Sei f eine k+1-stellige Funktion. Der μ-operator bildet f auf eine k-stellige Funktion g ab: g( x 1,..., x k ) = min{ n f( n, x 1,..., x k ) = 0 und f.a. m<n ist f( m, x 1,..., x k ) definiert } Zusätzlich soll min Ø als undefiniert gesetzt sein. Damit können echte partielle Funktionen entstehen! (Beispiel: Konstante Funktionen die nicht Null sind) Definition ( Klasse der μ-rekursiven Funktionen ): Die Klasse der μ-rekursiven Funktionen ist die kleinste Klasse von Funktionen, die die Basisfunktionen ( konstante Funktionen, Projektionen, Nachfolgerfunktion ) enthält und abgeschlossen ist unter Einsetzung, primitiver Rekursion und Anwendung des μ-operators. Satz: Die Klasse der μ-rekursiven Funktionen stimmt genau mit der Klasse der WHILEberechenbaren Funktionen überein ( damit auch mit GOTO-, Turing- ). Beweis: Dieser Beweis funktioniert analog zum Beweis für LOOP-Berechenbarkeit gegenüber primitiver Rekursivität, und führt daher nur das Konzept für die WHILE-Schleife und den μ-operator vor: <- : Falls P ein WHILE-Programm der Form WHILE xi 0 DO Q END ist, benutzen wir wieder eine Hilfsfunktion h( n, x ), die den Zustand der Programmvariablen x = < x 1,..., x k > nach n Ausführungen von Q wiedergibt: g P = h( μ( d i h )( x ), x ) [ μ( d i h )( x ) gibt gerade die minimale Wiederholungszahl des Programms Q wieder, für die x i den Wert 0 liefert. ] -> : g sei die durch Anwendung des μ-operators auf eine Funktion f entstandene Funktion. Also g = μf, so berechnet das folgende Programm g: x 0 := 0 ; y := f( 0, x 1,..., x n ) ; WHILE y 0 DO x 0 := x 0 + 1 ; y := f( x 0, x 1,..., x n ) END ( Für f existiert nach I.V. Bereits ein WHILE-Programm ) Satz (Kleene): Für jede n-stellige μ-rekursive Funktion f gibt es zwei (n+1)-stellige, primitiv rekursive Funktionen p und q, so dass sich f darstellen lässt als: f( x 1,..., x n ) = p( x 1,..., x n, μq( x 1,..., x n ) ) [ μq ist die n-stellige, durch Anwenden des Operators auf q entstandene Funktion. ] ~ ohne Beweis.

Proseminar Theoretische Informatik - WS07/08 - Prof. Helmut Alt IV.Die Ackermannfunktion Ackermann gab 1928 eine Funktion an, die intuitiv berechenbar ist und sogar total, aber nicht LOOP-berechenbar. [ siehe letzter Vortrag ] Vereinfachte Form der Definition: a( 0, y ) = y + 1 a( x, 0 ) = a( x - 1, 1 ) a( x, y ) = a( x 1, a( x, y -1 ) ) Die Idee war, eine Folge zu kreieren, die wächst, wie etwa: a+b, a*b, a b,... (...?). Die Tabelle zeigt für x,y den Wert und die Zahl der benötigten rekursiven Aufrufe. Am Beispiel a( 4,1 ) sieht man gut die Definition und das Wachstum. a( 4, 1 ) = a( 3, a( 4, 0 ) ) = a( 3, 13 ) = 65533 a( 4, 4 ) ist größer als die Zahl der Atome im ganzen Universum (wie war sie noch?).

Zusammenfassung aus dem letzten Vortrag: Die Ackermannfunktion ist total. Lemma A: y < a( x, y ) Lemma B: a( x, y ) < a( x, y + 1 ) Lemma C: a( x, y + 1 ) a( x + 1, y ) Lemma D: a( x, y ) < a( x + 1, y ) Allgemeine Monotonie-Eigenschaft: Für x, x, y, y mit x x und y y gilt: a( x, y ) a( x, y ) Definition: Wir ordnen jedem LOOP-Programm P eine Funktion f P zu, so dass gilt: f P : N -> N, f(n) = max{ i ( n i ) i ( n i ) } i durchläuft die Indizes der in P vorkommenden Variablen. n i seien die Werte der im Programm benutzten Variablen x i mit n i =x i und zwar vor Ausführung des Programms, das ist also die Summe der Eingaben, da alle anderen Variablen dann Null sind. n i seien analog die Variablenwerte nach Ausführung des Programms. f P (n) berechnet also die maximal mögliche Summe der im Programm vorkommenden Variablen nach Ausführung, für alle Eingabevarianten, für die die Summe der Eingabevariablen kleiner oder gleich n ist. Lemma E: Für jedes LOOP-Programm P gibt es eine Konstante k,so dass für alle n gilt: f P (n) < a( k, n ) Satz: Die Ackermannfunktion ist nicht LOOP-berechenbar. [ Beweiskonzept: annehmen a sei LOOP-berechenbar, P berechne g(n) := a(n,n)... LEMMA E: g(n) f P (n) < a(k,n) => g(k) f P (k) < a(k,k) = g(k) Widerspruch.]

Satz: Es gibt totale, WHILE-berechenbare Funktionen, die nicht LOOP-berechenbar sind. (Beweis zum obigen Satz:) Die Ackermannfunktion ist WHILE-berechenbar. Wir benutzen eine Mischung aus WHILE-Sprache und dem Formalismus der μ- rekursiven Funktionen, also eine Art von Pseudocode, von dem wir aber sicher sein können, dass wir ihn zu einem streng formal gesehen korrekten WHILE- Programm umformen können, da wir wissen, dass μ-rekursiv = WHILE = GOTO = TM gilt. Damit wird auch deutlich, dass die verschiedenen Konzepte als Hilfsmittel taugen, um z.b. Diesen Beweis übersichtlich gestalten zu können. Als erstes benutzen wir einen Stack, den wir über die primitiv rekursiven Funktionen c( x, y ) und ihre Umkehrfunktionen e( n ) und f( n ) realisieren (aus dem letzten Abschnitt rekursive Funktionen ) Ein Stack s mit sei realisiert durch eine natürliche Zahl als Datum: n = < n 1, n 2,..., n k > = c( n 1, c( n 2,..., C( n k, 0 )... ) ) Folgende Operationen werden auf dem Stack implementiert: INIT( s ) durch n := 0, wobei n die Variable ist, die den Stackinhalt trägt PUSH( a, s ) durch n := c( a, n ) POP( s ) durch r := e( n ) ; n := f( n ), wobei r die Ausgabe ist. Diese Operationen sind mit primitiv rekursiven Funktionen umgesetzt also in WHILE-Code umsetzbar. Die Variablennamen werden lesefreundlich angegeben, daher das Schlüsselwort INPUT, das angibt, welches die Eingabevariablen sind, OUTPUT, das die Ausgabevariable bestimmt und das Programm beendet. INPUT( x, y ); INIT( stack ); PUSH( x, stack ); PUSH( y, stack ); WHILE size( stack ) 1 DO y := POP( stack ) x := PUSH( stack ) IF x = 0 THEN PUSH( y + 1, stack ) ELSEIF 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 )

Die Abfrage size( stack ) 1 wird mit f( n ) 0 umgesetzt (WHILE-gerecht). Dieses Programm ist in WHILE-Syntax umwandelbar, entweder durch elementare Schritte ( x := y + c -> WHILE y 0 DO x := x + 1 END ; x := x + c ), oder durch Umwandlung der primitiv rekursiven Funktionen c, e, f in WHILE-Programme. Streng genommen bleibt noch zu zeigen, dass dieses Programm wirklich die Ackermannfunktion berechnet, aber es ist schnell klar, dass es die vereinfachte Definition direkt umsetzt.

Proseminar Theoretische Informatik - WS07/08 - Prof. Helmut Alt V. Ausklang Es gibt Funktionen, die man nicht angeben kann, obwohl sie wohldefiniert sind. Fleißiger Biber -> Entscheidbarkeit

Quellen: Uwe Schöning Theoretische Informatik-kurzgefaßt Spektrum Akad. Verlag 1995, 2. Auflage und 4.Auflage 2003 ( korrigierter Nachdruck ) http://www.wikipedia.org ( aktuell, 10.01.2008 ) ( Vorträge aus der Veranstaltung )