Theorembeweiserpraktikum SS 2016

Ähnliche Dokumente
Allgemeine Hinweise: TECHNISCHE UNIVERSITÄT MÜNCHEN. Name Vorname Studiengang Matrikelnummer. Hörsaal Reihe Sitzplatz Unterschrift

SWP Prüfungsvorbereitung

Frage, Fragen und nochmals Fragen

Was bisher geschah. deklarative Programmierung. funktionale Programmierung (Haskell):

Funktionale Programmierung mit Haskell

Diskrete Strukturen Kapitel 2: Grundlagen (Beweise)

Grundprinzipien der funktionalen Programmierung

Beispiele: (Funktionen auf Listen) (3) Bemerkungen: Die Datenstrukturen der Paare (2) Die Datenstrukturen der Paare

2. Universelle Algebra

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

Zahlen in Haskell Kapitel 3

Was bisher geschah Funktionale Programmierung in Haskell: Algebraische Datentypen Pattern Matching Polymorphie Typklassen Rekursive Datentypen:

ALP I. Funktionale Programmierung

Funktionale Programmierung Teil 2 Methodik: Spezifikation, Implementierung, Verifikation

Praktische Informatik 3: Einführung in die Funktionale Programmierung Vorlesung vom : Rekursive Datentypen

Strukturelle Rekursion und Induktion

Funktionale Programmierung ALP I. Funktionen höherer Ordnung. Teil 2 SS Prof. Dr. Margarita Esponda. Prof. Dr.

Formale Methoden in der Informatik Wiederholung klassische Logik Konkrete Datentypen (algebraische Strukturen) Abstrakte Datentypen

Funktionen höherer Ordnung

Einführung Datentypen Verzweigung Schleifen. Java Crashkurs. Kim-Manuel Klein May 4, 2015

2.5 Listen. Kurzschreibweise: [42; 0; 16] Listen werden mithilfe von [] und :: konstruiert.

Typdeklarationen. Es gibt in Haskell bereits primitive Typen:

Programmieren in Haskell

Der λ-kalkül. Frank Huch. Sommersemester 2015

Induktive Definitionen

Tutoraufgabe 1 (Datenstrukturen in Haskell):

Übersicht. Datenstrukturen und Algorithmen Vorlesung 5: Rekursionsgleichungen (K4) Übersicht. Binäre Suche. Joost-Pieter Katoen. 20.

Programmierung und Modellierung

Tutorium - Haskell in der Schule. Ralf Dorn - Dennis Buchmann - Felix Last - Carl Ambroselli

Java Einführung Operatoren Kapitel 2 und 3

JAVA-Datentypen und deren Wertebereich

Entwicklung eines korrekten Übersetzers

Funktionale Programmierung

Beispiellösungen zu den Übungen Datenstrukturen und Algorithmen SS 2008 Blatt 6

Vorsicht bei redundanten und unvollständigen Matches!

Modul 122 VBA Scribt.docx

WS 2011/2012. Georg Sauthoff 1. November 1, 2011

Theorem Proving. Software Engineering in der Praxis. Prädikatenlogik. Software Engineering in der Praxis Wintersemester 2006/2007

Programmieren in Haskell

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

Lösungvorschlag zum Übungsblatt 6: Software-Entwicklung I (WS 2007/08)

Haskell, Typen, und Typberechnung. Grundlagen der Programmierung 3 A. Einige andere Programmiersprachen. Typisierung in Haskell

Übungen zu Programmierung I - Blatt 8

C.3 Funktionen und Prozeduren

Grundbegriffe der Informatik

Programmieren in Haskell Programmiermethodik

Theoretische Informatik SS 03 Übung 3

Die Programmiersprache C Eine Einführung

Welche Informatik-Kenntnisse bringen Sie mit?

Teil 6: Induktiv definierte Mengen

Agenda. 1 Einleitung. 2 Binäre Bäume. 3 Binäre Suchbäume. 4 Rose Trees. 5 Zusammenfassung & Ausblick. Haskell Bäume. Einleitung.

Modul Entscheidungsunterstützung in der Logistik. Einführung in die Programmierung mit C++ Übung 2

In diesem Abschnitt betrachten wir nur quadratische Matrizen mit Komponenten aus einem Körper K, also A K n n für ein n N. Wenn (mit einem n > 1)

TECHNISCHE UNIVERSITÄT MÜNCHEN FAKULTÄT FÜR INFORMATIK

Kapitel 5: Abstrakte Algorithmen und Sprachkonzepte. Elementare Schritte

zu große Programme (Bildschirmseite!) zerlegen in (weitgehend) unabhängige Einheiten: Unterprogramme

Crashkurs Haskell Mentoring WiSe 2016/17. Anja Wolffgramm Freie Universität Berlin

Definieren Sie eine Funktion circlearea zur Berechnung der Fläche eines Kreises mit gegebenen Radius (Float).

Kapitel 7: Benutzerdefinierte Datentypen

Einführung Datentypen Verzweigung Schleifen Funktionen Dynamische Datenstrukturen. Java Crashkurs. Kim-Manuel Klein

Vorkurs: Mathematik für Informatiker

Theoretische Informatik. Alphabete, Worte, Sprachen

Pratts Primzahlzertifikate

Grundlagen der Programmierung 2 (1.C)

Effiziente Algorithmen und Datenstrukturen I. Kapitel 10: Lineare Algebra

1.2 LOOP-, WHILE- und GOTO-Berechenbarkeit

Kapitel 3: Variablen

Programmierung 1 (Wintersemester 2012/13) Lösungsblatt 11 (Kapitel 12)

EXCEL VBA Cheat Sheet

JavaScript. Dies ist normales HTML. Hallo Welt! Dies ist JavaScript. Wieder normales HTML.

SOI Die Schweizer Informatikolympiade

expr :: Expr expr = Mul (Add (Const 3) (Const 4)) (Div (Sub (Const 73) (Const 37)) (Const 6))

Informatik II - Tutorium

Funktionale Programmierung

Programmtransformationen und Induktion in funktionalen Programmen

Asymptotische Laufzeitanalyse: Beispiel

Verträge für die funktionale Programmierung Design und Implementierung

5 Logische Programmierung

Rekursive und primitiv rekursive Funktionen. Ein maschinenunabhängiges formales Berechnungsmodell auf den natürlichen Zahlen

Binary Decision Diagrams (Einführung)

Funktionale Programmierung mit Haskell. Jan Hermanns

Interpreter - Gliederung

Grundbegriffe der Informatik Tutorium 2

Informatik I Übung, Woche 40

Komplexität von Algorithmen

A N A L Y S I S I F Ü R T P H, U E ( ) 1. Übungstest (FR, ) (mit Lösung )

Das Briefträgerproblem

Tutoraufgabe 1 (Zweierkomplement): Lösung: Programmierung WS16/17 Lösung - Übung 2

Tutorium für Fortgeschrittene

Tag 8. Beispiel: Tabellen formatieren

Wiederholung ADT Menge Ziel: Verwaltung (Finden, Einfügen, Entfernen) einer Menge von Elementen

Übung 9 - Lösungsvorschlag

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

Nachname: Vorname: Matr.-Nr.: Punkte: 1. Aufgabe: ( / 25 Pkt.) Gegeben ist das folgende Struktogramm zur Berechnung von sin(x) mit Hilfe einer Reihe.

5. Woche Perfekte und Optimale Codes, Schranken. 5. Woche: Perfekte und Optimale Codes, Schranken 88/ 142

ROHRE FUER HOHE TEMPERATUREN ASTM A 106

ALP I Einführung in Haskell

Rekursive Funktionen Basisfunktionen

Theoretische Informatik SS 03 Übung 4

Grundlagen der Programmierung 2. Sortierverfahren

Transkript:

Institut für Programmstrukturen und Datenorganisation Lehrstuhl Programmierparadigmen Am Fasanengarten 5 76131 Karlsruhe http://pp.ipd.kit.edu/ Theorembeweiserpraktikum SS 2016 http://pp.ipd.kit.edu/lehre/ss2016/tba Lösung 4: Allgemeine und wechselseitige Rekursion Abgabe: 16. Mai 2016, 23:59 Uhr Besprechung: 17. Mai 2016 1 Listen zusammenfügen In dieser Aufgabe soll eine Funktion interleave definiert werden, welche zwei Listen durch Verschachtelung zusammenfügt. Beispiel: interleave [a1, a2, a3] [b1, b2, b3] = [a1, b1, a2, b2, a3, b3] und interleave [a1] [b1, b2, b3] = [a1, b1, b2, b3]. fun interleave :: " a list a list a list" "interleave xs [] = xs" "interleave [] ys = ys" "interleave (x#xs) (y#ys) = x#y#(interleave xs ys)" Unter welchen Voraussetzungen gilt die folgende Aussage? Beweisen Sie das entsprechende Theorem. interleave (xs 1 @ xs 2 ) (ys 1 @ ys 2 ) = interleave xs 1 ys 1 @ interleave xs 2 ys 2 theorem interleave_append: "length xs 1 = length ys 1 = interleave (xs 1 @xs 2 ) (ys 1 @ys 2 ) = (interleave xs 1 ys 1 )@(interleave xs 2 ys 2 )" proof(induction xs 1 ys 1 arbitrary:xs 2 ys 2 rule:interleave.induct) qed auto Mit der Induktionsregel von interleave theorem interleave_append2: "length xs 1 = length ys 1 = interleave (xs 1 @xs 2 ) (ys 1 @ys 2 ) = (interleave xs 1 ys 1 )@(interleave xs 2 ys 2 )" proof(induction xs 1 arbitrary:ys 1 xs 2 ys 2 ) Mit Induktion über den Datentyp, etwas aufwändiger case (Cons x xs 1 ) then show?case by (cases ys 1 ) auto qed auto 2 Merge Sort Wir arbeiten im Folgenden nur auf Listen über natürlichen Zahlen. Definieren Sie ein Prädikat sorted, welches prüft, ob in einer Liste jedes Element kleiner oder gleich den folgenden ist; le n xs ist True g.d.w. n kleiner oder gleich allen Elementen in xs. fun le :: "nat nat list bool" "le n [] = True" KIT Die Forschungsuniversität in der Helmholtz-Gemeinschaft

"le n (x#xs) = (n x le n xs)" fun sorted :: "nat list bool" "sorted [] = True" "sorted (x#xs) = (le x xs sorted xs)" Implementieren Sie nun Merge Sort: Eine Liste wird durch Aufteilung in zwei Listen sortiert, welche einzeln sortiert und wieder zusammengefügt werden. Definieren Sie mittels fun zwei Funktionen fun merge :: "nat list nat list nat list" "merge xs [] = xs" "merge [] ys = ys" "merge (x#xs) (y#ys) = (if (x y) then x#(merge xs (y#ys)) else y#(merge (x#xs) ys))" fun msort :: "nat list nat list" "msort [] = []" "msort [x] = [x]" "msort xs = (let n = (length xs) div 2 in (merge (msort (take n xs)) (msort (drop n xs)) ))" und zeigen Sie lemma le_le: " [ le x xs; x x ] = le x xs" by (induction xs) auto lemma le_merge: " [ le x xs; le x ys ] = le x (merge xs ys)" by (induction xs ys rule:merge.induct) auto lemma sorted_merge_sorted: " [ sorted xs; sorted ys ] = sorted(merge xs ys)" by(induction xs ys rule: merge.induct)(auto intro: le_merge simp add: le_le) theorem "sorted (msort xs)" by (induction xs rule:msort.induct)(auto intro: sorted_merge_sorted) Sie werden dafür Hilfslemmas über le und sorted beweisen müssen. Hinweise: Um eine Liste in zwei fast gleichlange Hälften zu zerteilen, können Sie die Funktionen n div 2, take und drop verwenden, wobei take n xs die ersten n Elemente von xs zurückgibt, drop n xs den Rest. Versuchen Sie erstmal, das Lemma alleine zu lösen und selbst herauszufinden, welche Hilfslemmas Sie dafür brauchen. Falls Sie so nicht weiterkommen, hier ein paar Überlegungen: Was muss gelten, damit merge sorted ist? Was muss gelten, wenn der zweite Parameter von le merge ist? Wie verhält sich le, wenn der erste Parameter kleiner wird? Und nun noch eine Meta-Frage: Haben Sie wirklich bewiesen, dass msort eine korrekte Sortierfunktion ist? 2

3 Wechselseitige Rekursion In bestimmten Fällen muss man Datentypen definieren, die voneinander abhängig sind, d.h. der eine wird im anderen verwendet und anders herum. Um dann Aussagen über diese Datentypen machen zu können, braucht man wechselseitige Rekursion. Wir wollen jetzt einen Datentyp definieren für arithmetische und boole sche Aussagen. Der Typ der vorkommenden Variablen(namen) soll nicht spezifiziert werden, deshalb verwenden wir für sie den Typparameter a. Da in arithmetischen Ausdrücken boole sche verwendet werden können (Bsp. if m < n then n m else m n ) bzw. anders herum (Bsp. m n < m + n ), müssen wir sie wechselseitig rekursiv definieren: datatype a aexp = arithmetische Ausdrücke IF " a bexp" " a aexp" " a aexp" funktionales if-then-else, entspricht?: z.b. in Java Sum " a aexp" " a aexp" Addition Diff " a aexp" " a aexp" Subtraktion Var a Variablen (speichern natürliche Zahlen) Const nat Konstanten (natürliche Zahlen) and wechselseitige Rekursion a bexp = boole sche Ausdrücke Less " a aexp" " a aexp" And " a bexp" " a bexp" Neg " a bexp" Wir brauchen auch noch eine Umgebung, die die Werte der Variablen liefert, also eine Funktion vom Typ der Variablen ( a) nach nat: type_synonym a env = " a nat" Definieren Sie jetzt Auswertungsfunktionen evala bzw. evalb, welche unter Verwendung einer Umgebung a env das Resultat der Operation liefert. Da die Datentypen wechselseitig rekursiv sind, sind es auch die Funktionen, die auf ihnen operieren. Deshalb müssen evala und evalb innerhalb eines fun definiert werden: fun evala :: " a aexp a env nat" and evalb :: " a bexp a env bool" erweitern Sie diese Definition "evala (IF b a1 a2) env = (if evalb b env then evala a1 env else evala a2 env)" "evala (Sum a1 a2) env = evala a1 env + evala a2 env" "evala (Diff a1 a2) env = evala a1 env - evala a2 env" "evala (Var v) env = env v" "evala (Const c) env = c" "evalb (Less a1 a2) env = (evala a1 env < evala a2 env)" "evalb (And b1 b2) env = (evalb b1 env evalb b2 env)" "evalb (Neg b) env = ( evalb b env)" Analog definieren Sie jetzt zwei Funktionen, welche Variablensubstitution durchführen: fun substa :: "( a b aexp) a aexp b aexp" and substb :: "( a b aexp) a bexp b bexp" "substa s (IF b a1 a2) = IF (substb s b) (substa s a1) (substa s a2)" "substa s (Sum a1 a2) = Sum (substa s a1) (substa s a2)" "substa s (Diff a1 a2) = Diff (substa s a1) (substa s a2)" 3

"substa s (Var v) = s v" "substa s (Const c) = Const c" "substb s (Less a1 a2) = Less (substa s a1) (substa s a2)" "substb s (And b1 b2) = And (substb s b1) (substb s b2)" "substb s (Neg b) = Neg (substb s b)" Der erste Parameter ist die Substitution, eine Funktion, welche Variablen auf Ausdrücke abbildet. Sie wird auf alle Variablen des Ausdrucks angewandt, weshalb der Resultattyp ein Ausdruck mit Variablen vom Typ b ist: Beweisen Sie nun, dass die Substitutionsfunktion Var einen Ausdruck in sich selbst überführt. Wenn man versucht, diese Aussage einzeln für arithmetische bzw. boole sche Ausdrücke zu zeigen, wird man feststellen, dass man jeweils die Aussage für die entsprechend anderen Ausdrücke im Induktionsschritt benötigt. Also müssen beide Theoreme gleichzeitig gezeigt werden. lemma "substa Var (a:: a aexp) = a" and "substb Var (b:: a bexp) = b" by(induction a and b) simp_all Wir beweisen jetzt ein fundamentales Theorem über die Interaktion zwischen Auswertung und Substitution: wenn man eine Substitution s auf einen Ausdruck a anwendet und dann mittels einer Umgebung env auswertet, erhält man das gleiche Resultat wie wenn man a auswertet mittels einer Umgebung, welche jede Variable x auf den Wert s x unter env abbildet. lemma "evala (substa s a) env = evala a ( λx. evala (s x) env)" and "evalb (substb s b) env = evalb b ( λx. evala (s x) env)" by(induction a and b) simp_all Abschließend sollen Sie eine Normalisierungsfunktion norma mit Typ a aexp a aexp definieren. Diese soll a aexps so umbauen, dass in der Bedingung eines IF nur Less stehen darf; falls dort And oder Neg steht, muss der IF-Ausdruck umgebaut werden. Dafür brauchen sie eine weitere, zu norma wechselseitig rekursive Funktion; wie sieht diese aus? Beweisen Sie dann zwei Aussagen darüber: norma verändert nicht den Wert, den evala liefert norma ist wirklich normal, d.h. keine Ands oder Negs tauchen in den IF-Bedingungen auf (dafür brauchen Sie wiederum zwei wechselseitig rekursive Funktionen; welche?). Beide Lemmas brauchen auch eine Aussage für die Funktion, welche die IF s umbaut. fun norma :: " a aexp a aexp" and normif :: " a bexp a aexp a aexp a aexp" "norma (IF b a1 a2) = normif b (norma a1) (norma a2)" "norma (Sum a1 a2) = Sum (norma a1) (norma a2)" "norma (Diff a1 a2) = Diff (norma a1) (norma a2)" "norma (Var v) = Var v" "norma (Const c) = Const c" "normif (Less a1 a2) t e = IF(Less (norma a1) (norma a2)) t e" "normif (And b1 b2) t e = normif b1 (normif b2 t e) e" "normif (Neg b) t e = normif b e t" lemma "evala (norma a) env = evala a env" and "evala (normif b t e) env = evala (IF b t e) env" 4

by (induction a and b arbitrary: and t e) auto fun normala :: " a aexp bool" and normalb :: " a bexp bool" "normala (IF b a1 a2) = (normalb b normala a1 normala a2)" "normala (Sum a1 a2) = (normala a1 normala a2)" "normala (Diff a1 a2) = (normala a1 normala a2)" "normala (Var v) = True" "normala (Const c) = True" "normalb (Less a1 a2) = (normala a1 normala a2)" "normalb (And b1 b2) = False" "normalb (Neg b) = False" lemma "normala (norma (a:: a aexp))" and "normala (normif (b:: a bexp) t e) = (normala t normala e)" by(induction a and b arbitrary: and t e) auto 5