Funktionale Programmierung ALP I Induktion und Rekursion WS 2012/2013 Prof. Dr. Margarita Esponda Prof. Dr. Margarita Esponda Funktionale Programmierung Vollständige Induktion (Mafi I) Die Vollständige Induktion ist eine mathematische Beweistechnik, die auf die Menge der natürlichen Zahlen spezialisiert ist. Vorgehensweise: 1. Induktionsanfang Text Text Man zeigt die Behauptung für k = 1 bzw. k = 0 2. Induktionsschritt Man nimmt an, die Aussage sei für wahr und zeigt damit, dass die Aussage für k+1 wahr ist. Wenn beide Schritte erfolgreich durchgeführt wurden, ist die Behauptung für alle natürlichen Zahlen gezeigt. Prof. Dr. Margarita Esponda Funktionale Programmierung Vollständige Induktion Beispiel: Vermutung: Die Summe der ersten n ungeraden Zahlen ist gleich n2 n n 2 2(i − 1) + 1 = n ∑ 2 2i − 1 = n ∑ i =1 i =1 Motivation: 1 = 12 1+ 3 = 22 1+ 3+ 5 = 32 1+ 3+ 5+ 7 = 42 ... Prof. Dr. Margarita Esponda … Funktionale Programmierung Vollständige Induktion (Mafi I) Beweis per vollständiger Induktion: Induktionsanfang: 1 2 2 ⋅ i − 1 = 2 ⋅1 − 1 = 1 = 1 ∑ für n = 1 i =1 Induktionsschritt: k wir nehmen an, dass für n = k 2 2i − 1 = k ∑ i =1 dann für n = k+1: ⎛ k ⎞ ∑ 2i − 1 = ⎜⎝ ∑ 2i − 1⎟⎠ + 2 ⋅ (k + 1) − 1 i =1 i =1 k +1 = k2 + 2 ⋅ k + 2 − 1 = k2 + 2 ⋅ k + 1 = (k + 1)2 Prof. Dr. Margarita Esponda daraus folgt, dass die Vermutung für alle n ∈ gilt. Funktionale Programmierung Baumeigenschaften und Vollständige Induktion Definition: a) Ein einzelner Blatt-Knoten ist ein Baum o b) Falls t1, t2,…,tm Bäume sind, dann ist ihre Verknüpfung unter einem Knoten o auch ein Baum (o t1, t2,…,tm ) o t1 t2 . . . tm Ein Baum ist balanciert, falls er ein Blatt oder von der Form (o t1, t2,…,tm) ist, wobei t1, t2,…,tm balanciert und von derselben Tiefe sind. Prof. Dr. Margarita Esponda Funktionale Programmierung Behauptung: Induktion über Bäume Ein balancierter m-Baum (Baum mit maximal m Kindern pro Knoten) mit m>1 und Tiefe n hat Motivation: o Tiefe 0 Tiefe 1 Tiefe 2 Tiefe n Prof. Dr. Margarita Esponda o o o t1 t2 . . .tm t1 t2 . . . tm ... .. . Funktionale Programmierung Induktion über Bäume 1. Induktionsanfang K = Knoten = mit Tiefe n = 0 2. Induktionsannahme mit Tiefe n = k, 3. Induktionsschritt Tiefe n = k+1 m k +1 − 1 K= m −1 k +1 m −1 m k +1 − 1 k +m ⋅ m = + m k +1 K= m −1 m −1 m k +1 − 1 + (m k +1 ) ⋅ (m − 1) m k +1 − 1 + m k + 2 − m k +1 = = m −1 m −1 m k + 2 − 1 m (k +1)+1 − 1 = = m −1 m −1 Prof. Dr. Margarita Esponda n +1 m −1 K= m −1 Funktionale Programmierung Vollständige Induktion Weitere Beispiele an der Tafel! Prof. Dr. Margarita Esponda Funktionale Programmierung Vollständige Induktion factorial 0 = 1 factorial n = n * factorial (n-1) endRecFactorial n = fact_helper 1 n where fact_helper a 0 = a fact_helper a n = fact_helper (a*n) (n-1) ? factorial = endRecFactorial Prof. Dr. Margarita Esponda Funktionale Programmierung Zu beweisen ist: factorial = endRecFactorial Für unseren Beweis müssen wir folgende Eigenschaft der fact_helper-Funktion per Induktion über n zeigen. fact_helper c n = c * factorial n ……… e.1 Induktionsanfang: für n = 0 fact_helper c 0 = c = fact_helper.1 c*1 = c * factorial 0 factorial.1 Induktionsannahme: fact_helper c k = c * factorial k Induktionsschritt: für n = k+1 fact_helper c (k+1) = fact_helper (c*(k+1)) k = c* (k+1) * factorial k = c * factorial (k+1) Prof. Dr. Margarita Esponda Funktionale Programmierung fact_helper c n = c * factorial n factorial 0 = 1 factorial n = n * factorial (n-1) ……… e.1 ………. factorial.1 ………. factorial.2 …………… endRecFactorial.1 endRecFactorial n = fact_helper 1 n where ………… fact_helper.1 fact_helper a 0 = a fact_helper a n = fact_helper (a*n) (n-1) .. fact_helper.2 1. Induktionsanfang n=0 factorial 0 factorial 0 = factorial.1 ?= endRecFactorial 0 1 = factorial_helper 1 0 factorial_helper.1 = endRecFactorial 0 endRecfactorial.1 Prof. Dr. Margarita Esponda Funktionale Programmierung fact_helper c n = c * factorial n ……… e.1 ………. factorial.1 factorial 0 = 1 factorial n = n * factorial (n-1) ………. factorial.2 …………… endRecFactorial.1 endRecFactorial n = fact_helper 1 n where ………… fact_helper.1 fact_helper a 0 = a fact_helper a n = fact_helper (a*n) (n-1) .. fact_helper.2 Induktions-Annahme 2. Induktionsschritt factorial (k+1) factorial k = endRecFactorial k für n = k+1 = (k+1) * factorial k factorial.2 = fact_helper (1*(k+1)) k e.1 = fact_helper 1 (k+1) fact_helper.2 = endRecFactorial (k+1) endRecFactorial.1 Prof. Dr. Margarita Esponda factorial = endRecFactorial Funktionale Programmierung Berechnung der Fibonacci-Zahlen 1. Lösung 2. Lösung fib 0 = 0 … fib.0 fib 1 = 1 … fib.1 fib n = fib (n-2) + fib (n-1) … fib.2 Endrekursive Funktion fib' n = quickFib 0 1 n where quickFib a b 0 = a … quickFib.1 quickFib a b n = quickFib b (a+b) (n-1) quickFib.2 Prof. Dr. Margarita Esponda Funktionale Programmierung Vollständige Induktion Zu beweisen ist: ? fib = fib' … fib˚.1 fib' n = quickFib 0 1 n where … quickFib.1 quickFib a b 0 = a quickFib a b n = quickFib b (a+b) (n-1) quickFib.2 Für unseren Beweis müssen wir folgende Eigenschaft der quickFibFunktion per Induktion über n zeigen. quickFib (fib i) (fib (i+1)) n = fib (i+n) Induktionsanfang: für n = 0 quickFib (fib i) (fib (i+1)) 0 = fib i quickFib.1 = fib (i+0) Prof. Dr. Margarita Esponda ……… ze.1 Funktionale Programmierung Induktions-Annahme: n = k quickFib (fib i) (fib (i+1)) k = fib (i+k) Induktionsschritt: ? quickFib (fib i) (fib (i+1)) (k+1) = fib (i+(k+1)) quickFib (fib i) (fib (i+1)) (k+1) quickFib.2 fib.2 = quickFib fib (i+1) (fib (i) + fib (i+1)) k = quickFib fib (i+1) (fib ((i+1)+1) k = fib ((i+1) + k) Induktions-Annahme = fib (i + (k+1)) quickFib (fib i) (fib (i+1)) n = fib (i+n)……… ze.1 Prof. Dr. Margarita Esponda Funktionale Programmierung Sind fib und fib' äquivalent? Behauptung: ? fib = fib' … fib˚.1 fib' n = quickFib 0 1 n where … quickFib.1 quickFib a b 0 = a quickFib a b n = quickFib b (a+b) (n-1) quickFib.2 1. Induktionsanfang: n = 0 fib 0 = 0 fib.0 2. Induktionsanfang: n = 1 fib 1 = 1 fib' 0 = quickFib 0 1 0 … fib˚.1 =0 … quickFib.1 fib' 1 = quickFib 0 1 1 fib'.1 = quickFib 1 1 0 quickFib.2 = 1 quickFib.1 Prof. Dr. Margarita Esponda Funktionale Programmierung quickFib (fib i) (fib (i+1)) n = fib (i+n)……… ze.1 Induktionsannahme: fib k = fib' k 3. Induktionsschritt: fib (k+1) ? = fib' (k+1) fib' (k+1) = quickFib 0 1 (k+1) fib'.1 = quickFib (fib 0) (fib 1) (k+1) fib.0 und fib.1 = fib (0+(k+1)) aus ze.1 = fib (k+1) Prof. Dr. Margarita Esponda ⇒ fib n = fib' n Funktionale Programmierung Strukturelle Induktion Die Strukturelle Induktion ist eine allgemeinere Form der Vollständigen Induktion. Mit diesem mathematischen Beweisverfahren lassen sich Aussagen über die Elemente von rekursiv aufgebauten Datenmengen wie zum Beispiel Listen, Bäumen oder Graphen beweisen. Die Datenmengen, die damit behandelt werden, müssen aus einer endlichen Anzahl von Konstruktionsschritten aus Grundelementen entstehen. Prof. Dr. Margarita Esponda Funktionale Programmierung Induktion über Listen Vorgehensweise: 1. Induktionsanfang Man zeigt eine bestimmte Eigenschaft P für die leere Liste [] 2. Induktionsschritt Man zeigt die Eigenschaft P(x:xs) unter der Annahme, dass P(xs) gilt. Prof. Dr. Margarita Esponda Funktionale Programmierung Induktion über Listen Beispiel: Nehmen wir an, wir möchten zeigen, dass die Verkettung über Listen assoziativ ist. Definition von (++): (++) :: [a] -> [a] -> [a] (++) [] ys = ys (++) (x:xs) ys = x : (++) xs ys Prof. Dr. Margarita Esponda Funktionale Programmierung Induktion über Listen Behauptung: Für alle Listen xs, zs und ys über den Datentyp a gilt die Assoziativität-Eigenschaft: (++) ((++) xs ys) zs = (++) xs ((++) ys zs) oder (xs ++ ys) ++ zs = xs ++ (ys ++ zs) Prof. Dr. Margarita Esponda Funktionale Programmierung Induktion über Listen Definition von (++): (++) :: [a] -> [a] -> [a] (++) [] ys = ys …………… (++).1 (++) (x:xs) ys = x : (++) xs ys …………… (++).2 Behauptung: (++) ((++) xs ys) zs = (++) xs ((++) ys zs) Beweis: (Induktion über xs) Induktionsanfang: xs = [] (++) ((++) [] ys) zs = (++).1 = (++).1 Prof. Dr. Margarita Esponda (++) ys zs (++) [] ((++) ys zs) Funktionale Programmierung Induktion über Listen (++) :: [a] -> [a] -> [a] (++) [] ys = ys …………… (++).1 (++) (x:xs) ys = x : (++) xs ys …………… (++).2 Induktionsschritt: (++) (x:xs) ((++) ys zs) (++) (x:xs) ((++) ys zs) ? = (++) ((++) (x:xs) ys) zs = x : (++) xs ((++) ys zs) = x : (++) ((++) xs ys) zs = (++) (x:((++) xs ys)) zs = (++) ((++) (x:xs) ys) zs (++).2 i.A. (++).2 (++).2 Prof. Dr. Margarita Esponda Funktionale Programmierung Vollständige Induktion Weitere Beispiele an der Tafel! Prof. Dr. Margarita Esponda Funktionale Programmierung Beispiele endrekursiver Funktionen Klassisches Beispiel einer nicht endrekursiven Definition ist: Die Standarddefinition der reverse-Funktion rev :: [a] -> [a] rev [] = [] rev (x:xs) = rev xs ++ [x] (++) :: [a] -> [a] -> [a] = ys (++) [] ys (++) (x:xs) ys = x:(xs ++ ys) Eine effizientere Version von rev: quickRev xs = rev_helper xs [] where rev_helper [] ys = ys rev_helper (x:xs) ys = rev_helper xs (x:ys) Prof. Dr. Margarita Esponda Funktionale Programmierung Sind rev und quickRev äquivalent? Zu beweisen ist: Für alle endlichen Listen xs :: [a] gilt: rev = quickRev Prof. Dr. Margarita Esponda Funktionale Programmierung Strukturelle Induktion über Bäume Beispiel: data Tree a = Nil | Leaf a | Node (Tree a) (Tree a) Vorgehensweise: 1. Induktionsanfang 1.1 Wir zeigen eine bestimmte Eigenschaft P für den leeren Baum Nil 1.2 Wir zeigen die Eigenschaft P für ein Blatt (Leaf a) 2. Induktionsschritt Wir zeigen die Eigenschaft P für ( Node l r ) unter der Annahme, dass P für den Teilbaum l und für den Teilbaum r gilt. Prof. Dr. Margarita Esponda Funktionale Programmierung Das allgemeine Induktionsschema data T a1 a2 . . . am = C1 t11 … t1n1 | C2 t21 … t2n2 ... Vorgehensweise: | Ck tk1 … tknk 1. Induktionsanfang 1.1 Wir zeigen eine bestimmte Eigenschaft P für alle Basis-Daten (alle Ci ohne Rekursion) 2. Induktionsschritt Wir zeigen die Eigenschaft P für jede rekursive Definition (Ci ti1 … tini) unter der Annahme, dass P für ti1 … tini gilt. Prof. Dr. Margarita Esponda