Rekursive Auswertungsprozesse in Haskell Auswertungsprozess, der durch eine rekursive Funktion bewirkt wird Beispiel: Auswertung der rekursiven Fakultätsfunktion 0! := 1 n! := n ∗ (n − 1)! fakultaet x P raktische Inf ormatik 1, W S = if x <= 1 then 1 else x*(fakultaet (x-1)) 2004/05, F olien Haskell−2, (12. N ovember2004) Seite 1 Auswertungsprozess, linear rekursiv bei verzögerter Auswertung (Nicht jeder Zwischenzustand ist angegeben) (fakultaet 6) (6 * (fakultaet (6-1))) (6 * (5 * (fakultaet (5-1)))) (6 * (5 * (4 * (fakultaet (4-1))))) (6 * (5 * (4 * (3 * (fakultaet (3-1)))))) (6 * (5 * (4 * (3 * (2 * (fakultaet (2-1))))))) (6 * (5 * (4 * (3 * (2 * 1))))) (6 * (5 * (4 * (3 * 2)))) (6 * (5 * (4 * 6))) (6 * (5 * 24)) (6 * 120) 720 P raktische Inf ormatik 1, W S 2004/05, F olien Haskell−2, (12. N ovember2004) Seite 2 Auswertungsprozess, linear rekursiv (fakultaet 6) Auswertungsprozess ist linear rekursiv Charakteristisch: P raktische Inf ormatik 1, W S nur eine rekursive Funktionsanwendung in jedem Ausdruck der Reduktionsfolge Zwischenausdrücke sind unbeschränkt in der Größe 2004/05, F olien Haskell−2, (12. N ovember2004) Seite 3 Applikative Funktionen Eine Funktion ist applikativ, wenn zuerst die Argumente ausgewertet werden, dann der (eigentliche) Rumpf der Funktion Eine Funktion nennt man strikt, wenn die Argumente auf jeden Fall ausgewertet werden, der Zeitpunkt jedoch nicht festgelegt ist. applikativ ⇒ strikt Wenn f applikativ die applikative Variante von f, dann gilt i.a: f und f applikativ sind semantisch verschieden P raktische Inf ormatik 1, W S 2004/05, F olien Haskell−2, (12. N ovember2004) Seite 4 Alternative Berechnungen der Fakultätsfunktion Iteriere folgende Regel: Produkt Zähler ⇒ ⇒ Produkt ∗ Zähler Zähler + 1 Programm: fakultaet_iter n = fakt_iter 1 1 n fakt_iter produkt zaehler max = if zaehler > max then produkt else fakt_iter (zaehler * produkt) (zaehler + 1) max fakt_iter_strikt produkt zaehler max = strikt_3 produkt zaehler max (if zaehler > max then produkt else fakt_iter_strikt (zaehler * produkt) (zaehler + 1) max) fakultaet_lin n = fakt_iter_strikt 1 1 n P raktische Inf ormatik 1, W S 2004/05, F olien Haskell−2, (12. N ovember2004) Seite 5 Endrekursion Eine Endrekursion ist eine lineare Rekursion. Zusätzlich muss gelten: alle rekursiven Aufrufe berechnen den Rückgabewert ohne Nachverarbeitung P raktische Inf ormatik 1, W S 2004/05, F olien Haskell−2, (12. N ovember2004) Seite 6 Auswertungsprozess, endrekursiv Auswertung von (fakultaet_iter 5) bei verzögerter Auswertung (fakultaet_iter 5) (fakt_iter 1 1 5) (fakt_iter (1*1) (1+1) 5) (fakt_iter (2*(1*1)) (2+1) 5) (fakt_iter (3*(2*(1*1))) (3+1) 5) (fakt_iter (4*(3*(2*(1*1)))) (4+1) 5) (fakt_iter (5*(4*(3*(2*(1*1))))) (5+1) 5) (5*(4*(3*(2*(1*1))))) 120 Das ist eine lineare Rekursion, es ist auch eine Endrekursion Auswertungsprozess zu fakultaet 6 nicht endrekursiv, da fakultaet (...) eingebettet in weitere Berechnung. P raktische Inf ormatik 1, W S 2004/05, F olien Haskell−2, (12. N ovember2004) Seite 7 Iterativer Auswertungsprozess: Fakultät (2) Iterativer Auswertungsprozess: (fakultaet_lin 6) (fakt_iter_strikt (fakt_iter_strikt (fakt_iter_strikt (fakt_iter_strikt (fakt_iter_strikt (fakt_iter_strikt (fakt_iter_strikt 720 1 1 6) 1 2 6) 2 3 6) 6 4 6) 24 5 6) 120 6 6) 720 7 6) Iterativer Prozess: Charakteristisch: P raktische Inf ormatik 1, W S Ist eine Endrekursion Argumente sind Basiswerte (bzw. Größe des Gesamtausdrucks bleibt beschränkt.) optimierte Rückgabe des Wertes 2004/05, F olien Haskell−2, (12. N ovember2004) Seite 8 Optimierung der Endrekursion imperative Programmiersprachen Endrekursion i.a. nicht optimiert. d.h. Wert wird durch alle Stufen der Rekursion zurückgegeben Endrekursion ist optimiert am Ende wird Wert unmittelbar zurückgegeben. Haskell Deshalb: Iterationskonstrukte in imperativen Programmiersprachen: for ...do, while, oder repeat ...until. P raktische Inf ormatik 1, W S 2004/05, F olien Haskell−2, (12. N ovember2004) Seite 9 Iteration in Haskell In Haskell: Iterative Auswertungsprozesse nur mittels guter Programmierung Naive Implementierung, verzögerte Reihenfolge der Auswertung tendieren zu: linear rekursiven, nicht endrekursiven bzw. nicht iterativen Prozessen. Vergleich: Iterativ gegen linear rekursiv: Anzahl Auswertungsschritte bleibt i.a. gleich Größe der Zwischenausdrücke ist kleiner P raktische Inf ormatik 1, W S 2004/05, F olien Haskell−2, (12. N ovember2004) Seite 10 Baumrekursion Beispiel Berechnung der Fibonacci-Zahlen 1, 1, 2, 3, 5, 8, 13, 21, . . . F ib(n) := 0 1 F ib(n − 1) + F ib(n − 2) fib n = if n <= 0 then 0 else if n == 1 then 1 else fib (n-1) + fib(n-2) P raktische Inf ormatik 1, W S 2004/05, F olien Haskell−2, (12. N ovember2004) Seite 11 falls n = 0 falls n = 1 sonst Auswertungsprozess zu fib fibs: applikative Variante von fib Der Auswertungs-Prozess ergibt folgende Zwischen-Ausdrücke: fibs 5 fibs 4 + fibs 3 (fibs 3 + fibs 2) + fibs 3 ((fibs 2 + fibs 1) + fibs 2) + fibs 3 (((fibs 1 + fib 0) + fibs 1) + fibs 2) (((1+0) + fibs 1) + fibs 2) + fibs 3 ((1 + fibs 1) + fibs 2) + fibs 3 ((1+1) + fibs 2) + fibs 3 (2 + fibs 2) + fibs 3 (2 + (fibs 1 + fibs 0)) + fibs 3 ....... P raktische Inf ormatik 1, W S 2004/05, F olien Haskell−2, (12. N ovember2004) Seite 12 + fibs 3 Auswertungsprozess zu fibs: Baum der Aufrufe 5 4 3 3 2 1 2 1 1 2 0 1 1 0 0 Das ist Baumrekursion Charakteristisch: Ausdrücke in der Reduktionsfolge • können unbegrenzt wachsen • enthalten mehrere rekursive Aufrufe • Aber: nicht geschachtelt (d.h. die Argumente eines rekursiven Aufrufs enthalten keine rekursiven Aufrufe) P raktische Inf ormatik 1, W S 2004/05, F olien Haskell−2, (12. N ovember2004) Seite 13 Geschachtelte Rekursion Ist der allgemeine Fall wird normalerweise selten benötigt, da i.a. nicht effizient berechenbar. Beispiel: Die Ackermannfunktion ----ack 0 ack 1 ack x ack x Ackermanns Funktion y = 0 = 0 | x >= 2 = y | x > 0 && y > 0 = ---1 2 x+2 ack (ack (x-1) y) (y-1) Vorstellung neuer syntaktischer Möglichkeiten in Haskell: Auswertung: von oben nach unten wird probiert, welche Definitionsgleichung passt: 1) Argumente anpassen 2) Bedingung rechts vom | prüfen P raktische Inf ormatik 1, W S 2004/05, F olien Haskell−2, (12. N ovember2004) Seite 14 Optimierte Ackermannfunktion ----ackopt ackopt ackopt ackopt ackopt ackopt Ackermanns Funktion optimiert ---0 y = 1 1 0 = 2 x 0 = x+2 x 1 = 2*x x 2 = 2^x x y | x > 0 && y > 0 = ackopt (ackopt (x-1) y) (y-1) *Main> logI10 (ackopt 5 3) 19728.301029995662 • • • --(Anzahl DezimalStellen) -- ( == 2^65536) sehr schnell wachsende Funktion man kann nachweisen: ack nicht primitiv rekursiv hat Anwendung in der Komplexitätstheorie P raktische Inf ormatik 1, W S 2004/05, F olien Haskell−2, (12. N ovember2004) Seite 15 Tabelle der Rekursionsprozesse: linear rekursiv endrekursiv iterativ Baumrekursion geschachtelte Baumrekursion P raktische Inf ormatik 1, W S maximal ein rekursiver Unterausdruck linear rekursiv und Gesamtresultat ist Wert des rekursiven Unterausdrucks endrekursiv und Argumente sind Basiswerte mehrere rekursive Unterausdruck, Argument des rekursiven Ausdrucks ohne weitere Rekursion mehrere rekursive Unterausdrücke auch in den Argumenten 2004/05, F olien Haskell−2, (12. N ovember2004) Seite 16 Optimierung: Iteration statt Rekursion Beispiel Berechnung von (fib fib 3 wird fib 2 wird fib 1 wird 5) 2 mal berechnet 3 mal berechnet 5 mal berechnet Genauer: Bei Berechnung von fib n für n ≥ 2 wird fib(1) jeweils (fib n)-mal berechnet √ Φn fib n ≈ √ Fazit: 5 wobei Φ = 1+2 5 ≈ 1.6180 fib(n) wächst exponentiell # Reduktionen für fib(n) ist exponentiell d.h. die Laufzeit von fib ist exponentiell P raktische Inf ormatik 1, W S 2004/05, F olien Haskell−2, (12. N ovember2004) Seite 17 Iterative Version von Fib Beobachtung: zur Berechnung von fib(n) benötigt man nur die Werte fib(i) für 1 ≤ i ≤ n. Idee: Berechnung einer Wertetabelle für fib. Verbesserte Variante: aus fib (n − 1) und fib (n − 2) berechne fib(n) Ohne Doppelberechnung Rechenvorschrift: (a, b) → (a + b, a) P raktische Inf ormatik 1, W S 2004/05, F olien Haskell−2, (12. N ovember2004) Seite 18 Iterative Version von fib: Funktionen fib_lin n = fib_iter a b zaehler = (fib_iter_strikt 1 0 n) if zaehler <= 0 then b else fib_iter (a + b) a (zaehler - 1) fib_iter_strikt a b zaehler = strikt_3 a b zaehler (if zaehler <= 0 then b else fib_iter_strikt (a + b) a (zaehler - 1)) P raktische Inf ormatik 1, W S 2004/05, F olien Haskell−2, (12. N ovember2004) Seite 19 Prozess für (fib lin 5) (fib_lin 5) (fib_iter_strikt (fib_iter_strikt (fib_iter_strikt (fib_iter_strikt (fib_iter_strikt 5 P raktische Inf ormatik 1, W S 1 1 2 3 5 0 1 1 2 3 2004/05, F olien Haskell−2, 5) 4) 3) 2) 1) (12. N ovember2004) Seite 20 Analyse der fib-Optimierung Für (fib_lin n) gilt: • ist operational äquivalent zu fib • benötigt linear viele Reduktionen abhängig von n • Größe der Ausdrücke ist beschränkt • Platzbedarf ist konstant (d.h. unabhängig) von n. (unter Vernachlässigung der Darstellungsgröße der Zahlen) erzeugt Iterativen Auswertungsprozess P raktische Inf ormatik 1, W S 2004/05, F olien Haskell−2, (12. N ovember2004) Seite 21 Terminierung: Hält ein Programm an? ((3n + 1)-Funktion) drein x = if x == 1 then 1 else if geradeq x then drein (x ‘div‘ 2) else drein (3*x+1) geradeq n = (rem n 2) == 0 Collatz Vermutung: diese Funktion hält an für jede positive natürliche Zahl als Eingabe P raktische Inf ormatik 1, W S 2004/05, F olien Haskell−2, (12. N ovember2004) Seite 22 Beispielausführungen von drein Zum Experimentieren verwende dreinlst. für 5: 5, 16, 8, 4, 2, 1 für 27: 27, 82, 41, 124, 62, 31, 94, 47, 142, 71, 214, 107, 322, 161, 484, 242, 121, 364, 182, 91, 274, 137, 412, 206, 103, 310, 155, 466, 233, 700, 350, 175, 526, 263, 790, 395, 1186, 593, 1780, 890, 445, 1336, 668, 334, 167, 502, 251, 754, 377, 1132, 566, 283, 850, 425, 1276, 638, 319, 958, 479, 1438, 719, 2158, 1079, 3238, 1619, 4858, 2429, 7288, 3644, 1822, 911, 2734, 1367, 4102, 2051, 6154, 3077, 9232, 4616, 2308, 1154, 577, 1732, 866, 433, 1300, 650, 325, 976, 488, 244, 122, 61, 184, 92, 46, 23, 70, 35, 106, 53, 160, 80, 40, 20, 10, 5, 16, 8, 4, 2, 1 Die Terminierung dieser Funktion drein wurde geprüft für alle Zahlen < 240 P raktische Inf ormatik 1, W S 2004/05, F olien Haskell−2, (12. N ovember2004) Seite 23 Terminierung Die Theorie zeigt: Programmiersprachen, die Programme ausschließen, die manchmal nicht terminieren sind nicht allgemein. D.h. nicht äquivalent zur Turingmaschine P raktische Inf ormatik 1, W S 2004/05, F olien Haskell−2, (12. N ovember2004) Seite 24 Terminierungsnachweise Normalerweise mit vollständiger Induktion bzw. Mit Induktion zu einer fundierten Ordnung. Beispiel: fib n = if n <= 0 then 0 else if n == 1 then 1 else fib (n-1) + fib(n-2) Beh: fib(n) terminiert mit einer ganzen Zahl für n ∈ IN0: Induktionsbasis ist 0 und 1: fib 0 und fib 1 terminieren und ergeben Resultat 0 bzw. 1. P raktische Inf ormatik 1, W S 2004/05, F olien Haskell−2, (12. N ovember2004) Seite 25 Terminierungsnachweis (2) Induktionsschritt: Für n > 1 gilt: fib n reduziert zu fib (n − 1) + fib (n − 2). Induktionshypothese gilt für n − 1 und n − 2, also terminiert fib n. Insgesamt ist damit die Terminierung gezeigt. QED Ungelöst: Die einfachen Ansätze zum Terminierungsbeweis für die 3n + 1-Funktion scheitern, da die Argumente unregelmäßig größer und kleiner werden. P raktische Inf ormatik 1, W S 2004/05, F olien Haskell−2, (12. N ovember2004) Seite 26 Ressourcenbedarf von Programmen, Effizienz, Wachstumsraten und Größenordnungen wichtige Ressourcen: • Zeit • Platz P raktische Inf ormatik 1, W S 2004/05, F olien Haskell−2, (12. N ovember2004) Seite 27 Weitere Ressourcen / Maße: • Anzahl benötigter Prozessoren bei parallelen Algorithmen • Größe des Programms • Kosten für die Kommunikation • Anzahl der Aufrufe bestimmter Unterprozeduren (Dienste): Datenbankzugriffe, usw. P raktische Inf ormatik 1, W S 2004/05, F olien Haskell−2, (12. N ovember2004) Seite 28 Weitere Ressourcen / Maße (2) Man kann auch noch betrachten: • • • • • Aufwand zur Erstellung des Programms organisatorischer Aufwand zur Nutzung Aufwand zum Portieren eines Programms in andere (Rechner-)umgebungen. Aufwand für Verifikation / Änderung eines Programms Kosten innerhalb eines organisatorischen Rahmens P raktische Inf ormatik 1, W S 2004/05, F olien Haskell−2, (12. N ovember2004) Seite 29 Optimierung Optimierung := Reduktion des Ressourcenbedarf von Programmen durch Abänderungen des Programms ohne Funktionalitätsänderung. Es gibt verschiedene Prioritäten bei Optimierung: Wettervorhersage Simulationen: Anwendung mit Datenübertragung: Java: P raktische Inf ormatik 1, W S 2004/05, F olien Haskell−2, (12. N ovember2004) Seite 30 Zeit Kommunikation Kommunikation,Portierbarkeit Optimierung (2). Zu beachten ist: • Wie oft wird dieses Programm benötigt? Lohnt sich der Optimieraufwand ? • optimierte Programme sind oft unübersichtlicher. • Optimierung wird durch Compiler erledigt • Optimierung kann die Portierbarkeit verschlechtern • experimentelle Feststellung des Ressourcenbedarfs ist fehlerbehaftet und abhängig von (Version der) Programmierumgebung P raktische Inf ormatik 1, W S 2004/05, F olien Haskell−2, (12. N ovember2004) Seite 31 Analyse von Programmen Wir verwenden für Haskell-Programme folgende Messungen. Benutze verzögerte Auswertung Zeit: Anzahl der Transformationsschritte Platz: (Gesamt-Speicher): Maximale Größe der Ausdrücke Arbeitsspeicher: Maximale Größe der Ausdrücke (ohne die Eingabe) arithmetische und Boolesche Operationen = 1 Transformationsschritt. P raktische Inf ormatik 1, W S 2004/05, F olien Haskell−2, (12. N ovember2004) Seite 32 Analyse von Programmen (2) Angabe des Ressourcenbedarf eines Algorithmus in Abhängigkeit von der Größe der Eingabe. Notation für Algorithmus alg bei Eingabe der Größe n: redalg(n) maximale Anzahl der Reduktionen bei verzögerter Auswertung für alle Eingaben der Größe n. P latzalg(n) Platzbearf: maximale Größe der Ausdrücke (des gerichteten Graphen) bei verzögerter Auswertung für alle Eingaben der Größe n. Die Eingaben nicht mitzählen P raktische Inf ormatik 1, W S 2004/05, F olien Haskell−2, (12. N ovember2004) Seite 33 Analyse von Programmen (3) Bei genauerer Analyse einer Problemklasse: Bezugsgrößen: !?: Turingmaschine oder anderes abstraktes Maschinenmodell Abhängigkeit vom Maschinenmodell? Aufwand eines Einzelschrittes (abstr. Maschine)? Aufwand der eingebauten Funktionen? (Multiplikation, Addition, Konversionen,usw.). benötigter Platz für Zahlen? I.a. nicht konstant. P raktische Inf ormatik 1, W S 2004/05, F olien Haskell−2, (12. N ovember2004) Seite 34 Beispiel: fib fib n = if n <= 0 then 0 else if n == 1 then 1 else fib (n-1) + fib(n-2) Bezugsgröße: eingegebene Zahl n Behauptung: Beweis: # rekursive Aufrufe für (fib n) ist ≤ fib(n + 1) mit vollständiger Induktion redfib(n) ≤ c ∗ fib(n + 1) wobei c eine Konstante ist. fib(n) ≈ 1.6n ⇒ redfib(n) ≈ 1.6n (einfach exponentiell) andere Bezugsgröße: Größe der Darstellung der Zahl n: n hat size(n) = dlog10(n)e Dezimalstellen. Zeitbedarf: ≈ 1.6(10 P raktische Inf ormatik 1, W S size(n) ) 2004/05, F olien Haskell−2, (doppelt exponentiell). (12. N ovember2004) Seite 35 Beispiel fakultaet fakultaet x = if x <= 1 then 1 else x*(fakultaet (x-1)) Anzahl der Reduktionen: fakultaet 1 if 1 <= 1 then ... if True then ... 1 fakultaet 1 : 3 Reduktionschritte P raktische Inf ormatik 1, W S 2004/05, F olien Haskell−2, (12. N ovember2004) Seite 36 Beispiel fakultaet 2 fakultaet 2 if 2 <= 1 then ... if False then ... 2*(fakultaet (2-1)) 2*(if (2-1) <= 1 then ... ) 2*(if 1 <= 1 then ... ) 2*(if True then ... ) 2* 1 2 fakultaet 2 : 8 Reduktionschritte P raktische Inf ormatik 1, W S 2004/05, F olien Haskell−2, (12. N ovember2004) Seite 37 Beispiel fakultaet 3 fakultaet 3 if 3 <= 1 then ... if False then ... 3*(fakultaet (3-1)) 3*(if (3-1) <= 1 then ... ) 3*(if 2 <= 1 then ... ) 3*(if False then ... ) 3*(2*fakultaet (2-1)) 3*(2*(if 2-1 <= 1 then ... 3*(2*(if 1 <= 1 then ... )) 3*(2*(if True then ... )) 3*(2* 1) 3*2 6 fakultaet 3 : 13 Reduktionschritte P raktische Inf ormatik 1, W S 2004/05, F olien Haskell−2, (12. N ovember2004) Seite 38 Beispiel fakultaet n Es sind: 5 ∗ (n − 1) + 3 Reduktionsschritte. Vermutung: redfakultaet(n) = 5 ∗ (n − 1) + 3 Nachweis mit vollständiger Induktion: Beh: fakultaet (n-1) (als Ausdruck) benötigt 5 ∗ (n − 2) + 4 Reduktionsschritte: für n ≥ 2 Basis: fakultaet (2-1) benötigt 4 Reduktionsschritte P raktische Inf ormatik 1, W S 2004/05, F olien Haskell−2, (12. N ovember2004) Seite 39 Beispiel fakultaet n: Nachweis Ind. Schritt: Nachzuweisen ist: fakultaet (n-1) benötigt 5 ∗ (n − 2) + 4 für n > 2. fakultaet (n-1) if (n-1) <= 1 then ... if n1 <= 1 then ... if False then ... n1*fakultaet (n1-1) -- n1 ist Basiswert > 1 Das sind 4 + 5 ∗ (n1 − 2) + 4 + 1 = 5 ∗ (n − 2) + 4 Reduktionsschritte P raktische Inf ormatik 1, W S 2004/05, F olien Haskell−2, (12. N ovember2004) Seite 40 Beispiel fakultaet n : Nachweis Anfangs-Reduktions-Schritt fakultaet n if n <= 1 then ... if False then ... n*fakultaet (n-1) Das sind 3 + (5 ∗ (n − 2) + 4) + 1 = 5 ∗ (n − 1) + 3 P raktische Inf ormatik 1, W S 2004/05, F olien Haskell−2, (12. N ovember2004) Seite 41 Komplexitäten von Algorithmen Beachte: breite Streuung des Ressourcenbedarfs ist möglich für die Menge aller Eingaben einer bestimmten Größe. Z.B. (3n+1)-Funktion mit Bezugsgröße: Anzahl der Stellen Komplexitäten von Platz und Zeit: Ressourcenbedarf im schlimmsten Fall im besten Fall im Mittel P raktische Inf ormatik 1, W S (worst-case) (best-case) Minimum von # Reduktionen bzw. Minimum der Größe der Ausdrücke. (average case) Welche Verteilung? 2004/05, F olien Haskell−2, (12. N ovember2004) Seite 42 Komplexitäten von Algorithmen Ein Algorithmus ist effizient, wenn er wenig Ressourcen benötigt Ein Algorithmus ist optimal, wenn er nicht schlechter“ ist als andere ” Algorithmen zur gleichen Problemklasse (Zeit/Platz)-Komplexität einer Problemklasse: ≡ Ressourcenverbrauch des optimalen Algorithmus. P raktische Inf ormatik 1, W S 2004/05, F olien Haskell−2, (12. N ovember2004) Seite 43 O-Schreibweise Verwendung: asymptotische Größenordnung von numerischen Funktionen hier für: redalg (n) und P latzalg (n) Definition Seien R, f : IN+ → IR+ zwei Funktionen: Wir schreiben: R(n) = O(f (n)), wenn es eine Konstante K gibt, so daß R(n) ≤ K ∗ f (n) für alle genügend großen n. P raktische Inf ormatik 1, W S 2004/05, F olien Haskell−2, (12. N ovember2004) Seite 44 O-Schreibweise: Bemerkungen Beachte R(n) = O(f (n)) keine Gleichung Beachte R(n) = O(f (n)) ist eine Abschätzung nach oben Die Angabe R(n) = O(f (n)) sollte möglichst optimales f verwenden Sprechweisen: R(n) ist von der Größenordnung f (n) R(n) hat höchstens Größenordnung f (n) P raktische Inf ormatik 1, W S 2004/05, F olien Haskell−2, (12. N ovember2004) Seite 45 Beispiele und Eigenschaften zu O() • √ n = O(n) • p(n) = O(2n) für alle Polynome p. • Wenn f (n) = O(c ∗ g(n)), dann auch f (n) = O(g(n)). • Wenn c > 1 und e > 0 eine Konstante, dann gilt: f (n) = O(cn+e) gdw. f (n) = O(cn) • Wenn c, d > 1, dann gilt: f (n) = O(logc(n)) gdw. f (n) = O(logd(n)) • Wenn c, d > 1, und c < d, dann gilt: cn = O(dn) , aber nicht dn = O(cn). P raktische Inf ormatik 1, W S 2004/05, F olien Haskell−2, (12. N ovember2004) Seite 46 Beispiele und Eigenschaften zu O() • Wenn f (n) = O(g(n)) und g(n) = O(h(n), dann gilt auch f (n) = O(h(n)). • Wenn eine Funktion f durch eine Konstante nach oben beschränkt ist, dann gilt f (n) = O(1). P raktische Inf ormatik 1, W S 2004/05, F olien Haskell−2, (12. N ovember2004) Seite 47 Beispiel fib fib Bezugsgröße: P raktische Inf ormatik 1, W S n: Eingabe d: Größe der Darstellung der Zahl n redfib(n) platzfib(n) = = O(1.62n) O(n) redfib lin(n) platzfib lin(n) = = O(n) O(n) redfib lin(d) platzfib lin(d) = = O(10d) O(10d) 2004/05, F olien Haskell−2, (12. N ovember2004) Seite 48 Einige Komplexitäten O(1) O(log(n)) O(n) O(n ∗ log(n)) O(n2) O(n3) O(nk ) O(2n) P raktische Inf ormatik 1, W S konstant logarithmisch linear fastlinear (oder auch n-log-n) quadratisch kubisch polynomiell exponentiell 2004/05, F olien Haskell−2, (12. N ovember2004) Seite 49 Komplexitäten: Veranschaulichung beispielhafte Tabelle zur intuitiven Veranschaulichung: Eingabedaten Algorithmus log2(n) n n2 n3 2n P raktische Inf ormatik 1, W S 10 100 1000 0.000003 sec 0.00001 sec 0.0001 sec 0.001 sec 0.001 sec 0.000007 sec 0.0001 sec 0.01 sec 1 sec 4 ∗ 1016 Jahre 0.00001 0.001 sec 1 sec 15 min nahezu ∞ 2004/05, F olien Haskell−2, (12. N ovember2004) Seite 50 Kommentare zu O() • • • • • Viele relevante Optimierungen ändern Größenordnung O() nicht Verwendung eines schnelleren Rechners: nur konstante Verbesserung der Zeit, d.h. O() ändert sich nicht. Die Bestimmung der genauen Komplexität des Ressourcenbedarfs einer Problemklasse ist jeweils ein sehr schweres theoretisches Problem. Oft sind nur gute obere Abschätzungen bekannt Bekannte untere Schranken sind oft trivial oder zu schwach P raktische Inf ormatik 1, W S 2004/05, F olien Haskell−2, (12. N ovember2004) Seite 51 Ω-Schreibweise Ziel: Größenordnung von numerischen Funktionen nach unten abschätzen. Seien R, f : IN+ → IR+ zwei Funktionen: R(n) = Ω(f (n)), wenn es eine Konstante Kgibt, so daß R(n) ≥ K ∗ f (n) für alle genügend großen n. P raktische Inf ormatik 1, W S 2004/05, F olien Haskell−2, (12. N ovember2004) Seite 52 Ω-Eigenschaften Analog zu O(·). • • • • • • • • • √ n √ = Ω( n) n = Ω(1). 2n = Ω(p(n)) für alle Polynome p. Wenn f (n) = Ω(c ∗ g(n)), dann auch f (n) = Ω(g(n)). m Wenn c > 1 und e > 0 eine Konstante, dann gilt: f (n) = Ω(cn+e) gdw. f (n) = Ω(cn) Wenn c, d > 1, dann gilt: f (n) = Ω(logc(n)) gdw. f (n) = Ω(logd(n)) Wenn c, d > 1, und c < d, dann gilt: dn = Ω(cn) , aber nicht cn = Ω(dn). Wenn f (n) = Ω(g(n)) und g(n) = Ω(h(n), dann gilt auch f (n) = Ω(h(n)). Wenn eine Funktion f durch eine Konstante nach unten beschränkt ist, dann gilt f (n) = Ω(1). P raktische Inf ormatik 1, W S 2004/05, F olien Haskell−2, (12. N ovember2004) Seite 53 Schnelle Berechnung von Potenzen bn für positive ganze Zahlen n. Die Potenzen sind rekursiv definiert durch: ( bn := 1 falls n = 0 b ∗ bn−1 sonst Direkte Kodierung des Algorithmus ergibt ein rekursives Programm: potenz b n = if n == 0 then 1 else b * (potenz b (n - 1)) Platz- und Zeitbedarf sind von der Größenordnung O(n) P raktische Inf ormatik 1, W S 2004/05, F olien Haskell−2, (12. N ovember2004) Seite 54 Optimierung der Potenzberechnung Idee: Statt b8 = b ∗ b ∗ b ∗ b ∗ b ∗ b ∗ b ∗ b berechne • b2 := b ∗ b • b4 = b2 ∗ b2 • b8 = b4 ∗ b4 allgemeine Rechenvorschrift: 1 falls n = 0 bn := (bn/2)2 falls n gerade und ≥ 2 b ∗ bn−1 falls n ungerade P raktische Inf ormatik 1, W S 2004/05, F olien Haskell−2, (12. N ovember2004) Seite 55 Haskell-Programm zur Potenz potenz_log b n = if n == 0 then 1 else if geradeq n then quadrat (potenz_log b (n ‘div‘ 2)) else b * (potenz_log b (n - 1)) geradeq n = (rem n 2) == 0 Platz- und Zeitbedarf abhängig von n ist O(log(n)) z.B. für n = 1000: 14 Multiplikationen. tatsächlicher Platz- und Zeitbedarf: O((log(n)3), wegen Multiplikation von großen Zahlen P raktische Inf ormatik 1, W S 2004/05, F olien Haskell−2, (12. N ovember2004) Seite 56 Analyse des Algorithmus zum größten gemeinsamen Teiler ggT(a, b) (Euklids Algorithmus) Teile a durch b gibt Rest r, wenn r = 0, dann ggT(a, b) := b wenn r 6= 0, dann berechne ggT(b, r). Beispiel ggT(30, 12) = ggT(12, 6) = 6 ggt a b = P raktische Inf ormatik if b == 0 then a else ggt b (rem a b) 1, W S 2004/05, F olien Haskell−2, (12. N ovember2004) Seite 57 Satz von Lamé SATZ (Lamé): Wenn der Euklidische ggt-Algorithmus k Schritte benötigt, dann ist die kleinere Zahl der Eingabe ≥ f ib(k). Platz- und Zeitbedarf von ggt: O(log(n)) Begründung: Wenn n die kleinere Zahl ist und der Algorithmus k Schritte benötigt, dann ist n ≥ f ib(k) ≈ 1.6180k Also ist k = O(log(n)) P raktische Inf ormatik 1, W S 2004/05, F olien Haskell−2, (12. N ovember2004) Seite 58 Test auf Primzahl-Eigenschaft Problem: Gegeben n. Frage: ist n eine Primzahl? Methode 1: finde den kleinsten Teiler > 1: primzahlq n = n == (kleinster_teiler n) kleinster_teiler n = finde_teiler n 2 finde_teiler n pruef_teiler = if n < (quadrat pruef_teiler) then n else if teiltq pruef_teiler n then pruef_teiler else finde_teiler n (pruef_teiler + 1) teiltq a b = 0 == (rem b a) √ (worst-case) Zeitbedarf: O( n) P raktische Inf ormatik 1, W S 2004/05, F olien Haskell−2, (12. N ovember2004) Seite 59 Primzahltest: Methode 2 Benutze kleinen Fermatschen Satz. Satz (Fermat): Wenn p eine Primzahl ist und 1 < a < p, dann ist ap ≡ a(mod p) Idee für Algorithmus: Teste für viele verschiedene a: Wenn für ein a: an ≡ 6 a(mod n), dann ist n keine Primzahl. Bei ausreichend vielen Zahlen a mit an ≡ a(mod n): mit hoher Wahrscheinlichkeit ist n Primzahl Aber: Ausnahmen sind möglich P raktische Inf ormatik 1, W S 2004/05, F olien Haskell−2, (12. N ovember2004) Seite 60 Primzahltest: Programm zu Methode 2 potenzmod b e m = if e == 0 then 1 else if geradeq e then rem (quadrat (potenzmod b (e ‘div‘ 2) m)) m else rem (b * (potenzmod b (e - 1) m)) m fermat_test_it n rnd = let a = (rnd ‘mod‘ n) in (potenzmod a n n) == a fermat_test n P raktische Inf ormatik 1, W S = and 2004/05, F olien Haskell−2, (map (fermat_test_it n) (take 100 (randomInts 2 n)))) (12. N ovember2004) Seite 61 Primzahltest: Bemerkungen Dies ist ein probabilistischer Algorithmus Eigenschaften Zeitverbrauch pro Test: O(log n). Die Antwort: ist keine Primzahl“ ist immer korrekt, ” während ist eine Primzahl“ nur mit hoher Wahrscheinlichkeit korrekt ” Die Ausnahmen nennt man Carmichael-Zahlen. 561,1105,1729,2465,2821,6601,8911,10585,15841,29341, . . . . Teilbarkeitstest durch die Primzahlen bis 43 schliesst alle Carmichaelzahlen ≤ 106 aus. P raktische Inf ormatik 1, W S 2004/05, F olien Haskell−2, (12. N ovember2004) Seite 62 Primzahltest: Neuere Ergebnisse Prüfung einer Zahl auf Primzahleigenschaft ist in polynomieller Zeit möglich (d.h. in O(log(n)) ). (siehe: M. Agrawal, N. Kayal, N. Saxena: PRIMES is in P ) P raktische Inf ormatik 1, W S 2004/05, F olien Haskell−2, (12. N ovember2004) Seite 63 Beispiel: Fermatsche Primzahlen n Vermutung von Pierre de Fermat: 22 + 1 ist immer eine Primzahl geometrische Konstruierbarkeit mittels Zirkel und Lineal von gleichseitigen Vielecken ist möglich, wenn die Anzahl der Seiten die Form 2m ∗ p hat und p eine Fermatsche Primzahl ist n Widerlegung der Vermutung: 22 + 1 ist keine Primzahl für n = 5, 6, 7, 8, 9 P raktische Inf ormatik 1, W S 2004/05, F olien Haskell−2, (12. N ovember2004) Seite 64 Beispiel: Fermatsche Primzahlen Main> fermat_prim_test 4 (65537,True) -- ist Primzahl Main> fermat_prim_test 5 (4294967297,False) Main> fermat_prim_test 6 (18446744073709551617,False) Main> fermat_prim_test 7 (340282366920938463463374607431768211457,False) Aber: einen Teiler zu berechnen dauert sehr (zu) lange. Mit iterativer Version von potenzmod: auch n = 10,11,12,13,14 widerlegbar. Offen: (n = 33, 34, 35, 40, 41, 44, 45, 46, 47, 50, . . .) P raktische Inf ormatik 1, W S 2004/05, F olien Haskell−2, (12. N ovember2004) Seite 65 Beispiel: Mersennesche Primzahlen sind von der Form 2p − 1, wobei p selbst eine Primzahl ist. Mersennesche Primzahlen sind Rekordhalter als größte Primzahlen Es sind Primzahlen für folgende Werte von p: 2, 3, 5, 7, 13, 17, 19, 31, 61, 89, 107, 127, 521, 607, 1279, 2203, 2281, 3217, 4253, 4423, 9689, 9941, 11213, 19937, . . . Der aktuelle Rekord ist p = 24036583, d.h. die Mersennesche Primzahl 224036583 − 1, Siehe http://www.mersenne.org/history.htm#found p = 2281 ist machbar mit Haskell Interpreter (einige Minuten) mersenne_prim_test 2281 P raktische Inf ormatik 1, W S 2004/05, F olien Haskell−2, (12. N ovember2004) Seite 66