Einleitung Algorithmen und Datenstrukturen Beispiel: Sortieren (Spezifikation 1) • Eingabe: Zahl n ∈ N, Zahlenfolge a ∈ Nn Johannes Waldmann, HTWK Leipzig • Ausgabe: Zahlenfolge b ∈ Nn mit: Vorlesung, SS 17 – Daten-Erhaltung: Multimenge von a = Multimenge von b – Monotonie: b ist schwach monoton steigend. Beispiel: • Eingabe: n = 4, a = [5, 1, 0, 1]. • Multimenge von a? korrekte Ausgabe(n)? – Typeset by FoilTEX – – Typeset by FoilTEX – Beispiel: Sortieren (Implementierung 1) Beispiel: Sortieren (Implementierung 2) • Algorithmus: Sortieren durch Auswählen (selection sort) • nur für den Fall n = 4 • benutzt Operation cexb(i, j) (compare-exchange): wenn bi > bj , dann vertausche bi mit bj b := a; für nat i von 1 bis n nat k := i; für nat j von i + 1 bis n wenn b[j] < b[k] dann k := j // b[k] ist minimal in b[i..n] vertausche b[i] mit b[k]; • Algorithmus (Ansatz) b := a; cexb(1, 2); cexb(3, 4); cexb(1, 3); cexb(2, 4); • Beweise: jeder Algorithmus, der nur cex-Operationen verwendet, ist daten-erhaltend. • erfüllt der o.g. Algorithmus die Monotonie-Eigenschaft? Nein. Warum nicht? • Beispiel-Rechnung für a = [5, 1, 0, 1] • allgemein: – Korrektheit (Daten-Erhaltung, Monotonie)? – Laufzeit? • Füge eine cex-Operation hinzu, so daß resultierender Algorithmus korrekt ist. – Typeset by FoilTEX – 2 – Typeset by FoilTEX – Beispiel Sortieren: Einordnung Eine Spezifikation ist eine Relation S ⊆ E × A. Ein Algorithmus ist • eine Vorschrift zur schrittweisen Rechnung • auf einer tatsächlichen (konkreten) oder gedachten (virtuellen, abstrakten) Maschine, • die aus einer Eingabe e ∈ E eine Ausgabe R(e) ∈ A erzeugt—oder keine (Notation: R(e) = ⊥ mit ⊥ ∈ / A) • hervorragend geeignet zum Lernen v. Methoden f. Algorithmen-Entwurf, Korrektheitsbeweis, Laufzeit-Analyse • der gesamte Band 3 von DEK: TAOCP behandelt Sortieren Der Algorithmus heißt • . . . wer aber tatsächlich eine Liste sortiert, macht wahrscheinlich etwas falsch: • partiell korrekt bezüglich S, falls ∀e ∈ E : R(e) = ⊥ ∨ (e, R(e)) ∈ S • total (terminierend), falls ∀e ∈ E : R(e) 6= ⊥ • total korrekt bezüglich S, falls ∀e ∈ E : (e, R(e)) ∈ S . . . und hätte besser eine andere Implementierung des abstrakten Datentyps Menge benutzen sollen. 4 – Typeset by FoilTEX – 5 Der abstrakte Datentyp Menge (Axiome) Der abstrakte Datentyp Menge (Signatur) für alle e,f ∈ E, m ∈ M : • diese Datentypen werden benutzt: – Element-Typ E, – Typ M der Mengen über E 1. 2. 3. 4. 5. • diese (getypten) Funkionssymbole gehören zur Signatur des abstrakten Datentyps Menge: – Konstruktion: ∗ empty : M ∗ insert : E × M → M ∗ union : M × M → M – Test: ∗ null : M → B, dabei ist B = {False, True} ∗ contains : E × M → B – Typeset by FoilTEX – 3 Grundbegriffe: Spezifikation, Algorithmus • das Sortieren ist eine alte und wichtige algorithmische Aufgabe (Lochkartensortiermaschinen, Hollerith, 1908) – Typeset by FoilTEX – 1 null(empty) = True; null(insert(e,m)) = False; contains(e,empty) = False; contains(e,insert(e,m)) = True; e6=f ⇒ contains(e,insert(f,m)) = contains(e,m); • weitere für delete,union (Übung) • für jede konkrete Implementierung muß Erfüllung der Axiome nachgewiesen werden. 6 – Typeset by FoilTEX – 7 Implementierungen von Mengen Grundbegriff: Datenstruktur • naiv: M realisiert durch E ∗, empty = [], insert(e, [m1, . . . , mk ]) = [e, m1, . . . , mk ] contains(e, [m1, . . . , mk ]): für i von 1 bis k { wenn mi = e return True } return False lineare Laufzeit • Def: eine (geeignete) Datenstruktur C für einen abstrakten Datentyp S . . . ist eine Organisationsform für Daten (ein konkreter Datentyp) mit korrekten (und effizienten) Algorithmen, die die Spezifikation von S implementieren. • oft gib es mehrere geeignete C für ein S, die passende Wahl hängt dann von weiteren Faktoren ab (z.B. erwartetes Anzahlverhältnis einzelner S-Operationen) • aus genauer Beschreibung der Struktur (z.B. heap-geordneter vollständig balancierter Binärbaum) können Implementierungen meist direkt abgeleitet werden • besser? verschiedene Varianten, siehe Vorlesung. – m monoton steigende Folge: contains logarithmisch, aber insert und union immer noch teuer (linear) – m als balancierter Suchbaum: contains und insert logarithmisch, union linear, in Spezialfällen schneller – Typeset by FoilTEX – 8 Inhalt und Ziel der Vorlesung • für die Lösung typischer Aufgaben, insbesondere – Grundlagen: konkrete Implementierungen der Konzepte (abstrakten Datentypen), die in der Modellierung benutzt werden, u.a.: (Multi)Menge, Folge, Funktion, Relation, Graph – Anwendungen: inbesondere: Eigenschaften von Graphen (mit Kanten-Gewichten) • (impliziert Erfüllung von Spezifikation 1) – Eingabe: n ∈ N, a ∈ Nn – Ausgabe: Permutation π : {1, . . . , n} → {1, . . . , n} mit: Folge [aπ(1), . . . , aπ(n)] ist schwach monoton steigend. • Beispiel: n = 4, a = [5, 1, 0, 1], bestimme π. • Satz: die Abbildung von a auf aπ = [aπ(1), . . . , aπ(n)] ist Daten-erhaltend (vorherige Def., Multimengen) • Beweis: vergl. Anzahl der Vorkommen von z in a und aπ : • die Methoden sind unabhängig von diesen Aufgaben nützlich #{i | aπ (i) = z} = #{i | aπ(i) = z} = #{π −1(j) | aj = z}|. 10 – Typeset by FoilTEX – • Aufgabenstellung: • naiv (schon gesehen) Sortieren durch Auswahl – Eingabe: ∗ gerichteter Graph G = (V, E) ∗ Kanten-Gewichte w : E → Q≥0 ∗ Knoten v0 ∈ V – Ausgabe: Funktion l : V → Q≥0 ∪ {+∞} mit: P ∗ l(v) = min{ e∈P w(e) | P ist Weg von v0 zu v}. quadratische Laufzeit • besser? verschiedene Varianten, siehe Vorlesung, z.B. Set<E> m:=empty; foreach E e in a { m:=insert(e,m); } while not(null(m)) { (e, m) := extract-min(m); print (e); } • Beispiel (siehe Tafel) Laufzeit n · log(n) (bei guter Implementierung für Mengen) 12 Aufgabe: Rundreise • Algorithmus? siehe Vorlesung. – Typeset by FoilTEX – 13 Einordnung dieser VL in das Studium • Aufgabestellung: – Eingabe: ∗ ungerichter Graph G = (V, E) mit V = {1, . . . , n} ∗ Kanten-Gewichte w : E → Q≥0 – Ausgabe: ∗ eine Permutation π von V mit: ∗ ∀i : π(i)π(i + 1) ∈ E P ∗ und {w(π(i)π(i + 1))|i ∈ V } ist minimal (unter allen zulässigen π) ∗ dabei Index-Rechnung modulo n, d.h. π(n + 1) = π(1) • Beispiel (siehe Tafel). Auswahl von LV zu Programmierung und Algorithmen: • 1. Sem: Modellierung • 1./2. Sem: (AO) Programmierung (strukturiert, imperativ, objekt-orientiert) • 2. Sem: Algorithmen und Datenstrukturen • 3. Sem: Softwaretechnik • 4. Sem: Fortgeschrittene (funktionale) Progr. • Wahl 5. Sem : Sprachkonzepte parallele Progr. • 1. Sem Master: Prinzipien von Programmiersprachen • Master: Theor. Inf. (Komplexität), Verifikation • Algorithmen? siehe Vorlesung – Typeset by FoilTEX – 11 Aufgabe: kürzeste Wege Implementierungen von Sortierverfahren – Typeset by FoilTEX – 9 Aufgabe: Sortieren (Spezifikation 2) • Methoden für Analyse (Korrektheit, Laufzeit) und Entwurf von Algorithmen und Datenstrukturen – Typeset by FoilTEX – – Typeset by FoilTEX – • Wahl Master: Algorithm Design 14 – Typeset by FoilTEX – 15 Organisatorisches Zeitplan für Übungsserien • jede Woche 2 VL Folien und weitere Informationen: http://www.imn. htwk-leipzig.de/˜waldmann/lehre.html (Sprechzeit: mittwoch 11:15, per Mail anmelden) Grundsätzlich: • jede Woche 1 Übung (pro Seminargruppe), dort Vorrechnen Ihrer Lösungen der Übungsaufgaben sollen in Kleingruppen (3 bis 4 Leute) bearbeitet werden zur Initialisierung: in KW 14 (= aktuelle Woche = Woche 0) • jeweils am Anfang der Woche x werden die Aufgaben der Übungsserie x + 1 bekanntgegeben, die in Übungen der Woche x + 1 vorgerechnet und bewertet werden. • Ü-Serie 0 (am Ende dieses Skriptes) zur Diskussion in Woche 0 (ab morgen), ohne Punkte, aber autotool-Pflichtaufgabe zählt • online-Übungsaufgaben im autotool • Prüfungszulassung: erfolgreich Vorrechnen (60 %) und erfolgreich autotool (60 % der Pflichtaufgaben) • in Übungen Woche 0: Einteilung in Gruppen • Ü-Serie 1 wahrscheinlich morgen (Dienstag): ähnlich zu Serie 0 (kein neuer Stoff), aber mit Punkten. • Prüfung: Klausur, keine Hilfsmittel – Typeset by FoilTEX – 16 – Typeset by FoilTEX – 17 Literatur Bewertung von Übungsserien • autotool: bewertet individuell (ca. 1 Pflicht-A/Woche) • Übungen: für jede der aktuellen Aufgaben A (ca. 4 Stück) – Übungsleiter ruft einen Teilnehmer T auf, dieser rechnet vor, die Leistung wird bewertet, alle anwesenden Mitglieder der Gruppe G von T erhalten diesen Wert. – T darf ersatzweise eine andere aktuelle Aufgabe A0 auswählen – bei Abwesenheit von T darf G einen anderen Vertreter T 0 ∈ G benennen. – es wird Gleichverteilung über alle T angestrebt • Übungsleiter kann von dieser Regelung im Einzelfall abweichen. – Typeset by FoilTEX – • K. Weicker und N. Weicker: Algorithmen und Datenstrukturen, Springer 2013, https: //link.springer.com/book/10.1007/978-3-8348-2074-7 • T. Ottman und P. Widmayer: Algorithmen und Datenstrukturen, Springer 2012, https: //link.springer.com/book/10.1007/978-3-8274-2804-2 • T. H. Cormen, C. E. Leiserson, R. L. Rivest: Algorithms, MIT Press 1991, https: //mitpress.mit.edu/books/introduction-algorithms • D. E. Knuth: The Art of Computer Programming, Vol. 3 (Sorting and Searching), Addison-Wesley, 1998, http://www-cs-faculty.stanford.edu/˜uno/taocp.html 18 – Typeset by FoilTEX – 19 Alternative Quellen Übung KW14 Ablauf der Übung • – Q: Aber in Wikipedia/Stackoverflow steht, daß . . . – A: Na und. • Es mag eine in Einzelfällen nützliche Übung sein, sich mit dem Halbwissen von Nichtfachleuten auseinanderzusetzen. Beachte aber https://xkcd.com/386/ • In VL und Übung verwenden und diskutieren wir die durch Dozenten/Skript/Modulbeschreibung vorgegebenen Quellen (Lehrbücher, referierte Original-Artikel, Standards zu Sprachen und Bibliotheken) • Diskussion der unten angegebenen Aufgaben 0.0 bis 0.3 • kurze Erläuterung des kooperativen Übungskonzeptes und Einteilung (durch Übungsleiter) in Gruppen (je 3 bis 4 Personen) • Bearbeitung der Aufgabe 0.4 (in den neu gebildeten Gruppen) und Diskussion • . . . gilt entsprechend für Ihre Bachelor- und Master-Arbeit. – Typeset by FoilTEX – 20 – Typeset by FoilTEX – 21 Aufgabe 0.1 (Mengen) Übungsserie 0 (Diskussion in KW14) • Beweisen Sie mittels der angegebenen Axiome: Aufgabe 0.0 (Leseübung) contains(2,insert(1,insert(3,empty)))=False • Wie begründen Ottman/Widmayer, daß es in der Vorlesung AD nicht so sehr auf die exakte Formulierung des Algorithmenbegriffs ankommt? In welcher anderen Vorlesung wird das wichtiger und warum? (Quelle mit Seiten- und Zeilennummer angeben.) • Geben Sie ein passendes Axiom für die Vereinigung union : M × M → M an. Verwenden Sie eine passende aussagenlogische Verknüpfung. • Der Wert von delete(e, m) soll die Menge m \ {e} sein. Geben Sie den Typ von delete an. Untersuche Sie (Beweis oder Gegenbeispiel): – ∀e ∈ E, m ∈ M : delete(e, insert(e, m)) = m – ∀e ∈ E, m ∈ M : insert(e, delete(e, m)) = m – Typeset by FoilTEX – 22 – Typeset by FoilTEX – 23 Aufgabe 0.3 (kürzestes Wege) Aufgabe 0.2 (Sortieren) Wir betrachten den Graphen Gn auf der Knotenmenge Vn = {0, 1, . . . , n}2 mit den Kanten Für a = [3, 1, 4, 1, 5, 9]: • geben Sie alle Permuationen π an, die die Spezifikation (Variante 2) des Sortierens erfüllen. • ((x, y), (x + 1, y)) vom Gewicht 4 • Führen Sie den Algorithmus Sortieren durch Auswahl mit Eingabe a aus. • ((x, y), (x, y + 1)) vom Gewicht 1 • ((x, y), (x + 1, y + 1)) vom Gewicht 2 (jeweils für alle x, y, für die das angegebene Paar tatsächlich in Vn2 liegt) • Zeichnen Sie G2. • Geben Sie in G2 alle Wege von (0, 0) zu (1, 2) an. Geben Sie zu jedem dieser Wege die Kosten an. Bestimmen Sie – Typeset by FoilTEX – 24 – Typeset by FoilTEX – Aufgabe 0.4 (Sortieren mit compare-exchange) l(1, 2), wobei l die Funktion aus der Spezifikation ist, und v0 = (0, 0). • Geben Sie weitere konkrete Funktionswerte von l an. 25 • Begründen Sie, daß folgendes Verfahren jede Eingabe der Breite 4 sortiert. Jedes Paar (i, j) bedeutet cex(i, j). • Beweisen Sie für i < j: Die Funktion l für Gi ist (als Menge von geordneten Paaren) Teilmenge der entsprechenden Funktion für Gj . (Zeichnen Sie G3) [(1,2), (3,4), (2,3), (1,2), (3,4), (2,3)] • Begründen Sie (jeweils durch ein Gegenbeispiel), daß man keines dieser Paare weglassen kann. • Begründen Sie l(k, 0) = 4k (in Gk und allen größeren) • Geben Sie weitere allgemeine Aussagen über l an. – Typeset by FoilTEX – 26 – Typeset by FoilTEX – 27 Aufgabe 0.5(A) (autotool) Übungsserie 1 (Diskussion in KW15) • Geben Sie ein compare-exchange-Sortierverfahren für 6 Elemente an mit weniger als 15 cex-Operationen. Aufgabe 1.0 (Leseübung) • (1 P) Wo und unter welchem Namen erscheint der Algorithmus Sortieren durch Auswählen in Weicker/Weicker? (Kapitel, Seitennummer) • (2 P) Welche zwei Unterschiede gibt es zur Version hier im Skript? – Typeset by FoilTEX – 28 – Typeset by FoilTEX – Aufgabe 1.1 (Mengen) Aufgabe 1.2 (Sortieren mit compare-exchange) • (1 P) Beweisen Sie mittels der angegebenen Axiome: contains(2,insert(1,insert(2,empty)))=True • (1 P) Geben Sie ein passendes Axiom für die Mengendifferenz difference : M × M → M an. • (3 P) Begründen Sie, daß folgendes Verfahren jede Eingabe der Breite 4 sortiert. Jedes Paar (i, j) bedeutet cex(i, j). [(2,3), (1,2), (3,4), (2,3), (1,2), (3,4)] • (2 P) Wie läßt sich ein Test equals : M × M → B auf Mengengleichheit implementieren, wenn nur die bis hier in Skript und Aufgaben angegebenen Operationen des abstrakten Datentyps Menge sowie alle aussagenlogischen Verknüpfungen zur Verfügung stehen? – Typeset by FoilTEX – 29 • (1 P) Begründen Sie durch ein Gegenbeispiel, daß man die erste Operation cex(2, 3) nicht weglassen kann. 30 – Typeset by FoilTEX – 31 Aufgabe 1.3 (kürzeste Wege) das lG4 (v) > lG5 (v) ist. Wir betrachten den Graphen Gn auf der Knotenmenge Vn = {1, . . . , n}2 und der Kantenmenge En = {((x1, x2), (y1, y2)) | (x1 − y1)2 + (x2 − y2)2 = 5}, die alle Gewicht 1 haben. • (1 P) Dieser Graph hat eine Beziehung zu einem Brettspiel—welche? • (1 P) Bestimmen Sie die Abstandsfunktion lG4 von v0 = (1, 1) aus. • (1 P) Erklären Sie das Muster der Vorkommen der geraden und ungeraden Funktionswerte von l. • (1 P) immer noch für v0 = (1, 1): Geben Sie ein v an, für – Typeset by FoilTEX – 32 Komplexität von Algorithmen und Problemem • auf einer konkreten Maschine: die konkrete (physikalische) Zeit einer Ausführung des Programms für eine Eingabe • Definition: worst-case-Zeitkomplexität eines Algorithmus • Definition: Komplexität eines Problems, Komplexitätsklassen • Bestimmung der Komplexität von Algorithmen mit Schleifen • asymptotischer Vergleich von Funktionen • (später) weitere Ressourcen (Platz, parallele Zeit) • (später) average-case-Komplexität • auf einer (konkreten oder) abstrakten Maschine: die Anzahl der Rechenschritte für eine Eingabe (beachte: Def. Algorithmus: schrittweise Ausführung) • Beispiel: Profiling/Coverage-Analyse (für C-Programme) – gprof zählt Unterprogramm-Aufrufe – gcov zählt Ausführungen von Anweisungen (Zeilen) Literatur: vgl. WW 2.3/2.4, OW S. 4/5 34 Coverage mit gcov ist die Funktion g++ -fprofile-arcs -ftest-coverage ex.cc -o ex cP : N → N : s 7→ max{time(A, x) | size(x) ≤ s} • ausführen: ./ex, erzeugt ex.gcda • Report: gcov ex.cc, erzeugt: less ex.cc.gcov in der ersten Spalte steht Anzahl der Ausführung: cP (s) = größte Laufzeit auf allen Eingaben mit Größe ≤ s • Bsp: prüfe, ob a[1 . . . n] schwach monoton steigt: for (int i = 0; i<n; i++) { int k = i; for (int j = i+1; j<n; j++) if (b[j]<b[k]) k = j; swap(b[i],b[k]); for nat i von 1 bis n-1 if a[i] > a[i+1] return False return True 1 Vergleich für [8, 1, 7, 2], aber n − 1 Vgl. für [1, 2, . . . , n] Vollständiger Quelltext: https://gitlab.imn. htwk-leipzig.de/waldmann/ad-ss17 – Typeset by FoilTEX – die Zeitkomplexität ist s 7→ (if s = 0 then 0 else s − 1) 36 Zeitkomplexität von Problemen – Typeset by FoilTEX – 37 Komplexität von Programmen • strukturiertes imperatives Programm ist Baum: – Blätter: elementare Anweisung – innere Knoten (zusammengesetzte Anweisungen): Nacheinanderausführung, Verzweigung, Wiederholung • für jede Funktion f : N → N: TIME(f ) := die Menge der Probleme (Spezifikationen), die sich durch einen Algorithmus mit Komplexität f lösen (implementieren) lassen. • Bsp (vorige Folie): Monotonie ∈ TIME(n 7→ n), Bsp (vorige VL): Sortieren ∈ TIME(n 7→ n(n − 1)/2) • für jede Menge von Funktionen F ⊆ N → N: S TIME(F ) = f ∈F TIME(f ) • Monotonie ∈ TIME(linear), Sortieren ∈ TIME(quadrat.) • TIME(alle Polynome) (Abkürzung: P) gilt als die Klasse der effizient lösbaren Probleme. • in der VL Alg. und DS sind wir fast immer in P – Typeset by FoilTEX – 35 • Definition: die Zeitkomplexität des Algorithmus A • kompilieren mit Instrumentierung 8: 9: 10: 11: 12: – Typeset by FoilTEX – Zeitkomplexität von Algorithmen https://gcc.gnu.org/onlinedocs/gcc/Gcov.html 5: 4: 10: 6: 4: 33 Was bedeutet Zeit? Plan – Typeset by FoilTEX – – Typeset by FoilTEX – • die Komplexität bestimmen wir durch: – elementar: 1 Schritt – zusammengesetzt: ∗ Nacheinanderausführung: Summe ∗ Verzweigung: 1 plus Maximum über die Zweige ∗ Wiederholung (Schleife): parametrische Summe, abhängig von Schleifensteuerung (Laufbereich) • später: Komplexität für (rekursive) Unterprogramme 38 – Typeset by FoilTEX – 39 Komplexität v. Progr. (Verzweigung) Komplexität v. Progr. (Schleifen) • Eingabe ist immer [a1, . . . , an] • Eingabe: [a1, . . . , an], Ausgabe und Spezifikation egal nat s := 0; for i from 1 to n if a[i] > 0 then s := s + 1 • for i from 1 to n { for j from 1 to n P P Kosten: ni=1 nj=1 1 = n2 • for i from 1 to n { for j from 1 to i P P Kosten: ni=1 ij=1 1 = . . . • Kosten für die Verzweigung: 1 + 1 oder 1 + 0, also wenigstens 1, höchstens 2 • Kosten für die Schleife: P P wenigstens ni=1 1 = n, höchstens ni=1 2 = 2n • Kosten für gesamtes Programm: bei jeder Eingabe wenigstens 1 + n, höchstens 1 + 2n • Es gibt für jedes n eine Eingabe mit Kosten 1 + 2n: Komplexität ist 1 + 2n • for i from 1 to n for j from i+1 to n for k from j+1 to n e; } e; } e geschlossene Darstellung? Verallgemeinerung (mehr Schleifen dieser Art)? – Typeset by FoilTEX – 40 Asymptotischer Vergleich von Funktionen – Typeset by FoilTEX – 41 Motivation: Abstraktion von. . . • konkreten Kosten elementarer Operationen s := s + 1 kostet 1 oder 2 oder 3? — egal! Wiederholung Funktion n 7→ 2n soll genauso gut sein wie n 7→ 3n. unterschiedliche Komplexitätsfunktionen und ihre Auswirkungen bei Änderung der Eingabegröße: • Kosten durch unwesentliche Programmteile, • wenn f (n) = log2 n, dann f (2n) = . . . z.B. Initialisierungen, die bei kleinen Eingaben evtl. die Gesamtkosten dominieren • wenn f (n) = c · n, dann f (2n) = 2 · f (n) n 7→ max(100, n) soll genauso gut sein wie n 7→ n • wenn f (n) = n2, dann f (2n) = . . . • Sprungstellen, z.B. n 7→ 2blog2 nc • wenn f (n) = 2n, dann f (n + 1) = . . . das ist nützlich, aber nicht alle Funktionen sind so einfach – Typeset by FoilTEX – 42 – Typeset by FoilTEX – Definition, Beispiele 43 Eigenschaften • Def: O(g) := {f | ∃s ≥ 0, c ≥ 0 : ∀n ≥ s : f (n) ≤ c · (g(n))} Funktion f wächst höchstens wie Funktion g Bezeichnung aus der Analysis (das Landau-Symbol) • ist reflexiv • ist nicht symmetrisch (Gegenbeispiel?) • betrachte: f1(n) = n, f2(n) = max(100, n), f3(n) = n /2. 2 • ist nicht antisymmetrisch (Gegenbeispiel?) • f1 ∈ O(f2), Beweis: wähle s = 0, c = 1. • ist transitiv • f2 ∈ O(f1), Beweis: wähle . . . • ist nicht total: • f1 ∈ O(f3), Beweis: wähle s = 0, c = 2. Für f1(n) = n, f5(n) = if 2 | n then n2 else 0 • f3 ∈ / O(f1), Beweis (indirekt): gilt f1 ∈ / O(f2) und f2 ∈ / O(f1). falls s und c lt. Def., dann . . . Widerspruch – Typeset by FoilTEX – die Relation {(f, g) | f ∈ O(g)}: 44 Aber wenn es nur um Polynome geht. . . – Typeset by FoilTEX – 45 Abgekürzte Notation für Funktionen . . . wozu dann der Aufwand? Polynome erkennt man leicht! Nein. Welche der folgenden Funktionen sind (beschränkt durch) Polynome? Von welchem Grad? • richtig: n 7→ n2 (historisch korrekt: λn.n2) • n 7→ n2 • häufig wird Notation der gebundenen Variable vergessen: n2 soll dann eine Funktion bezeichnen. • n 7→ n2 + 10n − 100 log n • Anwendung: n ∈ O(n2) • n 7→ (log n)log n P • n 7→ nk=1blog kc P • n 7→ nk=1blog(n/k)c • gefährlich wird das hier: ist x2y quadratisch oder linear? unklar, ob x 7→ x2y gemeint ist oder y 7→ x2y oder. . . • lustige work-arounds zur Vermeidung der richtigen Notation: für ein festes y“ u.ä. ” Solche Funktionen kommen als Kostenfunktionen von Algorithmen vor und müssen richtig eingeordnet werden. – Typeset by FoilTEX – die gebundene Variable n wird explizit notiert. 46 – Typeset by FoilTEX – 47 Abgekürzte Notation f. Mengen v. Funktionen • richtig: f ∈ O(g), denn O(g) ist eine Menge • Satz: falls lim • stattdessen häufig: f = O(g) . . . auch: n = O(n ) • Anwendungen (für f1(n) = n, f2(n) = max(100, n), f3(n) = n2/2) • wie bei allen Abkürzungen: für Fachleute nützlich, aber der Anfänger wundert sich. • limn→+∞ f1(n)/f2(n) = 1, limn→+∞ f2(n)/f1(n) = 1 • Anwendung: 3n + O(n2) = O(n2) ist Gleichung zwischen Mengen von Funktionen ∀f ∈ O(n2) : (n 7→ 3n + f (n)) ∈ O(n2) ∧ ∀g ∈ O(n2) : ∃f ∈ O(n2) : ∀n : 3n + f (n) = h(n) • limn→+∞ f1(n)/f3(n)?, limn→+∞ f3(n)/f1(n)?, • Umkehrung diese Satzes gilt nicht! Bsp: f4 = n 7→ 2blog2 nc, vergleiche mit f1. 48 Weitere Notationen – Typeset by FoilTEX – 49 Asympt. Vergleich von Standardfunktionen (wie immer: alle Funktionen aus N → N) • Def: O(g) := {f | ∃s ≥ 0, c ≥ 0 : ∀n ≥ s : f (n) ≤ c · (g(n))} f ∈ O(g) bedeutet: f wächst höchstens so wie g • Def: Ω(g) := {f | g ∈ O(f )}. f ∈ Ω(g) bedeutet: f wächst wenigstens so wie g • Def: Θ(g) := O(g) ∩ Ω(g). f ∈ Θ(g) bedeutet: f und g wachsen gleich schnell. • Potenzen verschiedener (auch nicht-ganzer) Grade: ∀p, q ∈ R>0 : p < q ⇒ np ∈ o(nq ) • Logarithmus und Potenz ∀p, q ∈ R>0 : logp(n) ∈ o(nq ) √ Bsp: log10 n ∈ o( 3 n) • Potenz und Exponential ∀p ∈ R>0, q ∈ R>1 : np ∈ o(q n) • Produkte von Potenz und Logarithmus np1 · logq1 n ∈ o(np2 · logq2 n) gdw. . . . ω(g) := Ω(g) \ O(g). • Satz: falls limn→+∞ f (n)/g(n) = 0, dann f ∈ o(g) Beweis (indirekt): falls g ∈ O(f ), dann für . . . – Typeset by FoilTEX – = c ∈ R existiert, dann f1 ∈ O(f2). • Beweis (Skizze): Definition, Einsetzen, Umformen limn xn = c ⇐⇒ ∀ > 0 : ∃s : ∀n ≥ s : c − ≤ xn ≤ c + , • gefährlich, weil das Symbol =“ ” dann nicht mehr symmetrisch und transitiv ist: n = O(n2) und n2 = O(n2), also folgt (optisch) n = n2 • Def: o(g) := O(g) \ Ω(g), f1(n) n→+∞ f2(n) 2 – Typeset by FoilTEX – Eine Vergleichsmethode alle Beweise mittels Limes-Kriterium 50 – Typeset by FoilTEX – 51 Anwendung Spezielle Funktionen Eine klassische Übungsaufgabe aus [CLR]: • Logarithmus • Ordne das asymptotische Wachstum von – in der Informatik grundsätzlich zur Basis 2 – die Basis ist oft ganz egal: log10 ∈ Θ(log2). • iterierter Logarithmus: log (d.h., bestimme alle O-Relationen zwischen) ∗ √ log n ∗ (log n)log n 2log n 2 n2 n! (log n)! ∗ log log n log log n log n n n · 2n log n 1 2 3 2n 1/ log n (3/2)n n log n log(n!) 2 n √ n+1 log∗(log n) 2 2 log n n n log n 2n 22 √ ∗ log n log n 2 exp(n) log(log n) 4 (n + 1)! log n – definiert durch n 7→ if n ≤ 1 then 0 else 1 + log∗blog nc – sehr langsam wachsend x 0 1 2 4 16 65536 265536 ∗ log x 0 0 1 2 3 4 5 • Fakultät, Def: n! := 1 · 2 · . . . · n – Satz: log(n!) = Θ(n log n) – Beachte: es gilt nicht n! ∈ Θ(nn) – Typeset by FoilTEX – • insbesondere: welche Paare sind Θ-äquivalent? 52 – Typeset by FoilTEX – 53 • (2 P) Wie oft wird Anweisung e ausgeführt? Geben Sie die Antwort als Funktion von n an. Übungsserie 2 (für KW 16) Aufgabe 2.1 for x = 1 to n for y = 1 to n if not (x = y) for z = 1 to n if not (x = z) && not (y = z) e • (1 P) Geben Sie die Folge der Belegungen von x, y, z an für n = 2, • (1 P) . . . , für n = 3. – Typeset by FoilTEX – 54 – Typeset by FoilTEX – 55 Aufgabe 2.2 Die Binärdarstellungen aller Zahlen von 0 bis n werden nebeneinandergeschrieben. Als Darstellung der 0 benutzen wir dabei die leere Ziffernfolge. Die Gesamt-Anzahl der Vorkommen der 1 nennen wir B(n). Beispiel: von 0 bis 3: [[], [1], [1, 0], [1, 1]], B(3) = 4. • (1 P) Bestimmen Sie B(100) (z.B. durch ein Programm) Darstellung von n wird. Die Gesamt-Anzahl der dabei hinzugefügten 0 nennen wir F (n). Beispiel: [[0, 0], [0, 1], [1, 0], [1, 1]], F (3) = 3. • (1 P) Bestimmen Sie F (100) (z.B. durch Modifikation des vorigen Programms) • (2 P) Geben Sie F (n) als Θ einer einfachen Funktion von n an. • (1 P) Geben Sie B(2w − 1) exakt an. • (2 P) Begründen Sie B(n) ∈ Θ(n log n). Die Binärdarstellungen von 0 bis n − 1 werden durch führende Nullen ergänzt, so daß jede so lang wie die – Typeset by FoilTEX – 56 – Typeset by FoilTEX – 57 Aufgabe 2.2 (Musterlösung einer Teilaufgabe) • B(100) = 319 1 1 1 1 • experimentell kann Wertetabelle bestimmt werden: w 0 1 2 3 4 5 6 7 8 B(2w − 1) 0 1 4 12 32 80 192 448 1024 • Zu zeigen ist B(n) ∈ Θ(n log n). Beweis: alle Binärzahlen untereinanderschreiben Bekannt sind 58 – ∀w > 0 : B(2w − 1) = w · 2w−1 (siehe oben) – B ist streng monoton (wenn x < y, dann B(x) < B(y), denn von x bis y sind y − x Zahlen hinzugekommen und jede enthält wenigstens ein 1-Bit) Beweis: – für jedes n gibt es w mit 2w − 1 ≤ n < 2w+1 − 1, nämlich w = blog(n + 1)c. Begründung: dann gilt w ≤ log(n + 1) < w + 1 nach Def. von b·c, also 2w ≤ n + 1 < 2w+1, daraus Behauptung. – wegen Monotonie von B und bekannten Werten gilt w · 2w−1 = B(2w − 1) ≤ B(n) < B(2w+1 − 1) = (w + 1) · 2w – in der oberen Schranke schätzen wir w nach oben ab: – Typeset by FoilTEX – 60 – Typeset by FoilTEX – 59 B(n) < (w + 1) · 2w+1 ≤ (log(n + 1) + 1) · 2log(n+1) = (log(n + 1) + 1) · (n + 1) Für n ≥ 1 setzen wir die Ungleichungskette fort · · · ≤ (log(2n)+1)·2n = (log n+1+1)·2n = (log n+2)·2n Für n ≥ 4 weiter: · · · ≤ (log n + log n) · 2n = 4n log n Daraus folgt B ∈ O(n log n), denn wir haben gezeigt ∀n ≥ 4 : B(n) ≤ 4n log n. – entsprechend für untere Schranke: B(n) ≥ w · 2w−1 > (log(n + 1) − 1) · 2log(n+1)−2 > (log n − 1) · 2log n−2 = (log n − 1) · n/4 Für n ≥ 4 ist log n ≥ 2 und log n − 1 ≥ log n − (log n/2), also B(n) ≥ · · · ≥ (log n/2) · n/4 = (1/8)n log n Daraus folgt n log n ∈ O(B), denn wir haben gezeigt ∀n ≥ 4 : n log n ≤ 8B(n). – Typeset by FoilTEX – 61 Aufgabe 2.3 Diskussion: aus B(2 − 1) = w · 2 mit n = 2 − 1 kann man (sollte man zunächst) die Überschlagsrechnung durchführen: w 1 0 1 0 1 0 1 das sind 2w Zeilen (die erste ist leer) mit je w Spalten und in jeder Spalte ist die Hälfte der Einträge gleich 1. daraus Vermutung: B(2w − 1) = w · 2w−1 – Typeset by FoilTEX – 1 1 0 0 1 1 w−1 w n ≈ 2w , also w ≈ log n, also B(n) ≈ log n · 2log n−1 = log n · n/2 ∈ Θ(n log n). (4 P) Welche O, Θ-Relationen gelten zwischen √ √ √n f1(n) = n − n, f2(n) = n , f3(n) = n Aber: das ist kein Beweis, man muß nachrechnen daß der Fehler bei ≈ “ nicht wesentlich ist, und das geht am ” sichersten durch exakten Nachweis der beiden O-Beziehungen – Typeset by FoilTEX – 62 – Typeset by FoilTEX – 63 Einfache Algorithmen auf Zahlen und Feldern Aufgabe 2.4 • (4 P) Für Funktionen f, g : N → N: Beweisen Sie max(f, g) ∈ Θ(f + g). Übersicht Hierbei bezeichnen • Euklidischer Algorithmus max(f, g) die Funktion n 7→ max(f (n), g(n)) • Multiplizieren durch Verdoppeln sowie f + g die Funktion n 7→ f (n) + g(n). • Schleifen-Invarianten • Schranken • binäre Suche in geordnetem Feld • dutch national flag – Typeset by FoilTEX – 64 Eingabe: nat x, nat y; Ausgabe: gcd(x,y) // x = X, y = Y (Bezeichung für Eingabe) while true // I: gcd(x,y) = gcd(X,Y) if x = 0 then return y if y = 0 then return x if x = y then return x if x < y then y := y - x else x := x - y • partielle Korrektheit: wg. Schleifen-Invariante I: 1. anfangs wahr, 2. invariant, 3. schließlich nützlich • Termination: x+y ist Schranke: (bound, ranking function) – Wertebereich ⊆ N – Wert nimmt bei jedem Schleifendurchlauf ab • Komplexität: linear in x + y, exponentiell in log x + log y • Die Teilbarkeitsrelation auf N: Def: a | c : ⇐⇒ ∃b ∈ N : a · b = c • Bsp: 13 | 1001, 13 | 13, 13 | 0, ¬(0 | 13), 0 | 0 • Eigenschaften: Halbordnung, nicht total. • der größte gemeinsame Teiler. Def: gcd(x, y) = g gdw. g | x ∧ g | y und ∀h : h | x ∧ h | y ⇒ h | g Beachte: hier kommt kein < “ vor! ” • Eigenschaften: gcd(0, y) = y, gcd(x, x) = x, gcd(x, y) = gcd(y, x) gcd(x, y) = gcd(x, x − y) 66 • zu jeder Schleife gehören: – Spezifikation ∗ die Invariante I (eine logische Formel) ∗ die Schranke S (ein Ausdruck mit Wert ∈ N) – Programmtext while B do K ( B edingung, K örper) I ist vor der Schleife wahr I ist invariant unter K I ist nach der Schleife nützlich K verringert S oder macht B falsch 68 Algorithmus von Euklid (Variante 2) • Multiplikation durch: Halbieren, Verdoppeln, Addieren • Eingabe: nat a, nat b; Ausgabe: a * b // A = a, B = b p := ... while a > 0 // I: a * b + p = A * B // Schranke: log (a) if odd a then p := ... (a, b) = (div(a,2), ...) return p – Typeset by FoilTEX – 69 Laufzeit von Euklid (Variante 2) • Folge der Belegungen (xs, ys), (xs−1, ys−1), . . . , (x1, 0). • Plan: wiederholte Subtraktion ⇒ Division mit Rest wobei ∀k : yk = xk−1 ∧ mod(xk , xk−1) = xk−2 und x0 = 0 • Def: mod(x, y) = z ⇐⇒ ∃f : x = f · y + z ∧ 0 ≤ z < y • ∀s > k : xk > xk−1 (Rest ist kleiner als Divisor) • Satz: y > 0 ⇒ gcd(x, y) = gcd(mod(x, y), y) • ∀s > k : xk − xk−1 ≥ xk−2 (Quotient ist ≥ 1) • Eingabe: nat x, nat y; Ausgabe: gcd(x,y) // x = X, y = Y (Bezeichung für Eingabe) while true // I: gcd(x,y) = gcd(X,Y) if y = 0 then return x (x,y) := (y, mod(x,y)) // simultan! • daraus folgt ∀s > k ≥ 2 : xk ≥ xk−1 + xk−2 • damit xs−1 ≥ Fs−1 für Fibonacci-Zahlen F0 = 0, F1 = 1, ∀k ≥ 0 : Fk+2 = Fk+1 + Fk • aus Fk ∈ Θ(q k ) für q ≈ 1.6 (Details: nächste Folie) • partiell korrekt wg. I (wie Variante 1) folgt logq (xs−1) ≥ s (Schrittzahl ist O(log y)) • Schranke: x + y wie vorher — es gibt besser Schranke – Typeset by FoilTEX – 67 • Anwendung in der Kryptographie (RSA): Potenzieren (nach einem Modul) durch Halbieren, Quadrieren, Multiplizieren (David Gries: The Science of Programming, Springer, 1981; Kapitel 11) – Typeset by FoilTEX – – Typeset by FoilTEX – Multiplizieren durch Verdoppeln Entwurf und Analyse von Schleifen •– – – – 65 Algorithmus von Euklid (Variante 1) Der größte gemeinsame Teiler (gcd) – Typeset by FoilTEX – – Typeset by FoilTEX – 70 – Typeset by FoilTEX – 71 Die Fibonacci-Zahlenfolge Binäre Suche in geordnetem Feld • Def: F0 = 0, F1 = 1, ∀k ≥ 0 : Fk+2 = Fk+1 + Fk • Leonardo Pisano, ca. 1200, http://www-groups.dcs. st-and.ac.uk/history/Biographies/Fibonacci.html • k 0 1 2 3 4 5 6 10 20 30 Fk 0 1 1 2 3 5 8 55 6765 832040 wächst exponentiell, Basis ist goldener Schnitt q ≈ 1.6 √ • Satz: mit q = ( 5 + 1)/2 gilt Fk = (q k − 1/(−q)k )/(q + q −1) Beweis: Induktion, benutze q 2 = q + 1, q −2 = −q −1 + 1 • wegen limk→∞ 1/(−q)k = 0 folgt Fk ∈ Θ(q k ) – Typeset by FoilTEX – 72 Spezifikation: Eingabe: a[1..n] schwach monoton steigend, x Ausgabe: falls exists i: a[i] = x, dann ein i mit a[i] = x, sonst NEIN Implementierung (divide and conquer ) nat l := ... ; nat r := ... while ... // Schranke: log (r - l) // I: a[1 .. l-1] < x , x < a[r+1 .. n] nat m = div (l+r,2) if a[m] = x then return m else if a[m] < x then ... else ... Laufzeit: Θ(log n). – Typeset by FoilTEX – Binäre Suche in geordnetem Feld (Var. 2) Binäre Suche (Var. 2) in Java Spezifikation (beachte: Grenzen sind l und r) • Eingabe: a[l..r] schwach monoton steigend, x • Ausgabe: falls ∃i : a[i] = x, dann solch ein i, sonst NEIN Implementierung (mit Rekursion statt Schleife): search (a [l .. r], x) = if l > r then return NEIN else nat m = div (l+r,2); if a[m] = x then return m else if a[m] < x then search(a[m+1 .. r],x) else search(a[l .. m-1],x) Korrektheit: x ∈ a[l . . . r] ⇐⇒ a nicht leer und (x < a[m] ∧ x ∈ a[l . . . m − 1]) ∨x = a[m] ∨ (x > a[m] ∧ x ∈ a[m + 1 . . . r]) boolean search (List<Integer> a, int x) { if (a.isEmpty()) return false; else { int m = (a.size() - 1) / 2; if (a.get(m) == x) return true; else if (a.get(m) < x) return search(a.subList( 0, m), x); else return search(a.subList(m+1,a.size()), x); } • benutzt interface List<T> mit Methode List<T> subList(int from, int to) zur Konstruktion einer Teilfolge (slice) als Ansicht (view) (d.h., ohne Daten zu kopieren) • in Var. 1 (Schleife) ist diese Ansicht implizit repräsentiert (durch l und r), das ist schlecht für den Leser – Typeset by FoilTEX – 74 Bemerkung zum Programmierstil 75 E.W. Dijkstra: A Discipline of Programming (Kap. 14), Prentice-Hall, 1976 • Eingabe: Folge a[1 . . . n] ∈ {Blau, Rot}∗ • Ausgabe: Folge b mit – Multimenge von a = Multimenge von b – b schwach monoton bzgl. B < R • Sonst wird der (optische, mentale) Abstand zwischen Spezifikation, Beweis und Implementierung zu groß . . . • und deswegen (der Beweis schwierig und) die Implementierung wahrscheinlich falsch. • Wenn man die explizite Repräsentation nicht vernünftig hinschreiben kann, hat man die falsche Sprache gewählt; • wenn die Repräsentation nicht effizient ist, dann den falschen Compiler. – Typeset by FoilTEX – – Typeset by FoilTEX – Die Flagge färben (Vorbereitung: 2 Farben) • Das, worüber man (in Spezifikation, in Beweis) spricht, soll im Programmtext explizit repräsentiert sein. Bsp. hier: Teilfolgen 76 Die Flagge färben (wirklich: 3 Farben) Ansatz (b wird in a konstruiert) while ( ... ) // Schranke: r - l // I: a[1..l-1] = B, a[r+1..n] = R if a[l] = B then ... else if a[r] = R then ... else { a[l] <-> a[r]; ... } – Typeset by FoilTEX – 77 Hinweis zu Übungsaufgabe 3.3 • Eingabe: Folge a[1 . . . n] ∈ {Blau, Weiß, Rot} ∗ • Eingabe: Felder a[1..s], b[1..t] schwach monoton steigend. Ausgabe: ein Paar (i, j) mit a[i] = b[j], falls das existiert. • Ausgabe: Folge b mit • Vorgehen: funktional (rekursiv) ⇒ iterativ (Schleife) – Multimenge von a = Multimenge von b – b schwach monoton bzgl. B < W < R Ansatz: l = ... ; m = ... ; r = ... // I: a[1..l-1]=B, a[l..m-1]=W, a[r+1..n]=R // Schranke? while ... if a[m]=B { a[m] <-> a[...]; ... } else if a[m]=R { a[m] <-> a[...]; ... } else { ... } – Typeset by FoilTEX – 73 78 • verallgemeinere (Teilfolgen): Eingabe: a[p . . . s], b[q . . . t] • Zerlegungen a = a[p] ∪ a[p + 1 . . . s], b = b[q] ∪ b[q + 1 . . . t] a ∩ b = (a[p] ∪ a[p + 1 . . . s]) ∩ b a[p] < b[q] ⇒ a[p] ∩ b = ∅, also a ∩ b = a[p + 1 . . . s] ∩ b entspr. für a[p] > b[q] • Variablen p, q in Schleife repräsentieren a[p . . . s], b[q . . . t] Invariante: a[1 . . . s] ∩ b[1 . . . t] = a[p . . . s] ∩ b[q . . . t] – Typeset by FoilTEX – 79 Aufgabe 3.2 (Euklid, Variante 3) Übungsserie 3 (für KW 17) Aufgabe 3.1 (Euklid, Variante 1) • (1 P) Kann man Zeile if x = y ... weglassen? • (1 P) Kann man Zeile if x = 0 ... weglassen? • (1 P) Die beiden Anweisungen if x = 0 ..., if y = 0 ... können aus der Schleife entfernt und vor diese geschrieben werden. Warum? Geben Sie die verschärfte Invariante an. • (1 P) Interessant ist dabei immer nur die Termination, denn partielle Korrektheit gilt in jedem Fall – warum? – Typeset by FoilTEX – Die GNU Multiprecision-Bibliothek (T. Granlund et al., FSF, 1991–2016) https://gmplib.org/manual/Binary-GCD.html enthält diesen gcd-Algorithmus, der (wie Variante 1, im Gegensatz zu Variante 2) keine Divisionen benutzt (Division durch 2 ist binär leicht realisierbar). while ... (a,b) := (abs(a-b), min(a,b)) // 1 if even(a) then a := div(a,2) // 2 if even(b) then b := div(b,2) // 3 Die Invariante soll auch hier sein: I : gcd(a, b) = gcd(A, B) (der gcd der aktuellen a, b ist der gcd der Eingabe). • (1 P) Begründen Sie, daß I invariant ist unter Anweisung 80 – Typeset by FoilTEX – 81 Aufgabe 3.3 (Suche in mehreren Feldern) 1, aber nicht invariant ist unter Anweisung 2 (ebenso 3) Spezifikation: Eingabe: Felder a[1..s], b[1..t], jedes ist schwach monoton steigend. Ausgabe: ein Paar (i, j) mit a[i] = b[j], falls das existiert, sonst NEIN. • (2 P) Deswegen wird Bedingung U : wenigstens einer ” von a, b ist ungerade“ betrachtet. Begründen Sie, daß I ∧ U invariant ist unter Anweisungen 2 (ebenso 3). • (1 P) Begründen Sie, daß I ∧ U invariant ist unter Anweisung 1. • (1 P) Beschreiben Sie das Verhalten dieses Algorithmus für a = sehr groß, b = sehr klein, und vergleichen Sie mit Euklid in Variante 1. • (3 P) Geben Sie eine Implementierung mit einer Laufzeit an, die durch eine lineare Funktion von s + t beschränkt ist. Benutzen Sie ein Programm mit einer Schleife. Geben Sie deren Invariante und Schranke an. • (2 P) Geben Sie √ ein Verfahren an, das die Aufgabe in o(t) löst, falls s = t. Benutzen Sie einen Algorithmus aus – Typeset by FoilTEX – 82 – Typeset by FoilTEX – 83 Aufgabe 3.4 (Suche im Rechteck) dem Skript. Spezifikation: Eingabe: ein Feld a[1..n, 1..n], eine Zahl x, wobei jede Zeile und jede Spalte von a schwach monoton steigen Ausgabe: ein Paar (i, j) mit a[i, j] = x, falls das existiert, sonst NEIN. • (4 P) Geben Sie eine Implementierung mit einer Laufzeit O(n) an. Benutzen Sie ein Programm mit einer Schleife. Geben Sie deren Invariante und Schranke an. – Typeset by FoilTEX – 84 – Typeset by FoilTEX – Sortieren in Feldern und Listen 85 Entscheidungsbäume • jedes Sortierverfahren, das die Elemente der Eingabe nur vergleicht (a[i] > a[j]) und vertauscht – Beispiele sind: Sortieren durch Auswählen, Compare-Exchange-Netzwerke – Nicht-Beispiele: Arithmetik a[i] + a[j], Indizierung b[a[i]] Übersicht • untere Schranke für Sortieren durch Vergleichen [WW] 6.3 • Inversionen [WW] 1.3 • Shell-Sort [WW] 4.3, [OW] 2.1.3 • läßt sich für jede Eingabelänge n als Baum darstellen: – innere Knoten sind Vergleiche a[i] > a[j], haben 2 Kinder (Fortsetzung bei >, bei ≤) – Blatt-Knoten sind Ausgaben (Permutationen) • Rechnen mit Folgen (Listen) • Jede der n! Permutationen kommt ≥ 1 mal vor • Sortieren durch Einfügen [WW] 4.1.3, [OW] 2.1.2 • Merge-Sort [WW] 7.1, [OW] 2.4 – Typeset by FoilTEX – • ⇒ Höhe des Baumes ist ≥ log2(n!) 86 – Typeset by FoilTEX – 87 Untere Schranke für Sortierverfahren Höhe und Breite von Binärbäumen • Def: Die Höhe h(t) eines Baumes t ist die Länge eines längsten Pfades von der Wurzel zu einem Blatt. • Für jedes vergleichsbasierte Sortierverfahren A gilt: für jedes n gilt: es gibt eine Eingabe der Länge n, für die A wenigstens dlog2(n!)e Vergleiche durchführt. • Def: Die Länge eines Pfades = Anzahl der Kanten (Schritte) auf dem Pfad • (die Anzahl der Knoten ist um eins größer) n 1 2 3 4 5 6 7 8 9 10 dlog2(n!)e 0 1 3 5 7 10 13 16 19 22 • welche speziellen Verfahren (für diese n) erreichen diese Schranke? • Satz: Für jeden Binärbaum t gilt: Die Anzahl der Blätter B(t) ist ≤ 2h(t). • Die Komplexität des Sortierens ist Ω(n log n). • Beweis durch Induktion. Anfang: h(t) = 0 : t ist Blatt. • welche allgemeinen Sortiervefahren sind in O(n log n)? Sortieren durch Auswählen nicht — ist in Θ(n2) Schritt: h(t) > 0: t hat Kinder t1, t2 mit h(ti) ≤ h(t) − 1 B(t) = B(t1) + B(t2) ≤ 2 · 2h(t)−1 = 2h(t) – Typeset by FoilTEX – 88 – Typeset by FoilTEX – Nebenrechnung: Wachstum von log n! Zählen von Inversionen • Def: für eine Folge a[1 . . . n]: Menge der Inversionen ist Inv(a) := {(i, j) | 1 ≤ i < j ≤ n ∧ a[i] > a[j]} # Inv(a) : Anzahl der Inversionen von a • Satz: log2 n! ∈ Θ(n log n) • Beweis: Q P – Umformung: log2 n! = log2 nk=1 k = nk=1 log2 k – Abschätzung nach oben (mit k ≤ n, Monotonie des log, Monotonie der Summe) Pn Pn k=1 log2 k ≤ k=1 log2 n = n log2 n deswegen log2 n! ∈ O(n log n) – Abschätzung nach unten Pn Pn k=1 log2 k ≥ k=dn/2e log2 k ≥ (n − 1)/2 · log2(n/2) Für n ≥ 4 gilt: (n − 1)/2 ≥ (n − n/2)/2 = n/4 und log2(n/2) = log2 n − 1 ≥ (log2 n)/2 deswegen n log n ∈ O(log2 n!) – Typeset by FoilTEX – • Bsp: a = [4, 2, 5, 3, 1], Inv(a) = {(1, 2), (1, 4), (1, 5), (2, 5), (3, 4), (3, 5)} • für alle a der Länge n: 0 ≤ # Inv(a) ≤ n(n − 1)/2 • Satz: wenn (k, k + 1) ∈ Inv(a) und b aus a durch a[k] ↔ a[k + 1] entsteht dann # Inv(b) = # Inv(a) − 1. • Bsp (forgesetzt von oben): k = 3, b = [4, 2, 3, 5, 1] Inv(b) = {(1, 2), (1, 3), (1, 5), (2, 5), (4, 5)} 90 – Typeset by FoilTEX – 91 Inversionen und einfache Sortierverfahren Zählen von Inversionen (Beweis) Bijektion zwischen Inv(a) \ {(k, k + 1)} und Inv(b): durch vollst. Fallunterscheidung für (i, j) ∈ Inv(a): • Satz: Jedes Sortierverfahren, das nur benachbarte Elemente vertauscht, • (i, j) und (k, k + 1) sind disjunkt: hat Komplexität Ω(n2). falls {i, j} ∩ {k, k + 1} = ∅, dann (i, j) ∈ Inv(b). • Beweis: jeder solche Tausch entfernt nur eine Inversion, • (i, j) und (k, k + 1) stimmen an einer Stelle überein: – – – – 89 es gibt aber Eingaben mit n(n − 1)/2 Inversionen. falls i < k = j, dann (i, j + 1) ∈ Inv(b) falls i < k ∧ k + 1 = j, dann (i, j − 1) ∈ Inv(b) falls i = k ∧ k + 1 < j, dann (i + 1, j) ∈ Inv(b) falls i = k + 1 < j, dann (i − 1, j) ∈ Inv(b) • Anwendung 1: (Satz) jedes Sortiernetz der Breite n, das nur benachbarte Positionen vergleicht (und tauscht), benötigt ≥ n(n − 1)/2 CEX-Bausteine. • Anwendung 2: (Plan) Sortieren durch Auswählen verbessern durch größere Abstände • (i, j) und (k, k + 1) stimmen an beiden Stellen überein: das ist genau Inversion, die entfernt wird – Typeset by FoilTEX – 92 – Typeset by FoilTEX – Inversionen und Laufzeit 93 Sortieren durch Einfügen • Plan (Sortieren durch Einfügen): • Sortieren durch Auswählen dauert immer |a| /2 2 for i from 2 to n // I: a[1..i-1] monoton füge a[i] in a[1..i-1] ein • wenn Inv(a) klein, dann ist a fast monoton,“ ” • dann sollte das Sortieren schneller gehen. • Realisierung (durch Vertauschungen): // I1: a ist Permutation der Eingabe // und a[1..i-1] ist monoton steigend for i from 2 to n { nat j := i-1; // I2: a[1..j] monoton und a[j+1..i] monoton // und (0<j and j<i-1) => a[j] <= a[j+2] while (j >= 1 and a[j] > a[j+1]) a[j] <-> a[j+1]; j := j-1; } • Gibt es Sortierverfahren mit Komplexität in O(# Inv(a))? • Nein, selbst wenn # Inv(a) = 0, muß man die gesamte Eingabe lesen, um Monotonie festzustellen • realistisches Ziel: Sortierverfahren in O(|a| + # Inv(a)) • Zeit: Θ(n + # Inv(a)) – Typeset by FoilTEX – 94 – Typeset by FoilTEX – 95 Shell-Sort: Vorbereitung Shell-Sort: Vorbereitung—Beweis • Bezeichnungen: k-geordnetes a , Resultat b := h-Sort(a) • (Eigenschaft) a[1..n] heißt k-geordnet, falls ∀i : a[i] ≤ a[i + k] • Beweis: zu zeigen ist ∀i : b[i] ≤ b[i + k] Bsp: a = [4, 2, 0, 6, 5, 1, 7, 8, 3] ist 3-geordnet. • Fall 1: wenn h | k, dann b[i] ≤ b[i + h] ≤ · · · ≤ b[i + p · h]. • (Algorithmus) a wird k-sortiert: • Fall 2: wenn nicht h | k, für i von 1 bis k − 1: sortiere a[i, i + k, i + 2k, . . . ] dann E = a[. . . , i − h, i, i + h, . . . ] Bsp: 2-Sort von a ist [0, 1, 3, 2, 4, 6, 5, 8, 7] • Satz: für h < k: wenn a k-geordnet ist und h-sortiert wird, ist es danach immer noch k-geordnet. und F = a[. . . , i + k − h, i + k, i + k + h, . . . ] b[i + k] ist ≥ als (i + k)/h Elemente von F . Davon sind i/h Stück ≥ als i/h Stück von E. Die sind ≥ als die i/h kleinsten von E, d.h. ≥ b[i]. – Typeset by FoilTEX – 96 – Typeset by FoilTEX – Shell-Sort: Idee 97 Shell-Sort: Hilfssatz 1 • Algorithmus: für eine geeignete Folge hl > . . . > h2 > h1: für s von l bis 1: a wird hs-sortiert durch Einfügen • Satz (trivial). h1 = 1 ⇒ Algorithmus ist korrekt. • Komplexität: hängt von h ab. z.B. h = [1]: quadratisch • Ziel bei der Konstruktion von h: – hi groß ⇒ Teilfolgen kurz ⇒ schnell sortiert – dabei genügend viele Inversionen entfernen – so daß weitere Schritte (kleine hi) auch schnell • D.L. Shell, CACM 2(7) 30–32, 1959. ausführliche Analyse in [DEK] Band 3, Abschnitt 5.2.1 • Implementierung: https://gitlab.imn.htwk-leipzig. • Lemma: Wenn gcd(h, k) = 1 und a ist h-geordnet und k-geordnet, – Typeset by FoilTEX – – Typeset by FoilTEX – dann für jedes d ≥ (h − 1) · (k − 1): a ist d-geordnet • Beweis: ∃a, b ∈ N : d = ah + bk (Satz v. Sylvester, 1884) • Beispiel: gcd(4, 7) = 1, größte nicht als a · 4 + b · 7 darstellbare Zahl ist . . . . de/waldmann/ad-ss17/blob/master/kw17/shell.cc 98 Shell-Sort: Hilfssatz 2 Shell-Sort: eine geeignete Differenzenfolge • Satz: Shell-Sort mit [. . . , 22 − 1, 21 − 1] dauert O(n3/2). • Lemma: Für Shell-Sort mit Differenzenfolge [. . . , hs+2, hs+1, hs, . . . ] mit gcd(hs+2, hs+1) = 1 • Vor hs-Sortieren gilt: Anzahl aller Inversionen in allen hs-Teilfolgen ist ≤ n · 2s+3 (nach Lemma 2) gilt nach hs+1-Sortieren: jede hs-Teilfolge hat ≤ (n/hs) · ((hs+2 − 1) · (hs+1 − 1)/hs) Inversionen • Anzahl aller Inversionen in allen hs-Teilfolgen ist ≤ hs · (n/hs)2 • Beweis: das Resultat ist d-geordnet für d ≥ (hs+2 − 1) · (hs+1 − 1). (Anzahl der Folgen, max. Inversionszahl einer Folge) Jede Teilfolge hat Länge ≤ n/hs • das hs-Sortieren kostet ≤ min(hs(n/hs)2, n · 2s+3) √ benutze linke Schranke für hs > n, dann rechte und ist d-geordnet für d ≥ (hs+2 − 1) · (hs+1 − 1)/hs. Von jeder Position jeder Teilfolge aus gibt es < (hs+2 − 1) · (hs+1 − 1)/hs Inversionen. – Typeset by FoilTEX – ≤ 2t +2t+1 +· · ·+2t+t/2 +2t+t/2 +· · ·+2t ∈ O(23t/2) = O(n3/2). √ (vereinfachte Rechnung mit n = 2t, n = 2t/2, hs = 2s) 100 Rechnen mit Folgen (Listen) – Typeset by FoilTEX – 101 Das Zusammenfügen von monotonen Folgen • Spezifikation: merge : L × L → L (a, b schwach monoton steigend und c = merge(a, b)) ⇒ – Multimenge(a) ∪ MM(b) = MM(c) – und c ist schwach monoton steigend • Bsp. merge([1, 2, 2, 3, 5], [0, 3]) = [0, 1, 2, 2, 3, 3, 5] • Implementierung: – merge(empty, b) = b; merge(a, empty) = a – merge(cons(x, a0), cons(y, b0)) = wenn x ≤ y, dann cons(x, merge(a0, cons(y, b0))) sonst cons(y, merge(cons(x, a0), b0)) • Korrektheit: benutzt MM(cons(x, y)) = {x} ∪ MM(y) • Komplexität (Anzahl der Vergleiche) ist ≤ |a| + |b| − 1 Das ist auch die Schranke für die Rekursion. • abstrakter Datentyp Folge L mit Elementtyp E mit Operationen – Konstruktoren: empty : L, cons : E × L → L – Accessoren (für nicht leere Folgen): head : L → E, tail : L → L – Test: null : L → B mit Axiomen: ∀x ∈ E, y ∈ L: – 1. head(cons(x, y)) = x, 2. tail(cons(x, y)) = y – 3. null(empty), 4. ¬ null(cons(x, y)) • Implementierung (Mathematik): L = E ∗ • Impl. (Programmierung): Zeiger, typedef C * L – leere Liste: nullptr – nichtleer: struct C { E head; L tail; } – Typeset by FoilTEX – 99 102 – Typeset by FoilTEX – 103 Merge: Korrektheit (1) Wegen Assoziativität: · · · = ({x} ∪ MM(a0)) ∪ MM(b) = MM(a) ∪ MM(b) zu zeigen: MM(a) ∪ MM(b) = MM(merge(a, b)) Beweis durch Induktion nach |a| + |b| • Falls . . . und x > y, dann symmetrisch. • – falls null(a), dann merge(a, b) = b und MM(a) ∪ MM(b) = ∅ ∪ MM(b) = MM(b). – falls null(b), dann symmetrisch • Falls a = cons(x, a0) und b = cons(y, b0) mit x ≤ y, dann merge(a, b) = cons(x, merge(a0, b)) und MM(merge(a, b)) = MM(cons(x, merge(a0, b))) = {x} ∪ MM(merge(a0, b). Wegen |a0| + |b| < |a| + |b| ist Induktionsvoraussetzung anwendbar und es gilt · · · = {x} ∪ (MM(a0) ∪ MM(b)) – Typeset by FoilTEX – 104 Merge: Korrektheit (2) – Typeset by FoilTEX – 105 Also ∀z ∈ MM(a0) ∪ MM(b) : x ≤ z. Def: a ist monoton ⇐⇒ null(a) oder a = cons(x, a ) und ∀z ∈ MM(a0) : x ≤ z und a0 ist monoton. Zu zeigen: wenn a monoton und b monoton, dann merge(a, b) monoton. Beweis durch Induktion nach |a| + |b| 0 Wg. Multimengen-Erhaltung ist MM(merge(a0, b)) = MM(a0) ∪ MM(b) und damit ∀z ∈ MM(merge(a0, b)) : x ≤ z • Falls null(a), dann merge(a, b) = b, das ist nach Voraussetzung monoton. Falls null(b), dann symmetrisch Nach Induktion ist merge(a0, b) monoton und (eben gezeigt) x ist ≤ jedem Element aus merge(a0, b). Damit ist cons(x, merge(a0, b)) monoton. • Falls . . . und x > y, dann symmetrisch. • Falls a = cons(x, a0) und b = cons(y, b0) mit x ≤ y, nach Def. Monotonie gilt ∀x0 ∈ MM(a0) : x ≤ x0 und ∀y 0 ∈ MM(b0) : y ≤ y 0 Wg. Transitivität gilt ∀y 0 ∈ MM(b0) : x ≤ y ≤ y 0 – Typeset by FoilTEX – 106 – Typeset by FoilTEX – Sortieren durch Zusammenfügen (Merge-S.) Merge-Sort: Korrektheit (1) zu zeigen: MM(a) = MM(sort(a)). Beweis durch Induktion nach |a|: • sort(a) = – wenn |a| ≤ 1, dann a – sonst: merge(sort(l), sort(r)), wobei (l, r) = split(a) • split(a[1 . . . n]) = (a[1 . . . h], a[h + 1 . . . n]) mit h = bn/2c • Bsp: sort([4, 1, 3, 2]) = merge(sort[4, 1], sort[3, 2]) = merge(merge(sort[4], sort[1]), merge(sort[3], sort[2])) = merge(merge([4], [1]), merge([3], [2])) = merge([1, 4], [2, 3]) = [1, 2, 3, 4] • erfüllt die Spezifikation des Sortierens (Beweis?) • funktioniert für beliebige Eingabelänge (nicht nur 2e) • Komplexität (Anzahl der Vergleiche)? für Beispiel: 5, allgemein: O(n log n) (noch zu zeigen) – Typeset by FoilTEX – 107 • falls |a| ≤ 1, dann sort(a) = a und MM(sort(a)) = MM(a) • falls |a| ≥ 2, dann MM(a) = MM(l) ∪ MM(r). Es gilt |l| < |a| und |r| < |a|, also lt. Induktion MM(sort(l)) = MM(l) und MM(sort(r)) = MM(r) nach Korrektheit von merge gilt MM(sort(a)) = MM(merge(sort(l), sort(r))) = MM(sort(l)) ∪ MM(sort(r)) = MM(l) ∪ MM(r) = MM(a) 108 – Typeset by FoilTEX – Merge-Sort: Korrektheit (2) 109 Komplexität von Merge-Sort zu zeigen: sort(a) ist monoton. Beweis durch Induktion nach |a|: • Bezeichnungen – S(n) = Kosten für sort auf Eingabe der Länge n – M (p, q) = p + q − 1 Kosten für merge von Längen p, q • falls |a| ≤ 1, dann sort(a) = a und a ist monoton. • Berechnung: S(n) = – wenn n ≤ 1, dann 0, – sonst S(bn/2c) + S(dn/2e) + M (bn/2c, dn/2e) • falls |a| ≥ 2, dann Es gilt |l| < |a| und |r| < |a|, nach Induktion sind sort(l) und sort(r) monoton. Also ist Voraussetzung für Aufruf von merge(sort(l), sort(r)) erfüllt. • Bsp: S(2) = S(1) + S(1) + M (1, 1) = 0 + 0 + 1 = 1, S(3) = S(1) + S(2) + M (1, 2) = 0 + 1 + 2 = 3, S(4) = S(2) + S(2) + M (2, 2) = 1 + 1 + 3 = 5, . . . Nach Spezifikation von merge ist dann das Resultat monoton. • Werteverlauf: – Typeset by FoilTEX – n 0 1 2 3 4 5 6 7 8 9 10 S(n) 0 0 1 3 5 25 vergleiche mit unterer Schranke für Sortieren! 110 – Typeset by FoilTEX – 111 Asymptotische Komplexität von Merge-Sort • S(n) = if n < 2 then 0 else S(bn/2c) + S(dn/2e) + n − 1 • speziell: S(2k ) = if k < 1 then 0 else 2 · S(2k−1) + 2k − 1 • Aufgaben 4.A (autotool) • Sortierverfahren für 5 Elemente mit höchstens 8 Vergleichen. 0 1 2 3 4 5 6 k S(2k ) 0 1 5 17 321 • Eigenschaften von Permutationen (k-Ordnung, Inversionszahl), Beispiel: • Vermutung: S(2 ) = . . . , Beweis durch Induktion nach k k Gesucht ist eine Permutation von [1 .. 9] mit den Eigenschaften: And [ Inversions EQ 7 , Ordered 6 , Ordered 4 ] • für beliebiges n: mit k = blog nc gilt 2k ≤ n < 2k+1, benutze spezielle Werte und Monotonie von S • Satz: S ∈ Θ(n log n), d.h.: Merge-Sort ist ein asymptotisch optimales Sortierverfahren – Typeset by FoilTEX – Übungsserie 4 (für KW 18) 112 – Typeset by FoilTEX – Aufgabe 4.1 (Permutationen) 113 Aufgabe 4.2 (Shell-Sort) Bestimmen Sie die Anzahl A(n) der Permutationen von [1 . . . n], die sowohl 2-geordnet als auch 3-geordnet sind. Für Eingabe [10, 9, . . . , 2, 1] (o.ä. — wird dann vom Übungsleiter vorgegeben): • Zusatz: (1 P) Diese Aufgabe erscheint in einem der im Skript zitierten Bücher. Geben Sie die exakte Fundstelle an. • (2 P) Shell-Sort mit Differenzenfolge [3, 2, 1] (o.ä.) an der Tafel vorrechnen. • (1 P) Geben Sie alle solche Permutationen für n = 4 an. • (1 P) Dabei Ordnung und Anzahl der Inversionen mit Schranken aus Hilfssatz 1 und 2 aus Skript vergleichen. • (1 P) Jede solche Permutation ist auch 5-geordnet, warum? Bestimmen Sie experimentell Zahlen c, d, so daß Shell-Sort mit Differenzenfolge [c, d, 1] möglichs wenig Element-Vergleiche ausführt. • (2 P) Beweisen Sie A(n) = Fn+1 (Fibonnaci-Folge). • (2 P) auf Eingabe [100, . . . , 2, 1] • (Zusatz) auf 100 zufälligen Eingaben der Länge 100 – Typeset by FoilTEX – 114 Hinweis: Bei der Bearbeitung der Aufgaben könnte diese Implementierung von Shell-Sort nützlich sein: https://gitlab.imn.htwk-leipzig.de/ waldmann/ad-ss17/blob/master/kw17/shell.cc. Bei der Präsentation im Seminar rechnen Sie an der Tafel ohne maschinelle Hilfe. – Typeset by FoilTEX – 116 j + 1, falls diese in [1 . . . n] liegen). Nachdem der Student eine Weile überlegt hat, erhebt er sich vom Schreibtisch, . . . (siehe oben). Untersuchen Sie für jedes n ≥ 1: – Typeset by FoilTEX – 115 Zusatz-Aufgabe 4.3 (Der Osterhase) (Wird diskutiert, sobald eine Gruppe eine Lösung anmeldet und sofern in der Übung Zeit ist. Das und evtl. Vergabe von Zusatzpunkten liegt im Ermessen der Übungsleiter.) Der listige Osterhase hat ein buntes Osterei versteckt, hinter einem der Grasbüschel 1, 2, . . . , n. Der fleißige Student sucht das Ei. Er erhebt sich vom Schreibtisch, geht zu Grasbüschel i und sieht nach. Ist das Ei dort, hat er gewonnen. Ist das Ei nicht dort, geht er zum Schreibtisch zurück, um weitere Übungsaufgaben zu bearbeiten. Hinter seinem Rücken nimmt der Osterhase das Ei von der Stelle j (diese war ungleich i) und versteckt es in einer der maximal zwei direkt benachbarten Positionen (j − 1 oder – Typeset by FoilTEX – 117 Übungsserie 5 (für KW 19) Aufgabe 5.A (autotool) Merge von a und b mit |a| = 2 und |b| = 4 (oder ähnlich) mit wenig Vergleichen. • Kann der Student das Ei finden? • Wenn ja, wie lange dauert das? Beispiel: n = 3. Schritt 1: teste Position 2. Falls das Ei nicht dort ist, dann ist es in 1 oder 3. Im nächsten Schritt muß es der Hase nach 2 legen, weil das die einzige Nachbarposition von 1 und von 3 ist. Deswegen ist Schritt 2: teste Position 2 sicher erfolgreich. – Typeset by FoilTEX – 118 – Typeset by FoilTEX – 119 Aufgabe 5.1 (Merge-Sort) ist das eine Verbesserung? Für Eingabe [10, 9, . . . , 2, 1] (o.ä. — wird dann vom Übungsleiter vorgegeben): • (2 P) Merge-Sort an der Tafel vorrechnen. • (1 P) Dabei die Vergleichs-Operationen aller Teilschritte zählen und mit Schranken aus Vorlesung vergleichen. Such-Aufgabe: zur Implementierung von sort in der Haskell-Standardbibliothek Data.List • (1 P) Wo ist der zugrundeliegende Algorithmus beschrieben (welches ist die älteste zitierte Quelle)? • Zusatz (1 P) Welche Änderung gegenüber Merge-Sort enthält dieser Algorithmus, und für welche Eingabefolgen – Typeset by FoilTEX – 120 Aufgabe 5.2 (Entscheidungsbäume, Merge) – Typeset by FoilTEX – 121 von merge erreicht? Benutzen Sie Entscheidungsbäume, um eine untere Schranke für die Anzahl der notwendigen Vergleiche bei merge(a, b) als Funktion von |a| und |b| zu erhalten. Die Blätter des Entscheidungsbaumes sind Permutationen von a · b, welche die relative Reihenfolge der Element aus a sowie der Elemente aus b beibehalten. Beispiel: eine solche Permutation von [a1, a2] · [b1, b2, b3] ist [b1, a1, b2, b3, a2]. • (1 P) Geben Sie alle Permutationen von [a1, a2, b1, b2, b3] mit dieser Eigenschaft an. • (1 P) Bestimmen Sie die minimale Anzahl der Blätter sowie die daraus resultierende Schranke allgemein als Funktion von |a| und |b|. Hinweis: verwenden Sie eine aus der Kombinatorik bekannte Funktion/Notation. • (1 P) Begründen Sie: unsere Implementierung von merge ist nicht optimal für |a| = 1. • (1 P) Geben Sie für |a| = 1 eine optimale Implementierung an. Benutzen Sie einen Algorithmus aus der Vorlesung (leicht modifiziert). • (1 P) Welche untere Schranke folgt daraus für M (2, 3)? Wird diese von der in VL angegebenen Implementierung – Typeset by FoilTEX – 122 – Typeset by FoilTEX – Analyse rekursiver Algorithmen Definition, Motivation • Wortbedeutung Rekursion: zurück (re) laufen (cursor) Übersicht • inhaltliche Bedeutung: ein rekursiver Algorithmus löst ein Problem mit Eingabe E durch: 1. E in (kein, ein oder mehrere) E1, . . . zerlegen – kein: ergibt Ende der Rekursion – ein: lineare Rekursion – mehrere: Baum-Rekursion 2. jedes Ei durch denselben Algorithmus lösen (ergibt Ai) 3. aus A1, . . . die Lösung A von E bestimmen [WW] Kapitel 7 • Multiplizieren durch Verdoppeln • Karatsuba-Multiplikation [OW] 1.2.3 • Master-Theorem [WW] 7.2 • Quick-Sort, Laufzeit im Mittel [WW] 7.3 • Median-Bestimmung in Linearzeit [WW] 7.4 – Typeset by FoilTEX – • Vorteil der Rekursion: man muß nur über 1. (teilen) und 3. (zusammensetzen) nachdenken, denn 2. ist nach Induktion richtig 124 – Typeset by FoilTEX – 125 Multiplizieren durch Verdoppeln Termination und Komplexität rekursiver Algorithmen (vgl. früher angegebener iterativer Algorithmus) mult(nat a, nat b) = if a = 0 then 0 else mod(a,2) * b + 2 * mult(div(a,2),b) • Termination: folgt aus Existenz einer Schranke S, die bei jedem rekursiven Aufruf abnimmt: wenn E −→ Ei, dann S(E) > S(Ei) ≥ 0 • offensichtlich partiell korrekt nach Def. von mod, div • terminiert, weil a eine Schranke ist (falls a > 0, dann a > a/2 ≥ ba/2c = div(a, 2)) • lineare Rekursion: Laufzeit ≤ Schranke • Baum-Rekursion: Laufzeit mglw. größer als Schranke a(n) = if n>0 then a(n-1) + a(n-1) else 1 Schranke ist n (linear), Laufzeit ist 2n (exponentiell) • mod(a,2) * b realisiert durch Fallunterscheidung • Laufzeit (Anzahl der Additionen) implizit: M (a) = if a = 0 then 0 else 1 + M (ba/2c) explizit: M (a) = if a = 0 then 0 else 1 + blog2 ac Beweis: benutzt a ≥ 2 ⇒ blog2 ac = 1 + blog2ba/2cc • Laufzeit implizit (Bsp. S(n) = 2 · S(n/2) + n − 1) explizite Form (Bsp. S ∈ Θ(n log n)) nach Rechnung – Typeset by FoilTEX – 123 126 – Typeset by FoilTEX – 127 Multiplikation von Binärzahlen Multiplikation von Binärzahlen mit bisher bekanntem Verfahren: • a = 2w a1 + a0, b = 2w b1 + b0 • mult(a,b) kostet log a Additionen. • a·b = (2w a1 +a0)(2w b1 +b0) = 22w a1b1 +2w (a1b0 +a0b1)+a0b0 eine Multiplikation für Bitbreite 2w ⇒ vier Mult. für Breite w und 3 Additionen für Breite 2w • jede dieser Additionen kostet ≥ log b Bit-Operationen • Multiplikation kostet log a · log b Bit-Operation. • Kosten: M (1) = 1, M (2w) = 4M (w) + 6w 8 16 32 w 1 2 4 Daten: M (w) 1 16 88 400 1696 28288 Vermutung: M (2k ) = 7 · 4k − 6 · 2k , Beweis: Induktion. geht das schneller? Überraschenderweise: ja! • Ansatz: w = d(log max(a, b))/2e (Hälfte der Bitbreite) a = 2w a1 + a0, b = 2w b1 + b0 mit 0 ≤ a0 < 2w , 0 ≤ b0 < 2w • also M (w) = 7w2 − 6w für w = 2k • Bsp. a = 13, b = 11, w = 2, a = 22 · 3 + 1, b = 22 · 2 + 3 • also M ∈ Θ(w2), also keine Verbesserung • Bestimme a· aus Teilprodukten der a1, a0, b1, b0 – Typeset by FoilTEX – 128 • a · b = (2w a1 + a0)(2w b1 + b0) benutze Nebenrechnung p = (a1 + a0) · (b1 + b0) a · b = 22w a1b1 + 2w (p − (a1b1 + a0b0)) + a0b0 • eine Multiplikation für Bitbreite 2w ⇒ drei Mult. für Breite w und 6 Additionen für Breite ≤ 2w • Kosten M 0(1) = 1, M 0(2w) = 3M 0(w) + 12w w 1 2 4 8 16 32 2k 0 k M (w) 1 27 129 483 1641 16689 25 · 3 − 24 · 2k • M 0(w) = 25(wlog2 3)−24w ∈ Θ(wlog2 3) = Θ(w1.58...) ⊆ o(w2) • A. Karatsuba, J. Ofman: Multiplication of Many-Digital Numbers by Automatic Computers, Doklady Akad. Nauk SSSR 145, 293-294, 1962. 130 Begründung des Hauptsatzes (1) e x f (n) = Θ(nlogb a) + ae · = Θ(nx) + nx · e X k=0 e X g(bk )/ak k=0 Begründung des Hauptsatzes (3) – Typeset by FoilTEX – 133 Begründung des Hauptsatzes (4) • für n = b , also e = logb n. Dann a = n mit x = logb a. P • f (n) = Θ(nx) + nx · ek=0 g(bk )/ak • für n = be, also e = logb n. Dann ae = nx mit x = logb a. P • f (n) = Θ(nx) + nx · ek=0 g(bk )/ak x • Falls g ∈ Θ(n 7→ nx), dann c1 · bkx ≤ g(bk ) ≤ c2 · bkx, P P • dann nx · ek=0 g(bk )/ak ∈ Θ(nx · ek=0(bx/a)k ) P = Θ(nx · ek=0 1) = Θ(nx · e) = Θ(nx log n) • Falls ∃y > x : g ∈ Θ(ny ), dann c1 · bky ≤ g(bk ) ≤ c2 · bky , P P • dann nx · ek=0 g(bk )/ak ∈ Θ(nx · ek=0(by /a)k ) Summe ist geom. Reihe zur Basis q = by /a > 1 q e+1 − 1 ) = Θ(nx(by /a)e) = Θ(nx · bye/ae) q−1 = Θ(bey ) = Θ(g(n)) • also f (n) ∈ Θ(nx) + Θ(nx log n) = Θ(nx log n) – Typeset by FoilTEX – 131 • also · · · ≤ Θ(nx) + c0 · nx · S = Θ(nx) + Θ(nx). 132 e – Typeset by FoilTEX – • die Summe ist geometrische Reihe zur Basis by /a < 1, P P 1 y k =S also ek=0(by /a)k < ∞ k=0(b /a) = 1 − by /a drei Fälle: A) nx am größten, B) Summanden für alle k ähnlich groß. C) Summand für k = 0 am größten. e • Anwenden für beide Varianten der Binärmultiplikation • Falls g ∈ O(n 7→ ny ) mit y < x, dann g(bk ) ≤ c0 · bky , P • also · · · ≤ Θ(nx) + c0 · nx · ek=0(by /a)k a−k · g(bk ) – Typeset by FoilTEX – • Herleitung und Aussage: – bestimme x aus Ansatz f (n) = nx (ignoriere g) nx = a · (n/b)x ⇒ x = . . . – vergleiche g mit nx, der größere bestimmt das Resultat ∗ polynomiell kleiner: ∃y < x : g ∈ O(ny ) ⇒ f ∈ Θ(nx) ∗ gleich: g ∈ Θ(nx) ⇒ f ∈ Θ(nx log n) ∗ poly. größer: ∃y > x : g ∈ Θ(ny ) ⇒ f ∈ Θ(g) (Version mit g ∈ Ω(ny ) siehe [CLR]) • für n = be, also e = logb n. Dann ae = nx mit x = logb a. P • f (n) = Θ(nx) + nx · ek=0 g(bk )/ak f (be) = a · f (be−1) + g(be) = a(a · f (be−2) + g(be−1)) + g(be) e X = ae · f (b0) + ae−k · g(bk ) k=0 • beschreibt asymptotisches Wachstum der Lösung f von f (n) = if n < s then c else a · f (n/b) + g(n) für a ≥ 1, b > 1, und n/b kann bn/bc oder dn/be sein Begründung des Hauptsatzes (2) für n = b , also e = logb n. Dann a = n mit x = logb a. e 129 Hauptsatz über Rekursionsgleichungen Multiplikation von Binärzahlen – Typeset by FoilTEX – – Typeset by FoilTEX – • · · · = Θ(nx · 134 – Typeset by FoilTEX – 135 Anwendungen des Hauptsatzes Quicksort (Algorithmus) Spezifikation: Ordnet a[1 . . . n] schwach monoton steigend Q(a[1 . . . n]): wenn n ≤ 1, dann fertig, sonst p = a[n] (das Pivot-Element) tausche Elemente in a[1 . . . n − 1], bestimme k ∈ [1 . . . n], so daß ∀1 ≤ i < k : a[i] < p und ∀k ≤ i < n : p ≤ a[i] vgl. dutch national flag (mit 2 Farben) a[k] ↔ a[n] ; Q(a[1 . . . k − 1]) ; Q(a[k + 1 . . . n]) • Mult. durch Verdoppeln: f (n) = f (n/2) + 1 Hauptsatz mit a = 1, b = 2, also x = log2 1 = 0; nx = 1 Fall 2: g ∈ Θ(nx), also f ∈ Θ(nx log n) = Θ(log n) • Mult. von Binärzahlen: f (n) = 4f (n/2) + 3n Hauptsatz mit a = 4, b = 2, also x = log2 4 = 2; nx = n2 Fall 1: g ∈ O(ny ) mit y = 1 < x, also f ∈ Θ(nx) • Karatsuba-Mult. f (n) = 3f (n/2) + 6n Hauptsatz mit a = 3, b = 2, also x = log2 3 ≈ 1.58, Fall 1: g ∈ O(ny ) mit y = 1 < x, also f ∈ Θ(nx) • f (n) = 2f (n/2) + n log n, a = 2, b = 2, x = log2 2 = 1, HS nicht anwendbar : g ∈ / O(n1−), g ∈ / Θ(n), g ∈ / Θ(n1+) 2 Lösung (mit anderen Methoden): f ∈ Θ(n log n) – Typeset by FoilTEX – • Korrektheit: – Multimengen-Erhaltung, weil nur getauscht wird – Ordnung: vor den beiden Q-Aufrufen gilt: ∀1 ≤ i < k : a[i] ≤ a[k] und ∀k < i ≤ n : a[k] ≤ a[i] • Termination: |a| ist Schranke (aber Laufzeit ∈ / O(|a|)) • C.A.R. Hoare, Computer Journal 5 (1962), 10–15 136 Quicksort (Laufzeit) • Element-Vergleiche nur beim Partitionieren. Eingabe-Elemente x, y werden genau dann verglichen, wenn x oder y das Pivot ist und beide nicht bereits durch eine vorigen Pivot getrennt wurden. Q(n) = Q(k − 1) + Q(n − k) + n − 1 • Komplexität (d.h. maximale Laufzeit über alle Eingaben jeder Länge) ist quadratisch, • falls Eingabe eine zufällige Permutation von [1 . . . n], betrachte Elemente (nicht Indizes) x < y und das erste Pivot p mit x ≤ p ≤ y. betrachte geordnete Eingabe [1, 2, . . . , n], dann k = n Q(n) = Q(n − 1) + Q(0) + n − 1 = Q(n − 1) + n − 1 • falls p ∈ {x, y}, dann wird x mit y verglichen, sonst nicht. die Wahrscheinlichkeit dafür ist 2/(y − x + 1). • Laufzeit bei ungeordneten“ Eingaben ist besser ” ⇒ mittlere Laufzeit (über alle Eingaben) ist besser • besser Wahl des Pivot-Elements ist möglich 138 • die erwartete Vergleichszahl (= Laufzeit) ist P Q(n) = 1≤x<y≤n 2/(y − x + 1). – Typeset by FoilTEX – Quicksort (mittle Laufzeit – Rechnung) • Q(n) = P 1≤x<y≤n 2/(y • unser Pivot: a[n], schlecht für geordnete Eingabe − x + 1) • ist a[div(n, 2)] besser? für geordnete Eingabe ideal aber auch für diese Wahl gibt es schlechte Eingaben (Ü) • Unter- und Obersumme des Integrals: R n+1 Rn P 1 (1/x)dx ≤ n−1 k=1 k+1 ≤ 1 (1/x)dx 2 Pn−1 1 loge(n + 1) − loge 2 ≤ k=1 k+1 ≤ loge n • zufällige Wahl des Pivot-Index ist besser • Implementierung in openjdk-1.8.0: Dual-Pivot Quicksort, Vladimir Yaroslavskiy, Jon Bentley, and Joshua Bloch. • Folgerung: Q ∈ Θ(n log n) Auf zufälligen Eingaben ist Quicksort asymptotisch optimal. – zwei Pivots ⇒ drei Teilfolgen – Pivots berechnet aus mehreren Kandidaten 140 Median-Bestimmung – Typeset by FoilTEX – 141 Median ohne Sortieren (ein Spezialfall) • Def: Ein Element m einer Folge a[1 . . . n] heißt Median: #{i | a[i] < m} ≤ n/2 und #{i | a[i] > m} ≤ n/2 (etwas umständlich wg. Möglichkeit von Duplikaten in a) • Bsp: median([3, 0, 1, 20, 2]) = 2 (vgl. mit Mittelwert) • Median von [a1, . . . , a5] mit 6 Vergleichen? d.h. ohne zu sortieren, denn dlog2(5!)e = 7 • Implementierung (replacement selection) – ein KO-Turnier für [a1, . . . , a4] (3 Spiele = Vergleiche) – der Sieger as ist nicht der Median (sondern zu groß) – setze a5 dort ein, wo as begonnen hat, a5 wiederholt die 2 Spiele von as – der Sieger at ist nicht der Median (sondern zu groß) – noch ein Spiel zwischen denen, die gegen at verloren haben, der Sieger ist der Median • Motivation: Median ist der ideale Pivot für Quicksort. kann man den Median effizient bestimmen? • ein naheliegendes, Verfahren ist: sort(a[1 . . . n])[dn/2e] das kann man aber in Quicksort nicht benutzen • überraschenderweise: Median kann in Linearzeit bestimmt werden. – Typeset by FoilTEX – 139 Quicksort (Verbesserungen) n 1 2 3 4 5 6 7 8 29 37 103 472 • Q(n) 0 1 3 6 5 10 35 0 1 2.7 4.8 7.4 10.3 13.5 P Pn−1 1 n−k • Q(n) = 2 n−1 k=1 k+1 = 2(n + 1) k=1 k+1 − 2(n − 1) – Typeset by FoilTEX – 137 Quicksort (mittle Laufzeit — Herleitung) • Kosten für |a| = n ≥ 2 abhängig von k: – Typeset by FoilTEX – – Typeset by FoilTEX – (A. Hadian und M. Sobel, 1969, zitiert in [DEK] 5.3.3.) 142 – Typeset by FoilTEX – 143 Median und Selektion (Plan) Selektion in Linearzeit (Realisierung) • Spezif.: select(k, a) := ein k-kleinstes Element • gestattet Implementierung median(a) := select(d|a|/2e, a) • Implementierung von select(k, a[1 . . . n]) für n groß: – m := ein Wert in der Nähe des Medians von a – L := {a[i] | a[i] < m}; E = {· · · = m}; R := {· · · > m} – falls k ≤ |L|, dann select(k, L) – falls |L| < k ≤ |L| + |E|, dann m – falls |L| + |E| < k, dann select(k − (|L| + |E|), R) • Lemma: für |a| = n gilt |L| ≥ 3n/10, |R| ≥ 3n/10. Beweis: zähle Elemente x ≤ mi ≤ m. Folgerung: |L| ≤ 7n/10, |R| ≤ 7n/10 • Komplexität S(n) für select(k, a) mit |a| = n, n groß: S(n) ≤ 6n + S(n/5) + n + S(7n/10) Ansatz: S(n) ≤ c · n. Resultat: S ∈ O(n) • Korrektheit: L 3 x < m < y ∈ R und richtig zählen • Laufzeit: hängt von geeigneter Wahl von m ab: Ziele: weder |L| noch |R| groß, m schnell zu berechnen – Typeset by FoilTEX – • der Wert m wird so bestimmt: – teile a in Gruppen G1, G2, . . . je 5 Elemente – für jedes i bestimme mi := der Median von Gi – m := der Median von {m1, m2, . . .} (rekursiv) • Blum et al., JCSS 7(4) 448-461, 1973: https: //doi.org/10.1016/S0022-0000(73)80033-9 144 – Typeset by FoilTEX – 145 Aufgabe 6.2 (Rekursionsgleichungen) Übungsserie 6 (für KW 20) Entscheiden Sie, ob der Hauptsatz anwendbar ist. Falls ja, lösen Sie dann die Gleichung. (Jeweils 2 P) Falls nein, lösen Sie dann die Gleichung. (Zusatz: 2 P) Aufgabe 6.A (autotool) zur Bestimmung des Medians von 5 Elementen mit 6 Vergleichen. • T1(n) = 8 · T1(n/2) + 4 · n3 • T2(n) = 8 · T2(n/4) + n2 • T3(n) = 8 · T3(n/2) + n log n • T4(n) = 9 · T4(n/3) + n2 log n – Typeset by FoilTEX – 146 Aufgabe 6.2 (ein seltsames Sortierverfahren) Zum Sortieren einer Folge a[1 . . . n] wird dieses rekursive Verfahren V vorgeschlagen: wenn n ≤ 2, dann sortiere a mit 0 oder 1 Vergleich. sonst: p = bn/3c + 1, q = d2n/3e V (a[1 . . . q]); V (a[p . . . n]); V (a[1 . . . q]) – Typeset by FoilTEX – 147 wesentlich, ob bei der Bestimmung von p und q auf- oder abgerundet wird? • (1 P) Bestimmen Sie die Laufzeit von V nach dem Hauptsatz über Rekursionsgleichungen. Ist V ein nützliches Sortierverfahren? • (1 P) Wenden Sie V an auf [8, 2, 4, 5, 1, 6, 3] (oder ähnlich, wird vom Übungsleiter vorgegeben) Expandieren Sie dabei nur die obersten rekursiven Aufrufe. Nehmen Sie an, daß die weiteren korrekte Resultate liefern. • (2 P) Beweisen Sie die Korrektheit von V . Ist es dabei – Typeset by FoilTEX – 148 Aufgabe 6.3 (Quicksort) 149 Zusatz (1 P) . . . beliebiger Länge n. • (2 P) Quicksort für eine vorgegebene Eingabe (z.B. [1, 3, 5, 7, 9, 8, 6, 4, 2]) an der Tafel vorrechnen. • Betrachten Sie diese Variante von Quicksort, für eine vorher gewählte Zahl B ≥ 1: bei jedem rekursiven Aufruf: wenn die Länge der Eingabefolge ≤ B ist, dann kehren wir sofort zurück, ohne die Eingabe zu verändern. Ansonsten (Eingabe länger als B) Partition und Rekursion. • Um das Verhalten von Quicksort von a[1 . . . n] bei monotoner Eingabe zu verbessern, wählt man als Pivot immer das Element auf dem mittleren Index. Man führt dazu (bei jedem rekursiven Aufruf) für n > 1 zunächst a[bn/2c] ↔ a[n] aus und partitioniert dann a[1 . . . n − 1] usw. wie im Algorithmus aus Skript. Nach Rückkehr aller rekursiven Aufrufe sortieren wir das Array durch Einfügen. (2 P) Wie teuer ist das abschließende Sortieren (abhängig von Schranke B und Eingabelänge n)? (1 P) Wie schnell werden monotone Eingaben dadurch sortiert? (1 P) Geben Sie eine für dieses Verfahren aufwendigste Eingabe der Länge 8 an. – Typeset by FoilTEX – – Typeset by FoilTEX – 150 – Typeset by FoilTEX – 151 Dynamische Programmierung Beispiel, Definition Übersicht • F (0) = 0, F (1) = 1, ∀n ≥ 2 : F (n) = F (n − 1) + F (n − 2) Bestimmung von F (n) lt. Def. benötigt Fn Zeit, also Θ(q n) [WW] Kapitel 8 • das geht aber in Linearzeit, mit Array f [0 . . . n]: f [0] := 0; f [1] := 1; für k von 2 bis n: f [k] := f [k − 1] + f [k − 2]; return f [n] • Definition • Münzenwechseln • längste gemeinsame Teilfolge • Definition: dynamische Programmierung – Implementierung eines rekursiven Algorithmus – durch Vorausberechnung und dann Nachnutzung der Resultate rekursiver Aufrufe – besonders wirksam, wenn viele Aufrufe übereinstimmen • Matrixproduktkette • RNA-Strukturbestimmung – Typeset by FoilTEX – 152 Beispiel: Geldwechseln (Plan) • gegeben: Münzwerte m ∈ Nk>0, s ∈ N gesucht: minimale Anzahl von Münzen mit Summe s • rekursiv: A(s) = if s = 0 then 0 else 1 + min{A(s − mi) | 1 ≤ i ≤ k, s ≥ mi} • dynamische Programmierung: benutze Array a[0 . . . s] a[0] := 0; für t von 1 bis s: a[t] := 1 + min{a[t − mi] | 1 ≤ i ≤ k, t ≥ mi} return a[s] 154 – Typeset by FoilTEX – Verstreute Teilfolgen • Spezifikation (longest common subsequence) – gegeben: v, w ∈ Σ∗ – gesucht: u mit u ≤ v ∧ u ≤ w, so daß |u| maximal lcs(v, w) := die Länge eines solchen u • Bsp: aba ≤ bacbacba wegen i = [2, 4, 8] • äquivalent: u entsteht aus v durch Löschen von Zeichen (aber ohne Umordnung der nicht gelöschten) • Eigenschaften der Relation ≤ auf Σ∗ – (trivial) ist Halbordnung, ist nicht total, – (nicht trivial — C. Nash-Williams, 1965) jede Antikette (Menge v. paarweise unvergleichbaren Elementen) ist endlich • Anwendung: kürzeste Editier-Folge – von v zu u: Zeichen löschen (|v| − lcs(v, w) Stück) – von u zu w: Zeichen einfügen (|w| − lcs(v, w) Stück) • Anwendungen: – (algorithmische) Biologie: Vergleich von RNA-Folgen – Analyse der Ähnlichkeit von Texten – Bestimmung von Patches bei Quelltextverwaltung (automat. Zusammenführung von unabh. Änderungen) 156 Bestimmung von LCS (Plan) – Typeset by FoilTEX – 157 Bestimmung von LCS (Realisierung) • Eingabe: v[1 . . . p], w[1 . . . q], Ausgabe: lcs(u, w) • benutze Array L[1 . . . p + 1, 1 . . . q + 1] mit Spezifikation L[i, j] = lcs(v[i . . . p], w[j . . . q]) • Invariante: die bereits zugewiesenen Werte sind korrekt L[∗, q + 1] := 0; L[p + 1, ∗] := 0; für i von p bis 1: für j von q bis 1: • lcs(empty, w) = 0; lcs(v, empty) = 0 • lcs(cons(v1, v 0), cons(w1, w0)) = das Maximum von . . . (vollst. Fallunterscheidung nach Startposition einer längsten gemeinsamen Teilfolge) – 1 in v und 1 in w: falls v1 = w1, dann 1 + lcs(v 0, w0) – ≥ 1 in v und > 1 in w: lcs(cons(v1, v 0), w0) – > 1 in v und ≥ 1 in w: lcs(v 0, cons(w1, w0)) jedes Argument von lcs ist Suffix von v bzw. von w. L[i, j] := max{ if v[i] = w[j] then 1 + L[i + 1, j + 1] else 0, L[i, j + 1], L[i + 1, j]}; • dyn. Prog.: berechne L[i, j] := lcs(v[i . . . |v|], w[j . . . |w|]) für i von |v| + 1 bis 1, j von |w| + 1 bis 1 benötigt Θ(|v| · |w|) Zeit (und Platz) – Typeset by FoilTEX – 155 Gemeinsame Teilfolgen • Def: u ∈ Σ∗ ist (verstreute) Teilfolge (scattered subsequence) von v ∈ Σ∗, Notation u ≤ v, falls ∃i1 < . . . < i|u| : ∀k : uk = vik – Typeset by FoilTEX – 153 Beispiel: Geldwechseln (Realisierung) • Spezifikation – gegeben: Münzwerte m ∈ Nk>0, Betrag s ∈ N P – gesucht: Münz-Anzahlen a ∈ Nk mit s = ni=1 miai Pn – so daß i=1 ai (Anzahl der Münzen) minimal • Satz: wenn a eine optimale Lösung für s ist und a0 eine P P optimale Lösung für s − mi, dann a ≤ 1 + a0. • deswegen Implementierung: A(0) = [0, . . . , 0], A(s) := ein Vektor mit minimalem Gewicht aus: für i ∈ [1, . . . n]: falls s ≥ mi: bestimme A(s − mi), füge 1 für i hinzu. • Baum-Rekursion, Verzweigungsgrad k • dynamische Programmierung: A(0), A(1), . . . , A(s) – Typeset by FoilTEX – – Typeset by FoilTEX – 158 return L[1, 1]; • Quelltexte und Profiling: siehe Archiv • lange gemeinsame Teilfolge durch Analyse von L – Typeset by FoilTEX – 159 LCS (Anwendung bei Quelltextverwaltung) RNA-Sekundärstruktur (Definitionen) • Bezeichnungen: – RNA: Molekülkette, steuert Protein-Synthese – Primärstruktur: Folge der Moleküle ∈ {A, C, G, U }∗ – Sekundärstruktur: Paarbindungen der Moleküle erlaubte Bindungen: {{C, G}, {G, U }, {U, A}} – Tertiärstruktur: 3-dimensionale Anordnung • Aufgabe (git rebase): – betrachte eine Datei in Version A, – Entwickler 1 ändert A →1 A1, – Entwickler 2 ändert A →2 A2, – . . . und will Änderungen von Ent. 1 übernehmen https://git-scm.com/book/en/v2/ Git-Branching-Rebasing • Aufgabe (RNA-Sekundärstruktur-Vorhersage): – Eingabe: eine Primärstruktur p – Ausgabe: eine dazu passende Sekundärstruktur s mit minimaler freier (maximaler gebundener) Energie • Lösung: – berechne kürzeste Editierfolgen (patch) Pi : A → Ai, mittels lcs(A, Ai) auf Zeilen (nicht auf Buchstaben) – wenn P1 ∩ P2 = ∅, dann wende P2 auf A1 an sonst markiere Konflikt, erfordet manuelle Lösung – Typeset by FoilTEX – • s als Klammer-Wort über Alphabet {., (, )} ohne Kreuzungen: a1 − a2, b1 − b2, a1 < b1 < a2 < b2 160 RNA-Sekundärstruktur (Implementierung) 161 RNA-Sekundärstruktur (Impl. — Detail) • . . . die richtigen Werte in geeigneter Reihenfolge: – schließlich benötigt wird M [1, n] – M [i, j] hängt ab von M [i + 1, j − 1] sowie für i ≤ k < j : M [i, k] und M [k + 1, j] – Schranke für diese Abhängigkeiten ist: (j − i) • Eingabe: p[1 . . . n] ∈ {A, C, G, U } ∗ • Ausgabe: max. Bindungszahl aller Sekundärstrukt. für p • Implementierung (Plan): SP(p) = wenn |p| ≤ 4 (minimal hairpin length), dann 0, sonst das Maximum von – wenn {p[1], p[n]} ∈ B, dann 1 + SP(p[2 . . . n − 1]) – für k von 1 bis n − 1: SP(p[1 . . . k]) + SP(p[k + 1 . . . n]) • Realisierung durch dynamische Programmierung: Matrix M [1 . . . n, 1 . . . n] mit Spezif. M [i, j] = SP(p[i . . . j]). füllen in geeigneter Reihenfolge; return M [1, n]; • Ruth Nussinov et al., SIAM J. Applied Math, 1978 – Typeset by FoilTEX – – Typeset by FoilTEX – 162 • – insgesamt benötigt werden M [i, j] für 1 ≤ i ≤ j ≤ n – Bestimmung nach aufsteigenden Werten der Schranke: erst für j − i = 0 (Diagonale), dann j − i = 1, usw. • Realisierung: for d from 0 to n : for i from 1 to n − d : j := i + d, . . . https://gitlab.imn.htwk-leipzig.de/ waldmann/ad-ss17/tree/master/kw20 – Typeset by FoilTEX – 163 Greedy (gierige) Algorithmen Weiteres zu RNA-Strukturen • Struktur-Vorhersage: mehr Realismus durch: – genaueres Energie-Modell z.B. E(C, G) = 3, . . . – Pseudoknoten (2 Klammerntypen) .((.[[..).]].). (die Dyn.-Prog.-Matrix wird dadurch 4-dimensional) • Struktur-Design: (ist schwieriger, kein dyn. Prog.) – gegeben ist Sekundarstruktur s (Klammernwort) – gesucht ist Primärstruktur p, für die s eine (oder sogar: die einzige) optimale Sekundärstruktur ist A. Bau et al.: RNA Design by Program Inversion, WCB 2013 http://cp2013.a4cp.org/sites/default/files/ Übersicht • Definition • Nochmal Münzenwechseln • Approximations-Algorithmen für Bin-Packing uploads/WCB13_proceedings.pdf • F. Hufsky, 2016: http://bioinfowelten.uni-jena.de/ 2016/12/07/spielen-fuer-die-wissenschaft/ – Typeset by FoilTEX – 164 Beispiel, Definition 165 Bin Packing (Koffer packen): Spezifikation • naive Implementierung f. Münzenwechseln: • Spezifikation (als Entscheidungsproblem): M (s) := bestimme die größte Münze mi ≤ s – Eingabe: Kapazität eines Behälters (Eimer, Koffer) c ∈ N, Anzahl e ∈ N, Folge x von Zahlen – Frage: gibt es eine Zerlegung von x in höchstens e disjunkte zerstreute Teilfolgen, jede mit Summe ≤ c? und dann 1 + M (s − mi). • Bsp: m = [1, 5, 8]; 19 → [8, 8, 1, 1, 1], optimal ist [8, 5, 5, 1] Bsp: m = [1, 2, 5, 10], s = 19 (EUR-Münzen/Scheine) • Spezifikation (als Optimierungsproblem): • Vergleich der Algorithmenentwurfsprinzipien: – Eingabe: c, x wie oben – Ausgabe: ein minimales e, so daß . . . (wie oben) – rekursiv : Lösung aus Teillösungen zusammensetzen – dyn. Prog.: diese Teillösungen effizient verwalten – gierig: eine Teillösung benutzen, andere ignorieren dadurch evtl. inkorrekte (nicht optimale) Ausgabe eventuell reicht diese für den Anwendungsfall aus – Typeset by FoilTEX – – Typeset by FoilTEX – • Bsp: c = 10, e = 4, x = [3, 3, 3, 3, 5, 6, 6, 6] • ist Modell für reale Ressourcen-Zuordnungs-Aufgaben 166 – Typeset by FoilTEX – 167 Bin Packing: Algorithmen Online- und Offline-Algorithmen • vollständige Lösung durch Aufzählen aller Zuordnungen z: Gegenstand → Koffer, davon gibt es e|x| viele • kein effizienter Algorithms (Polynomialzeit) bekannt • dynamische Programmierung verbessert die Laufzeit nicht, denn es gibt zu viele Teilprobleme (jede Teilmenge von x, also 2|x| viele) jedes Element xi ohne Kenntnis von [xi+1, . . . , xn] verarbeitet (platziert) wird und die Entscheidung nicht zurückgenommen werden kann • die ursprüngliche Spezifikation verlangt nur einen offline-Algorithmus: die Eingabe kann vollständig gelesen werden, bevor eine Entscheidung fällt. • wir betrachten gierige Algorithmen: schnell (quadratisch), aber nicht optimal. • – (Börsen)handel online: Kaufvertrag wirkt sofort – Interbankenhandel offline (Ausgleich bei Tagesabschluß) • interessant ist dann die Frage, wie weit Ausgabe des Algorithmus höchstens vom Optimum entfernt ist (wir suchen Schranke für den Approximationsfehler) – Typeset by FoilTEX – • ein Algorithmus (für Bin Packing) heißt online, wenn 168 – Typeset by FoilTEX – 169 Online-Algorithms: First Fit (FF) Untere Schranke für Online-Algorithmen • First Fit: für i von 1 bis n: – lege xi in den Eimer mit kleinstem Index, in den es paßt. • Satz: für jeden Online-Algorithmus A für Binpacking gibt es eine Eingabe, für die A wenigstens 4/3 der optimalen Eimerzahl verbraucht. • Satz: First Fit benutzt ≤ 2 mal soviele Eimer wie nötig. P • ab jetzt: Kapazität 1, Gewichte xi ∈ Q, S := xi • Beweis: betrachte m mal 1/2 − , dann m mal 1/2 + . – nach Verarbeiten der ersten Hälfte sind b Eimer belegt. Es gilt b < (m/2) · 4/3 (sonst Gegenbeispiel) – nach Verarbeiten der zweiten Hälfte: jeder neue Eimer enthält genau einen Gegenstand die alten Eimer (b Stück) höchstens zwei G. – insgesamt ≥ 2m − b Eimer benutzt. – Optimum ist m, also 2m − b < m · 4/3 (sonst Gegenb.) – addiere beide Ungl ⇒ Widerspruch • Lemma: optimale Packing benutzt ≥ dSe Eimer. • Lemma: wenn FF Eimer b1 bis bk verwendet, dann ist b1 > 1/2, . . . , bk−1 > 1/2. • Beweis (Satz): P – bk ≥ 1/2 ⇒ k · 1/2 ≤ bi = S P – bk < 1/2 ⇒ (k − 1) · 1/2 < k−1 bi = S − bk < S − 1/2 1 – Typeset by FoilTEX – 170 Schärfere untere Schranke für FF – Typeset by FoilTEX – Übungsserie 7 (für KW 21) • Satz: Es gibt Eingaben, für die FF ≥ 5/3 des Optimums benutzt. Organisatorisches • in KW 21 wegen der Feiertage keine Übungen • Beweis (für klein genug): • stattdessen m mal 1/7 + , m mal 1/3 + , m mal 1/2 + . – autotool-Aufgaben (RNA, LCS, Binpack–FFD) – ein Hörsaal-Übung (zur regulären Vorlesungszeit) – welche Verteilung liefert FF? – welches ist die optimale Verteilung? – Typeset by FoilTEX – 171 172 Aufgabe 7.1 (RNA-Struktur) – Typeset by FoilTEX – 173 .(((((...)))((...))), ausgibt. Begründen Sie die Korrektheit, beschreiben Sie die Laufzeit. • (1 P) Algorithmus aus Skript für vorgegebene Primärstruktur an der Tafel ausführen. • (1 P) Modifizieren Sie den Algorithmus aus dem Skript so, daß das genauere Energiemodell aus der zitierten Arbeit von Bau et al. (S. 89 unten) benutzt wird. • (2 P) Der im Skript angegebene Algorithmus bestimmt die maximale Anzahl (bzw. maximale gebundene Energie) der Bindungen, aber nicht die Bindungen selbst. Geben Sie einen Algorithmus an, der aus dem fertig befüllten Array M eine optimale Menge von Paarbindungen bestimmt und als Klammerwort, z.B. – Typeset by FoilTEX – 174 – Typeset by FoilTEX – 175 Aufgabe 7.2 (Greed) https://gitlab.imn.htwk-leipzig.de/waldmann/adss17/tree/master/kw20 Wir nennen ein Münzsystem einfach, wenn das gierige Verfahren für jeden Betrag eine Darstellung mit minimaler Münzenzahl liefert. Zusatz (1 P) Welche Systeme [x, y, 1] sind einfach? • (1 P) (Lese-Übung) Der Pearson-Test (zitiert in J. Shallit, 2002, http://www.cs.uwaterloo.ca/˜shallit/ Papers/change2.ps) stellt fest, ob ein System einfach ist. Führen Sie diesen Algorithmus für das Münzsystem [1, 2, 5, 10, 25] (oder ein anderes vom Übungsleiter vorgegebenes) aus. • (1 P) vollständige und gierige Zerlegungen mit gegebenen Parametern an der Tafel ausrechnen. • (2 P) Welche der Systeme mit drei Münzen [x, y, 1] mit 10 ≥ x > y > 1 sind einfach? Geben Sie dabei für die nicht einfachen Systeme jeweils den kleinsten Betrag an, für den der gierige Algoritmus keine optimale Zerlegung liefert. Benutzen Sie ggf. Implementierungen aus – Typeset by FoilTEX – 176 – Typeset by FoilTEX – 177 Bäume als Impl. von Mengen, Abbildungen, Folgen Aufgabe 7.3 (Bin Packing) First Fit Decreasing (FFD) = First Fit für die absteigend sortierte Eingabefolge. • Für eine Eingabefolge aus: je 6n Gegenständen der Größen 1/2 + , 1/4 + 2, 1/4 + und 12n Gegenständen der Größe 1/4 − 2, und klein genug: – (1 P) welches ist die optimale Packung? – (2 P) welche Packung wird von FFD berechnet? Was genau heißt dabei klein genug“? ” Übersicht vgl. [WW] 4.4, 6.2 • Suchbäume, Suchen, Einfügen, Löschen • Höhen-Balance, Rotation • evtl. Größen-Balance • (1 P) warum nützt First Fit Increasing“ (FF für ” aufsteigend geordnete Eingabe) nichts? • ADT Menge, Vereinigung, Durchschnitt • ADT Folge, disjunkte Vereinigung (Verkettung) – Typeset by FoilTEX – 178 – Typeset by FoilTEX – Bäume in der Graphentheorie Bäume in der Informatik • Graph, Knoten, Kanten, Weg, Zusammenhang, Kreis • Satz: die folgenden Eigenschaften ungerichteter Graphen G = (V, E) sind paarweise äquivalent: – G ist zusammenhängend und G ist kreisfrei – G ist (kanten)minimal zusammenhängend d. h., G ist zshg. und ∀e ∈ E : (V, E \ {e}) ist nicht zshg. – G ist (kanten)maximal kreisfrei d. h., jedes Hinzufügen einer Kante erzeugt einen Kreis jede kann als Definition von G ist Baum“ dienen. ” • Eigenschaft: Baum mit n Knoten hat n − 1 Kanten. Beweis durch Induktion nach n – Typeset by FoilTEX – 179 180 • gerichtet: – ein Knoten ist Wurzel, hat Eingangsgrad 0 – Kanten zeigen von Wurzel weg – Knoten mit Ausgangsgrad 0: Blätter – die anderen: innere Knoten • geordnet: – die Nachbarn jedes Knoten haben eine Reihenfolge – können linkes Kind von rechtem Kind unterscheiden • markiert: (innerer) Knoten enthält Schlüssel • Bäume sind wichtige Datenstrukturen: – Bäume repräsentieren Mengen (von Schlüsseln) – Operationen in O(Grad · Höhe) möglich – Typeset by FoilTEX – Binärbäume 181 Binärbäume (Beispiele Größe, Höhe) • Def: mit zwei Arten von Knoten: – Blattknoten, äußerer Knoten (keine Kinder, kein Schlüssel): Leaf – Verzweigungsknoten, innerer Knoten: (zwei Kinder l, r, ein Schlüssel k): Branch(l, k, r) • Größe (Anzahl der Knoten) size(Leaf) = 1, size(Branch(l, k, r)) = 1 + size(l) + size(r) • Höhe (Länge eines längsten Pfades von Wurzel zu Blatt) height(Leaf) = 0, height(Branch(l, k, r)) = 1 + max{height(l), height(r)} = = = = size (Branch(Branch(Leaf,2,Leaf),3,Branch(Leaf,5,L 1 + size(Branch(Leaf,2,Leaf)) + size (Branch(Leaf, 1 + 1 + size (Leaf) + size(Leaf) + 1 + size(Leaf) 1 + 1 + 1 + 1 + 1 + 1 7 = = = = = height (Branch(Branch(Leaf,2,Leaf),3,Branch(Leaf,5 1 + max (height (Branch(Leaf,2,Leaf)), height(Bran 1 + max (1 + max(height(Leaf),height(Leaf)), 1 + m 1 + max (1 + max(0,0) , 1 + max 1 + max (1 + 0, 1 + 0) 2 • Satz: ∀t : size(t) ≤ 2height(t)+1 − 1 – Typeset by FoilTEX – 182 – Typeset by FoilTEX – 183 Binärbäume (Beweis Größe/Höhe) Binärbäume (Realisierungen) Satz: ∀t : size(t) ≤ 2height(t)+1 − 1 Beweis: Induktion nach height(t): • in Sprachen mit algebraischen Datentypen (Haskell) data Tree k = Leaf | Branch (Tree k) k (Tree k) • Anfang: height(t) = 0 ⇒ t = Leaf ⇒ size(t) = 1 • Schritt: wenn 0 < h = height(t), dann t = Branch(l, k, r) • in Sprachen mit Zeigern (C, Java, . . . ) height(l) ≤ height(t) − 1 und height(r) ≤ height(t) − 1. struct branch {tree left, K key, tree right}: leaf = nullptr; typedef branch * tree; size(t) = size(Branch(l, k, r)) = 1 + size(l) + size(r) ≤ 1 + 2height(l)+1 − 1 + 2height(r)+1 − 1 ≤ 2height(t)−1+1 + 2height(t)−1+1 + (1 − 1 − 1) = 2height(t)+1 − 1 • implizite Realisierungen z.B.: a[1 . . . n], Kinder von a[i] sind a[2i] und a[2i + 1] – Typeset by FoilTEX – 184 Baum-Durchquerungen 185 Baum-Durchquerungen (Beispiele) t = Branch(Branch(Leaf,2,Leaf),1,Branch(Branch(Leaf, • Abbildung von Binärbaum zu Folge von Schlüsseln immer l vor r, Lage von k unterschiedlich: • pre(Leaf) = [], pre(Branch(l, k, r)) = [k] ◦ pre(l) ◦ pre(r) • ino(Leaf) = [], ino(Branch(l, k, r)) = ino(l) ◦ [k] ◦ ino(r) • post(Leaf) = [], post(Branch(l, k, r)) = post(l)◦post(r)◦[k] • Preorder und Postorder auch für beliebigen Knotengrad. Inorder nur für Binärbäume sinnvoll definierbar. • ohne Berücksichtigung der Reihenfolge: die Menge der Schlüssel. keys(Leaf) = ∅, keys(Branch(l, k, r)) = keys(l) ∪ {k} ∪ keys(r) – Typeset by FoilTEX – – Typeset by FoilTEX – ino(t) = ino(Branch(Branch(Leaf,2,Leaf),1,Branch(Branch(Lea = ino(Branch(Leaf,2,Leaf)) ++ [1] ++ ino(Branch(Bran = ino(Leaf) ++ [2] ++ ino(Leaf) ++ [1] ++ ino(Branch = [] ++ [2] ++ [] ++ [1] ++ ino(Leaf) ++ [4] ++ ino( = [2,1,4,3] pre(t) = [1,2,3,4] post(t) = [2,4,3,1] keys(t) = {1,2,3,4} 186 Suchbäume — Definition, Suchen – Typeset by FoilTEX – 187 Suchbäume — Suchen (Beispiel) contains (4, Branch(Branch(Leaf,2,Leaf),3,Branch(L = contains (4, Branch(Leaf,5,Leaf)) = contains (4, Leaf) = false • Def: ein binärer Baum t heißt Suchbaum gdw. ino(t) ist monoton steigend. • äquivalent: für jeden Teilbaum Branch(l, k, r) von t gilt: ∀x ∈ keys(l) : x < k und ∀x ∈ keys(r) : k < x • Such(K) := Menge der Suchb. mit Schlüsseln vom Typ K • Spezif.: contains(x, t) ⇐⇒ (x ∈ keys(t)), Impl.: contains(x, Leaf) = false contains(x, Branch(l, k, r)) = if x = k then true else if x < k then contains(x, l) else contains(x, r) • Korrektheit: durch Induktion nach height(t), ist Schranke für lineare Rekursion, Komplexität: Θ(height(t)) – Typeset by FoilTEX – 188 Suchbäume — Einfügen 189 Suchbäume — Einfügen (Beispiel) • Spezifikation: insert : K × Such(K) → Such(K), keys(insert(x, t)) = {x} ∪ keys(t) • Implementierung: insert(x, Leaf) = Branch(Leaf, x, Leaf) insert(x, Branch(l, k, r)) = if x = k then Branch(l, k, r) else if x < k then Branch(insert(x, l), k, r) else Branch(l, k, insert(x, r)) • Korrektheit: Induktion. Zu zeigen ist (u.a.), daß jeder konstruierte Knoten die Suchbaum-Eigenschaft hat • Termination/Komplexität: lineare Rekursion mit Schranke height(t) – Typeset by FoilTEX – – Typeset by FoilTEX – 190 insert (4,Branch(Branch(Leaf,3,Leaf),5,Branch(Bran = Branch(insert(4,Branch(Leaf,3,Leaf)),5,Branch(Bran = Branch(Branch(Leaf,3,insert(4,Leaf)),5,Branch(Bran = Branch(Branch(Leaf,3,Branch(Leaf,4,Leaf)),5,Branch – Typeset by FoilTEX – 191 Suchbäume — Einfügen (Beweis) Branch(l, k, insert(x, r)) ∈ Such(K). 1. Lemma t ∈ Such(K) ⇐⇒ t = Leaf ∨t = Branch(l, k, r) ∧ l ∈ Such(K) ∧ r ∈ Such(K) ∧ ∀x ∈ keys(l) : x < k ∧ ∀x ∈ keys(r) : k < x. Beweis: Es gelten: ∀y ∈ keys(l) : y < k weil t Suchbaum ist • ⇒ “ :ino(Branch(l, k, r)) monoton ⇒ ino(l) monoton und ” ino(r) monoton, also nach Induktion l, r ∈ Such(K). ∀y ∈ keys(insert(y, r)) : k < y, weil keys(insert(x, r)) = {x} ∪ keys(r) nach Induktion und k < x (haben wir getestet) und ∀y ∈ keys(r) : k < y, weil t Suchbaum ist. 2. Korrektheit des Einfügens: zu zeigen sind • keys(insert(x, t)) = {x} ∪ keys(t) — das ist einfach • x ∈ K, t ∈ Such(K) ⇒ insert(x, t) ∈ Such(K) Bsp. betrachte letzten Zweig des Algorithmus: zeige, daß (unter den gegebenen Voraussetzungen) – Typeset by FoilTEX – 192 Persistente und ephemere Datenstrukturen 193 Bestimmen und Löschen des Minimums • wir betrachten persistente (unveränderliche) Suchbäume: – werden einmal konstruiert und nie verändert, – Operationen (wie insert) erzeugen neuen Baum • das Gegenteil sind ephemere (veränderliche) Strukturen: – Operationen können Daten in-place“ verändern ” • vollständige Persistenz hat diese Vorteile: – Semantik nicht von implizitem Zustand abhängig – beliebiges sharing von Teilstrukturen möglich – einfache Parallelisierung von Operationen • ist Operationen erzeugen neuen Baum“ ineffizient? ” nein, es werden nur O(height(t)) neue Knoten allokiert. – Typeset by FoilTEX – – Typeset by FoilTEX – • Spezifikation: extractMin : Such(K) → K × Such(K) wenn keys(t) = M 6= ∅, dann extractMin(t) = (m, t0) mit m = min M und keys(t0) = M \ {m}. • Implementierung: extractMin(Branch(l, k, r)) = – falls l = Leaf, dann . . . – sonst let (m, l0) = extractMin(l) in . . . • lineare Rekursion, Laufzeit: O(height(t)) 194 Suchbäume — Löschen – Typeset by FoilTEX – 195 Übungsserie 8 für KW 22 • Spezifikation: delete : K × Such(K) → Such(K) Aufgabe 8.A (autotool) keys(delete(x, t)) = keys(t) \ {x} • Rekonstruktionsaufgaben pre/in/post-order • Implementierung: • Einfügen/Löschen in Suchbäumen – delete(x, Leaf) = . . . – delete(x, Branch(l, k, r)) = ∗ falls x < k, dann Branch(delete(x, l), k, r) ∗ falls x > k, dann . . . ∗ falls x = k, dann · falls r = Leaf, dann . . . · sonst let (m, r0) = extractMin(r) in . . . • lineare Rekursion, Laufzeit: O(height(t)) – Typeset by FoilTEX – 196 – Typeset by FoilTEX – Grundsätzliches 197 Aufgabe 8.1 (Bäume) Auch wenn es nicht explizit dasteht: alle Aussagen sind zu begründen. Es mag ja sein, daß in der Schule trainiert wird, bestimmen Sie“ von geben Sie an“ zu unterscheiden. ” ” Sie sind jetzt aber an einer Hochschule, und dort gibt es nicht für jeden Arbeitsschritt eine separate Einladung und Anleitung, denn das Studienziel ist, daß Sie wissenschaftliche Methoden des Fachgebietes selbständig anwenden. Das wissenschaftliche Vorgehen zeichnet sich gerade dadurch aus, daß jeder Schritt begründet und jedes Resultat überprüfbar ist. Für die durch B(n) := if n > 0 then Branch(B(n − 1), n, B(n − 1)) else Leaf definierten Binärbäume: – Typeset by FoilTEX – – Typeset by FoilTEX – 198 • (1 P) Wieviele innere Knoten hat B(n)? • (1 P) Wieviele Blätter? • (2 P) Summe der Schlüssel? 199 Aufgabe 8.2 (Suchbäume) Aufgabe 8.3 (Suchbäume) Implementieren Sie diese Spezifikation • (1 P) Gegen Sie für M = {3, 5, 7, 8, 11, 13, 25} Suchbäume t mit keys(t) = M der Höhe 2, 3, 4, 5 an. • up : K × Such(K) → Such(K) • (1 P) Für einen Suchbaum t wird contains(20, t) ausgewertet. Dabei wird der gesuchte Wert der Reihe nach mit [5, 40, 30, 10, 11, 33, 14] verglichen — angeblich. Begründen Sie, daß das nicht stimmen kann. in Zeit O(height(t)). (3 P) Ergänzen Sie den Ansatz • up(x, Leaf) = . . . • (2 P) Beweis oder Gegenbeispiel: • up(x, Branch(l, k, r)) = – ∀x ∈ K, t ∈ Such(K) : x ∈ keys(t) ⇒ insert(x, delete(x, t)) = t – ∀x ∈ K, t ∈ Such(K) : x ∈ / keys(t) ⇒ delete(x, insert(x, t)) = t – Typeset by FoilTEX – keys(up(x, t)) = {k | k ∈ keys(t) ∧ x ≤ k} – falls x ≤ k, dann. . . – falls x > k, dann. . . (1 P) Bestimmen Sie up(5, t) für t = der Baum, der durch 200 – Typeset by FoilTEX – 201 Balancierte Suchbäume Einfügen von [1, 8, 2, 7, 3, 6, 4, 5] in dieser Reihenfolge in Leaf entsteht. Motivation • Laufzeit vieler Algorithmen f. Suchbäume: O(height(t)). • für jeden binären Suchbaum t gilt height(t) ≤ # keys(t) < 2height(t) (Beweis: Induktion) also log2 # keys(t) < height(t) ≤ # keys(t). • ein effizienter Suchbaum ist ein solcher mit Höhe log2 # keys(t) . . . oder Θ(log # keys(t)). • das kann erreicht werden durch eine strukturelle Invariante ( jeder Teilbaum ist balanciert“) ” • das Herstellen der Invariante (bei jedem Konstruktor-Aufruf) darf aber nicht zu aufwendig sein – Typeset by FoilTEX – 202 – Typeset by FoilTEX – Zu strenge Balance Höhen-Balance (Definition) • Ein Binärbaum t heißt vollständig, wenn jedes Blatt die Tiefe height(t) hat. – ⇒ # keys(t) = 2height(t) − 1, also height(t) = log2 # keys(t) – gibt es nur für diese Schlüssel-Anzahlen! • Def: ein Baum t heißt höhen-balanciert, falls für jeden Teilbaum Branch(l, k, r) von t gilt: height(l) − height(r) ∈ {−1, 0, +1}. • . . . fast vollständig, falls jede Blatt-Tiefe ∈ {h, h − 1} mit h = height(t) und Blätter mit Tiefe h links von denen mit Tiefe h − 1 stehen – ⇒ 2h−1 ≤ # keys(t) ≤ 2h − 1, ⇒ h = dlog2 # keys(t)e – für jede Schlüssel-Anzahl genau ein solcher Baum, – finde t1, t2 mit keys(t1) = {2 . . . 7}, keys(t2) = {1 . . . 7}, – was folgt für die Komplexität des Einfügens? – Typeset by FoilTEX – 204 Höhen-Balance erzwingt logarithmische Höhe • Satz: t ∈ AVL(K) ⇒ # keys(t) ≥ Fheight(t)+2 − 1 • die Menge der höhen-balancierten Suchbäume: AVL(K), mit Höhe h: AVLh(K) Adelson-Velski, Landis; 1962 • das ist eine nützliche strukturelle Invariante, denn: – t ∈ AVL(K) ⇒ height(t) ∈ Θ(log(size(t))) – eine durch Einfügen eines Schlüssels zerstörte Invariante läßt sich leicht reparieren – Typeset by FoilTEX – 205 Operationen für balancierte Suchbäume • aus dem Code für insert(x, t), delete(x, t) für unbalancierte Suchbäume wird Code für balancierte Suchbäume: mit Fibonacci-Zahlen F0 = 0, F1 = 1, Fn+2 = Fn + Fn+1 • Beweis: – height(t) = 0. Dann t = Leaf, # keys(t) = 0 = F2 − 1 – height(t) = 1. Dann t = . . . – height(t) = h ≥ 2. Dann t = Branch(l, k, r) mit (height(l) = h − 1 und height(r) ≥ h − 2) oder (height(l) ≥ h − 2 und height(r) = h − 1). dann # keys(t) ≥ (Fh − 1) + 1 + (Fh+1 − 1) = Fh+2 − 1 • Anwendg.: log(Fh) ∈ Θ(h) ⇒ log # keys(t) ≥ c · height(t), ⇒ height(t) ∈ O(log # keys(t)) – Typeset by FoilTEX – 203 206 • jeder Aufruf des Konstruktors Branch(l, k, r) wird ersetzt durch smart constructor balance(Branch∗(l, k, r)), • dabei gilt ∀x ∈ keys(l) : x < k, ∀y ∈ keys(r) : k < y, l, r ∈ AVL(K) und | height(l) − height(r)| ≤ 2. Resultat ∈ AVL(K) • Zusatzkosten O(height(t)), falls Rebalancieren in Θ(1) für insert: tatsächlich nur Θ(1) – Typeset by FoilTEX – 207 Balancieren durch Rotieren (1) Balancieren durch Rotieren (2) • Fall 1.2: t = Branch∗(Branch(ll, lk, lr), k, r), • Knoten mit Höhendifferenz 2 : ll ∈ AVLh(K), lr ∈ AVLh+1(K), r ∈ AVLh(K) – Fall 1: t = Branch∗(l, k, r), l = Branch(ll, lk, lr) ∈ AVLh+2(K), r ∈ AVLh(K) ∗ Fall 1.1: ll ∈ AVLh+1(K), lr ∈ AVL{h,h+1}(K) ∗ Fall 1.2: ll ∈ AVLh(K), lr ∈ AVLh+1(K) – Fall 2 (Fälle 2.1, 2.2) symmetrisch • eine Rechts-Rotation allein hilft nicht (nachrechnen!) • lr = Branch(lrl, lrk, lrr) mit lrl, lrr ∈ AVL{h,h−1}(K) • Links-Rot. in l ⇒ l0 = Branch(Branch(ll, lk, lrl), lrk, lrr) keys(l) = keys(l0),l ∈ Such(K) ⇒ l0 ∈ Such(K), Branch(ll, lk, lrl) ∈ AVLh+1(K) • löse Fall 1.1 durch Rotation nach rechts – ersetze t durch t0 = Branch(ll, lk, Branch(lr, k, r)). keys(t) = keys(t0), t ∈ Such(K) ⇒ t0 ∈ Such(K) Branch(lr, k, r) ∈ AVLh+1(K), t0 ∈ AVLh+2(K). – beachte: funktioniert auch für lr ∈ AVLh−1(K), das wird für Behandlung von 1.2 benötigt – Typeset by FoilTEX – • dann erfüllt Branch∗(l0, k, r) die Voraussetzung von 1.1 (ggf. unter Benutzung von beachte:“) ” Rechts-Rotation ergibt t0 ∈ AVLh+2(K). 208 – Typeset by FoilTEX – 209 Korrektheit und Anzahl der Rotationen: Insert Korrektheit und Anzahl der Rotationen: Delete • für alle (smart) Konstruktor-Aufrufe Branch∗(l, k, r) zeige: | height(l) − height(r)| ≤ 2 • für alle Aufrufe balance(Branch∗(l, k, r)) ist zu zeigen | height(l) − height(r)| ≤ 2 • folgt aus height(t) ≤ height(insert(x, t)) ≤ height(t) + 1 • folgt aus height(t) − 1 ≤ height(delete(x, t)) ≤ height(t) • Begründung: – durch nicht balanc. Einfügen steigt Höhe um max. 1 – betrachte untersten Knoten (Teilbaum) t mit Höhendifferenz 2 dann height(balance(t)) = height(t) nur im Fall . . . und dieser tritt beim Einfügen nicht ein. – ⇒ nach Rotieren wieder Original-Höhe – ⇒ Knoten darübe benötigen keine Rotationen • wenn beim Rotieren die Höhe verringert wird, dann muß darüber auch evtl. auch noch rotiert werden, usw. • Das Löschen eines Knotens kann Θ(height(t)) Rotationen erfordern. • Bsp: betrachte Fibonacci-Baum T0 = T1 = Leaf, Tk+2 = Branch(Tk+1, Tk ) und lösche den Knoten ganz rechts • insgesamt beim Einfügen höchstens einmal rotieren – Typeset by FoilTEX – 210 – Typeset by FoilTEX – Ergänzungen Anwendungen Suchbäume • AVL-Operationen ausprobieren: benutze autotool-Aufgabe • realisieren abstrakten Datentyp (ADT) Menge – – – – • Quelltexte https://gitlab.imn.htwk-leipzig.de/ waldmann/ad-ss17/tree/master/kw22/avl https://gitlab.imn.htwk-leipzig.de/autotool/all0/ blob/master/collection/src/Baum/AVL/Ops.hs java.util: TreeSet<K> implements Set<K> contains : K × Set(K) → B, empty, insert, delete Komplexität O(height(t)) für balancierte Bäume: O(log # keys(t)) • in inneren Knoten Schlüssel und Wert speichern: • exakte Spezifikationen mit vollständig maschinell überprüften Beweisen (Nipkow et al., 2004): realisiert ADT Abbildung – lookup: K × Map(K, V ) → V ∪ {⊥}, empty, insert (update), delete (Ü: welche Typen?) – Komplexität wie oben https://www.isa-afp.org/browser_info/current/AFP/ AVL-Trees/AVL.html – Typeset by FoilTEX – 211 212 Weitere Operationen für Suchbäume – Typeset by FoilTEX – 213 Übungsserie 9 für KW 23 • Massen-Operationen: intersection, difference, union: Set(K) × Set(K) → Set(K), compose (join): Map(A, B) × Map(B, C) → Map(A, C) Aufgabe 9.A • (autotool) Einfügen und Löschen in AVL-Bäumen • Komplexität für Union(t1, t2): durch Iterieren über Schlüsselmenge des kleineren Baumes: min(|t1|, |t2|) · log max(|t1|, |t2|) • durch Implementierung von balance(Branch∗(l, k, t)) für beliebige | height(l) − height(r)| in O(height(t1) + height(t2)) • schnelleres Union für disjunkte Mengen (das ist auch nützlich in Teilbäumen) – Typeset by FoilTEX – 214 – Typeset by FoilTEX – 215 Aufgabe 9.1 (Rotieren) Aufgabe 9.2 (AVL-Struktur) Aufgabe 13.2–4 aus [Cormen, Leiserson, Rivest, Stein] (deutsche Ausgabe als E-Buch in der Bibliothek) Die Aussage ist zu ergänzen: . . . in jeden anderen binären ” Suchbaum mit der gleichen Schlüsselmenge . . .“, sonst ist sie trivial falsch. (2 P) Lösen Sie die Aufgabe für den Spezialfall, daß t1 ein vollständiger binärer Suchbaum mit 7 Schlüsseln und t2 eine rechtsläufige Kette ist. (2 P) Lösen Sie die Aufgabe allgemein. – Typeset by FoilTEX – 216 • (2 P) Was ist die minimale Tiefe (d.h. Abstand von der Wurzel) der Blätter aller AVL-Bäume mit Höhe h? • (2 P) Leiten Sie daraus einen weiteren Beweis für height(t) ∈ O(log size(t)) ab. • (3 P) Konstruieren Sie einen Baum t = Branch(l, k, r) ∈ AVL(K) mit size(l)/ size(r) > 1000. (Nicht konkret aufmalen, sondern beweisen, daß es einen gibt. Welche Höhe hat er?) – Typeset by FoilTEX – Heap-geordnete Bäume Aufgabe 9.3 (AVL-Operationen) • (3 P) Bestimmen Sie t1, . . . , t7 für t0 = Leaf, tk = insert(k, tk−1). Übersicht • der abstrakte Datentyp PWS (PQ) Welche Balance-Operationen finden dabei statt? • heap-geordnete Bäume [WW] Kap. 10, [OW] Abschn. 6.1 • (3 P) Bestimmen Sie t1, . . . , t7 für t0 = vollständiger binärer Suchbaum mit Schlüsseln {1, 2, . . . , 7}, tk = delete(k, tk−1). • vollständig balancierte Binärbaume (Anwendung: Heap-Sort) Welche Balance-Operationen finden dabei statt? – Typeset by FoilTEX – • evtl. Ausblick: Quake Heaps 218 – Typeset by FoilTEX – Motivation und Plan • wird u.a. für Bestimmung kürzester Wege benötigt • wir benutzen Binärbäume t mit diesen Eigenschaften: – heap-geordnet: für jeden Teilbaum Branch(l, k, r) von t: ∀x ∈ keys(l) : k ≤ x, ∀y ∈ keys(r) : k ≤ y – fast vollständig balanciert: alle Blätter in Tiefe h oder (rechts davon) h − 1. • diese Forderung ist diesmal nicht zu streng, denn es gibt genügend viele Repräsentationen einer festen Menge von Schlüsseln (Bsp: {1, 2, . . . , 7}) • die Menge soll nicht vollständig geordnet werden, weil das evtl. zu teuer ist (also kein Suchbaum) • Operationen in O(height(t)) = O(log # keys(t)) . . . oder noch weniger 220 Binäre Heaps (Implementierung) – Typeset by FoilTEX – 221 Binäre Heaps: Einfügen, Verringern • die fast vollständige Balance wird durch eine implizite Baumdarstellung erreicht: – – – – 219 Binäre Heaps (Plan) • abstrakter Datentyp: Vorrang-Warteschlange (priority queue) (Priorität ∈ N, kleiner ⇒ wichtiger), Operationen: – insert : (K × N) × PQ(K) → PQ(K) – extractMin : PQ(K) ,→ (K × PQ(K)) (partielle Ftk.) bestimmt und entfernt einen wichtigsten Eintrag – decrease : (K × N) × PQ(K) → PQ(K) erhöht Priorität das ist der Plan, tatsächlich sind die Typen noch anders – Typeset by FoilTEX – 217 • insert(k, A[1 . . . n]): – füge neues Element an: A[n + 1] := k, – repairere Heap-Ordnung (auf Pfad von n + 1 zu Wurzel) ∗ i := n + 1, (A[i] ist evtl. zu klein, wandert nach oben) ∗ solange i > 1 und A[parent(i)] > A[i]: A[parent(i)] ↔ A[i]; i := parent(i). Branch-Knoten stehen in einem Array A[1 . . . n] K1 ist die Wurzel Ki = Branch(K2i, A[i], K2i+1) für i > n : Ki = Leaf • Korrektheit (Invariante): ∀j : j 6= i ⇒ A[parent(j)] ≤ A[j]. • diese Form bleibt immer erhalten • Laufzeit: O(height(t)) = O(log n). (evtl. ändern wir n um 1) • gleicher Algorithmus zum Reparieren nach decrease(i, v, A): Aneu[i] := v ≤ Avorher[i] • die Operationen reparieren ggf. die Heap-Ordnung durch Vertauschung von Elementen. – Typeset by FoilTEX – 222 – Typeset by FoilTEX – 223 Binäre Heaps: Minimum bestimmen und entfernen Binäre Heaps: Heap erzeugen • gegeben: Folge (Multimenge) von Schlüsseln M gesucht: binärer Heap t mit keys(t) = M • triviale Lösung: fortgesetztes Einfügen P Laufzeit (mit h = log n): hk=1 2k · k = Θ(n log n) (welches ist der schlechteste Fall?) • alternative Lösung: – Eingabe in A[1 . . . n] schreiben, – für i von n/2 bis 1: repariere A[i] ist zu groß“. ” Invariante: ∀j : j > i ⇒ Teilbaum ab j ist heap-geordnet Ph Laufzeit: k=1 2k · (h − k) = Θ(n) • NB: Unterschied Heap/Suchbaum: beweise, daß es nicht möglich ist, einen Suchbaum in O(n) zu konstruieren. • Heap-Ordnung ⇒ das Minimum steht immer in A[1] • Minimum entfernen: A[1] := A[n], n := n − 1, reparieren (A[i] ist evtl. zu groß, wandert nach unten) – i := 1, – solange A[i] > A[left(i)] ∨ A[i] > A[right(i)]: A[i] ↔ min(A[left(i)], A[right(i)]) i := vorige Position des Minimums • Korrektheit (Invariante): ∀j : (parent(j) 6= i) ⇒ A[parent(j)] ≤ A[j] • Laufzeit: O(height(t)) = O(log n). – Typeset by FoilTEX – 224 Bemerkung zur Implementierung (I) – Typeset by FoilTEX – 225 Bemerkung zur Implementierung (I) • wir hatten in erster Näherung diese Typen behauptet: • diese Verweise muß man richtig verwalten, • das geht gar nicht, denn um einen Schlüssel zu verringern, muß man wissen, wo er steht — man kann ihn aber nicht suchen (weil der Heap kein Suchbaum ist) • Lösung: ein zusätzliches Array R, Zähler t – insert : (K × N) × PQ(K) → PQ(K) – decrease : (K × N) × PQ(K) → PQ(K) denn durch Operationen wie A[parent(i)] ↔ A[i] werden Plätze getauscht. • Lösung: das Einfügen liefert einen Verweis in den Heap, der beim Verringern benutzt wird: – insert : (K × N) × PQ(K) → (Ref(K) × PQ(K)) – decrease : (Ref(K) × N) × PQ(K) → PQ(K) – Typeset by FoilTEX – – bei jedem insert: t := t + 1; R[t] = n + 1 (dort beginnt die Bahn des eingefügten Elements, t ist der Verweis-Rückgabewert des insert) – bei jedem A[i] ↔ A[j]: auch R[i] ↔ R[j] – decrease(t, v) bezieht sich dann auf A[R[t]]. Details, Beispiele: siehe [WW] 226 – Typeset by FoilTEX – Ausblick: schnellere Heaps Anwendung binärer Heaps: Heapsort • das ist ein Sortierverfahren: – Eingabe in A[1 . . . n] schreiben – Heap-Ordnung herstellen (Komplexität Θ(n)) – fortgesetztes extractMin (Komplexität Θ(n log n)) liefert Elemente in aufsteigender Reihenfolge • wenn man dafür Max-Heap (statt Min-Heap) benutzt, kann man Heap und Ausgabe im gleichen Array abspeichern • ergibt asymptotisch optimales Sortierverfahren mit wenig (d.h. konstantem) zusätzlichen Platzbedarf (vgl. merge-sort) – Typeset by FoilTEX – 227 • hier gezeigte binäre Heaps realisieren insert, decrease, extractMin jeweils in O(log n) • das kann ein balancierter Suchbaum auch • es gibt Heaps (z.B. Fibonacci heaps, Quake heaps) für die decrease schneller geht (in O(1)) und die anderen Op. immer noch in O(log n). (decrease ist häufigste Operation im später betrachteten Algorithmus von Dijkstra zum Bestimmen kürzester Wege) • dafür sind fortgeschrittene Analyse-Techniken nötig • T. M. Chan: Quake Heaps, 2013, http://link.springer.com/ chapter/10.1007/978-3-642-40273-9_3 228 – Typeset by FoilTEX – 229 Aufgabe 10.1 (Binäre Heaps) Übungsserie 10 für KW 24 • (3 P) Repräsentiert das Array einen Heap? Wenn nein, repräsentiert es einen Zwischenzustand bei der Ausführung von insert? von extractMin? Aufgabe 10.A (autotool) • insert, decrease, extractMin für binäre Heaps – [2, 11, 3, 7, 6, 4, 8, 12, 10] – [2, 5, 3, 8, 6, 7, 4] – [1, 6, 3, 7, 5, 2, 8, 9] • (2 P) Eine Folge von Operationen, die dann vom Übungsleiter vorgegeben wird, an der Tafel vorrechnen (ohne Hilfsmittel). Beispiele: Für den durch das Array [1, 2, . . . , 7] implizit repräsentierten Heap: – Typeset by FoilTEX – 230 – Typeset by FoilTEX – 231 Aufgabe 10.2 (Kombination Suchbaum und Heap) – solange extractMin, bis der Heap leer ist. – für k von 1 bis 7: die Priorität von k auf −k verringern. Wir betrachten binäre Bäume, deren Schlüssel Zahlenpaare sind, so daß für die ersten Komponenten die Heap-Eigenschaft und für die zweiten Komponenten die Suchbaum-Eigenschaft gilt. (Es wird keine Balance-Eigenschaft gefordert.) • (1 P) Geben Sie einen solchen Baum t mit folgender Schlüsselmenge an: {(5, 1), (4, 3), (7, 4), (3, 0), (1, 5), (6, 7)} • (2 P) Beweisen Sie: für jede Schlüsselmenge M ⊆ N × N, deren ersten Komponenten paarweise verschieden sind – Typeset by FoilTEX – 232 und deren zweiten Komponenten paarweise verschieden sind, gibt es genau solchen Baum t mit keys(t) = M . – Typeset by FoilTEX – 233 Aufgabe 10.3 (Young-Tableaux) (4 P) [CLRS] Aufgabe 6-3 a,c,d,e. Hinweis: Induktion nach der Größe von M . • (2 P) Geben Sie ein Verfahren zum Einfügen an. Hinweis: Rotationen. Fügen Sie (2, 2) in t ein. – Typeset by FoilTEX – 234 Direkter Zugriff (Hashing und Anwend.) • Aufgabe: sortiere eine Folge von 1.000.000 Zahlen. Lösung: Merge-, Heap-, Quick-, Bubble-Sort usw. [WW] 9, [CLRS] 11 • Aufgabe: sortiere eine Folge von 1.000.000 natürlichen Zahlen aus dem Intervall [0 . . . 1000] • Counting-Sort, Lösung: . . . • Hash-Tabellen • Hinweis: • Radix-Sort, Tries Aufgabe: sortiere eine Folge von 1.000.000 Bits 236 – Typeset by FoilTEX – 237 Hashing zur Implementierung des ADT Menge Sortieren durch Zählen • Aufgabe: sortiere eine Folge a von n natürlichen Zahlen aus dem Intervall [0 . . . B] • Lösung: benutze Array c[0 . . . B], initialisiert mit [0, . . . , 0] – für i von 1 bis n: { k := a[i]; c[k] := c[k] + 1 } Invariante: ∀k : c[k] = #{j | 1 ≤ j < i ∧ a[j] = k} – für k von 0 bis B: drucke c[k] mal k • Laufzeit ist n + B, also für festes B: Sortieren in O(n)? • Ja. Das ist kein Widerspruch zu Schranke Ω(n log n), denn diese gilt nur für vergleichsbasierte Verfahren • Spezifikation: – empty, contains, insert : K × Set(K) → Set(K), delete – Semantik: dynamisch (ephemer, mutable) Operationen zerstören vorige Werte • Plan zur Implementierung: – benutze Array a[0..m − 1] von Wahrheitswerten – Funktion (hash) h : K → [0..m − 1] – contains(x, S) ⇐⇒ a[h(x)] • dazu müssen diese Fragen geklärt werden: – welcher Wert für m (Kapazität)? – welche Funktion h? – was passiert bei Kollision x 6= y ∧ h(x) = h(y)? • Algorithmus Sortieren durch Zählen“ (counting sort) ” benutzt direkten Zugriff (Zahlenwerte der Eingabe) – Typeset by FoilTEX – 235 Motivation Übersicht – Typeset by FoilTEX – – Typeset by FoilTEX – 238 – Typeset by FoilTEX – 239 Hashfunktionen (1) Hashfunktionen (2) • Ziel h : N → [0..m − 1] • Ziel: Funktion (hash) h : K → [0..m − 1] – h soll Wertebereich möglichst gleichmäßig ausnutzen – Wert h(x) sollte von allen Bits von x abhängen • Realisierung in zwei Schritten: – von K zu N – von N zu [0..m − 1] • Divisionsmethode: h(x) = mod(x, m) – m sollte nicht von der Form 2e sein – Ü: m sollte nicht 2e − 1 sein • Schritt 1 ist grundsätzlich deswegen möglich, weil alle Daten binär im (Haupt)speicher stehen und jede Bitfolge eine natürliche Zahl beschreibt. • Multiplikationsmethode: h(x) = bm · mod(q · x, 1)c √ – für eine irrationale Zahl q, z.B. ( 5 + 1)/2 – dabei bedeutet mod(·, 1) : R → R : z 7→ z − bzc – Ü: kann mit Ganzzahl-Arithmetik implementiert werden, benutze q ≈ Q/2e für passendes Q ∈ N und m = 2e. • wir nehmen deswegen an, daß K = N – Typeset by FoilTEX – 240 – Typeset by FoilTEX – 241 Hashing mit offener Adressierung Hashing mit Verkettung (Chaining) • das Kollisions-Problem: falls x 6= y ∧ h(x) = h(y): S0 = empty; S1 = insert(x, S0); contains(y, S1) =? • Motivation: Vermeidung des Aufwandes (Zeit und Platz) für die Verwaltung der Mengen (z.B. Zeiger für Listen) • Lösung (Plan) – Element-Typ des Arrays ist nicht B, sondern Set(K) – meist repräsentiert durch einfach verkettet Liste • Tabellen-Einträge sind K ∪ {⊥}, bei Konflikt zw. x und y wird y an einer anderen Stelle in der Tabelle gespeichert. • Beispiel (lineares Sondieren) – insert(x, S): für p von h(x) bis mod(h(x) + m − 1, m): falls a[p] = ⊥, dann a[p] := x und fertig, falls a[p] = x, dann fertig – contains(x, S): für p von h(x) bis mod(h(x) + m − 1, m): falls a[p] = ⊥, dann false falls a[p] = x, dann true – delete(x, S)? Vorsicht! • Lösung (Realisierung) – contains(x, S) = contains(x, a[h(x)]). – insert(x, S) : a[h(x)] := insert(x, a[h(x)]) – delete(x, S) entsprechend • Laufzeit: 1 + ((maximale) Größe der Mengen h(x)) bei gleichmäßigem Hashing: 1 + size(S)/m = 1 + α – Typeset by FoilTEX – 242 Offene Adressierung und Delete – Typeset by FoilTEX – 243 Lineares Sondieren und Haufen (Clustering) • naives Löschverfahren a[h(x)] = ⊥ ist nicht korrekt • Laufzeit von contains und insert ist O((maximale) Länge eines belegten Abschnitts) • gelöschte Einträge müssen gesondert markiert werden • selbst bei gleichmäßiger Hashfunktion wächst diese Größe stärker als size(S)/m, denn die Wahrscheinlichkeit dafür, daß ein neuer Eintrag in ein Intervall I fällt, ist |I|/m. ⇒ es ist zu erwarten, daß große Haufen (cluster) noch größer werden. • die so markierten Stellen können beim Einfügen wieder benutzt werden • zum Vergleich: bei Chaining: die Wsk, daß ein neuer Eintrag in eine bestimme Menge fällt, ist 1/m. ⇒ es ist zu erwarten, daß alle Mengen ähnlich groß sind. – Typeset by FoilTEX – 244 245 Erwartete Laufzeit f. doppeltes Hashing Offene Adr. mit doppeltem Hashing • Plan: bei Kollision von x mit y ⇒ verschiedene Sondierungs-Folgen für x und y ⇒ keine Haufen-Bildung • Realisierung: – (linear: für p in [h(x), h(x) + 1, h(x) + 2, . . . ] . . . ) – doppeltes Hashing: benutze zwei Hashfunktionen h1, h2 und für p in [h1(x), h1(x) + h2(x), h1(x) + 2h2(x), . . . ] . . . • unter der Annahme, daß alle Werte von mod(h1(x) + i · h2(x), m) gleich wahrscheinlich sind, bestimmen wir die erwartete Laufzeit für eine erfolglose Suche (oder das Einfügen eines neuen Elementes) • Kollision für i = 0 mit Wsk 1/α unter dieser Voraussetzung: Kollision für i = 1 mit Wsk. 1/α, gesamt Wsk.: 1/α2 P erwartete Schrittzahl insg. ≤ k≥0(1/α)k = 1/(1 − α) • damit durch mod(h1(x) + i · h2(x), m) alle Werte in [0..m − 1] erreicht werden, muß gcd(h2(x), m) = 1 sein. • zur Erinnerung: Chaining: 1 + α. zum Beispiel: m prim und 0 < h2(x) < m Vergleiche Zahlenwerte für α = 1/2, α = 2/3 oder m = 2e und h2(x) ungerade – Typeset by FoilTEX – – Typeset by FoilTEX – 246 – Typeset by FoilTEX – 247 Amortisierte Komplexität Eine Variante des doppelten Hashing • insert(x, S), beim Sondieren mit p = h1(x) + i · h2(x): Übersicht falls a[p] = y mit y 6= ⊥ und y 6= x: [CLRS] Kapitel 17.4 – bisher: bestimme nächste Sondierungs-Adresse für x – alternativ (Brent, 1973) ∗ bestimme Ersatz-Adresse q = p + h2(y) für y, ∗ falls a[q] frei ist: a[p] := x; a[q] := y ∗ sonst weiter sondieren für x. • Motivation • Definition • Beispiel: Vergrößerung von Hashtabellen • Beispiel: Quake Heaps • vgl. [WW] Algorithmus 9.10 oder [OW] Abschnitt 4.3.4 • Erweiterung dieser Idee: Kuckucks-Hashing (evtl. Ü) – Typeset by FoilTEX – 248 Motivation • anzustreben ist α = 1/2 (oder ähnlich, je nach Verfahren) • # keys(S) vorher unbekannt, α wird überschritten: re-hashing (alle Elemente in eine Tabelle doppelter Größe übertragen, mit neuer Hashfunktion) • Komplexität: 1. das ist teuer, 2. das geschieht selten 250 Die Potential-Methode • Ziel: Beschreibung der Gesamtkosten einer Folge von Operationen im schlechtesten Fall. • Def: Operationen o ∈ O mit tatsächlichen Kosten c(o) haben amortisierte Kosten ca(o), P P falls ∀s ∈ O∗ : o∈s c(o) ≤ o∈s ca(o) • Bsp: die amortisierten Kosten für insert mit re-hashing sind O(1) für jede Folge, die mit leerer Tabelle beginnt. • tatsächliche Kosten für insert (re-hash bei α > 1/2) 1, 2, 3, 1, 5, 1, 1, 1, 9, 1, 1, 1, 1, 1, 1, 1, 17, 1, . . . die Partialsummen pi dieser Folge: 1, 3, 6, 7, 12, 13, 14, 15, 24, 25, 26, . . . , 31, 48, 49, . . . es gilt pi ≤ 3 · i (d.h.: kleiner als die P.S. von 3, 3, 3, . . . ) – Typeset by FoilTEX – • Ziel: Prioritätswarteschlange mit amortisierten Kosten insert : O(1), decrease : O(1), extractMin : O(log n) • Realisierung: – Liste von vollständig höhen-balancierten Bäumen mit binären und unären Knoten – tatsächliche Kosten: insert : O(1), decrease : O(1), extractMin : O(n) – Beweis der amortisierten Kosten durch geeignetes Potential (im wesentlichen: Anzahl der unären Knoten) • T. M. Chan: Quake Heaps, 2013, http://link.springer.com/ Bsp: P (T ) = 2 · Anzahl der insert seit letztem re-hash • amortisierte Kosten von Operation o (bzgl. P ): ca(o) = c(o) + P (nach o) − P (vor o) P P • denn o∈s ca(o) = o∈s c(o) + P (nach s) − P (vor s) P P wenn P (Anfang) = 0, dann o∈s c(o) ≤ o∈s ca(o) • Bsp: Hashing. P (leer) = 0 und chapter/10.1007/978-3-642-40273-9_3 – ca(insert) ohne re-hash: 1 + 2(e + 1) − 2e = 3 – ca(insert) mit re-hash: (2e + 1) + 2 · 1 − 2e = 3 W. Mulzer: Erdbebenhaufen, https: //page.mi.fu-berlin.de/mulzer/notes/ha/quake.pdf 252 – Typeset by FoilTEX – Strukturelle Invarianten von Quake Heaps 253 extractMin für Quake Heaps • Q-Heap ist Liste von Bäumen mit Eigenschaften: – innere Knoten binär oder unär, Schlüssel in Blättern – alle Blätter gleich tief – jeder inn. Knoten i hat Verweis auf kleinstes Blatt m(i) – jedes Blatt b hat Verw. h(b) auf höchstes i mit m(i) = b • insert(x, S) in O(1): ein neuer Baum (Blatt) mit Schlüssel x der Höhe 0 • extractMin(S): – bestimme Wurzel w, für die m(w) minimal ist Kosten: O(Anzahl Bäume) – lösche Knoten auf Pfad von w zu m(w), dadurch entstehen neue Bäume, Kosten: O(Höhe). – Operat. zum Reduzieren der Baum-Anzahl u. -Höhe • Reduktion der Anzahl: solange es zwei Bäume gleicher Höhe h gibt: fasse diese zu einem Baum (mit binärer Wurzel) der Höhe h + 1 zusammen Kosten: O(Anzahl Bäume vorher), Resultat: O(Höhe + log n) Bäume • decrease(x, v, S) in O(1) (mit x in Blatt b): – Eintrag in b wird auf v verringert – falls h(b) keine Wurzel ist: h(b) wird aus seinem Vorgänger entfernt (dieser ist binär, wird unär) dadurch entsteht neuer Baum mit h(b) als Wurzel – Typeset by FoilTEX – 251 Amortisierte Analyse von Quake Heaps • Potentialfunktion P : Datenstrukur → N – Typeset by FoilTEX – 249 Def. und Bsp.: Amortisierte Komplexität • wie wählt man die Größe einer Hashtabelle? – Größe muß vor erster Operation fixiert werden, kann danach nicht geändert werden – zu klein ⇒ hoher Belegungs-Faktor α, hohe Laufzeiten (viele Kollisionen), Überlauf (keine freien Plätze) – zu groß ⇒ Speicher verschenkt (viele freie Plätze) – Typeset by FoilTEX – – Typeset by FoilTEX – 254 – Typeset by FoilTEX – 255 Potential für Quake Heaps Logarithmische Höhe und Erdbeben • P (H) = K + 2 · B + 4 · U mit • mit ni = Anzahl der Knoten aller Bäume in Höhe i (n0 = Anzahl der Blätter = Anzahl der Schlüssel) soll immer gelten: ∀i : ni+1 ≤ 3/4 · ni. – B = Anzahl der Bäume, – K = Anzahl aller Knoten, U = . . . der unären Knoten • ⇒ die Höhe jedes Baumes ist dann ≤ log4/3 n ∈ O(log n) • Erdbeben“ (quake): falls ∃i : ni+1 > 3/4 · ni, ” dann i0 := das kleinste solche i, lösche alle Knoten der Höhe > i0. Kosten: Anzahl dieser Knoten (= D) • insgesamt: c(insert) = O(log n + Anzahl Bäume + D) was ist die passende Potentialfunktion, für die ca(insert) = O(log n) und ca(insert), ca(decrease) ∈ O(1)? – Typeset by FoilTEX – 256 – insert: c = 1, ∆(K) = 1, ∆(B) = 1, ∆(U ) = 0,ca = 4 – decrease: . . . – extractMin: c = O(log n + B0 + D), ca = O(log n) ∗ Pfad löschen: ∆(K + B) < 0, ∆(U ) ≤ 0 ∗ Bäume zusammenfassen: ∆(B) = log n − B0, ∆(K) = −∆(B), ∆(U ) = 0 ∗ Erdbeben: ∆(K) ≤ 0, ∆(B) ≤ ni, ∆(U ) ≤ −ni/2 – Typeset by FoilTEX – 257 Aufgabe 11.1 (Hashing) Übungsserie 11 für KW 25 Für Aufgabe 11.A (autotool: Hashing) • (1 P) Hashing mit linearem Sondieren, • Hashing mit Verkettung • (1 P) doppeltes Hashing, • Hashing mit linearem Sondieren • (2 P) doppeltes Hashing in der Variante von Brent (siehe Skript bzw. dort angegebene Literatur) • doppeltes Hashing – Typeset by FoilTEX – • ca(o) so festlegen, daß ca(o) ≥ c(o) + ∆(P ) für den Algorithmus an einem Beispiel an der Tafel vorführen. 258 Aufgabe 11.2 (Kuckucks-Hashing) – Typeset by FoilTEX – 259 Aufgabe 11.3 (Amortisierte Analyse) engl. cuckoo hashing Wiederholung (1. Semester): • (1 P) Zitieren Sie die wissenschaftliche Primär-Quelle (die referierte Publikation der Erfinder) für diesen Algorithmus (Autor, Titel, Jahr, Ort (Konferenz)) • Schlange und Keller sind Listen mit beschränktem Zugriff: • Ein Keller (stack) hat die Operationen push (Einfügen) und pop (Extrahieren, beides am linken Ende). • (1 P) Geben Sie die Invariante des Verfahrens an. Welche Laufzeit der Operationen (contains, insert) ergibt sich daraus? Wo ist der Laufzeit-Unterschied zu den in der VL betrachteten Verfahren? Die Schlange S soll durch zwei Keller L, R implementiert werden. • (2 P) Führen Sie den Algorithmus an einem Beispiel an der Tafel vor. – Typeset by FoilTEX – • Die Warteschlange (queue) (ohne Prioritäten) hat die Operationen enqueue (Einfügen am rechten Ende) und dequeue (Extrahieren am linken Ende) • Invariante: der Inhalt von s ist append(L, reverse(R)). 260 • leere Schlange: L = R = leerer Keller. – Typeset by FoilTEX – 261 • (2 P) Geben Sie eine Potentialfunktion P an, bezüglich derer die amortisierten Kosten von enqueue und dequeue O(1) sind. • enqueue(x, S) = push(x, R) • dequeue(S) = 1. falls L leer, dann: solange R nicht leer: push(pop(R), L) 2. pop(L) Geben sie P (S0), P (S1), . . . für die o.g. Operationsfolge an. Aufgaben: • (1 P) Führen Sie S1 = enqueue(3, S0), S2 = enqueue(4, S1), S3 = dequeue(S2), S4 = enqueue(5, S3), S5 = dequeue(S4) vor. • (1 P) welches sind die tatsächlichen Kosten von enqueue und dequeue (als Funktion von |L| und |R|)? Die Kosten von push und pop sind 1. – Typeset by FoilTEX – 262 – Typeset by FoilTEX – 263 Graphen: Eigenschaften, einfache Algorithmen Aufgabe 11.4 (Zusatz) (Quake Heaps) • (2 P) beschreiben Sie das Verhalten von QH für: Einfügen mehrerer Schlüssel, dann wiederholtes extractMin, bis der Heap leer ist. Überblick Welche Komplexität hat dieses Sortierverfahren? Geben Sie den Verlauf des Potentials an. • (2 P) Geben Sie eine Operationsfolge an, die mit leerem Heap beginnt und ein Erdbeben enthält. Geben Sie den Verlauf des Potentials an. • (2 P) Das Potential im Skript (übernommen aus zit. Skript von Mulzer) ist anders als das im Artikel von Chan. Ist der Unterschied wesentlich? – Typeset by FoilTEX – 264 Motivation, Definition, Beispiele • G = (V, E), (ungerichtet) E ⊆ V 2 , (gerichtet) E ⊆ V Andreas Brandstädt: Graphen und Algorithmen, Teubner 1994, https://link.springer.com/book/10.1007/ 978-3-322-94689-8 Hansjoachim Walther, Günther Nägler: Graphen — Algorithmen — Programme, Fachbuchverlag Leipzig 1987 • Bezeichnungen, Eigenschaften • Datenstrukturen zur Repräsentation von Graphen • Tiefensuche, Breitensuche • topologisches Sortieren, Zusammenhangskomponenten – Typeset by FoilTEX – 265 Spezielle Graphen, Graph-Operationen 2 • Graph = zweistellige Relation (ungerichtet: symmetrisch) • Relationen (und damit auch Graphen) sind fundamental für Prädikatenlogik, Modellierung, Informatik. • Graphen, mit denen derzeit viel Geld verdient wird: – das WWW (Knoten: URLs; Kanten: Verweise) – das sogenannte soziale Netzwerk (Knoten: Personen, genauer: Werbe-Ziele; Kanten: sogenannte Freundschaften) • Graphentheorie: Eulerkreise (1736), Landkartenfärbung (Kempe 1879) . . . • Graph-Algorithmen: Anwendung von Datenstrukturen – Typeset by FoilTEX – 266 • Spezielle Graphen: – unabhängiger Graph In (n Knoten, keine Kanten) – vollständiger Graph (Clique) Kn (n Knoten, alle Kanten) – Pfad Pn (n Knoten, n − 1 Kanten) – für n ≥ 3: Kreis Cn (n Knoten, n Kanten) • Operationen: – Komplement c(V, E) = (V, E) = (V, V2 \ E) – disjunkte Summe (V1, E1) ∪ (V2, E2) = (V1 ∪ V2, E1 ∪ E2) – Verkettung (join) G1 + G2 = c(c(G1) ∪ c(G2)) • weitere spezielle Graphen: – vollständig bipartit Ka,b = Ia + Ib, – Stern K1,b, Rad K1 + Cn – Typeset by FoilTEX – Eigenschaften von Graphen 267 Verbindungen, Abstände • u ∼G v: u und v sind verbunden in G, falls es in G einen Pfad u → . . . → v gibt – G ungerichtet: ∼G ist eine Äquivalenzrelation auf V . – Die Äquivalenzklassen V /∼G heißen Zusammenhangskomponenten – G heißt zusammenhängend, wenn |V / ∼G | = 1 • Knotenzahl: |V (G)|, n; Kantenzahl: |E(G)|, m • G ungerichtet: Nachbarn G(u) := {v | {u, v} ∈ E(G)} mit verkürzter Notation für Kanten: {v | uv ∈ E(G)} • G gerichtet: Nachfolger G(u) := {v | (u, v) ∈ E(G)} Vorgänger: G−(u), mit Spiegelbild G− := (V, E −). • Grad eines Knotens degG(u) = #G(u) Minimalgrad: δ(G) = min{degG(u) | u ∈ V } Maximalgrad: ∆(G) = max{degG(u) | u ∈ V } • G ist r-regulär, falls ∀u ∈ V : degG(u) = r • Bsp: Petersen-Graph ( 52 , {uv | u ∩ v = ∅}) ist 3-regulär. (Das kann man ohne Zeichnung nachprüfen.) • distG(u, v) := die Länge (d.h. Anzahl der Kanten) eines kürzesten Pfades in G von u nach v. (+∞, falls es keinen solchen gibt) – diese Def. gilt für ungerichtete und für gerichtete G – Durchmesser diam(G) := maxu,v∈V distG(u, v) – Radius rad(G) := minu∈V maxv∈V distG(u, v) – Typeset by FoilTEX – – Typeset by FoilTEX – 268 Die Größe spezieller Teilgraphen Repräsentationen von Graphen • Unabhängigkeitszahl α(G): die maximale Größe der unabhängigen Teilmengen in G • Annahme: direkter Zugriff für Knoten: V = [1, 2, . . . , n] • Aufgabe: (effiziente) Repräsentation von E – schneller Zugriff: Adjazenz-Matrix a : V 2 → B mit uv ∈ E ⇐⇒ a[u, v] = true – wenig Platz: Adjanzenz-Listen: für jeden u ∈ V : die Menge G(u) repräsentiert als (einfach verkettete) Liste • Cliquenzahl ω(G): die maximale Größe der vollständigen Teilmengen in G • Taillenweite (girth) g(G): die minimale Größe der Kreise in G. • wir verwenden grundsätzlich die AL-Darstellung, • Übungsaufgaben: bestimme alle im Skript gennanten Parameter für alle im Skript genannten Graphen. wenigstens zur Repräsentation der Eingabe von Graphalgorithmen g(Petersen), χ(Petersen), ω(K3,3), rad(C5), α(C7), . . . – Typeset by FoilTEX – 269 (intern könnten diese andere Datenstrukturen benutzen) 270 – Typeset by FoilTEX – 271 Das Durchlaufen von Graphen (Schema) Breitensuche (breadth first search, BFS) • – Eingabe: Graph G = (V, E) – Ausgabe: Folge von Knoten s ∈ V ∗, Relation p auf V • done := ∅; todo := {v0}; p[v0] = ⊥; while todo 6= ∅ wähle v ∈ todo (z.B. den ältesten oder den neuesten) todo := todo \ {v}; done := done ∪ {v} für alle u ∈ G(v) \ done : todo := todo ∪ {u}; p[u] := v • v ∈ done ⇐⇒ c[v] = schwarz, (todo: grau, sonst: weiß) • Invarianten/Eigenschaften: – p ist die Vorgänger-Relation eines Baumes – jedes x ∈ todo ∪ done ist von v0 aus erreichbar durch Weg P (x) : v0 → . . . → p[p[x]] → p[x] → x – jeder Nachbar von x ∈ done ist schwarz oder grau – schließlich: done = die von v0 erreichbaren Knoten, – Typeset by FoilTEX – 272 Tiefensuche (depth first search, DFS) • Bezeichnung d(x) := |P (x)| oder +∞, falls x weiß Satz: ∀x : d(x) = distG(v0, x) • Beweis: Inv.: distG(v0, x) ≤ d(x), weil P (x) ein Weg v0 →∗ x ist. Inv.: todo = [x1, . . . , xk ] ⇒ d(x1) ≤ . . . ≤ d(xk ) ≤ d(x1) + 1. Zeige Satz durch Induktion über distG(v0, x) • Laufzeit von BFS(G) ist O(n + m) = O(|V | + |E|). Beweis: für jeden Knoten und für jede Kante O(1). – Typeset by FoilTEX – • ordne F = DFS(G) durch zeitliche Reihenfolge der Bäume sowie in jedem Knoten zeitliche R. der Kinder F = [t1, . . . , tk ] mit ti ∈ (V ) • alternative Formulierung mit Rekursion: DFS1(x) := Tree(V ) = {Branch(v, [t1, . . . , tk ]) | v ∈ V, ti ∈ Tree(V )} c[x] := grau; for y ∈ G(x): if y ∈ weiß then {p[y] := x; DFS1(y); } c[x] := schwarz • die DFS-Reihenfolge von G • Erweiterung gegenüber Schema: besuche alle Knoten DFS(G) : while (weiß 6= ∅) { wähle v0 ∈ weiß; DFS1(v0) } • DFS(G) = (V, {(p[x], x) | x ∈ V, p[x] 6= ⊥}) ist der DFS-Wald von G (eine disjunkte Vereinigung von Bäumen) ist die Preorder-Reihenfolge von F , Notation <pre(F ) (Reihenfolge der Entdeckung = der Graufärbung) • in Anwendungen wird auch die Postorder-Reihenfolge von F benutzt, Notation <post(F ) (Reihenfolge der Erledigung = der Schwarzfärbung) 274 – Typeset by FoilTEX – DFS-Klassifikation der Kanten • Bezeichnungen: {u, v} ist ungerichtete Baum-, Rückwärts-, Querkante ⇐⇒ (u, v) oder (v, u) ist Baum-, . . . -kante. Baum-Kante, falls x →F y Rückwärts-Kante, falls y →∗F x Vorwärts-Kante, falls x →≥2 F y Quer-Kante, sonst. • Satz: für ungerichtete Graphen G = (V, E): jedes e ∈ E ist Baum-Kante oder Rückwärts-Kante • Satz: Mit F = DFS(G) gilt: (x, y) ∈ E(G) ist bezüglich F = DFS(G). – Baum- oder Vorwärtskante, falls x <pre(F ) y ∧ y <post(F ) x – Rückwärtskante, falls y <pre(F ) x ∧ x <post(F ) y – Querkante, falls y <pre(F ) x ∧ y <post(F ) x (Der Fall x <pre(F ) y ∧ x <post(F ) y kommt nicht vor.) – Typeset by FoilTEX – (d.h., es gibt keine Querkanten) • Beweis: falls xy Querkante, (x, y) gerichtete Querkante, dann nach Def. y <post(F ) x, aber Kante (y, x) verlangt x <post(F ) y, Widerspruch. 276 – Typeset by FoilTEX – Gerichtete kreisfreie Graphen (DAG) 277 Topologisches Ordnen • Bezeichnung: DAG (directed acyclic graph): • Def: eine totale Ordnung (V, ≤) heißt topologische Ordnung für gerichteten Graph G = (V, E), falls ∀(x, y) ∈ E : x < y. gerichteter Graph ohne gerichteten Kreis • Satz: Für jeden gerichteten Graphen G: G ist DAG ⇐⇒ DFS(G) erzeugt keine Rückwärtskanten • Beweis: • Anwendung: V : Aufgaben, E: Abhängigkeiten, (<): Ausführungsreihenfolge • Satz: G besitzt topologische Ordnung ⇐⇒ G ist DAG. ⇒“: (indirekt) ” falls (x, y) Rückwärtskante, dann Kreis y →∗F x → y • Beweis: ⇒“: (indirekt) betrachte Kreis C in G und (V (C), ≤) ” ⇐“: (direkt) mit F = DFS(G) ist >post(F ) eine ” topologische Ordnung. ⇐“: (indirekt) falls Kreis C in G, ” y ∈ V (C) mit y minimal bzgl. <pre(F ) und (x, y) ∈ E(C). Dann y →∗T x und (x, y) wird Rückwärtskante – Typeset by FoilTEX – 275 DFS für ungerichtete Graphen • Def.: Mit F = DFS(G): (x, y) ∈ E(G) heißt – – – – 273 Bezeichnungen für DFS-Bäume und -Ordnung • implementiere todo als Keller (stack): – Extrahieren und Einfügen am linken Ende – Typeset by FoilTEX – • implementiere todo als Warteschlange (queue): – Extrahieren von v am linken Ende, – Einfügen aller u ∈ G(v) am rechten Ende. 278 – Typeset by FoilTEX – 279 Minimal-Gerüste Definition Minimalgerüst Überblick • Def. Ein Baum T heißt Gerüst von G, falls V (T ) = V (G). • Satz: G ist zusammenhängend ⇐⇒ G besitzt Gerüst. • Def. Minimalgerüst, • Def. ein (kanten-)gewichteter Graph • Algorithmus von Kruskal • ADT Mengensystem • Implementierung Mengensystem durch disjoint-set-forest ist ein Paar (G, w) mit w : E(G) → R P • Def. für H ⊆ G: w(H) = {w(e) | e ∈ E(H)} • Def. T ist ein Minimalgerüst (MST) für (G, w), falls w(T ) = min{w(T 0) | T 0 ist Gerüst für G} • Motivation: Verbindungen von Bestandteilen technischer Systeme (Rohrleitungen, Straßen, Leiterbahnen,. . . ) – Typeset by FoilTEX – 280 – Typeset by FoilTEX – 281 Algorithmus (Eigenschaften, Realisierungen) Algorithmus (Schema) • schrittweise Konstruktion eines MST durch Hinzufügen von sicheren Kanten (die die Invariante nicht verletzen) • in jedem Fall gilt – Anfang: (V, A) hat |V | Komponenten der Größe 1 – Schluß: (V, A) ist eine Komponente der Größe |V |. • // Invariante: ∃T : (V, A) ⊆ T und T ist MST für G A := ∅ ; while A ist kein Gerüst wähle sichere Kante e ∈ E(G); A := A ∪ {e} • Algorithmus von Kruskal: C: eine beliebige Komponente • Satz: A erfüllt Invariante, C eine Zsgh-Komponenten von (V, A), • Algorithmus von Prim: e eine leichteste Kante zw. C und V \ C. zusätzliche Invariante: Kanten von A bilden einen Baum. Dann ist e sicher. C: die Knotenmenge dieses Baums Beweis: in T gibt es eine Kante f zw. C und V \ C. Dann ist T \ {f } ∪ {e} auch ein MST für G. – Typeset by FoilTEX – 282 – Typeset by FoilTEX – Algorithmus von Kruskal (1956) Union-Find-Strukturen • Plan: e := eine leichteste Kante, die eine beliebige Komponente C von A mit V \ C verbindet • [OW] Kapitel 6.2, [CLR] Kapitel 21 • abstrakter Datentyp zur dynamischen Repräsentation von Äquivalenzklassen einer Relation R – Union(x, y): R := R ∪ {(x, y)} – equiv(x, y): gilt x ∼R y mit (∼R) = (R ∪ R−)∗ ? • Realisierung: – E 0 := sortiere E nach aufsteigendem Gewicht – für xy aus E 0: falls x 6∼A y, dann A := A ∪ {xy}. • Realisierung mittels – find(x): kanonischer Repräsentant von [x]∼R , so daß ∀x, y : equiv(x, y) ⇐⇒ find(x) = find(y) • Kosten: – Θ(m log m) für Sortieren von E – m mal feststellen, ob x ∼A y für einen solchen Test haben wir O(log n) Zeit, ohne die Laufzeit asymptotisch zu erhöhen. (beachte: n − 1 ≤ m wg. Zusammenhang von G) – Typeset by FoilTEX – 283 • Beispiel für kanonische Repräsentation: – Menge N × (N>0), Äq.-Relation (x1, y1) ∼ (x2, y2) ⇐⇒ x1 · y2 = x2 · y1, Repr. von [(x, y)]∼ ist (x/g, y/g) mit g = gcd(x, y) 284 Mengensysteme (DSF, disjoint set forest) – Typeset by FoilTEX – 285 Effiziente Implementierung von Union in DSF • zur Implementierung von Union / find • Basis: Union(x, y) : – find(x): die Wurzel des Baumes, der x enthält. – Union(x, y): find(x) wird Kind von find(y). s := find(x); t := find(y); if s 6= t then p[s] := t • Realisierung des Baumes durch Rückwärts-Zeiger (jeder Knoten auf Vorgänger) in Array p : V → V ∪ {⊥} find(x) : if p[x] = ⊥ then x else find(p[x]) Satz: ∀x : find(x) ist eine Wurzel • Verbesserung: . . . if height(s) < height(t) then p[s] := t else p[t] := s • dann gilt ∀x : height(x) ≤ log(size(x)) • height(x) in Array H : V → N abspeichern. • Union(x, y) : Aktualisieren: p[t] := s; H[s] := max{H[s], 1 + H[t]} s := find(x); t := find(y); if s 6= t then p[s] := t korrekt, aber es können unbalancierte Bäume entstehen. – Typeset by FoilTEX – 286 – Typeset by FoilTEX – 287 Effiziente Implementierung von find in DSF Zusammenf./Ausblick: MST-Algorithmen • Basis: find(x) : if p[x] = ⊥ then x else find(p[x]) • Algorithmus von Kruskal (1956) Laufzeit O(m log m) ⊆ O(m log n) • Verbesserung: Pfad-Kompression: • Der Algorithmus von Prim (1957) (und Jarnik, 1930) zur Bestimmung eines MST – Wurzel s für x bestimmen wie bisher – für jeden Knoten y auf Pfad von x zu s: p[y] := s – ist ähnlich zu später behandeltem Algorithmus von Dijkstra zur Bestimmung kürzester Pfadlängen, – wird deswegen danach und nur kurz (oder als Übungsaufgabe) behandelt. – hat Laufzeit O(n log n + m) • Berechnung von H[] wird nicht geändert – Bestimmung der tatsächlichen Höhe ist zu teuer – Pfadverkürzungen wirken sich nicht auf H aus – es gilt ∀x : height(x) ≤ H[x] • insgesamt wird Laufzeit deutlich verbessert (auf o(log∗(n)) ⊂ o(log n), Details siehe Literatur.) – Typeset by FoilTEX – 288 – Typeset by FoilTEX – 289 Aufgabe 12.1 (vorrechnen) Übungsserie 12 für KW 26 Algorithmen an der Tafel ausführen, ggf. auch als Teil der Diskussion einer der folgenden Aufgaben. Aufgabe 12.A (autotool) • Breitensuche • (1 P) Breitensuche • Tiefensuche • (1 P) Tiefensuche • Minimalgerüst • (1 P) Algorithmus von Kruskal zur Bestimmung eines Minimalgerüstes • (1 P) Union/Find-Operationen in Disjoint Set Forest – Typeset by FoilTEX – 290 – Typeset by FoilTEX – 291 Aufgabe 12.3 (Tiefensuche) Aufgabe 12.2 (Graph-Eigenschaften) • (2 P) Sei DFS(G) = [. . . , t1, . . . , t2, . . . ] der Tiefensuchwald eines gerichteten Graphen G (d.h., der Baum t1 wird vor dem Baum t2 durchlaufen). • (1 P) Bestimmen Sie Durchmesser und Radius des Petersen-Graphen. • (1 P) Geben Sie Algorithmen zur Bestimmung von Durchmesser und Radius von Graphen an (= Aufgabe [WW] 4.15). Geben Sie ein Beispiel an, bei dem G eine Kante von t2 nach t1 enthält. • (2 P) Wenn rad(G) = r bekannt ist, z.B. r = 3, welches sind der minimale und der maximale Wert von diam(G)? Geben Sie Graphen an, die diese Werte erreichen. Begründen Sie, daß G niemals eine Kante von t1 nach t2 enthält. • (2 P) Seien t ∈ DFS(G), Branch(x, [. . . , s1, . . . , s2, . . . ]) Teilbaum von t und Knoten y ∈ s1, z ∈ s2. Begründen Sie: falls y →∗G z, dann y →∗G x. Hinweis: benutzen Sie <post(F ) – Typeset by FoilTEX – 292 – Typeset by FoilTEX – 293 Kürzeste Wege Aufgabe 12.4 (Minimalgerüste) • (1 P) Lösen Sie Ihre Instanz der autotool-Aufgabe Minimalgerüst durch den Algorithmus von Kruskal. Überblick WW 10 • (3 P) [CLR] Problem 23-4 (Alternative Algorithmen . . . ) • von einem Knoten: Algorithmus von Dijkstra WW 5.3 • zwischen allen Knoten: Algorithmus von Floyd und Warshall – Typeset by FoilTEX – 294 – Typeset by FoilTEX – 295 Definitionen Algorithmus von Dijkstra • Plan: Anpassung der Breitensuche – Spezifikation: Länge → Gewicht, |P | → w(P ) – Implementierung: Warteschlange (queue) → Prioritätswarteschlange (heap) • Spezifikation: kürzeste Wege von einem Knoten zu allen anderen (single source shortest paths) – Eingabe: ∗ kantengewichteter Graph (G, w), Gewichte ≥ 0, ∗ Knoten s ∈ V (G) – Ausgabe: Funktion (Array) d : V → R ∪ {∞} mit d[t] = dist(G,w)(s, t) • c[·] := weiß; d[·] := ∞; H := {(s, 0)}; c[s] := grau; d[s] := 0 while grau 6= ∅ x := extractMin(H); c[x] := schwarz for y ∈ G(x) \ schwarz d[y] := min{d[y], d[x] + w(x, y)} if c[y] = weiß then {insert(y, d[y], H); c[y] := grau} else if c[y] = grau then decrease(y, d[y], H) • Bezeichnungen: – dist(G,w)(s, t) := min{w(P ) | P ist Pfad von s nach t} P – w(P ) = {w(e) | e ∈ P } (wurde schon definiert) – das ist sinnvolle Verallgemeinerung von distG(s, t) – Typeset by FoilTEX – • Inv: ∀v : dist(s, v) ≤ d[v], ∀v ∈ schwarz : dist(s, v) = d[v] 296 Algorithmus von Dijkstra: Korrektheit – Typeset by FoilTEX – 297 Algorithmus von Dijkstra: Laufzeit • Kosten für die Bestandteile des Algorithmus: • ∀v : dist(s, v) ≤ d[v]: wenn d[y] := d[x] + w(x, y), dann gibt es nach Induktion einen Weg mit diesen Kosten von s zu y (über x). – Verwaltung der Knotenfarben (schwarz, grau, weiß) durch direkten Zugriff (Array) in O(1) – effiziente Prioritätswarteschlange (z.B. Quake Heap) ∗ n mal extractMin, jeweils O(log n) ∗ m mal insert oder decrease, jeweils O(1) • ∀v ∈ schwarz : dist(s, v) = d[v] Beweis indirekt: betrachte erstes v, für das direkt vor Schwarz-Färbung gilt dist(s, v) < d[v]. dann gibt es Pfad P : s →∗ v mit Kosten < d[v]. b := der erste nicht schwarze Knoten auf P , a := Vorgänger von b (a ∈ schwarz, b ∈ grau) nach Induktion d[a] = dist(s, a) nach Konstruktion w(P ) ≥ d[b] ≥ d[v], Widerspruch. • Gesamtkosten: O(n log n + m) • Bemerkung: hier wurde ∀e : w(e) ≥ 0 benutzt. – Typeset by FoilTEX – 298 Algorithmus von Dijkstra: über den Autor 299 Kürzeste Wege für alle Knotenpaare • Edsger W. Dijkstra, 1930–2002 • ACM Turing Award 1972, http://amturing.acm. org/award_winners/dijkstra_1053701.cfm • Manuskripte: http://www.cs.utexas.edu/users/EWD/ Lesetipp: EWD 1305 Answers to questions from students of Software Engineering – Typeset by FoilTEX – – Typeset by FoilTEX – 300 • [CLR] Kapitel 25, [OW] 9.5.3, [WW] 8.2 • Spezifikation: (all pairs shortest paths) – Eingabe: kantengewichteter Graph (G, w), Gewichte ≥ 0, – Ausgabe: Funktion (Array) d : V 2 → R ∪ {∞} mit d[s, t] = dist(G,w)(s, t) • mögliche Implementierung: for s ∈ V : Algorithmus von Dijkstra mit Start s Kostet O(n2 log n + nm), erfordert schnelle (komplizierte) PQ-Implementierung • betrachten hier einfache Algorithmen in O(n3) • auch als Wiederholung zu dynamischer Programmierung – Typeset by FoilTEX – 301 Der tropische Halbring Matrizen über Halbringen • auf der Menge T = R ∪ {+∞} definieren die Operationen – ⊕: Minimum (neutrales Element +∞) – ⊗: Addition (neutrales Element 0) einen Halbring (Monoid (T, ⊕, +∞), Monoid (R, ⊗, 0), Distributivgesetz) • Bezeichnung: Matn(S): Menge der n × n-Matrizen über S • T = tropischer Halbring, zu Ehren des brasilianischen Mathematikers Imre Simon (1943–2009) • dieser Halbring paßt zu Minimierung von Wegen, denn – ⊗: Reihenschaltung, Addition entlang eines Weges – ⊕: Parallelschaltung, Auswahl eines kürzesten – ∞: kein Weg; 0: ein Weg der Länge 0 – Typeset by FoilTEX – 302 • Satz: S ist Halbring ⇒ Matn(S) ist Halbring, mit – ⊕Mat(S) ist die übliche Matrixaddition (A ⊕Mat(S) B)i,j = Ai,j ⊕S Bi,j , neutral: Null-Matrix – ⊗Mat(S) ist übliche Matrixmultiplikation (A ⊗Mat(S) B)i,j = (Ai,1 ⊗S B1,j ) ⊕S · · · ⊕S (Ai,n ⊗S Bn,j ) neutral: Einheitsmatrix ∞ ∞ 0 ∞ • Bsp. in Mat2(T): 0 = ,1= , ∞ ∞ ∞ 0 2 ∞ 1 3 2 ∞ 1 3 ⊕ = ..., ⊗ = ... 3 0 2 ∞ 3 0 2 ∞ – Typeset by FoilTEX – 303 Matrizen von Weg-Kosten Berechnung von Matrix-Potenzen • gewichteter Graph (G, w) mit V (G) = {1, . . . , n} ist eine tropische Matrix W mit Wx,y = if (x, y) ∈ E then w(x, y) else ∞ • Berechnung von M n für M ∈ Matn(S) durch R := 1; for k ∈ [1, . . . , n] {R := R ⊗ M } • für die Potenzen von W gilt: (W k )x,y = min. Kosten aller Wege der Länge k von x zu y • die all-pairs-shortest-paths-Matrix zu W ist demnach W ∗ = 1 ⊕ W ⊕ W 2 ⊕ . . . (unendl. Summe in Matn(T)) • Berechnung durch R := M ; for k ∈ [1, . . . , dlog2 ne] {R := R ⊗ R} kostet log n · n3 Operationen. • mittels dynamischer Programmierung ist O(n3) erreichbar • alle Kosten ≥ 0 ⇒ kürzeste Wege haben < n Kanten W ∗ = 1 ⊕ W ⊕ W 2 ⊕ · · · ⊕ W n−1 (endliche Summe) = (1 ⊕ W )n−1 (Addition ist komm. und idempotent) – Typeset by FoilTEX – kostet n · n3 Operationen. 304 Algorithmus von Floyd und Warshall – Typeset by FoilTEX – 305 Übungsserie 13 für KW 27 • Eingabe: Kostenmatrix W ∈ Matn(T), Elemente ≥ 0 Ausgabe: Matrix der kürzesten Wege W ∗ = (1 ⊕ W )n−1 Allgemeines • Mo. 7:30 N001 Vorlesung (= Zusammenfassung) • Implementierung: berechne Folge M0, . . . , Mn−1 = W ∗ mit Mh[x, y] := minimale Kosten aller Wege x = p0 → p1 → · · · → pk = y mit p1, . . . , pk−1 ∈ {1, . . . , h} • Mo. 12:00 G119 Hörsaal-Übung (Serie 13 sowie ggf. frühere Zusatzaufgaben) – h ist Parameter der dynamischen Programmierung – M0 := 1 ⊕ W (Wege haben Länge 0 oder 1) – Mh+1[x, y] := Mh[x, y] ⊕ Mh[x, h + 1] ⊗ Mh[h + 1, y] (Fallunterscheidung: Weg von x nach y benutzt h + 1, dann höchstens einmal, oder gar nicht) • Do. oder Fr. (online-Stundenplan beachten!) Hörsaal-Übung (Prüfungsvorbereitung) (Hr. Wenzel) Fragen, die dann diskutiert werden sollen, sind Herrn Wenzel vorher per Mail mitzuteilen. • Kosten: O(n ) 3 • R. Floyd, CACM 5(6) 1962; S. Warshall, JACM 9(1) 1962 – Typeset by FoilTEX – 306 Aufgaben 13.A (autotool) – Typeset by FoilTEX – 307 Aufgabe 13.1 (Algorithmus von Prim) Der Algorithmus von Prim zur Bestimmung eines Minimalgerüstes entsteht aus dem Algorithmus von Dijkstra zur Bestimmung kürzester Pfade, indem die Anweisung d[y] := min{d[y], d[x] + w(x, y)} durch die Anweisung d[y] := min{d[y], w(x, y)} ersetzt wird. Jedesmal, wenn dort w(x, y) < d[y], notieren wir x als Vorgänger von y (in einem Array p durch die Zuweisung p[y] := x). Diese Vorgänger-Zuordnung kann wechseln, solange y grau ist. Die Vorgängerkanten bilden am Ende des Algorithmus einen Baum, der ein Minimalgerüst für (G, w) ist. zu Algorithmen von • Dijkstra, • Prim, • Floyd und Warshall Das sind dann nicht unbedingt Pflicht-Aufgaben. Nutzen Sie trotzdem diese Gelegenheit, sich diese Algorithmen vom autotool vorführen zu lassen. • (1 P) Führen Sie den Algorithmus von Prim für Ihre Instanz der autotool-Aufgabe Minimalgerüst durch. – Typeset by FoilTEX – 308 • (2 P) Begründen Sie: jedesmal, wenn ein x als Minimum extrahiert wird, dann ist die Kante {x, p[x]} eine sichere Kante für den Schnitt zwischen C = schwarz und V \ C. (Das ist [WW] Aufgabe 5.6) – Typeset by FoilTEX – 309 Aufgabe 13.2 (Algorithmus von Dijkstra) • (2 P) Wie unterscheidet sich asymptotisch die Komplexität einer Implementierung des Algorithmus von Dijkstra mit fast vollständig balancierten binären Heaps von einer Implementierung mit Quake Heaps – für Graphen mit |E| ∈ Θ(|V |2) (sogenannte dichte Graphen)? – für Graphen mit |E| ∈ Θ(|V |) (sogenannte dünne Graphen)? • (2 P) [CLR] Übung 24.3–8. Was passiert für W = 1? Für W = 2? Zusatz : 24.3–9. – Typeset by FoilTEX – 310 – Typeset by FoilTEX – 311 Aufgabe 13.3 (all pairs shortest paths) • (2 P) Für jede der drei im Skript angegebenen Variante der Berechnung der Matrix W ∗: kann die Rechnung abgekürzt (d.h., die Komplexität verringert) werden, falls die kürzesten Pfade nur von einem Knoten aus zu bestimmen sind? • (2 P) Welche Information über G enthält die Matrix A∗, wenn A die Adjazenzmatrix des Graphen G ist und der zugrundeliegende Halbring B (Wahrheitswerte) mit den Operationen ⊕ = ∨ und ⊗ = ∧? – Typeset by FoilTEX – Weitere Beispiele zu Graphen und -Algorithmen Färbungen (Definition, Beispiele) • eine (konfliktfreie) c-Färbung von G ist Abb. f : V → {1, . . . , c} mit ∀uv ∈ E : f (u) 6= f (v) • chromatische Zahl χ(G) = min{c | G hat eine c-Färbung} • Bsp: χ von: P5, C5, I5, K5, K3,3, Petersen. 312 – Typeset by FoilTEX – 313 Chromatische Zahl und Maximalgrad Färbungen (Geschichte) • Satz: χ(G) ≤ ∆(G) + 1 • Der Vierfarbensatz: G ist planar (besitzt kreuzungsfreie ebene Zeichnung) ⇒ χ(G) ≤ 4 • Beweis: Konstruktion einer Färbung durch den folgenden (offensichtlichen) Greedy-Algorithmus: • Diese Vermutung (Guthrie 1852, Cayley 1878) und ihre Beweisversuche (Kempe 1879, Tait 1880) sind ein Ursprung der modernen Graphentheorie. Für eine beliebige Reihenfolge [v1, . . . , vn] der Knoten: • Beweis (mit Computerhilfe) durch Appel und Haken 1977 c(vi) := mex M mit M = {c(vj ) | j < i ∧ vj vi ∈ E}, mex M := min(N>0 \ M ) • vereinfacht durch Robertson, Saunders, Seymour, Thomas 1995 • Bsp: ein G und eine Knotenreihenfolge, so daß die vom Algorithmus berechnete Färbung nicht minimal ist. • maschinell verifizierter Beweis durch Gonthier 2005, siehe http://www.ams.org/notices/200811/ • Beweis: folgt aus c(vi) ≤ |M | + 1 und |M | ≤ |G(vi)| – Typeset by FoilTEX – • Aufgabe: für welche Graphen gilt χ(G) = ∆(G) + 1? 314 315 Hohe chromatische Zahl ohne Dreiecke Der Satz von Brooks • Brooks 1941: G zusammenhängend und G nicht vollständig und G kein ungerader Kreis ⇒ χ(G) ≤ ∆(G). • Beweis: (nach Cor Hurkens, https://www.win.tue.nl/˜wscor/OW/CO1b/) • Def: ω(G) := max{n : Kn ⊆ G} (größte Clique in G) • Satz: χ(Kn) = n, Satz: ω(G) ≤ χ(G). • Satz: ∀c : ∃Gc : ω(G) = 2 ∧ χ(G) = c Bsp: G2 = P2, G3 = C5, G4 = . . . • Beweis (Mycielski, 1955) – Konstruktion von M (G) für G = (V, E) als ∗ Knoten: V ∪ V 0 ∪ {0} mit V 0 = disjunkte Kopie von V ∗ Kanten: E ∪ {xy 0 | xy ∈ E} ∪ {x00 | x ∈ V } – Eigenschaften: ∗ G ohne Dreieck ⇒ M (G) ohne Dreieck ∗ χ(M (G)) = χ(G) + 1 – x mit Grad ∆(G), hat Nachbarn y, z mit xy ∈ / E. – wenn G0 = G \ {y, z} zshg., dann T = BFS(G0, x). Knotenreihenfolge: y, z, dann <post(F ) (endet mit x) es ist immer eine Farbe aus {1, . . . , ∆(G)} frei. – wenn G0 nicht zshg., dann einfachere Fälle, siehe Quelle. • Anwendung: χ(Petersen) ≤ 3 – Typeset by FoilTEX – – Typeset by FoilTEX – • Bsp: C5 = M (P2). Def: Grötzsch-Graph := M (C5) 316 – Typeset by FoilTEX – Effizientes Färben 317 Komplexitätstheorie • die Spezifikation • . . . untersucht Schwierigkeiten von Problemen gewünschtes Resultat: P ist schwer“, ” d.h., besitzt keinen Polynomialzeit-Algorithmus – Eingabe G, – Ausgabe: konfliktfreie Färbung c : V (G) → 2, falls existiert, NEIN sonst hat effizienten Algorithmus: BFS, Schichten abwechselnd färben, auf Konflikte prüfen. • für Eingabe G, Ausgabe: . . . c : V (G) → 3,. . .“ ” ist kein Polynomialzeit-Algorithmus bekannt. • das ist aber sehr schwer nachzuweisen, ? vgl. auch die Million-Dollar-Frage“ P = NP ” http://www.claymath.org/ millennium-problems/p-vs-np-problem – P: Menge der in Polynomialzeit lösbaren Probleme – NP: Menge der durch Suchbäume polynomieller Tiefe lösbaren Probleme 2-Färbung ∈ P, 3-Färbung ∈ NP, offen: 3-Färbung ∈ P – Typeset by FoilTEX – 318 – Typeset by FoilTEX – 319 Zusammenfassung Reduktionen • wenn man für A ∈ NP nicht zeigen kann, daß A ∈ / P, • dann zeigt man ersatzweise A gehört zu den schwersten ” Problemen in NP“, Def: falls jedes B ∈ NP sich auf A reduzieren läßt: • B ≤P A, A wenigstens so schwer wie B“ ” • . . . durch Angabe von Polynomialzeitverfahren für f : Eingabe für B → Eingabe für A mit ∀x : x ∈ B ⇐⇒ f (x) ∈ A • Ideen — z.B.: Balance • Sätze — zeigen die Nützlichkeit der Ideen z.B.: t ist AVL-balanciert ⇒ height(t) ≤ log1.6 size(t) • Methoden — sind Quellen für Ideen z.B.: Induktion über die Höhe von Bäumen • Bsp: ∀B ∈ NP : B ≤P Halteproblem für NP ≤P SAT SAT = erfüllbare aussagenlogische Formeln ≤P 3COL = 3-färbbare Graphen (⇒ SAT und 3COL gleich schwer) – Typeset by FoilTEX – Übersicht was haben wir hier eigentlich gelernt? 320 und warum? • Methoden sind universell (⇒ wiederverwendbar ) – Typeset by FoilTEX – Datenstrukturen Algorithmen • (Entwurf ⇒) Spezifikation ⇒ Algorithmus (⇒ Programm) • wesentliche Eigenschaften von Algorithmen: • konkrete Repräsentation (z.B.: Baum, Hash-Tabelle) eines abstrakten (mathemat.) Begriffs (z.B.: Menge) • die Axiome des abstrakten Datentyps sind die Spezifikation für die Operationen des konkreten Datentyps – Korrektheit (bzgl. Spezifikation) – Komplexität (bzgl. Kostenmodell) • Methoden für Korrektheitsbeweise • die Idee hinter jeder Datenstruktur besteht aus: ⇒ Methoden zum Algorithmenentwurf – Invariante (Baum ist Suchbaum, ist AVL-balanciert, x ∈ T ⇐⇒ T1(h1(x)) = x ∨ T2(h2(x)) = x,. . . ) – effizienten Algorithmen zum Erhalt der Invariante (Rotation, Insert mit Verdrängen alter Einträge,. . . ) – Induktion (von n − 1 auf n) ⇒ lineare Rekursion (Iteration) – Induktion (von mehreren ni < n auf n) ⇒ baum-artige Rekursion (divide and conquer) – Typeset by FoilTEX – 322 – Typeset by FoilTEX – • untere Schranke (Entscheidungsbäume): Ω(n log n) • Komplexität eines Algorithmus A ist Funktion cA : Eingabegröße s 7→ maximale Laufzeit von A auf Eingaben der Größe ≤ s • asymptotischer Vergleich von Komplexitäten cA ∈ O(cB ) (unabh. von Hardware, Programm, Sprache, Compiler) • Komplexität cS einer Aufgabe (einer Spezifikation S): beste Komplexität aller Algor., die S implementieren – obere Schranke für cS : Angabe eines Algorithmus, – untere Schranke: direkter Unmöglichkeitsbeweis (Bsp: Entscheidungsbäume f. Sortierverfahren) oder Reduktion von anderer Spezifikation bekannter Komplexität (PQ mit insert und extractMin in O(1)?) • These: S effizient lösbar ⇐⇒ cS ∈ Polynome • Verfahren und ihre Eigenschaften: – – – – – naiv: durch Einfügen, durch Auswählen: O(n2) verbessert: Shell-Sort: O(n3/2) optimal: Merge-Sort im Mittel optimal: Quick-Sort optimal: Quicksort mit Median in O(n) • Datenstrukt., mit denen man auch optimal sortieren kann: – balancierter Suchbaum (alle einfügen, dann Inorder) – Prioritätswarteschlange (Heap erzeugen, z.B. durch Einfügen, dann extractMin bis leer) 324 – Typeset by FoilTEX – Sortieren (Einschätzung) 325 Suchbäume und Heaps dieses Semester: • Gemeinsamkeit: balancierte Binärbäume, mit Schlüsseln • diese Algorithmen, ihre Eigenschaften, deren Beweise: • Unterschied: wurde gelehrt und geübt, wird geprüft. • Implementierung von Algorithmen: VLn Programmierung ab 3. Semester: • wer Sortier-Algorithmen tatsächlich selbst implementiert, macht es falsch — es gibt Bibliotheken • wer mittels Bibliotheksfunktion sortiert, macht es sehr wahrscheinlich auch falsch — denn er benutzt eine Liste, meint aber eine Menge, für die gibt es deutlich bessere Implementierungen – Typeset by FoilTEX – 323 Sortieren (Technik) Komplexität, Effizienz – Typeset by FoilTEX – 321 326 – Suchbaum: implementiert Menge hat Operation contains – heap-geordneter Baum: impl. Prioritätswarteschlange hat Operation extractMin (und kein contains) • Diskussion: – man kann jeden Suchbaum als PQ verwenden, – aber dann sind insert und decrease zu teuer, – ⇒ schlechtere Laufzeit für Dijkstra auf dichten Graphen – Typeset by FoilTEX – 327 Wie weiter? Wie weiter? (Werbung für meine Vorlesungen) Bachelor • 3./4. Sem.: Softwaretechnik/Softwareprojekt Entwurf von Softwaresystemen, d.h. Spezifikation ihrer Komponenten, so daß Anwendungsaufgabe gelöst wird Implementierung der Komponenten: Auswahl passender Datenstrukturen und Algorithmen • 4. Sem: fortgeschrittene Programmierung (u.a. generische Polymorphie, Funktionen höherer Ordnung) • 5. Sem: Sprachkonzepte der parallelen Programmierung • in jeder Informatik-Vorlesung werden fachspezifische Algorithmen und Datenstrukturen untersucht (z.B. Bildverarbeitung: Quad-Trees, Künstliche Intelligenz: heuristische Suche, Theoretische Inf.: CYK-Parser) • und dabei die hier gezeigten Entwurfs- und Analyse-Methoden angewendet (z.B. divide and conquer, dynamische Prog., O-Notation) – Typeset by FoilTEX – 328 Eine Aufgabe für die Semesterpause • 1. Sem: Prinzipien von Programmiersprachen (Syntax, Semantik (statische, dynamische), Pragmatik) • – Compilerbau (a.k.a. praktische Semantik) – Constraint-Programmierung – Symbolisches Rechnen – Typeset by FoilTEX – 329 Plan der Vorlesungen/Übungen • Def: c : V → {0, 1, . . . , |E|} heißt graceful, wenn – c injektiv – und {|c(x) − c(y)| : xy ∈ E} = {1, . . . , |E|}. • Def: G = (V, E) heißt graceful, wenn für G eine graceful Färbung existiert. • Bsp: wer ist graceful: K4, K5, C6, C7, P8, P9, K1,4, vollst. Binärbaum der Höhe 2, 3 (autotool), . . . , n • Aufgabe: jeder Baum ist graceful. (Geben Sie einen Algorithmus an, der jeden Baum graceful färbt.) • zum Üben: 1. Pfade, 2. Raupen (= Löschen der Blätter ergibt Pfad), 3. Hummer (= Löschen . . . Raupe) Übersicht nach Kalenderwochen • KW 14: 2 VL: – 1. Einführung – 2. Komplexität von Algorithmen und Problemen • KW 15: Übungen Serie 1 (zu VL 1,2) — 2 VL: – 3. Asymptotischer Vergleich von Funktionen – 4. Einfache Algorithmen (1) Schleifen • KW 16: Übungen Serie 2 (zu VL 3) — 1 VL: – 5. Einfache Algorithmen (2) Rekursion Vorsicht! nicht zuviel Zeit investieren! – Typeset by FoilTEX – Master 330 – Typeset by FoilTEX – 331 • KW 17: Übungen Serie 3 (zu VL 4,5) — 2 VL: • KW 21: keine Übungen — 1 VL (Mo.): • KW 18: Übungen Serie 4 (zu VL 6) — 1 VL (Fr.): • KW 22: Übungen Serie 8 (zu VL 12) — 2 VL: – Hörsaal-Übung Serie 7 (zu VL 10, 11) sowie Zusatz-Aufgaben – 6. Sortieren (1) (Schranke, Inversionen, Shell-Sort) – 7. Sortieren (2) (Merge-Sort) – 13. Bäume (2) Balance, AVL – 14. Prioritätswarteschlangen, heap-geordnete Bäume – 8. Analyse rekursiver Algorithmen • KW 19: Übungen Serie 5 (zu VL 7) — 2 VL: • KW 23: Übungen Serie 9 (zu VL 13) — 1 VL (Do.): – 9. Quick-Sort, Median – 10. Dynamische Programmierung – 15. Direkter Zugriff (1) Counting-Sort, Hashing • KW 24: Übungen Serie 10 (zu VL 14) — 2 VL: • KW 20: Übungen Serie 6 (zu VL 8,9) — 2 VL: – 16. amortisierte Analyse – 17. Graphen: Eigenschaften, einfache Algorithmen – 11. greedy Algorithmen – 12. Bäume (1) Suchbäume – Typeset by FoilTEX – 332 333 Wörter, die es nicht gibt • KW 25: Übungen Serie 11 (zu VL 15,16) — 2 VL (beide Mo.): Häufige Übersetzungsfehler in der Informatik – 18. Minimalgerüste, Mengensysteme – 19. kürzeste Wege (single source) • merge — mischen? richtig: zusammenfügen, einordnen, verzahnen, verschränken • KW 26: Übungen Serie 12 (zu VL 17,18) — 2 VL: http://www.roadtrafficsigns.com/merge-signs – 20. kürzeste Wege (all pairs) – 21. weitere Algorithmen auf Graphen thru traffic merge left: Durchgangsverkehr links mischen? • (minimal) spanning tree — (kleinster) Spannbaum? • KW 27: Übungen Serie 13 (zu VL 19,20) — 2 VL (beide Mo.): wenn schon, dann aufspannender Baum“, aber die ” empfohlene deutsche Bezeichnung (z.B. [Brandstädt], [Walther/Nägler] ist (Minimal)gerüst. – 23. Zusammenfassung, Ausblick – Hörsaal-Übung (Zusatz-Aufgaben, Fragen) – Typeset by FoilTEX – – Typeset by FoilTEX – • side effect — Seiteneffekt? richtig: Nebenwirkung. 334 – Typeset by FoilTEX – 335 • control flow — Kontrollfluß? richtig: Programmablauf(steuerung) (to control — kontrollieren? richtig: steuern) • problem — Problem? besser: Aufgabe sowohl bei Hausaufgaben als auch in der Komplexitätstheorie: die Aufgabe (nicht: das Problem) der 3-Färbung. [CLR] (engl.) verwendet exercise (einfache Übungsaufgabe) und problem (umfangreiche Hausaufgabe) – Typeset by FoilTEX – 336