5.1 Berechenbarkeit 5 Theorie der Algorithmen Frage: Gilt für jedes beliebige Problem, dass es entweder mit dem Computer lösbar (berechenbar) ist oder als unlösbar erkannt werden kann? (Hilbertsches Entscheidungsproblem) 5.1 Berechenbarkeit 5.1.1 Äquivalenz der Algorithmus-Begriffe 5.1.2 Das Halteproblem 5.1.3 Das Äquivalenzproblem 5.1.4 Rekursionssatz 5.2 Komplexität von Algorithmen 5.2.1 Vorüberlegungen und Beispiele 5.2.2 O-Kalkül 5.2.3 Polynomialer und exponentieller Aufwand 5.2.4 Die Klassen P und NP 5.3 Korrektheit: Test und Verifikation von Programmen 5.3.1 Testen 5.3.2 Verifikation Praktische Informatik I © Prof. Dr. W. Effelsberg 5. Theorie der Algorithmen Antwort: Nein! Das Hilbertsche Entscheidungsproblem ist nicht berechenbar. Beispiel Gegeben sei irgendeine beliebige Aussage über die natürlichen Zahlen. Dann gibt es keinen Algorithmus, der feststellt, ob diese Aussage wahr oder falsch ist. (Unvollständigkeitstheorem von Gödel) Weitere Beispiele von Church, Kleene, Post, Turing, ca.1930 - 1940. 5-1 Praktische Informatik I © Prof. Dr. W. Effelsberg 5. Theorie der Algorithmen 5-2 Präzisierung des Algorithmus-Begriffs 5.1.1 Äquivalenz der Algorithmus-Begriffe Gödel: Folge von Regeln zur Bildung mathematischer Funktionen aus einfacheren mathematischen Funktionen. Man könnte auch einen Algorithmus definieren als eine Verarbeitungsvorschrift, die in Java angegeben werden kann. Church: Lambda-Kalkül Turing: Turing - Maschine (abstrakte Maschine mit sehr einfachen Anweisungen) Church - Turing - These Dann vermutet man schon, dass ein äquivalenter Algorithmus auch in C oder FORTRAN oder Pascal oder LISP oder PROLOG angegeben werden kann. Dies trifft in der Tat zu. Programmiersprachen unterscheiden sich nicht in der Mächtigkeit, sondern in der Natürlichkeit, Effizienz, Klarheit usw., in der sie ein bestimmtes Problem ausdrücken können. Alle Definitionen von Algorithmus sind gleichwertig. Wir erkennen: Die Berechenbarkeit eines Problems hängt nicht von der Programmiersprache ab. Praktische Informatik I © Prof. Dr. W. Effelsberg 5. Theorie der Algorithmen 5-3 Praktische Informatik I © Prof. Dr. W. Effelsberg 5. Theorie der Algorithmen 5-4 Beispiel: Fermat'sche Vermutung 5.1.2 Das Halteproblem Gegeben ein beliebiges Programm P und beliebige Daten D dazu. Wird das Programm jemals anhalten, oder läuft es endlos lange? Es gibt keine natürlichen Zahlen a, b, c, so dass an + bn = c n gilt für n > 2. Algorithmus Das Halteproblem ist nicht berechenbar. Modul Fermat (n) /* Prüfe die Fermat'sche Vermutung mit n als Eingabe */ Wiederhole für a = 1, 2, 3, ... Wiederhole für b = 1, 2, 3, ...,a Wiederhole für c = 2, 3, 4, ..., a + b Falls an + bn = cn dann gebe a, b, c und n aus, stoppe D.h., es gibt keinen Algorithmus, der für beliebiges P und beliebiges D das Halteproblem lösen kann. Stoppt für n = 1 Stoppt für n = 2 (a = 1, b = 1, c = 2) (a = 4, b = 3, c = 5) Was geschieht für beliebiges n > 2? Praktische Informatik I © Prof. Dr. W. Effelsberg 5. Theorie der Algorithmen 5-5 Praktische Informatik I © Prof. Dr. W. Effelsberg 5. Theorie der Algorithmen 5-6 Beweis der Nichtberechenbarkeit des Halteproblems Algorithmus "Stop-Tester" Beweistechnik: Beweis durch Widerspruch • Angenommen, es gäbe einen Algorithmus, der das Halteproblem löst. Wir nennen ihn Stop-Tester. • Dann konstruieren wir einen Algorithmus “fun” derart, Lies P Lies D /* Programm /* Daten Falls dann sonst P(D) stoppt, gib JA aus gib NEIN aus. */ */ dass Stop-Tester(fun) die Antwort “JA” liefert, wenn “fun” nicht terminiert und die Antwort “NEIN”, wenn “fun” terminiert. • Damit haben wir einen immanenten Widerspruch, und es kann Stop-Tester somit nicht geben. Stop - Tester - Spezial Lies P Lies P /* Programm */ als Daten Falls P(P) stoppt, dann gib JA aus sonst gib NEIN aus. Praktische Informatik I © Prof. Dr. W. Effelsberg 5. Theorie der Algorithmen 5-7 Praktische Informatik I © Prof. Dr. W. Effelsberg 5. Theorie der Algorithmen 5-8 Algorithmus fun(P) Algorithmus fun(fun) /* Wir nehmen an, dass der Algorithmus Stop-Tester und damit auch Stop-Tester-Spezial existiert. */ Lies fun Stop-Tester-Spezial(fun) Falls Antwort = JA dann gehe in eine Endlosschleife sonst stoppe. Lies P Stop-Tester-Spezial(P) Falls Antwort = JA dann gehe in eine Endlosschleife sonst stoppe. Fu n P S top p t F u n (F un )? Ja N ein S to pp t P (P )? Ja an h alten N ein E n d lo ssc hleife a n ha lte n E n dlossch leife Praktische Informatik I © Prof. Dr. W. Effelsberg 5. Theorie der Algorithmen 5-9 Praktische Informatik I © Prof. Dr. W. Effelsberg 5. Theorie der Algorithmen 5-10 Widerspruch in fun(fun) 5.1.3 Das Äquivalenzproblem Wenn der Algorithmus “fun” stoppt, dann gerät er in eine Endlosschleife. Wenn “fun” nicht stoppt, dann gerät er auf eine STOPAnweisung. Gegeben seien zwei beliebige Programme P1 und P2. Man gebe einen Algorithmus an, der feststellt, ob P1 und P2 für beliebige Daten D dieselbe Ausgabe erzeugen (also äquivalent sind). Wir schließen Behauptung Gäbe es einen Algorithmus Stop-Tester, so würde sich unter ausschließlicher Verwendung dieses Algorithmus ein immanenter Widerspruch zeigen lassen. Daraus folgt, dass es einen Algorithmus Stop-Tester nicht geben kann. Das Äquivalenzproblem ist nicht berechenbar. Praktische Informatik I © Prof. Dr. W. Effelsberg 5. Theorie der Algorithmen 5-11 Praktische Informatik I © Prof. Dr. W. Effelsberg 5. Theorie der Algorithmen 5-12 Partielle Berechenbarkeit Partielle Berechenbarkeit Bisher haben wir verschiedene Probleme betrachtet, die nicht berechenbar sind (d.h. keine algorithmische Lösung haben). Ein Problem heißt partiell berechenbar, wenn es einen Algorithmus gibt, der für jeden Eingabewert, für den ein Ergebnis definiert ist, nach endlich vielen Schritten anhält und das korrekte Ergebnis liefert. In allen anderen Fällen, in denen kein Ergebnis definiert ist, bricht der Algorithmus nicht ab. Bisher: P rob lem b erech en ba r nich t b erech en b a r Jetzt: P ro blem Beispiel Das Halteproblem ist partiell berechenbar. Beweis: b e re ch en ba r Schrittweise Ausführung des Programms P(D). Falls die schrittweise Ausführung hält, wissen wir, dass das Programm hält. Falls die schrittweise Ausführung nicht hält, können wir keine Aussage machen (vielleicht wird sie irgendwann in sehr ferner Zukunft halten?) Praktische Informatik I © Prof. Dr. W. Effelsberg 5. Theorie der Algorithmen 5-13 p artie ll b ere ch en ba r Praktische Informatik I © Prof. Dr. W. Effelsberg n ich t b ere ch en ba r 5. Theorie der Algorithmen 5-14 5.1.4 Rekursionssatz 5.2 Komplexität von Algorithmen Gegeben sei ein Programm P(D), das eine bestimmte Funktion ausführt. Dann gibt es ein Programm P'(P'), das dieselbe Funktion ausführt, wobei es eine Kopie von sich selbst als Eingabedaten benutzt. 5.2.1 Vorüberlegungen und Beispiele Berechenbarkeit, wie zuvor eingeführt, bedeutet nur, dass ein Problem prinzipiell algorithmisch lösbar ist. Es heißt aber nicht, dass es mit vernünftigem Aufwand praktisch durchführbar ist. Beispiel 1 Modul Drucke(D) Gib D aus. Dann gibt es ein Modul Drucke', das seinen eigenen Programmtext ausdruckt. A lle A u fga b en ste llu ng en B e rech e nb are A ufga b e n ste llu ng en Beispiel 2 Man kann einen Compiler in einer Programmiersprache so schreiben, dass er sich selbst compilieren kann! Praktische Informatik I © Prof. Dr. W. Effelsberg 5. Theorie der Algorithmen 5-15 B e rech en - u nd d urch fü h rb a re A ufga b en ste llu ng en Praktische Informatik I © Prof. Dr. W. Effelsberg 5. Theorie der Algorithmen 5-16 Ressourcen Beispiel 1: Komplexität der Multiplikation Bei der Ermittlung der Komplexität eines Algorithmus betrachtet man in der Regel die folgenden Ressourcen Zeit und Speicherplatz. Häufig geht eine Optimierung des Bedarfs an einer Ressource auf Kosten der anderen Ressource (z. B. weniger Zeit, dafür mehr Speicher). Es seien zwei 4-stellige Zahlen zu multiplizieren. Es wird der übliche Schul-Algorithmus angewendet. Jede Zeile kann in 4 Operationen errechnet werden. Es gibt 4 Zeilen, die anschließend zu addieren sind. Insgesamt ist die Anzahl der Operationen proportional zu n2, wenn n die Anzahl der Ziffern ist. 1984 x 6713 In der Komplexitätstheorie wird meist die Anzahl der Operationen in Abhängigkeit von der Anzahl der Eingabedaten als Komplexitätsmaß betrachtet. 11904 1 3888 1984 5952 13318592 Praktische Informatik I © Prof. Dr. W. Effelsberg 5. Theorie der Algorithmen 5-17 Praktische Informatik I © Prof. Dr. W. Effelsberg 5. Theorie der Algorithmen 5-18 Verbesserter Multiplikationsalgorithmus Beispiel 2: Sortieren durch Auswahl Zerlegung der vierstelligen Multiplikation in zwei zweistellige M;ultiplikationen: A B 19 84 (100*A + B) = 10000*AC + = 10000*AC + = 10000*AC + x C D 67 13 Gegeben seien n Zahlen, die zu sortieren sind. Algorithmus Auswahlsortieren * (100*C + D) 100*AD + 100*BC + BD 100*(AD + BC) + BD 100*[(A + B)(C + D) - AC - BD] +BD AC = 19 x 67 = 1273 (A+B)(C+D)-AC-BD = (103x80)-1273-1092 = BD = 84 x 13 = 1092 1273 5875 1092 13318592 5875 Komplexität: Proportional zu n2 (n Durchläufe mit jeweils größenordnungsmäßig n Vergleichen) Alle Multiplikationen sind nur noch 2-stellig. Es sind nur noch 3 Zeilen mit je 4 Ziffern zu addieren. Man kann generell zeigen, dass die Anzahl der Operationen proportional zu n1,59 < n2 ist. Praktische Informatik I © Prof. Dr. W. Effelsberg Wiederhole n-mal Markiere die erste Zahl der Eingabemenge. Vergleiche sie mit der zweiten, dritten usw. Wenn eine kleinere als die erste gefunden wird, markiere diese. Wenn das Ende der Eingabemenge erreicht ist, Übertrage die markierte kleinste Zahl in den Ausgabe-Datenstrom und sperre sie für die weitere Bearbeitung. 5. Theorie der Algorithmen 5-19 Anmerkung: Es gibt Sortieralgorithmen mit Komplexität n log n. Praktische Informatik I © Prof. Dr. W. Effelsberg 5. Theorie der Algorithmen 5-20 Asymptotisches Verhalten 5.2.2 O-Kalkül In der Praxis interessiert oft nicht so sehr die genaue Anzahl der Operationen, sondern das asymptotische Wachstum für große n. Berechnung der Komplexität unter Abstraktion Beispiel • von weniger dominanten Termen (die für große Werte • von Konstanten (die maschinenabhängig sind) des Komplexitätsparameters n nicht mehr signifikant sind) Sei 3n2 + 5n die Anzahl der Operationen. Dann ist für großes n der quadratische Anteil dominierend. Man sagt, die Komplexität wächst mit n2. Größe n der Daten 10 log2n •s n •s 0.000003 s 0.00001 s n2 •s 2n •s 0.0001 s 0.001 s 100 0.000007 s 0.0001 s 0.01 s 1014 Jahrhunderte 1,000 0.00001 s 0.001 s 1s astronomisch 10,000 0.000013 s 0.01 s 1.7 min astronomisch 100,000 0.000017 s 0.1 s 2.8 h astronomisch Praktische Informatik I © Prof. Dr. W. Effelsberg 5. Theorie der Algorithmen 5-21 Praktische Informatik I © Prof. Dr. W. Effelsberg 5. Theorie der Algorithmen 5-22 Asymptotisches Wachstum (1) Asymptotisches Wachstum (2) Definition 1 Definition 2 Seien f und g zwei positive, reellwertige Funktionen, die auf einem gemeinsamen Bereich D definiert sind. Dann bedeutet f = O(g), dass es eine Konstante c > 0 und einen Anfangswert x0 gibt derart, dass Es bedeutet f(x) ≤ cg(x) für alle x > x0, f = Ω (g), dass es eine Konstante c > 0 und einen Anfangswert x0 gibt derart, dass x, x0 ∈ D f (x) ≥ cg(x) für alle x > x0 , x, x0 ∈ D gilt. gilt. Man sagt, f wächst asymptotisch höchstens wie g. Man sagt, f wächst asymptotisch mindestens wie g. Praktische Informatik I © Prof. Dr. W. Effelsberg 5. Theorie der Algorithmen 5-23 Praktische Informatik I © Prof. Dr. W. Effelsberg 5. Theorie der Algorithmen 5-24 Einfache Rechenregeln des O-Kalküls Beispiel für den O-Kalkül (1) (2) (3) (4) (5) (6) (7) (8) Sortieren durch Auswahl Eingabeparameter: n Anzahl der Elemente Der Vergleich zweier Zahlen ist in konstanter Zeit c 1 möglich. f = O(f) O(O(f)) = O(f) cO(f) = O(f) O(f+c) = O(f) O(f) + O(f) = O(f) O(f) * O(g) = O(fg) O(f) + O(g) = O(f+g) O(fg) = O(f) * O(g) Innere Schleife: t1 = nc1 Äußere Schleife: t2 = nt1 = n2 c1 Konvention: Diese Gleichungen werden von links nach rechts gelesen. Gesamter Rechenaufwand: O(f) ist, mathematisch gesehen, eine Menge von Funktionen. t = t2 = n2 c1= O(n2) Mengenoperationen: M1 + M2 := { x + y | x ∈ M1 und y ∈ M2 } M1 * M2 := { x * y | x ∈ M1 und y ∈ M2 } Praktische Informatik I © Prof. Dr. W. Effelsberg 5. Theorie der Algorithmen 5-25 Praktische Informatik I © Prof. Dr. W. Effelsberg 5. Theorie der Algorithmen 5-26 Beweis von Regel (7) als Beispiel Beispiel: Multiplikation mit dem Standard-Algorithmus im O-Kalkül (7) O(f) + O(g) = O(f+g) 1984 x 6713 11904 1 3888 1984 5952 13318592 h1(n) = O(f), also: Es gibt c1, n1 mit h1(n) ≤ c1f(n) für alle n > n1 h2(n) = O(g), also: Es gibt c2, n2 mit h2(n) ≤ c2g(n) für alle n > n2 Addition liefert h1(n) + h2(n) ≤ c1f + c2g für alle n > max(n1,n2). Setzen wir h3(n) = h1(n) + h2(n), c3 = max(c1,c2) und n3 = max(n1,n2), so gilt h3(n) ≤ c3 (f + g), für alle n > n3, was nach Definition h3(n) = O(f + g) bedeutet. Eingabeparameter: n1, n2 Längen der Faktoren Multiplikation zweier Ziffern in konstanter Zeit c1 möglich. Addition zweier Ziffern sei in konstanter Zeit c2 möglich. Berechnung einer Zeile: t1 = n1 * c1 Berechnung von n2 Zeilen: t 2 = n 2 * t1 = n 2 * n 1 * c 1 Addition von n2 Zeilen der Länge ≤ n1 + 2: t3 = n2 * (n1 + 2) * c2 t = t2 + t3 = n1n2c1 + (n1 + 2) n2c2 = n1n2c1 + n1n2c2 + 2n2c2 = n1n2(c1 + c2) + 2n2c2 = O(n1n2 + n2) = O(n1n2) 2 mit n := max {n1, n2} ist t = O(n*n) = O(n ) Praktische Informatik I © Prof. Dr. W. Effelsberg 5. Theorie der Algorithmen 5-27 Praktische Informatik I © Prof. Dr. W. Effelsberg 5. Theorie der Algorithmen 5-28 Zwei Arten von Schranken Für ein gegebenes Problem lässt sich oft eine untere Schranke für die Komplexität einer Lösung aus der Theorie angeben, unabhängig vom Algorithmus. Beispiel: Minimumsuche Suche das Minimum aus n unsortierten Zahlen. Jede Zahl muss mindestens einmal angesehen (verglichen) werden. Daher gilt: Das Problem der Minimumsuche hat Komplexität Ω (n). Darüber hinaus lässt sich für einen gegebenen Algorithmus die Abhängigkeit der Anzahl der Operationen von n ermitteln und dadurch eine für diesen Algorithmus spezifische Schranke ermitteln. Beispiel: Minimumsuche Ein dummer Algorithmus A1 sortiert die n Zahlen und erhält dann das Minimum als erste Zahl des Ergebnisses. Sortieren durch Auswahl: O(n2) Bestimmung der ersten Zahl: O(1) Der Algorithmus A1 hat also die Komplexität O (n2). Praktische Informatik I © Prof. Dr. W. Effelsberg 5. Theorie der Algorithmen 5-29 Praktische Informatik I © Prof. Dr. W. Effelsberg 5. Theorie der Algorithmen 5-30 Obere und untere Schranken Vergleich zweier Algorithmen t t m ax m ax O be re S ch ra n ke g e ge be n d u rch A lgo rith m u s Z eit A 1 A u nte re S ch ra nk e a us T h eo rie 2 n n n A ufw an d sp ara m ete r 0 Wir sehen: Die Erforschung solcher Schranken wird in der Komplexitätstheorie behandelt, einem wichtigen Zweig der Theoretischen Informatik. Praktische Informatik I © Prof. Dr. W. Effelsberg 5. Theorie der Algorithmen 5-31 Der asymptotisch optimale Algorithmus ist nicht unbedingt der bessere für alle n; es kann sich lohnen, für kleine n enen anderen Algorithmus zu wählen als für große n. Praktische Informatik I © Prof. Dr. W. Effelsberg 5. Theorie der Algorithmen 5-32 Rekurrenzrelation: "Teile und herrsche" Beispiel 1 für "Teile-und-herrsche": Sortieren Das Verfahren "Teile und Herrsche" erweist sich oft als gutes Entwurfsprinzip für effiziente Algorithmen! Idee Aufteilen des Gesamtproblems in kleinere Teilprobleme derart, dass die Summe der Aufwände für die Teilprobleme und des Aufwands für das Zusammenfügen geringer ist als der Aufwand für das direkte Lösen des Gesamtproblems. Modul TH-Sortiere(Liste) /*Sortiert eine gegebene Liste aus n Namen alphabetisch.*/ Falls n > 1 dann TH-Sortiere(erste Listenhälfte) TH-Sortiere(zweite Listenhälfte) Mische die zwei Hälften zusammen Dies ist der Trick bei allen effizienten Sortieralgorithmen! Praktische Informatik I © Prof. Dr. W. Effelsberg 5. Theorie der Algorithmen 5-33 Praktische Informatik I © Prof. Dr. W. Effelsberg 5. Theorie der Algorithmen 5-34 Aufwand für TH-Sortier-Algorithmus Entwicklung von T(n) (1) k Tn = 2T(n / 2) + cn () T(n) sei der Aufwand für das Sortieren von n Zahlen. Sortieren von n/2 Zahlen erfordert T(n/2). Mischen der beiden Hälften ist proportional zu n. Der Aufwand für das TH-Sortieren durch Halbieren und Mischen ist also T(n) = 2 T(n/2) + cn T(1) = k falls n = 1 falls n > 1 T(n) = 2T(n/2) + cn = 2(2T(n/4) + cn/2) + cn = 4T(n/4) + 2cn = 4(2T(n/8) + cn/4) + 2cn = 8T(n/8) + 3cn .......... Behauptung T(n) = 2iT(n/2i) + icn (i ist die aktuelle Rekursionsstufe) Diese Rekurrenzrelation (rekursives Gleichungssystem) hat die geschlossene Lösung: T(n) = cn log n + kn Beweis durch vollständige Induktion über i: Wir erkennen: Schluss von i auf i + 1: i i T(n) = 2 T(n/2 ) + icn i i+1 i = 2 (2T(n/2 ) + cn/2 ) + icn i+1 i+1 = 2 T(n/2 ) + (i+1)cn i = 1: 1 1 2 T(n/2 ) + 1cn = 2T(n/2) + cn T(n) = O(n log n) Das ist besser als O(n2)! ⇒ Das Verfahren "Teile und herrsche" hat also zu einem Algorithmus mit geringerer Komplexität geführt. Praktische Informatik I © Prof. Dr. W. Effelsberg 5. Theorie der Algorithmen k T(n ) = i i 2 T(n / 2 ) + icn 5-35 Praktische Informatik I © Prof. Dr. W. Effelsberg falls n = 1 falls n > 1 mit i ≥ 1 5. Theorie der Algorithmen 5-36 Beispiel 2 für "Teile-und-herrsche": Multiplikation Für Zweierpotenzen Betrachte nur solche n, die Zweierpotenzen sind: 20 21 2 i-1 2i n Denn da der Zeitaufwand des Algorithmus mindestens linear wächst (Ω(n)), gilt für alle n ≤ n2: T(n) ≤ T(n2) i i-1 i mit n2 := 2 , so dass 2 < n ≤ 2 = n2. Dann gilt: n = 2i bzw. i = log2 n = ld n Sei n > 1. Dann ist T(n) = = = = © Prof. Dr. W. Effelsberg 5. Theorie der Algorithmen Nun gilt: X * Y = A * C * 104 + 102 + BD ((A + B) * (C + D) - AC - BD) * Die Zehnerpotenzen bedeuten nur ein Schieben der Zahlen nach links beim Addieren. Es sind nun nur noch drei Multiplikationen mit Zahlen halber Länge nötig: A * C, B * D und (A + B) * (C + D) 2iT(n/2i) + icn nT(1) + cn ld n nk + cn ld n O(n ld n) Praktische Informatik I Multiplikation von 4-stelligen Zahlen durch Zurückführung auf die Multiplikation von 2-stelligen Zahlen. Es sei X * Y zu berechnen. Dann trenne man X und Y auf in Zahlen mit halber Länge. Beispiel: X = 1984; A = 19 B = 84 Y = 6713; C = 67 D = 13 Der Additionsaufwand ist proportional zu n, n = Anzahl der Ziffern 5-37 Praktische Informatik I © Prof. Dr. W. Effelsberg 5. Theorie der Algorithmen 5-38 Aufwand für die TH-Multiplikation T(n) T(1) 5.2.3 Polynomialer und exponentieller Aufwand = 3T(n/2) + cn = k Eine gute Näherung für die Durchführbarkeit von Algorithmen ist die Annahme, dass Lösung der Rekurrenzrelation ergibt: ld 3 T(n) = (2c + k)n - 2cn ld 3 = O(n ) 1,59 = O(n ) c • Algorithmen mit polynomialem Aufwand (O(n )) durchführbar sind 2 Also ist auch hier der Aufwand geringer als O(n ) beim Schul-Algorithmus. n • Algorithmen mit exponentiellem Aufwand (O(c )) nicht durchführbar sind Daher ist es eine zentrale Fragestellung der Theoretischen Informatik, ob es für ein gegebenes Problem einen Algorithmus mit polynomialem Aufwand geben kann. Praktische Informatik I © Prof. Dr. W. Effelsberg 5. Theorie der Algorithmen 5-39 Praktische Informatik I © Prof. Dr. W. Effelsberg 5. Theorie der Algorithmen 5-40 Klassifikation der Komplexität von Problemen P ro blem stellu n g Beispiel 1: bin-packing problem Gegeben n Kästen mit unterschiedlichem Gewicht, T Lastwagen mit maximaler Zuladung G. Ist es möglich, alle Kästen zu verladen? 3 T onnen p o lyn om ina l e in A lg orith m u s m it p o lyno m in a len A ufw a n d ist b ek a n n t ? 3 To nnen e x p on en tie ll k ein A lg o rith m u s m it p o lyn om ina le n A ufw a n d be ka n nt 4 T on nen m a n w eiß : es ka n n ke in en po lyno m in a len A lg o rithm us geb en 5 T onnen 8 T o nnen 5 T o nn en Besonders die Probleme aus der mittleren Klasse sind für Informatiker interessant! n = 6 K äste n T = 2 La stz üg e m a xim a le La d u ng G = 1 4 T o n ne n Ein einfacher Fall des Kastenproblems Praktische Informatik I © Prof. Dr. W. Effelsberg 5. Theorie der Algorithmen 5-41 Praktische Informatik I © Prof. Dr. W. Effelsberg 5. Theorie der Algorithmen 5-42 Algorithmus "Schwerster Kasten zuerst" Lösung 5 T onn en 3 T o n n en 8 T o n n en 3 T onnen 5 T o nn e n 8 Tonnen 3 T o nnen 4 T onnen 4 To nn en 5 T o n n en 3 T o n n en 5 T o nnen E in e L ösu ng de s K aste np rob lem s m a x im ale La du n g G = 1 4 T o n ne n N ac hd em ein La stzu g m it d em A lg o rithm u s "Sch w erste K ä sten z ue rs t" be la de n w urde , m üssen d ie verbleib en d en K ästen n ich t u nb ed ing t auf de n nä ch sten W a gen pa ssen . Führt nicht in allen Fällen zu einer Lösung! Beachte: Viele Probleme der Informatik sind analog zum binpacking problem, z.B. das Laden von n Programmen unterschiedlicher Größe in den Speicher von T parallelen Prozessoren. Praktische Informatik I © Prof. Dr. W. Effelsberg 5. Theorie der Algorithmen 5-43 Praktische Informatik I © Prof. Dr. W. Effelsberg 5. Theorie der Algorithmen 5-44 Beispiel 2: Travelling Salesman Beispiel 3: Hamilton-Zyklus Gegeben ein Straßennetz zwischen n Städten mit Entfernungen. Kann ein Handelsreisender mit Kilometerbeschränkung eine Rundreise machen, bei der er jede Stadt genau einmal besucht? Gegeben ist ein Straßennetz als Graph. Gibt es eine Rundreise, bei der jede Stadt genau einmal besucht wird? K no te n b ed euten S tä d te, L in ien b ed euten Stra ß en. D er ein fach e Fa ll e in es H a m ilto n -Z yk lus Die Lösung heißt Hamilton-Zyklus. Es ist kein Algorithmus mit polynomialem Aufwand bekannt! Praktische Informatik I © Prof. Dr. W. Effelsberg 5. Theorie der Algorithmen 5-45 Praktische Informatik I © Prof. Dr. W. Effelsberg 5. Theorie der Algorithmen 5-46 Lösung zum Beispiel-Graphen Beispiel 4: Stundenplanproblem Gegeben eine Liste von Fächern, zu unterrichtende Schüler und ein Lehrplan (Anzahl der Stunden in jedem Fach in jedem Schuljahr). Gibt es einen Stundenplan, bei dem kein Schüler eine Freistunde hat? Es ist kein Algorithmus mit polynomialem Aufwand bekannt! Ansätze in der Praxis • Suche Näherungslösung statt perfekter Lösung ( z. B. Stundenplan mit kleinen Lücken) • Suche Algorithmus, der für durchschnittliche Einga- befälle schnell arbeitet, selbst wenn der ungünstigste Fall exponentiell bleibt E in e Lö su n g z u d en H a m ilto n -Z yk len Praktische Informatik I © Prof. Dr. W. Effelsberg 5. Theorie der Algorithmen 5-47 Praktische Informatik I © Prof. Dr. W. Effelsberg 5. Theorie der Algorithmen 5-48 NP-Vollständigkeit 5.2.4 Die Klassen P und NP Alle Probleme, die mit polynomialem Aufwand berechnet werden können, für die es also einen Algorithmus gibt, der durch ein Polynom nach oben beschränkt ist, bilden die Klasse P. (Wie schon erwähnt, bedeutet das nicht immer, dass die Berechnung praktikabel ist, denn das Polynom kann sehr groß sein!) Ein Problem heißt NP-vollständig (NP-complete), wenn gilt: Wenn es für dieses Problem einen polynomialen Algorithmus gibt, dann gibt es für alle Probleme in NP einen polynomialen Algorithmus. NP-vollständige Probleme sind die "schwersten" Probleme in NP. Alle Probleme, zu denen eine (wie auch immer ermittelte) gegebene Lösung in polynomialer Zeit verifiziert (als korrekt bewiesen) werden kann, bilden die Klasse NP. Die Beispiele 1 bis 4 (bin-packing, travelling salesman, Hamilton-Zyklus, Stundenplan) sind NP-vollständig. Die Klasse P ist in der Klasse NP enthalten. Viele Informatiker glauben, dass P ≠ NP ist, dass also P eine echte Teilmenge von NP ist. Die vorangegangenen vier Beispiele sind alle in NP (eine wie auch immer ermittelte Lösung ist mit polynomialem Aufwand verifizierbar). Man weiß bis heute nicht, ob es Probleme gibt, die in NP, aber nicht in P sind! Praktische Informatik I © Prof. Dr. W. Effelsberg 5. Theorie der Algorithmen 5-49 Praktische Informatik I © Prof. Dr. W. Effelsberg 5. Theorie der Algorithmen 5-50 Zusammenfassung Komplexität (1) Zusammenfassung Komplexität (2) P ro ble m P in N P (vorge sch lag ene Lö su ng p olyno m ia l verifiz ierb ar) nic ht in N P NP NPv o lls tä nd ig ex p o n en tie ll? p olyno m ia l (z.B . Sortieren) e x p o n en tiell ex p on en tie ll! P Praktische Informatik I © Prof. Dr. W. Effelsberg ? = N P -vo llstä nd ig (w en n p olyn o m ia le L ö sun g fü r d ieses P ro b le m e x istie rt, d an n h ab en a lle P ro b le m e in N P ein e p olyn o m ia le L ö su n g ) NP 5. Theorie der Algorithmen nich t N P -vo lls tä nd ig z.B . b in p ac kin g tim e ta ble 5-51 Praktische Informatik I © Prof. Dr. W. Effelsberg 5. Theorie der Algorithmen 5-52 5.3 Korrektheit: Test und Verifikation von Programmen 5.3.1 Testen Als Testen (engl.: debugging) bezeichnet man die Ausführung eines Programms für eine Menge von Testdaten. Korrektheit bedeutet, dass ein Algorithmus oder ein Programm das in der Spezifikation beschriebene Problem für beliebige Eingabedaten korrekt löst. Die Menge der Testdaten ist endlich und in fast allen praktischen Fällen sehr viel kleiner als die Menge der möglichen Eingabedaten. Deshalb kann Testen nur das Vertrauen in die Korrektheit eines Programms erhöhen, nicht aber die Korrektheit beweisen! Die Korrektheit kann immer nur in Bezug auf eine Spezifikation gezeigt werden! Definitionen 1. Ein Programm terminiert, wenn es für alle Eingaben letztendlich anhält. 2. Ein Programm ist partiell korrekt, wenn das Ergebnis im Falle des Terminierens immer korrekt ist. In der Praxis erweist sich die Auswahl einer angemessenen Testdatenmenge als sehr schwierig. Ebenso schwierig ist die Analyse der Überdeckung eines Programms durch gegebene Testdaten. Hierzu hat man im Software Engineering Hilfsmittel entwickelt. 3. Ein Programm ist total korrekt, wenn es terminiert und partiell korrekt ist. 4. Zwei Techniken zum Prüfen der Korrektheit • Testen • Verifikation (formaler Beweis der Korrektheit) Praktische Informatik I © Prof. Dr. W. Effelsberg 5. Theorie der Algorithmen 5-53 Praktische Informatik I © Prof. Dr. W. Effelsberg 5. Theorie der Algorithmen 5-54 Ablauf des Testens Beispiel für Testen Es ist ein Programm zu schreiben, das zwei ganze Zahlen multipliziert. Als Operationen sollen nur Addition, Subtraktion, Multiplikation mit 2 und Division durch 2 zulässig sein. Ü berdec k ung 100% 70% E nde des T es tens Praktische Informatik I © Prof. Dr. W. Effelsberg 1 public int mult(int x1, int y1) { 2 int x, y, z; 3 z = 0; 4 if ((x1 > 0) && (y1 > 0)) { 5 x = x1; 6 y = y1; 7 while (x != 0) { 8 if (x % 2 == 1) 9 z = z + y; 10 y = 2 * y; 11 x = x/2; 12 } // while 13 } // if 14 return z; 15 } T es taufw and 5. Theorie der Algorithmen 5-55 Praktische Informatik I © Prof. Dr. W. Effelsberg 5. Theorie der Algorithmen 5-56 Erster Ansatz: Testen als Schwarzer Kasten Zweiter Ansatz: Testen als Weißer Kasten (eng: black box testing) (eng: white box testing) Testen für alle x1, y1 < 1012 ohne Kenntnis der Programmstruktur. Testen unter Kenntnis der Programmstruktur. Auswahl der Testdaten so, dass eine möglichst gute Überdekkung des Programmcodes erreicht wird. Ergibt 1012*1012 = 1024 Testfälle! Anweisungstest Bei 1ms pro Ausführung ca. 3*1013 Jahre Rechenzeit! Auswahl der Testdaten so, dass jede Anweisung im Programm mindestens einmal ausgeführt wird. Fazit Vorteil: unnötige Anweisungen werden entdeckt (solche, die durch keinen Testdatenfall erreicht werden können). Es sind nur relativ wenige Testfälle nötig. Es kann selbst beim Testen mit Zufallszahlen nur ein sehr kleiner Prozentsatz der möglichen Eingabedaten getestet werden. Nachteil: Viele wichtige Fälle werden überhaupt nicht getestet. Beispiel if (b) a; Wenn die Bedingung b erfüllt ist, wird die Anweisung a ausgeführt. Damit ist sowohl die if-Anweisung als auch a einmal durchlaufen worden. Der Fall "b == false" wird nicht getestet! Praktische Informatik I © Prof. Dr. W. Effelsberg 5. Theorie der Algorithmen 5-57 Praktische Informatik I © Prof. Dr. W. Effelsberg 5. Theorie der Algorithmen 5-58 Verzweigungstest Beispiel für den Verzweigungstest (1) Gegeben sei das Flussdiagramm des Programms. Dann werden die Testdaten so ausgewählt, dass jede Verzweigung (Verbindungslinie zwischen Kästchen) mindestens einmal durchlaufen wird. if (b1) a1; else a2; if (b2) a3; else a4; tr ue Vorteil: bessere Überdeckung als mit dem Anweisungstest. fa lse b 1? Nachteil: erfasst immer noch nicht alle relevanten Fälle. a1 a2 fa lse tr u e b2? a3 Praktische Informatik I © Prof. Dr. W. Effelsberg 5. Theorie der Algorithmen 5-59 a4 Praktische Informatik I © Prof. Dr. W. Effelsberg 5. Theorie der Algorithmen 5-60 Beispiel für den Verzweigungstest (2) Wegetest Es gibt vier mögliche Anweisungsfolgen für a1 bis a4: a1;a3 a1;a4 a2;a3 a2;a4 Im Wegetest werden alle möglichen Ablauffolgen von Anweisungen mindestens einmal durchlaufen. Für das Beispiel mult sehen wir: Gilt nun für alle Testdatenfälle, dass sie entweder die Kombination b1 true und b2 false oder b1 false und b2 true enthalten, so sind die Anforderungen an den Verzweigungstest erfüllt (alle Pfade im Flußdiagramm werden mindestens einmal durchlaufen), aber die Ablauffolgen a1;a3 a2;a4 werden nicht getestet. ≤ 0 beliebig 1 beliebig ≤0 ≥1 2 ≥ 1 3 ≥ 1 x1 y1 durchlaufene Anweisungen 3, 4, 14 3, 4, 14 3, 4, 5, 6, 7, 8, 9, 10, 11, 14 3, 4, 5, 6, 7, 8, 10, 11, 7, 8, 9, 10, 11, 7,14 ... Es gibt zu viele mögliche Ablauffolgen wegen der Schleife! Reduktion in der Praxis a) Schleife 0-mal durchlaufen b) Schleife 1-mal durchlaufen c) Schleife k-mal durchlaufen, k ≥ 2, fest. Praktische Informatik I © Prof. Dr. W. Effelsberg 5. Theorie der Algorithmen 5-61 Praktische Informatik I © Prof. Dr. W. Effelsberg 5. Theorie der Algorithmen 5-62 Suche nach typischen Fehlern Code-Inspektion (Code Review) Mit etwas Erfahrung stellt man fest, dass Programmierer immer wieder Fehler machen. Man entwirft daher die Testdaten so, dass sie nach diesen typischen Fehlern suchen. Programmcode kann nicht nur durch den Rechner, sondern auch durch den Programmierer getestet werden. Ein in der Praxis häufig eingesetztes und erstaunlich wirksames Verfahren ist die Code-Inspektion (code review, "Schreibtischtest"). Dabei wird der Programmcode eines Programmierers von einem anderen Programmierer auf mögliche Fehler untersucht. Beispiele • Feldindex außerhalb der Grenzen des Feldes (arrays) Diese Methode erzieht zugleich zur strukturierten Programmierung und zur Dokumentation im Code (durch Kommentare). • Anzahl der Schleifendurchgänge +/- 1 • Namenskollision zwischen lokalen und globalen Va- riablen und Parametern • Rundungsfehler bei Gleitkommaoperationen Durch Testen können auch Compilerfehler oder Fehler in den Laufzeitroutinen gefunden werden (im Gegensatz zur Verifikation!). Praktische Informatik I © Prof. Dr. W. Effelsberg 5. Theorie der Algorithmen 5-63 Praktische Informatik I © Prof. Dr. W. Effelsberg 5. Theorie der Algorithmen 5-64 Beweis für das Terminieren 5.3.2 Verifikation Unter Verifikation versteht man den formalen Beweis der Korrektheit eines Programms durch mathematische Methoden. Dazu muss bewiesen werden, dass das Programm für beliebige Eingabedaten terminiert und jeweils korrekte Ergebnisse liefert. • Programme ohne Schleifen terminieren immer. • Für Schleifen gilt: Durch mindestens eine Anweisung im Rumpf der Schleife muss eine Variable derart verändert werden, dass nach einer endlichen Anzahl von Durchläufen die Endebedingung erfüllt ist. Beweistechnik 5. Man suche einen Ausdruck A mit Variablen aus der Schleifenbedingung, dessen Werte in einer endlichen geordneten Menge M liegen ( z.B. in einem endlichen Intervall aus den ganzen Zahlen). 6. Man zeige, dass A bei jedem Schleifendurchgang streng monoton wächst (oder abnimmt). Praktische Informatik I © Prof. Dr. W. Effelsberg 5. Theorie der Algorithmen 5-65 Praktische Informatik I © Prof. Dr. W. Effelsberg 5. Theorie der Algorithmen 5-66 Beispiel für einen Beweis des Terminierens Terminierung rekursiver Algorithmen In Zählschleifen ist die Zählvariable der Ausdruck A. Ähnlich wie Terminierung der Schleifen Anderes Beispiel Beispiel Für die while-Schleife im Algorithmus mult gilt: 1. 0 ≤ x ≤ x1 2. Die Anweisung x=x/2 läßt x in jedem Durchlauf monoton abnehmen. Die Variable x wird also mit Sicherheit den Wert 0 erreichen und damit die Schleife terminieren lassen. public int fakultaet (int k) { if ( k == 0) return 1; else return (k * fakultaet (k - 1)); } Ähnlich kann man das Terminieren von rekursiven Prozeduren oder Funktionen beweisen. A ist hier k, der Wert nimmt monoton ab, untere Grenze ist 0. Schwieriger zu zeigen bei indirekter Rekursion: A ruft B, B ruft A Praktische Informatik I © Prof. Dr. W. Effelsberg 5. Theorie der Algorithmen 5-67 Praktische Informatik I © Prof. Dr. W. Effelsberg 5. Theorie der Algorithmen 5-68 Beweis der Korrektheit von Programmstücken Der formale Beweis der Korrektheit eines vollständigen Programms für alle möglichen Eingabedaten ist in der Praxis meist sehr schwierig oder unmöglich. Man kann aber manchmal die Korrektheit von wichtigen Programmstücken, insbesondere Schleifen, beweisen. Beweis durch Induktion Analog zur Mathematik beweist man: 1. Die Berechnungen in der Schleife sind beim ersten Durchlauf korrekt. 2. Angenommen sie sind beim n-ten Durchlauf korrekt, dann sind sie auch beim n+1-ten Durchlauf korrekt. Praktische Informatik I © Prof. Dr. W. Effelsberg 5. Theorie der Algorithmen 5-69 Beispiel für Korrektheitsbeweis einer Schleife durch Induktion (1) public long potenziere(int x) { // gibt 2x zurück, wobei x als nicht-negative // Ganzzahl angenommen wird int i; long summe; summe = 1; for (i = 0; i < x; i++) { summe += summe; // *** } return summe; } Praktische Informatik I © Prof. Dr. W. Effelsberg 5. Theorie der Algorithmen 5-70 Beispiel für Korrektheitsbeweis einer Schleife durch Induktion (2) Zusicherungen (assertions) 1. Das erste Mal, wenn *** erreicht wird, ist summe = 2n (also 21) 2. Nehmen wir an, dass *** zum n-ten Male erreicht wird, dann ist summe = 2n. Beim (n + 1)-ten Male, ist dann summe = 2n + 2n = 2n+1. 3. Deshalb gilt für jedes n, dass summe = 2n ist, sobald *** zum n-ten Male erreicht wird. 4. Wird die return- Anweisung je erreicht, dann gibt es zwei Möglichkeiten. Entweder wurde die Schleife nicht durchlaufen, so dass in diesem Fall x = 0 ist und deshalb der Anfangswert von summe nicht geändert wird. Dann ist summe = 1, was gleichbedeutend mit 20 ist. Oder die Scheife wurde durchlaufen, so dass in diesem Falle die mit *** markierte Stelle xmal erreicht wurde. Somit ist summe = 2x. Beim Beweisen (Verifizieren) von Programmstücken muss man sich klarmachen, welche Voraussetzungen an einer bestimmten Programmstelle gelten. Zusicherungen (assertions) sind logische Ausdrücke über Programmvariablen. Sie beschreiben, welche logischen Annahmen an einer bestimmten Stelle im Programm gemacht werden können. Gegeben sei folgende Situation: ... assertion1; statement1; statement2; statement3; assertion2; ... Wenn es nun gelingt, unter der Annahme von assertion1 und unter Verwendung der statements den Ausdruck assertion2 herzuleiten, hat man die Korrektheit des Programmstücks formal bewiesen. Es wird also wird also auf jeden Fall 2x ausgegeben, sofern nur die Ausgabeanweisung erreicht wird. assertion1 heißt auch pre-condition, assertion2 heißt post-condition. Praktische Informatik I © Prof. Dr. W. Effelsberg 5. Theorie der Algorithmen 5-71 Praktische Informatik I © Prof. Dr. W. Effelsberg 5. Theorie der Algorithmen 5-72 Algorithmische Ableitungsregeln Zerlegung in Unteralgorithmen Gilt die Aussage P vor Ausführung von Algorithmus A und beschreibt die Aussage Q die funktionale Abhängigkeit der Ausgabegrößen von den Eingabegrößen, so kann aus der Gültigkeit von P und der Ausführung von A die Gültigkeit von Q nach der Ausführung abgeleitet werden. Ist eine Zerlegung von A in Unteralgorithmen A 1,...,An gegeben, für die jeweils [Pi ]Ai [Qi ], 1 ≤ i ≤ n gilt, so muss P → P1 , Qn → Q, Qi −1 → Pi , 1 % i ≤ n gelten. Wenn darüberhinaus alle Ai terminieren, ist A (total) korrekt. In Zeichen: [P] A [Q]. [P] A [Q] bedeutet nichts anderes als [P ]∧ A → [Q ] (logische Implikation) Praktische Informatik I © Prof. Dr. W. Effelsberg 5. Theorie der Algorithmen 5-73 Praktische Informatik I © Prof. Dr. W. Effelsberg 5. Theorie der Algorithmen 5-74 Beweis des Terminierens der Zerlegung Ableitungsregel für die if-Anweisung Zunächst macht man die Induktionsannahme, dass alle Unteralgorithmen terminieren. Dann zeige man, dass die Zerlegung terminiert, d.h. keine unendliche Schleife eintritt, und schließlich, dass bei der Zusammensetzung der Unteralgorithmen nur endlich viele Wiederholungen möglich sind. Dann wendet man die Regel auf die nichtelementaren Unteralgorithmen an. [P] if (B) else [Q] A1 A2 Ableitungsregel Aus [P ∧ B] A1 [Q] und [P ∧ ¬ B] A2 [Q] folgt ---------------------------------------[P] if (B) A1 else A2 [Q] Praktische Informatik I © Prof. Dr. W. Effelsberg 5. Theorie der Algorithmen 5-75 Praktische Informatik I © Prof. Dr. W. Effelsberg 5. Theorie der Algorithmen 5-76 Ableitungsregeln für Schleifen Ableitungsregel für die while - Schleife Schleifeninvariante Eine Schleifeninvariante ist ein logischer Ausdruck, der sich von Durchlauf zu Durchlauf der Schleife nicht ändert. Die Schleifeninvariante ist somit auch nach dem letzten Durchlauf, beim Schleifenende, gültig und kann deshalb zum Beweis der Korrektheit der Schleife herangezogen werden. Aus [P ∧ B] A [P] folgt[P] while (B) A [P ∧ ¬ B] P ist die Schleifeninvariante. P muss sich auf Variable aus dem Schleifenrumpf A beziehen. Die Gültigkeit von ¬ B beim Schleifenende ist wichtig für den Beweis der Korrektheit! while (B) A; P nein B ? ja P P ∧ B P ∧ NOT B A Praktische Informatik I © Prof. Dr. W. Effelsberg 5. Theorie der Algorithmen 5-77 Praktische Informatik I © Prof. Dr. W. Effelsberg 5. Theorie der Algorithmen 5-78 Beispiel für eine Schleifeninvariante Verfication is a social process Berechnung der Summe der ersten n Zahlen • Das Überzeugen durch einen Beweis in der Mathema- tik oder genauso auch eine Programmverifikation ist ein sozialer Prozess. public int summe(int n) { int i,s; s = 0; i = 0; while (i < n) { i++; s += i; // *** } return s; } • Verifikationen sind oft lang und schwer lesbar. • Die Spezifikation ist selbst informal; der Schritt vom Informalen zum Formalen ist niemals verifizierbar! • Die Spezifikation ist außerdem oft sehr umfangreich (z.B. für “Einkommensteuerberechnung”, “Betriebssystem”, “Compiler”) und in der Regel nicht vollständig. • Programme interagieren mit der realen (informalen) Umwelt, zum Beispiel mit I/O-Treibern, Benutzerschnittstellen, A/D-Wandlern usw., die nicht verifizierbar sind. An der Stelle *** gilt die Schleifeninvariante P summe = 0+1+2+3+...+i bei jedem i-ten Durchlauf der Schleife. Mit der Endebedingung der Schleife ¬ (i < n) ist wegen des monotonen Wachstums von i dann i = n. Somit gilt: summe = 0+1+2+3+...+n Die Schleife ist also korrekt. Praktische Informatik I © Prof. Dr. W. Effelsberg 5. Theorie der Algorithmen 5-79 Praktische Informatik I © Prof. Dr. W. Effelsberg 5. Theorie der Algorithmen 5-80