Modul: Algorithmik SS 2016 Volker Diekert1 19. Juli 2016 1 Übungen: Lukas Fleischer, Filip Krumpe, Julian Liedtke 1 / 387 1. Vorlesung, 04.04.2016 Folien sind nur Orientierungshilfen zum Vorlesungsstoff Im Netz und in Büchern gibt es bessere Ausarbeitungen. Eine Buchempfehlung lautet: Introduction to Algorithms“ Thomas H. Cormen, Charles E. Leiserson, Ronald L. Rivest, ” Clifford Stein 2 / 387 Landau-Symbole-Oh-oh Definition: ◮ O(f) Es gilt g ∈ O(f ), falls ∃c > 0 ∃n0 ∀n ≥ n0 : g (n) ≤ c · f (n). Also: g wächst nicht schneller als f . ◮ o(f) Es gilt g ∈ o(f ), falls ∀c > 0 ∃n0 ∀n ≥ n0 : g (n) ≤ c · f (n). Also: g wächst echt langsamer als f . 3 / 387 Landau-Symbole-Omega-Theta ◮ Ω(f) g ∈ Ω(f ) ⇔ f ∈ O(g ) Also: g wächst mindestens so schnell wie f . ◮ ω(f) g ∈ ω(f ) ⇔ f ∈ o(g ) Also: g wächst echt schneller als f . ◮ Θ(f) g ∈ Θ(f ) ⇔ (f ∈ O(g ) ∧ g ∈ O(f )) Dies heißt, g und f wachsen asymptotisch gleichschnell. 4 / 387 Reale Rechenzeiten Vergleich (1 Operation = 1 ms) vs. (1 Operation = 1 µs) Algorithmus n n log(n) n2 n3 2n 1 Minute Rechenzeit 1 OP=1 ms 1 OP=1 µs 6, 0 · 104 4.893 244 39 15 6, 0 · 107 2, 8 · 106 7.746 391 26 1 Stunde Rechenzeit 1 OP=1 ms 1 OP=1 µs 3, 6 · 106 2, 0 · 105 1.897 153 21 3, 6 · 109 1, 3 · 108 60.000 1.533 32 10-fache Beschl. ∗ 10 ∼√∗ 10 ∗ √10 ∗ 3 10 + log2 (10) Es gilt: Je schneller der Rechner, desto mehr lohnen sich effiziente Algorithmen! 5 / 387 Komplexitätsmaße ◮ Komplexität im ungünstigsten Fall (worst case). ◮ Komplexität im Mittel (average case) benötigt eine Wahrscheinlichkeitsverteilung der Eingabe. Mittlerer Zeitbedarf: tA,Mittel (n) = E (tA (x), |x| = n) Dabei sei E (tA (x), |x| = n) der bedingte Erwartungswert von tA (x) unter der Bedingung |x| = n 6 / 387 Beispiel: Quicksort Beim Quicksort-Algorithmus ist die Anzahl der Vergleiche im ungünstigsten Fall tQ (n) ∈ Θ(n2 ). Mittlerer Zeitbedarf: tA,Mittel (n) ∈ O(n log n) 7 / 387 Durchschnittsanalyse Die Durchschnittskomplexitätsanalyse ist oft schwierig. Gleichverteilung der Eingaben gleicher Länge: tA,Mittel (n) = 1 X tA (x) |Xn | x∈Xn mit Xn := {x ∈ X | |x| = n} Sinnvoll? 8 / 387 Beispiel binäre Suchbäume Beispiel 1.1 Gleichverteilung bei binären Suchbäumen: 1 2n Es gibt n+1 n (= (n + 1)-te Catalansche Zahl) verschiedene Binärbäume mit n Knoten. 2n 4n ∼√ n πn n! ∼ √ 2πn n n Gleichverteilung: Mittlere Baumhöhe ist ungefähr e √ n. 9 / 387 Beispiel binäre Suchbäume Beispiel 1.2 Gleichverteilung der Eingaben: Realistischer: Verteilung, die sich durch eine Gleichverteilung von Permutationen ergibt. Eingabe π = (3, 5, 1, 4, 6) ergibt einen Baum mit Wurzel 3 und dann wird von links nach rechts eingefügt“. ” Damit: Mittlere Baumhöhe Θ(log(n)). n! wächst wesentlich schneller als 1 n n+1 4 . Also ergeben sehr viele Permutationen dieselben Suchbäume. π = (3, 5, 1, 4, 6), π ′ = (3, 1, 5, 6, 4) und π ′′ = (3, 5, 6, 4, 1) ergeben identische Bäume. 10 / 387 Maschinenmodelle: Turingmaschine Die Turingmaschine (TM) ist ein mathematisch leicht exakt beschreibbares Berechnungsmodell. Allerdings ist der zeitraubende Speicherzugriff (Bandzugriff) in der Realität nicht gegeben. Arbeitet ein Algorithmus auf einer TM schnell, so ist er schnell! 11 / 387 Maschinenmodelle: Registermaschine x1 x2 x3 x4 x5 x6 x7 x8 x9 . . . Eingabe READ ONLY Speicher RAM 0 = Akku 1 = 1.Reg 2 = 2.Reg 3 = 3.Reg 4 = 4.Reg IC ✲ . Programm . . y1 y2 y3 y4 y5 y6 y7 y8 y9 . . . Ausgabe WRITE ONLY 12 / 387 Unter Schranken / Beispiel Sortieren Einer der schwierigen Aspekte der Algorithmentheorie ist die Suche nach unteren Schranken. Satz 1.3 (Sortieralgorithmen) Jeder Sortieralgorithmus, der ausschließlich auf Schlüsselvergleichen basiert, benötigt im Mittel und daher auch im schlechtesten Fall Ω(n log n) Vergleiche. Beweis: Wir fassen Sortieralgorithmen als Entscheidungsbäume auf, d.h. als Binärbäume, deren inneren Knoten mit Vergleichen der Art gilt x[i] < x[j]?“ beschriftet sind. Es gibt ” n! Permutationen von n Elementen. Fasst man jede Permutation als einen Pfad durch einen Entscheidungsbaum auf, so muss dieser mindestens n! Blätter haben. Jeder binäre Baum mit n! Blättern hat eine Mindesthöhe von log(n!) ∈ Ω(n log(n)). Die Höhe des Entscheidungsbaums entspricht aber dem Zeitaufwand des Algorithmus. Eine ähnliche Argumentation führt auf die untere Schranke für die mittlere Anzahl der Vergleiche. Genaueres im Abschnitt über Entropie. 13 / 387 Sortieren ist schwieriger als den Median zu finden ◮ Um 5 Elemente zu sortieren benötigen wir im schlechtesten Fall ⌈log2 (5!)⌉ = ⌈log2 (120)⌉ = 7 Vergleiche. ◮ Den Median-aus-5 zu finden erfordert nur 6 Vergleiche. ◮ Siehe Tafelbeweis. 14 / 387 Mastertheorem II Satz 2.1 (Mastertheorem II) Sei r ≥ 0 mit Pr i=1 αi < 1 und t(n) ≤ r X i=1 t(⌈αi n⌉) ! + O(n). Dann gilt t(n) ∈ O(n). Bemerkung. Ohne Einschränkung gibt es eine Konstante c mit ! r X t(n) ≤ t(⌈αi n⌉) + c · n. i=1 15 / 387 Beweis Mastertheorem II Wähle ein ε und ein n0 > 0 so, dass αi n0 ≤ n0 − 1 und P Pr dass r ⌈α n⌉ ≤ ( i i=1 i=1 αi ) · n + r + 1 ≤ (1 − ε)n für alle n ≥ n0 . Wähle ein γ so, dass c < γε und t(n) < γn für alle n < n0 . Für den Induktionsschritt (n ≥ n0 ) gilt: ! r X t(n) ≤ t(⌈αi n⌉) + cn ≤ i=1 r X i=1 γ⌈αi n⌉ ! + cn (mit Induktion) ≤ (γ(1 − ε) + c)n ≤ γn 16 / 387 Medianberechnung in linearer Zeit Gegeben sei ein Feld a[1 . . . n] von Zahlen. Gesucht ist das ⌊n/2⌋-kleinste Element in einer sortierten Reihenfolge der ai . Allgemeiner sei 1 ≤ k ≤ n. Berechne SELECT(k, a[1 . . . n]). Gesucht ist also das k-kleinste Element m, d.h., berechne m ∈ { a[i] | 1 ≤ i ≤ n } mit: |{i | a[i] < m}| < k und |{i | a[i] > m}| ≤ n − k 17 / 387 Median der Mediane Bestimme ein Pivotelement als Median der Mediane aus 5: Wir teilen das Feld in Fünferblöcken auf. In jedem Block wird der Median bestimmt (mit 6 Vergleichen möglich). Wir bestimmen rekursiv den Median p dieses Feldes (mit dem gesamten Algorithmus). Der Wert p wird als Pivotelement im folgenden verwendet. Kosten: T ( n5 ). Genauer gilt: T ( n5 ). Dies beeinflusst (nur) die Kostante im O-Term. Zur besseren Lesbarkeit werden die Rundungen häufig ignoriert. 18 / 387 Quicksortschritt Mit dem Pivot p zerlege so, dass für gewisse m1 < m2 gilt: a[i] < p a[i] = p a[i] > p für 1 ≤ i ≤ m1 für m1 < i ≤ m2 für m2 < i ≤ n Kosten: maximal n Schritte. Fallunterscheidung: 1. k ≤ m1 : Suche das k-te Element rekursiv in a[1], . . . , a[m1 ]. 2. m1 < k ≤ m2 : Das Ergebnis ist p. 3. k > m2 : Suche das (k − m2 )-te Element in a[m2 + 1], . . . , a[n]. 19 / 387 30 – 70 Aufteilung Die Wahl des Pivots als Median-aus-Fünf ergibt die folgende Ungleichungen für m1 , m2 : 3 n ≤ m2 10 und m1 ≤ 7 n 10 Damit ergeben sich die Kosten für den Rekursionsschritt als T ( 7n 10 ). Denn: Die Hälfte der 5-er Mediane ist ≤ p. Dies betrifft also (mindestens) n/10 der Blöcke. In jedem Block aus 5 Elementen sind mindestens 3 kleiner oder gleich dem Blockmedian. 20 / 387 Zeitanalyse Sei T (n) die Gesamtzahl der Vergleiche. Wir erhalten folgende Rekursionsgleichung für T (n): n 7n +T + O(n) T (n) ≤ T 5 10 Aus dem Mastertheorem II folgt damit T (n) ∈ O(n). 21 / 387 Zahl der notwendigen Schlüsselvergleiche T (n) ≤ T n 5 +T 7n 10 + 6n 2n + 5 5 2n Hierbei ist 6n 5 der Aufwand für die Bestimmung der Blockmediane und 5 der Aufwand für den Zerlegungsschritt ist. Denn wir können bei der richtigen Positionierung des Medians der Mediane jeweils in Fünferblöcken operieren und müssen daher aus einem Fünferblock jeweils nur noch zwei Elemente mit dem Pivotelement vergleichen. 7 Es ergibt sich, dass damit T (n) ≤ 16n gilt: mit 15 + 10 = 9n 8n 8n T (n) ≤ T ( 10 ) + 5 und damit T (n) ≤ 10 · 5 = 16n. 9 10 erhalten wir Achtung: Wegender unterdrückten Rundungen ist 16 zu niedrig, aber: 7n n Der Term T 10 wird im Mittel näher bei T 2 liegen, d.h., der Medianalgorithmus verhält sich im Mittel besser. In Praxis ist jedoch Quickselect die bessere Methode. Später. 22 / 387 2. Vorlesung, 05.04.2016 Themen: 1. Wiederholung: Elemente der diskreten Wahrscheinlichkeit. 2. Bucket-Sort. 3. Quicksort und Quickselect. 23 / 387 Wahrscheinlichkeitsraum Ein diskreter Wahrscheinlichkeitsraum ist eine endliche oder abzählbare Menge Ω zusammen mit einer Abbildung Pr : Ω → [0, 1] in das reelle 0-1-Intervall, welche die folgende Bedingung erfüllt: X Pr[ω] = 1 ω∈Ω Ein Ereignis ist eine Teilmenge A ⊆ Ω. Die Wahrscheinlichkeit von A: X Pr[ω] Pr[A] = ω∈A Eine Zufallsvariable X ist hier stets eine reellwertige Funktion X :Ω→R 24 / 387 Erwartungswert Der Erwartungswert von X wird wie folgt definiert: X X (ω)Pr[ω] E [X ] = ω∈Ω Bei einer Gleichverteilung ist der Erwartungswert der Mittelwert über die Funktionswerte der Zufallsvariablen. Es gilt dann: E [X ] = 1 X X (ω) |Ω| ω Pr[X = x] = { ω ∈ Ω | X (ω) = x } E [X ] = X ω X (ω)Pr[ω] = X x Pr[X = x] x 25 / 387 Markov-Ungleichung Satz 3.1 Sei X eine Zufallsvariable mit X (ω) ≥ 0 für alle ω und E [X ] > 0. Dann gilt für alle λ > 0: 1 Pr X ≥ λE [X ] ≤ λ Linearität des Erwartungswertes. Es gilt: E [aX + bY ] = aE [X ] + bE [Y ] 26 / 387 Dichte und Verteilung Ist X : Ω → R eine Zufallsvariable, so assoziiert man mit X ihre diskrete Dichte fX : R → [0, 1] und ihre Verteilung FX : R → [0, 1]. Diese sind wie folgt definiert: fX : R → [0, 1], fX (x) = Pr[X = x] FX : R → [0, 1], FX (x) = Pr[X ≤ x] Aus der Dichte lässt sich die Verteilung berechnen, und die Verteilung bestimmt die Dichte. Sehr verschiedene Zufallsvariablen können auf die gleiche Verteilung (Dichte) führen. Häufig spielt der konkrete Wahrscheinlichkeitsraum häufig gar keine Rolle. Insbesondere ist: X x fX (x) E [X ] = x∈R 27 / 387 Unabhängigkeit Zwei Zufallsvariablen X und Y heißen unabhängig, wenn für alle x, y ∈ R Pr[X = x ∧ Y = y ] = Pr[X = x] · Pr[Y = y ] Falls X und Y unabhängig sind, so gilt: E [XY ] = E [X ] E [Y ] Betrachtet man die Zufallsvariable X − E [X ], so ist deren Erwartungswert 0. Interessanter ist das Quadrat dieser Zufallsvariablen (X − E [X ])2 . 28 / 387 Varianz Der Erwartungswert von (X − E [X ])2 heißt die Varianz Var[X ] von X und misst, wie stark X von E [X ] abweicht. Es gilt: Var[X ] = E (X − E [X ])2 h i = E X 2 − 2E [X ] X + E [X ]2 = E X 2 − 2E [X ] E [X ] + E [X ]2 = E X 2 − E [X ]2 Satz 3.2 Für unabhängige Zufallsvariablen X und Y gilt: Var[X + Y ] = Var[X ] + Var[Y ] 29 / 387 Tschebyschev-Ungleichung Mit σX wird die Standardabweichung von X bezeichnet, sie ist definiert durch p σX = Var[X ]. Der Name ergibt sich aus der folgenden Beziehung. Satz 3.3 Sei λ > 0. Dann gilt: 1 Pr |X − E [X ]| ≥ λ σX ≤ 2 λ 30 / 387 Bernoulli-Experimente Bei einem (Jacob Bernoulli, 1654–1705) misst man Erfolg oder Misserfolg durch ein 0-1-Ereignis. Typischerweise setzt man Pr[X = 1] = p und Pr[X = 0] = q = 1 − p. Damit ist E [X ] = p und Var[X ] = p − p 2 = pq. Seien X1 , . . . , Xn paarweise unabhängige Bernoulli-Experimente und X = X1 + · · · + Xn . Dann gilt E [X ] = np. Ferner Var[X ] = E X 2 − E [X ]2 = E (X1 + · · · + Xn )2 − (np)2 X X E [Xi · Xj ] + E Xi2 − (np)2 = i6=j i 2 = n(n − 1)p − np − (np)2 = np 2 − np = np(1 − p) = npq. 31 / 387 Bucket-Sort: Sortieren in Eimern Eingabe seien Zahlen a1 , . . . , an ∈ [0, 1). Wir wollen sie auf einer RAM in erwarteter Linearzeit sortieren. Definiere ein Feld B[0..(n − 1)]. Jedes Bucket (Eimer) b[i] ist eine initial leere Liste von Zahlen. In einem linearen Durchlauf hänge aj and die Liste im Bucket B[⌊n · aj ⌋] an. Sortiere die Liste B[i] in einem Listengeeigneten Verfahren: etwa Bubble-Sort. Füge die Listen B[i] zu der sortierten Liste B[0], . . . , B[n − 1] zusammen. Sei Xi (π) = |B[i]| (π) die Zufallsvariable, die die Länge des Buckets B[i] misst (wenn π die Eingabepermutation ist). Dann ist die Laufzeit bzw. die erwartete Laufzeit X O( Xi2 (π)). i O( X E Xi2 ). i 32 / 387 Analyse von Bucket-Sort Worst case: Quadratisch O(n2 ). Angenommen, die aj sind paarweise unabhängig gleichverteilt in [0, 1) gewählt. Dann gilt Pr[aj landet in B[i]] = 1/n Also E [Xi ] = n · 1 n = 1 und Var[Xi ] = 1 − 1/n. Es folgt X X (Var[Xi ] + E [Xi ]2 ) = 2n − 1. E Xi2 = i i Im Mittel erhalten wir eine lineare Laufzeit O(n). 33 / 387 Quicksort Quicksort-Algorithmus 1962 von Hoare: Wähle Pivotelement. Zerlege das Feld in zwei Teilfelder mit Pivot als Trennung. Nach linear vielen Vertauschungen sind die Elemente im linken Teilfeld kleiner oder gleich Pivot, im rechten größer oder gleich Pivot. Wende auf beide Teilfelder rekursiv den gleichen Algorithmus an. Wichtig: die Wahl des Pivots. Laufzeit ist optimal, falls das Pivotelement gleich dem mittleren Element des Feldes (Median) ist. In der Praxis bewährt: die Median-aus-Drei-Methode. 34 / 387 Quicksort mit Median-aus-3 procedure quicksort(A[ℓ . . . r ] : array of integer) begin if ℓ < r then p := Index des Median von A[ℓ], A[(ℓ + r ) div 2], A[r ]; (* Mathematische Analyse benutzt Median aus 3 zufällig gewählten Elementen*) m := partitioniere(A[ℓ . . . r ], p); (* Feld bzgl. A[p] partitionieren *) quicksort(A[ℓ . . . m]); (* linkes Teilfeld sortieren *) quicksort(A[m + 1 . . . r ]); (* rechtes Teilfeld sortieren *) endif endprocedure Bemerkung Tatsächlich kann es besser sein, das kleiner Feld zuerst zu sortieren. (Rekursionstiefe bleibt dann logarithmisch.) 35 / 387 3. Vorlesung: 11. April 2016 Analyse von Quicksort und Quickselect. 36 / 387 Quicksort: Komplexität Worst-case Der Quicksort-Algorithmus ist quadratisch: In jedem Schritt enthält eines der beiden Teilfelder genau ein Element. Mögliches Szenario: Liste bereits (fast) sortiert, Pivot ist stets das erste oder letzte Element. Hier: Durchschnittsanalyse unter der Annahme einer zufälliger Auswahl des Pivotelements. Die alternative Annahme, dass das Feld zufällig angeordnet ist, ist möglich, aber sinnlos2 Satz 3.4 Q(n) := P die mittlere Anzahl der Schlüsselvergleiche. H(n) := nk=1 k1 = n-te harmonische Zahl. Dann gilt für Quicksort: Q(n) = 2(n + 1)H(n) − 4n. 2 Frei nach Loriot (1923-2011) 37 / 387 Quicksort: Interpretation der Durschnittsanalyse Es ist H(n) − ln n ≈ 0,57 . . . = Eulersche Konstante. Also: Q(n) ≈ 2(n + 1)(0,57 + ln n) − 4n ≈ 2n ln n − 2,8n ≈ 1,38n log2 n − 2,8n. Theoretische Grenze: log(n!) = n log n − 1,44n; Quicksort ist im Mittel um 38% schlechter. Eine Durchschnittsanalyse der Median-aus-Drei-Methode liefert 1,18n log n − 2,2n. Dies ist im Mittel nur noch um 18% schlechter. 38 / 387 Quicksort: Durschnittsanalyse 1. Ansatz: Für n = 1 gilt offensichtlich Q(1) = 0 = 2 · 2 · 1 − 4 · 1. Für n ≥ 2 gilt: n 1X [Q(i − 1) + Q(n − i)] Q(n) = (n − 1) + n i=1 = (n − 1) + n 2X n i=1 Q(i − 1) Dabei ist (n − 1) die Zahl der Vergleiche beim Pivotieren und [Q(i − 1) + Q(n − i)] die mittlere Zahl der Vergleiche für das rekursive Sortieren der beiden Teilhälften; dabei sind alle Positionen für das Pivotelement gleich wahrscheinlich (deswegen der Faktor 1/n). Die Behauptung ist jetzt Rechnen”. ” 39 / 387 Quicksort: Durschnittsanalyse Also: nQ(n) − (n − 1)Q(n − 1) = n(n − 1) + 2 n X i=1 Q(i − 1) −(n − 1)(n − 2) − 2 n−1 X i=1 Q(i − 1) = n(n − 1) − (n − 2)(n − 1) + 2Q(n − 1) Wir erhalten: = 2(n − 1) + 2Q(n − 1) nQ(n) = 2(n − 1) + 2Q(n − 1) + (n − 1)Q(n − 1) = 2(n − 1) + (n + 1)Q(n − 1) Nun erhält man, etwa mit Induktion leicht” die Behauptung. ” Ein anderer (besserer ?) Beweis kommt gleich. 40 / 387 Quickselect Algorithmus 3.1 function quickselect(A[ℓ . . . r ] : array of integer, k : integer) : integer begin if ℓ = r then return A[ℓ] else p := random(ℓ, r ); m := partitioniere(A[ℓ . . . r ], p); k ′ := (m − ℓ + 1); if k ≤ k ′ then return quickselect(A[ℓ . . . m], k) else return quickselect(A[m + 1 . . . r ], k − k ′ ) endif endif endfunction 41 / 387 Durchschnittsanalyse mit Zufallsvariablen ◮ Q(n) durchschnittliche Anzahl an Vergleichen bei Quicksort, um ein Feld der Größe n zu sortieren (bzw. bei Quickselect, um das k-te Element in einem Feld der Größe n zu finden). Das Feld ist fest gewählt. Jedes Element wird genau einmal ein Pivot-Element. Mit π bezeichnen wir die zufällige Reihenfolge, in der Pivot-Elemente gezogen werden. Es sei 1 ≤ k ≤ n fest. Im Folgenden bezeichnen i, j Werte mit 1 ≤ i < j ≤ n. Im Laufe von Quickselect (oder auch Quicksort) werden i und j maximal einmal verglichen. Falls sie verglichen werden ist dann i oder j aktuelles Pivotelement. ◮ Xij (π) := i wird mit j verglichen“ ∈ {0, 1}. ” Es gilt in beiden Fällen X X Q(n) = E [ Xij ] = E [Xij ] = ◮ 1≤i<j<n 1≤i<j<n X Pr[Xij = 1] . 1≤i<j<n 42 / 387 Durchschnittsanalyse von Quicksort Pr[Xij ] ist die Wahrscheinlichkeit, dass in der Zufallsfolge π das erste Element in dem Intervall [i, . . . , j] entweder i oder j ist. (Ansonsten werden i und j getrennt und nie verglichen.) Also 2 . Pr[Xij ] = j −i +1 Also Q(n) = X Pr[Xij = 1] = 1≤i<j<n Wir berechnen q(n) = Q(n)/2 = X 1≤i<j≤n X 1≤i<j≤n 2 . j −i +1 1 . j −i +1 Behauptung q(n) = (n + 1)H(n) − 2n. 43 / 387 Beweis von q(n) = (n + 1)H(n) − 2n: q(n) = X n−1 n−d 1≤i<j≤n = XX 1 1 = j −i +1 d +1 n−1 X n−d d=1 d wie Differenz” ” d=1 i=1 d +1 = −n + n−1 X n−d d=0 d +1 n−1 X d +1−1 = −n + nH(n) − d +1 d=0 = −n + nH(n) − n − Also = −n + nH(n) − n + H(n) = (n + 1)H(n) − 2n n−1 X −1 d +1 d=0 Q(n) = 2q(n) = 2(n + 1)H(n) − 4n ≈ 2n ln n ≈ 1, 38n log2 (n). 44 / 387 Durchschnittsanalyse von Quickselect Unterscheide 3 Fälle: 1. Fall: i < j ≤ k. Xij (π) = i oder j wird als erstes ” 2 im Intervall [i, . . . , k] gezogen“ = k−i+1 X X 1≤i<k i<j≤k X k −i k −i +1 1≤i<k X 1 =2 1− k −i +1 Xij (π) = 2 1≤i<k = 2(k − 1 − H(k)) wobei H(k) ∈ Θ(ln k) die harmonische Funktion ist. 2 und 2. Fall: k ≤ i < j, analog folgt Xij (π) = j−k+1 X X Xij (π) = 2(n − k + 1 − H(n − k + 1)) k<j≤n k≤i<j 45 / 387 Durchschnittsanalyse: 1. und 2. Fall Die beiden ersten Fälle ergeben zusammen einen linearen Term: 2n − H(k) − H(n − k + 1) ∈ 2n − Θ(log n). 46 / 387 Durchschnittsanalyse von Quickselect 3. Fall: i < k < j Xij (π) = X X 2 j−i+1 Xij (π) = 2 1≤i<k k<j≤n X X 1≤i<k k<j≤n =2 X 1≤i<k <2 X 1≤i<k 1 j −i +1 1 1 + ··· + k −i +2 n−i +1 (ln(n − i + 1) − ln(k − i)) n = 2 ln k −1 47 / 387 Durchschnittsanalyse von Quickselect ◮ ◮ ◮ ◮ 1. Fall + 2. Fall zusammen ergeben < 2n n Mit kn ≤ 2n ergibt sich: Q(n) < 2 n + ln k−1 ≤ 2(1 + ln(2))n n (für n ≥ 2): Im Fall k = ⌈n/2⌉ folgt mit n1 2n ≤ ⌈n/2⌉ Q(n) > 2 (1 + ln(2)) n − c log(n) für ein geeignetes c Das heißt, Q(n) = 2(1 + ln(2))n − log -Terme für k ≈ n/2. Für die Median-Berechnung mit Quickselect werden im Mittel also 3,38n < 2 · 1,693147181n < 3,4n Vergleiche benötigt. 48 / 387 4. Vorlesung 12. April 2016 Hashing-Verfahren sind in der Praxis allgegenwärtig. Sie sind theoretisch und praktisch gut untersucht. Wir behandeln hier nur die Grundkonzepte. 49 / 387 Erinnering: Geburtstagsparadoxon Sind mehr als 23 Personen auf einer Party, so ist die Wahrscheinlichkeit größer als 1/2, dass zwei Gäste am gleichen Tag Geburtstag haben. Stellen wir die Gäste in eine Reihe und jeder nennt seinen Geburtstag (Tag und Monat), so erhalten wir eine Folge. Die Wahrscheinlichkeit, dass die ersten i + 1 Folgenglieder alle verschieden sind, ist dann: n n−1 i n−i 1 ≤ · ··· 1 − ··· =1· 1− n n n n n Die Wahrscheinlichkeit, dass alle m Geburtstage verschieden sind, ist daher: Pr[alle verschieden] ≤ m−1 Y i=0 i 1− n ≤ m−1 Y i e− n = e− Pm−1 i=0 i n = e− m(m−1) 2n i=0 Der Grenzwert 1/2 wird also spätestens im Bereich von m = n = 365 (oder 366) ist dies 23. √ 2n ln 2 unterschritten. Für 50 / 387 Folgerung für Hashing-Verfahren Hat eine Hashtabelle nicht mindestens quadratische Größe, so ist mit Kollisionen zu rechnen. Also, Kollisionsauflösung ist ein wichtiges Thema, wird aber aus Zeitgründen hier nur durch Verkettung gelöst. Dass Kollisionen auftreten, kann man auch beim Bildersammeln feststellen. 51 / 387 Coupon Collector Problem Coupon Collection: Angenommen, beim Kauf einer Schachtel findet man jedes Bild aus einer Sammlung von m Bildern mit der Wahrscheinlichkeit 1/m. Dann muss man durchschnittlich mH(m) ≈ m ln m Schachteln kaufen, bevor die Sammlung vollständig ist. Die Folge der Bilder wird als eine Folge zufälliger Hasheinträge in eine Tabelle der Größe m interpretiert. Wir teilen diese in m Abschnitte ein. Der i-te Abschnitt endet, wenn man einen bisher nicht verwendeten Hasheintrag besucht. Wir definieren Xi als die Länge der Abschnitte, also X1 = 1. Die Wahrscheinlichkeit, dass j das letzte Element in Abschnitt i m ist, ist m−i+1 m . Also gilt E [Xi ] = m−i+1 . Damit ist " m # m m X X X 1 m =m = mH(m). E Xi = m−i +1 m−i +1 i=1 i=1 i=1 52 / 387 Open Street Map Daten, die in OSM eingetragen werden, erhalten fortlaufende Nummern als Schlüssel. Früher dachte man irrtümlich, 32 Bit würden reichen, aber nach einem Überlauf ging man zu 64 Bit über. Die Daten werden in einer zeitlichen Reihenfolge in die OSM-Datenbank eingetragen. Direkte Adressierung array[0..264 − 1] ist unmöglich. Angenommen, wir interessieren uns nur für die OSM Daten aus Stuttgart. Dies sind ca. 220 Datensätze. Vorgehen: In der Preprocessing-Phase füttere die Stuttgarter Daten in ein Hashtabelle. Typischerweise nimmt man eine kleine Zahl von Kollisionen bewusst in Kauf. Nachdem man einmal die Daten gefiltert hat, kann man sie etwa sortieren, um dann auf direkte Adressierung zurückgreifen zu können. Dies ist ein nicht-fiktive Anwendung. Offensichtlich sind die Stuttgarter Einträge fern 64 jeder Zufallsverteilung in dem Raum 0.., . . . , 2 − 1 . 53 / 387 Steuernummern Präludium Jeder Bürger der BRD erhält (seit 2007) eine Steueridentifikationsnummer. Dies ist noch falsch! Richtig ist laut Wikipedia: Die Steueridentifikationsnummer ist eine zufällige 10-stellige Dezimalzahl mit einer elften Ziffer als Prüfziffer. Die erste Ziffer ist keine 0. Es gibt also 9 · 109 mögliche Steueridentifikationsnummern in dem Universum von 100.000.000.000 elf-stelligen Zahlen. Sei jetzt S die Menge der steuerpflichtigen Bürger in Stuttgart. Setze n = |S|. Naive Schätzung: n ≤ 200.000. Wir wollen jetzt diese, sagen wir maximal 218 Schlüssel abspeichern. Wir verwenden eine Hash-Tabelle. Die Größe dieser Tabelle soll linear in n sein und möglichst einen Speicherzugriff in O(1) erlauben. Fiktive Anwendung 2016: Sei L eine Liste der Nummern von Personen aus der BRD mit Firmenbeteiligungen in Panama. Dann lässt sich flink feststellen, wo das Finanzamt Stuttgart genauer hinschauen könnte. 54 / 387 eTIN vs. Steueridenitifikationsnummer Seit 2003 haben Steuerpflichtige auch eine eTIN. Dies ist ein 14-stelliger Code. Meine beginnt mit den 8 Buchstaben DKRTVLKR und dann folgen 2 Ziffern, ein Buchstabe – bei mir F – zwei Ziffern sowie ein Buchstabe als Prüfziffer. Steueridenitifikationsnummern lassen sich sehr gut hashen. Es reicht, wie bei Bucketsort, für Stuttgarter, einfach die 18 ersten Bits der Steueridenitifikationsnummer als Hashwert zu verwenden. Die Tabellengröße entspricht ungefähr der Zahl der Einträge und die mittlere Zeit festzustellen, ob eine Nummer einem Stuttgarter gehört, ist O(1). Denn die Nummern wurden zufällig erzeugt. Für eTIN’s ist dies falsch! Die Verteilung der eTIN’s ist überhaupt nicht zufällig. 55 / 387 Problem und Lösung 1. Problem: Annahmen über Schlüsselmengen zu realen Daten können nicht von einer Gleichverteilung ausgehen. Vergl. Satz von Loriot: Möglich, aber sinnlos”. ” U 2. Ansatz: Die Menge S ⊆ U wurde nicht zufällig in |S| gewählt. 3. Lösung: Universelles und perfektes Hashing. 4. Pragmatik: Bei vielen Anwendungen ist der Speicherplatz wichtiger als die Suchzeit. Man nimmt also häufig bewusst kleinere Hashtabellen, wenn die die Suchzeiten gering bleiben. 56 / 387 Universelles Hashing Im Folgenden, wenn wir hashen: ◮ ◮ ◮ ◮ ◮ ◮ U ein Universum von möglichen Schlüsseln. S ⊆ U eine Teilmenge von n Elementen die in einer Hashtabelle T der Größe m abgespeichert werden soll. |S| = n, |T | = m mit dem Belegungsgrad β = n/m. h : U → T Hashfunktion. H eine Familie von Hashfunktionen. Gleichverteilung auf H. Wir behandeln nur Hashing mit Verkettung: Jeder Tabelleneintrag T [i] ist eine Liste mit den Schlüsseln h−1 (i) ⊆ S. Definition 4.1 H heißt universell, falls für alle x 6= y aus U gilt Pr[h(x) = h(y )] ≤ 1/m. 57 / 387 Existenz universeller Hashfamilien Satz 4.2 Sei p eine Primzahl mit p ≥ |U| und Fp = { 0, . . . , p − 1 } der Körper, in dem wir modp” rechnen. Für a ∈ F∗p = Fp \ { 0 } und b ∈ Fp setze ” hab (x) = (ax + b mod p) mod m. Dann ist hab (x) ∈ Z/mZ = { 0, . . . , m − 1 } = T und H = hab (a, b) ∈ F∗p × Fp eine universelle Familie von Hashfunktionen der Größe (p − 1)p. 58 / 387 Beweis von Satz 4.2 |H| = (p − 1)p ist trivial. Für x ∈ U definiere hab,p (x) = ax + b mod p ∈ Fp . Betrachte jetzt x, y ∈ U mit x 6= y . Dann gilt, da a 6= 0 ∈ Fp : hab,p (x) = ax + b mod p 6= ay + b mod p = hab,p (y ). Sei r = hab,p (x) und s = hab,p (y ). Dann kann man (a, b) aus (r , s) in Fp zurückrechnen. a = (r − s)(x − y )−1 mod p, b = r − ax mod p. Die Gleichverteilung auf H = F∗p × Fp überträgt sich auf eine Gleichverteilung in Hp = { (r , s) ∈ Fp × Fp | r 6= s } . Also Pr[{ h ∈ H | h(x) = h(y ) }] = Pr[{ r ≡ s mod m | (r , s) ∈ Hp }] 59 / 387 Beweis von Satz 4.2. Fortsetzung Es gilt für jedes r ∈ Fp : Pr[{ (r , s) ∈ Hp | r ≡ s mod m }] = Pr[{ s ∈ Fp \ { r } | r ≡ s mod m }] Ferner: |{ s ∈ Fp \ { r } | r ≡ s mod m }| ≤ ⌈p/m⌉ − 1 ≤ p+m−1 p−1 −1= m m Wir erhalten Pr[{ s ∈ Fp \ { r } | r ≡ s mod m }] ≤ 1/m. Also gilt die Behauptung, sogar genauer: 1 2 1 − ≤ Pr[{ h(x) = h(y ) | h ∈ H }] ≤ . m p m 60 / 387 Erwartungswerte beim universellen Hashing Satz 4.3 Sei H universell, u ∈ U und h : U → T ∈ H zufällig gewählt. Sei S ⊆ U mit n = |S| und m = |T |, β = n/m. Sei Nu die Zufallsvariable Nu = |{ v ∈ S | h(u) = h(v ) }|. Dann gilt: 1. Für u ∈ S gilt E [Nu ] ≤ 1 + β. 2. Für u ∈ / S gilt E [Nu ] ≤ β. Beweis: Setze Xuv (h) = [h(u) = h(v )] (Indikatorfunktion). Dann E [Xuv ] ≤ 1/m, da H universell. Setze X Xuv . Yu = v ∈S,u6=v Dann E [Yu ] ≤ n m = β. 1. Für u ∈ S gilt E [Nu ] = 1 + E [Yu ] ≤ 1 + β. 2. Für u ∈ / S gilt E [Nu ] = E [Yu ] ≤ β. 61 / 387 Zweistufiges Hashing Perfektes Hashing für statische Daten Im Folgenden sei S ⊆ U statisch und |S| = n. Gesucht ist eine bestmögliche” ” Hashfunktion h : U → T , die injektiv auf S ist, also notwendig m = |T | ∈ Ω(n) und die sich schnell finden lässt. Dies gelingt durch perfektes Hashing mit m = 4n. Wir beginnen mit einer beliebigen universellen Familie H und definieren für k ∈ T die Zufallsvariable nk : H → N durch nk (h) = |{ u ∈ S | h(u) = k }|. Satz 4.4 Für m = n gilt E " X k∈T # nk2 ≤ 2n − 1. 62 / 387 Beweis von Satz 4.5 Für alle x gilt x 2 = x + 2 x2 . Also X X X nk nk 2 nk = (nk + 2 )=n+2 . 2 2 k∈T k∈T Zeige daher nur E k∈T " X nk k∈T 2 Sei wieder Xuv (h) = [h(u) = h(v )]; dann ist X nk = 2 k∈T # ≤ n−1 . 2 X { u,v }∈( Xuv . S 2 ) Da H universell ist, folgt E [Xuv ] ≤ 1/m = 1/n. Also " # X nk n 1 n−1 ≤ E · = . 2 2 n 2 k∈T 63 / 387 Wahl einer primären Hashfunktion und sekundäre Tabellen Aus Satz 4.5 folgt, dass für mehr als die Hälfte aller h ∈ H gilt X nk2 (h) < 4n. k∈T Wir können also davon ausgehen, dass wir nach erwartet P konstant vielen Versuchen eine feste primäre Hashfunktion hS gefunden haben, die k∈T nk2 (hS ) < 4n erfüllt. Die Idee ist jetzt, die Werte in T [k] in Hashtabellen Tk zu speichern, wobei immer |Tk | = nk2 = nk2 (hS ) gelten soll. Dies geschieht mittels injektiver sekundärer Hashfunktionen, die jeweils aus universellen Familien Hn2 gewählt werden. Die Summe der k Größen aller sekundären Hashtabellen ist also durch 4n begrenzt. 64 / 387 Injektive Hashfunktionen Satz 4.5 Für m = n2 gilt Pr[h ist injektiv] ≥ 1/2. Bemerkung: Die Aussage des Satzes ähnelt stark derjenigen im Geburtstagsparadoxon. Beweis: Sei X = P { u,v }∈(S2 ) Xuv . Dann ist n2 1 n 1 < = . E [X ] ≤ 2m 2 2 m Für mehr als die Hälfte der h ∈ H einer universellen Familie H ist also X (h) < 1. Nun ist X (h) stets eine natürliche Zahl und es ist X (h) = 0 ⇐⇒ h ist injektiv. 65 / 387 Perfektes Hashing: Realisierung Sei S ⊆ U fest und |S| = n. Wir nehmen an, dass 4n < |U| gilt. 1. Wähle Primzahl p ≥ 4 |U| und verwende für m ≤ 4n die Hashfunktionen hab,m (x) = (ax + b mod p) mod m. Dies definiert universelle Familien Hm . P 2. Finde hS ∈ H4n mit k∈T nk2 (hS ) ≤ 4n. 3. Bilde die primäre Hashstruktur T . 4. Definiere Sk = T [k] ⊆ U mit |Sk | = nk (hS ). Setze mk = nk2 (hS ). 5. Für jedes k ∈ T definiere ein sekundäre Hashtabelle Tk der Größe mk . 6. Finde für jedes k eine eigene injektive Hashfunktion hk ∈ Hmk , die injektiv auf Sk ist. Für eine statische Menge S können wir durch perfektes Hashing eine Suchzeit von O(1) im schlechtesten Fall garantieren, wobei die Hashtabellen insgesamt nur linearen Speicherplatz verbrauchen. 66 / 387 5. Vorlesung, 18.04.2016 Hashing und Authentifizierung Entropie: untere Schranken 67 / 387 Paarweise universelle Hashfamilien Eine Familie H von Hashfunktionen h : U → T heißt paarweise universell, falls für m = |T | und alle x, y ∈ U mit x 6= y und alle r , s ∈ T gilt: Pr[h(x) = r ∧ h(y ) = s] = 1/m2 . Satz 4.6 Sei d ≥ 1 und p eine Primzahl und T = Fp . Sie ferner U = Fdp , d.h., ein Schlüssel x wird blockweise durch d Werte in { 0, . . . , p − 1 } codiert: x = (x1 , . . . , xd ). Für (a, b) = (a1 , . . . , ad , b) ∈ Fd+1 definiere p hab (x) = (( d X ai xi ) + b mod p). i=1 Dann ist hab (x) ∈ Fp = T und Hp,d = Familie von Hashfunktionen. eine paarweise universelle hab (a, b) ∈ Fd+1 p 68 / 387 Beweis von Satz 4.6 Seien r , s ∈ Fp und (x1 , . . . , xd ), (y1 , . . . , yd ) ∈ U mit xi 6= yi für ein i ∈ { 1, . . . , d }. Ohne Einschränkung ist i = 1. Fixiere (a2 , . . . , ad ) ∈ Fpd−1 . Dann gibt es für jedes Paar (r , s) ∈ F2p genau ein Paar (a1 , b) ∈ F2p mit h(a1 ,...,ad ,b) (x) = r und h(a1 ,...,ad ,b) (y ) = s. Hieraus folgt Pr[h(x) = r ∧ h(y ) = s] = 1/p 2 . 69 / 387 Hashing und Authentifizierung: elektronische Unterschrift Alice und Bob einigen sich öffentlich auf das folgende Schema. 1.) Ein Dokument ist ein Element x ∈ U = Fdp für eine Primzahl p. 2.) Die Unterschrift t ist der Hashwert hab (x) ∈ Fp mit hab ∈ Hp,d . 3.) Bob wählt h ∈ Hp,d zufällig und übermittelt h geheim, etwa mittels RSA, an Alice. 4.) Nachdem Alice h kennt übermittelt sie ein Dokument x ∈ U in der Form (x, h(x)) an Bob, wobei h(x) ihre Unterschrift ist. Szenario Bob erhält ein unterschriebenes Dokument (y , s) und will sicher” sein, dass Alice y ∈ U ” mit s unterschrieben hat. 70 / 387 Sichere elektronische Unterschrift sind möglich Satz 4.7 Angenommen Alice beabsichtigt, an Bob über Oskar ein unterschriebenes Dokument (x, h(x)) zu senden, der jedoch (y , s) mit x 6= y weitergibt. Oskar wählt die Unterschrift” s ∈ Fp bzgl. irgendeiner selbstgewählten Strategie. Falls Oskar die geheime ” Hashfunktion h nicht kennt, gilt: Pr[Bob akzeptiert die Unterschrift] = 1/p. Proof. Übungsaufgabe. 71 / 387 Weiterführende Literatur Perfektes Hashing wurde von Fredman, M. L., Komlós, J., and Szemerédi, E. 1984. Storing a Sparse Table with O(1) Worst Case Access Time. J. ACM 31, 3 (Jun. 1984), 538-544 eingeführt Dynamisches perfektes Hashing wurde in der folgenden Arbeit untersucht. Dietzfelbinger, M., Karlin, A., Mehlhorn, K., Meyer auf der Heide, F., Rohnert, H., and Tarjan, R. E. 1994. Dynamic Perfect Hashing: Upper and Lower. SIAM J. Comput. 23, 4 (Aug. 1994), 738-761. Hashing und Authentifizierung: diverse Publikationen, spätestens seit: Bellare, M., Canetti, R., and Krawczyk, H.: Keying hash functions for message authentication. In: Advances in Cryptology – Crypto 96 Proceedings. LNCS 1109, Springer, 1996, S. 1–15 72 / 387 Entropie Entropie ist ein dem altgriechischen entlehntes Kunstwort und kann als ein Maß für Unbestimmtheit oder Unordnung gedeutet werden. ◮ In der Physik erhält die Entropie über die Boltzmann-Konstante eine Einheit: Joule/Kelvin. Fundamentale Bedeutung durch den zweiten Hauptsatz der Thermodynamik. ◮ Quantenmechanik: von-Neumann-Entropie (1932). ◮ Philosophie: Zeitempfinden folgt der Entropiezunahme? Zeitreisen? ◮ Informationstheorie: Shannon-Entropie (1948). ◮ Hier: Entropie von Zufallsvariablen mit endlichem Wertebereich. 73 / 387 Entropie in der Informationstheorie Sei X : Ω → W eine Zufallsvariable mit endlichem Wertebereich W . Im Folgenden Pn sei |W | = n und pi = Pr[X = wi ] für W = { w1 , . . . , wn }. Also gilt i=1 pi = 1 und pi ≥ 0. Definiere die Shannon-Entropie durch H(X ) = H(p1 , . . . , pn ) = − n X pi log(pi ). i=1 Hier und im Folgenden log(x) = log2 (x) und x log(x) = 0 für x = 0. H(X ) unterscheidet sich nur um den konstanten Faktor ln(2) von der natürlichen” ” von-Neumann-Entropie: He (X ) = He (p1 , . . . , pn ) = − n X pi ln(pi ). i=1 74 / 387 Lemma von Gibbs Lemma P 5.1 Seien n i=1 pi = 1, Pn i=1 qi ≤ 1 und pi , qi ≥ 0 beliebig, dann gilt n X i=1 pi ln(pi ) ≥ n X pi ln(qi ). i=1 Der Beweis benutzt für |x| < 1 die Reihendarstellung − ln(1 − x) = (oder nach einem Schaubild): x − 1 ≥ ln x. Folgerung für H(X ) = H(p1 , . . . , pn ) Für beliebige Verteilungen qi gilt H(X ) = H(p1 , . . . , pn ) ≤ − Gleichheit nur bei (p1 , . . . , pn ) = (q1 , . . . , qn ). Pn P i=1 pi xk k≥k k und daher log(qi ) mit 75 / 387 Beweis des Lemmas von Gibbs Ohne Einschränkung ist pi > 0 für alle i. Zu zeigen: 0≥ n X pi ln( i=1 qi ). pi Wegen x − 1 ≥ ln x reicht zu zeigen: 0≥ n X pi ( i=1 Dies ist äquivalent zu 0≥( n X i=1 Die letzte Zeile gilt, da nach Voraussetzung qi − 1). pi qi ) − 1. Pn i=1 qi ≤ 1. 76 / 387 Einige weitere Eigenschaften und Folgerungen ◮ ◮ ◮ H(p1 , . . . , pn ) ≤ − Pn i=1 pi log(1/n) = log2 (n). H(p1 , . . . , pn , 0) = H(p1 , . . . , pn ). Gruppierungseigenschaft: H(p1 , . . . , pn ) = H(p1 + p2 , p3 , . . . , pn ) + (p1 + p2 )H( p1 p2 , ). p1 + p2 p1 + p2 Bemerkung zum Beweis 1. Zeile: Lemma von Gibbs. 2. Zeile: trivial. 3. Zeile: sieht kompliziert aus, ist aber trivial. 77 / 387 Lemma von Kraft Lemma 5.2 Sei k ≥ 1 und T ein saturierter k-Baum, also T 6= ∅ und es hat jeder innere Knoten genau k Kinder. Sei B die Menge der Blätter und für i ∈ B sei ti die Tiefe von Blatt i. Dann gilt X k −ti = 1. i∈B Beweis. Besteht T nur aus einer Wurzel, so ist die Behauptung richtig. Ansonsten seien T1 , . . . , Tk die Kinder der Wurzel mit Blattmengen Bj . Die Behauptung folgt induktiv: k X X k −(ti −1) = k. j=1 i∈Bj Häufige Anwendung Für Binärbäume gilt P i∈B 2−ti ≤ 1. 78 / 387 Untere Schranke für das Sortieren mittels Entropie Vergleichsbasiertes Sortieren Sie S ein vergleichsbasiertes Sortierverfahren. Dann können wir S durch den Ablauf auf Permutationen π ∈ Perm(n) als einen Binärbaum T auffassen und jedem Blatt genau eine Permutation π zuordnen. (Selbsttest: Zeige dies!) An den Blättern finden keine Vergleiche statt. Sei tπ die Tiefe eines Blattes π. Dann 1 P erfüllt die erwartete Zahl der Vergleiche n! π tπ die Ungleichung log(n!) ≤ 1 X tπ . n! π P Beweis. Nach dem Lemma von Kraft gilt π 2−tπ ≤ 1. Zusammen mit dem Lemma von Gibbs ergibt sich X 1 X 1 1 1 X log(n!) = − log( ) ≤ − log(2−tπ ) = tπ . n! n! n! n! π π π 79 / 387 6. Vorlesung, 19.04.2016 Bottom-Up Heapsort Greedy Algorithmen 80 / 387 Heapsort Konvention: a[1 . . . n] ist ein Feld von Zahlen. Indexrechnungen werden vereinfacht durch a[i] = −∞ für i < 0 und a[i] = +∞ für n < i. Definition 6.1 Ein (Min-)Heap ist ein Feld a[1 . . . n] mit der Eigenschaft a[i] ≤ min{a[2i], a[2i + 1]}. Heapsort aus zwei Teilen: 1. Heapaufbau. Der Heap wird dabei von rechts nach links aufgebaut, wodurch viele kleine und nur wenige große Heaps betrachtet werden. Danach ist a[1] das kleinste Element. 2. Sortieren. Wir sortieren durch Vertauschung von a[1] und a[n]. Danach steht das kleinste Element hinten. Wir betrachten jetzt mit a[1 . . . n − 1] als neues Feld. Die Heapbedingung in a[1 . . . n − 1] ist jetzt, wenn überhaupt, nur bei a[1] verletzt und a[1] muss einsinken. 81 / 387 Heapsort x y 2 Vergleiche, um min{x, y , z} zu bestimmen z Ist y das Minimum, dann vertausche x und y . Analog für z. Ist x das Minimum, dann stoppt der Einsinkprozess. 82 / 387 Reheap Algorithmus 6.1 Reheap procedure reheap(i, n: integer) var m: integer; begin if i ≤ n/2 then m := min{a[i], a[2i], a[2i + 1]}; if (m 6= a[i]) ∧ (m = a[2i]) then swap(i, 2i); reheap(2i, n) elsif (m 6= a[i]) ∧ (m = a[2i + 1]) then swap(i, 2i + 1); reheap(2i + 1, n) endif endif endprocedure (∗ i ist die Wurzel ∗) (∗ 2 Vergleiche! ∗) (∗ vertausche x, y ∗) (∗ vertausche x, z ∗) 83 / 387 Heap-Aufbau for i := n 2 downto 1 do reheap(i, n) endfor Die Invariante hierfür ist: a[i . . . n] erfüllt die Heap-Bedingung bereits vor dem Aufruf reheap(i − 1, n). Für i = n2 + 1 ist dies richtig. Setze i um 1 herab, dann ist die Heapbedingung in a[i] eventuell verletzt. Nach dem Einsinken ist die Invariante erneut erfüllt. 84 / 387 Zeitanalyse Das Einsinken kostet 2 · (Höhe des Teilbaums unter a[i]) Vergleiche. Wir führen die Analyse für n = 2k − 1 durch, d.h. die maximale Höhe des Heaps ist k − 1. Allgemein gibt es ◮ ◮ ◮ ◮ 20 Bäume der Höhe k − 1, 21 Bäume der Höhe k − 2, 2i Bäume der Höhe k − 1 − i, 2k−1 Bäume der Höhe 0. 85 / 387 Zeitanalyse Daher sind zum Heapaufbau für n = 2k − 1 maximal Q1 (n) = 2 · k−1 X i=0 2i (k − 1 − i) Vergleiche nötig. Nach einer Indexvertauschung (j = k − 1 − i) ergibt sich: Q1 (n) = 2k · Wir zeigen auf der nächsten Folie Satz 6.2 P k−1 X j=0 j≥0 j j · 2−j ≤ 2k · X j≥0 j · 2−j · 2−j = 2 und erhalten damit: Heapaufbau ist in linearer Zeit mit weniger als 2(n + 1) Vergleichen möglich. 86 / 387 Beweis von P j≥0 j · 2−j = 2 Wir setzen für |z| < 1: f (z) = X j≥0 und leiten ab: f ′ (z) = X j≥0 Also: z · f ′ (z) = Also: X j≥0 j · (1/2)j = zj = 1 1−z j · z j−1 = X j≥0 j · zj = 1 (1 − z)2 z (1 − z)2 1 f ′ (1/2) = =2 2 2 · (1 − (1/2))2 87 / 387 Standard Heapsort Algorithmus 6.2 Heapsort procedure heapsort(n: integer) begin for i := n2 downto 1 do reheap(i, n) endfor for i := n downto 2 do swap(1, i); reheap(1, i − 1) endfor endprocedure Satz 6.3 Standard Heapsort erfordert 2n log n + O(n) Vergleiche. Beweis: Der Aufbau erfordert O(n) und der Abbau durch Einsinken 2n log n Vergleiche. 88 / 387 Bottom-Up-Heapsort Bemerkung 6.4 Eine Analyse der Durchschnittskomplexität von Heapsort ergibt einen mittlerer Aufwand von 2n log n Vergleichen. Damit ist Standard-Heapsort zu Quicksort nicht konkurrenzfähig. Bottom-Up-Heapsort benötigt wesentlich weniger Vergleiche. Nach dem Entfernen der Wurzel wird zuerst der potentielle Einsinkpfad des Elementes bestimmt. Es wird der Weg verfolgt, der immer zum kleineren der beiden Nachfolger führt (Kosten: nur log n statt 2 log n Vergleiche). Da erwartungsgemäß dieses Element tief einsinken wird, bietet sich anschließend eine bottom-up Bestimmung der tatsächlichen Position auf dem Einsinkpfad an. Hoffnung: Die bottom-up Bestimmung erfordert insgesamt nur O(n) Vergleiche. 89 / 387 Grundidee x0 Es gilt xi ≤ yi für 1 ≤ i ≤ Höhe. ✛ ✲ y1 x1 Vergleich Das Einsinken geschieht längs dieses Pfades, der mit log n Vergleichen bestimmt werden kann. y2 ✛ ✲ x 2 y3 ✛ ✲ x3 x4 ✛ ✲ y4 90 / 387 Die mittlere Höhe eines Knotens Die erwartete Höhe eines Knotens in einem Binärbaum mit zufälliger Knotenverteilung ist: ∞ 1 1 1 1X n 0 · + 1 · + 2 · + ··· = =1 2 4 8 2 2n n=0 Wir bestimmen jetzt vom Blatt aus (also bottom-up) die tatsächliche Position auf dem Einsinkpfad. Ist die Position i gefunden, so werden die Elemente x0 , . . . , xi zyklisch vertauscht (x0 geht an die Stelle von xi , und x1 , . . . , xi rutschen hoch). 91 / 387 Varianten Es kann gezeigt werden, dass im schlechtesten Fall höchstens 1,5n log n + o(n log n) Vergleiche benötigt werden. Wenn man nach Carlsson auf dem Pfad eine binäre Suche anwendet, so kommt man auf einen Aufwand von höchstens n log n + O(n log log n). Eine binäre Suche ist aber in der Praxis zu aufwendig und außerdem steigt man in den Pfad i.Allg. zu hoch ein. Durch eine leichte Abwandlung der reinen bottom-up Positionsbestimmung können wir die Zahl der wesentlichen Vergleiche auf n log n + o(n log n) bringen. 92 / 387 Anwendungen Verwalten wir eine Prioritätswarteschlange (= Datenstruktur, die die Operationen insert, delete-min, decrease-key unterstützt) in einem Heap, so benötigt jede dieser Operationen O(log n) Zeit, wenn die Schlange nicht mehr als n Elemente enthält. 93 / 387 Greedy Entwurfsstrategie Gierige Algorithmen – Greedy Algorithms Nehme das größte Stück zuerst!” ” 94 / 387 Optimalitätsprinzip Greedy ( gierig“) bezeichnet Lösungsstrategien, die auf der schrittweisen Berechnung von ” Teillösungen (lokalen Optima) basieren. Dieses Verfahren eignet sich für Probleme, bei denen jede Teilfolge einer optimalen Folge auch optimal ist (Optimalitätsprinzip). 95 / 387 Kürzeste Wege Klassisches Beispiel für die Greedy-Strategie ist die Bestimmung kürzester Wege (von einer Quelle aus) in einem Graphen mit positiven Kantengewichten. Graph: G = (V , E , γ) mit V die Knotenmenge, E ⊆ V × V die gewichteten Kanten, γ : E → N die Gewichtsfunktion. Das Gewicht eines Pfades ist gleich der Summe der Kantengewichte. Sei d(u, v ) für u, v ∈ V das Minimum der Gewichte aller Pfade von u nach v (mit der üblichen Konvention, dass d(u, v ) = ∞ gilt, falls kein Pfad von u nach v existiert). Die Aufgabe ist es, bei gegebenen Graphen G und Knoten u ∈P V für jedes v ∈ V einen Pfad u = u0 , u1 , u2 , . . . , un−1 , un = v mit minimalem Gewicht ni=1 γ(ui−1 , ui ) = d(u, v ) zu bestimmen. 96 / 387 Beispiel Dijkstra-Algorithmus Startknoten 0 1 1 6 3 ∞ 3 8 2 13 4 ∞ ∞ 3 6 ∞ 97 / 387 Beispiel Dijkstra-Algorithmus Startknoten 0 1 1 6 3 7 3 8 2 13 4 ∞ ∞ 3 6 14 98 / 387 Beispiel Dijkstra-Algorithmus Startknoten 0 1 1 6 3 7 3 8 2 13 4 11 7 3 6 14 99 / 387 Beispiel Dijkstra-Algorithmus Startknoten 0 1 1 6 3 7 3 8 2 13 4 11 7 3 6 13 100 / 387 Beispiel Dijkstra-Algorithmus Startknoten 0 1 1 6 3 7 3 8 2 13 4 9 7 3 6 13 101 / 387 Beispiel Dijkstra-Algorithmus Startknoten 0 1 1 6 3 7 3 8 2 13 4 9 7 3 6 12 102 / 387 Beispiel Dijkstra-Algorithmus Startknoten 0 1 1 6 3 7 3 8 2 13 4 9 7 3 6 12 103 / 387 Komplexität Dijkstra B := ∅; R := {u}; U := V \ {u}; v (u) := nil; D(u) := 0; while (R 6= ∅) do x := delete-min(R); B := B ∪ {x}; forall (x, y ) ∈ E do if y ∈ U then U := U \ {y }; v (y ) := x; D(y ) := D(x) + γ(x, y ); insert(R, y , D(y )); elsif D(x) + γ(x, y ) < D(y ) then v (y ) := x; D(y ) := D(x) + γ(x, y ); decrease-key(R, y , D(y )); endif endfor endwhile 104 / 387 Komplexität Der Dijkstra-Algorithmus verändert in jeweils den Rand. Es wird in dem Rand ◮ n mal ein insert, ◮ n mal ein delete-min, ◮ e mal ein decrease-key durchgeführt. Die Laufzeit hängt also wesentlich von der verwendeten Datenstruktur ab, die man für den Rand verwendet. 105 / 387 Bemerkungen zum Dijkstra-Algorithmus Ohne Einschränkung e ≥ n − 1 und n ≥ 2. Der Rand wird in dem abstrakten Datentyp einer Prioritätswarteschlange verwaltet. 1. Randverwaltung als Feld ergibt ein Aufwand von O(n2 ). 2. Für dünne Graphen (O(e) ⊆ o(n2 / log n)) ist es günstiger, den Rand R in einem Heap zu verwalten. Der Aufwand des Algorithmus wird damit nach der obigen Herleitung O(e log n + n log n) ⊆ O(e log n). 3. Bei Verwendung der Datenstruktur der Fibonacci-Heaps ergibt sich ein Aufwand von O(e + n log n). (Dies gilt als asymptotisch optimal: später) 4. Der Dijkstra-Algorithmus liefert nicht notwendigerweise ein korrektes Ergebnis, falls für die Kantengewichte auch negative Zahlen erlaubt sind. 106 / 387 Minimale aufspannende Bäume: Prim-Algorithmus Definition 7.1 Ein Graph G = (V , E ) heißt zusammenhängend, wenn je zwei Knoten durch einen Pfad verbunden sind. Definition 7.2 Ein Baum ist ein zusammenhängender, kreisfreier, ungerichteter Graph. Bemerkung 7.3 Jeder Baum mit n Knoten besitzt genau n − 1 Kanten. Definition 7.4 Ein minimaler aufspannender Baum (minimal spanning tree, MSB) zu einem gewichteten Graphen P G = (V , E , γ) ist ein Baum B = (V , F , γ|F ) mit F ⊆ E mit minimalem Gewicht γ(B) := e∈F γ(e). 107 / 387 Prim-Algorithmus wähle x0 ∈ V beliebig; B := {x0 }; R := ∅, U := V \ {x0 }; T := ∅; forall (x0 , y ) ∈ E do U := U \ {y }; v (y ) := x0 ; D(y ) := γ(x, y ); insert(R, y , D(y )) endfor while R 6= ∅ do x := delete-min(R); B := B ∪ {x}; T := T ∪ {v (x)x}; forall (x, y ) ∈ E , y 6∈ B do if y ∈ U then U := U \ {y }; v (y ) := x; D(y ) := γ(x, y ); insert(R, y , D(y )); elsif γ(x, y ) < D(y ) then v (y ) := x; D(y ) := γ(x, y ); decrease-key(R, y , D(y )); endif endfor endwhile return T 108 / 387 Beispiel Prim-Algorithmus Startknoten 1 3 6 8 2 4 13 3 6 109 / 387 Beispiel Prim-Algorithmus Startknoten 1 3 6 8 2 4 13 3 6 110 / 387 Beispiel Prim-Algorithmus Startknoten 1 3 6 8 2 4 13 3 6 111 / 387 Beispiel Prim-Algorithmus Startknoten 1 3 6 8 2 4 13 3 6 112 / 387 Beispiel Prim-Algorithmus Startknoten 1 3 6 8 2 4 13 3 6 113 / 387 Beispiel Prim-Algorithmus Startknoten 1 3 6 8 2 4 13 3 6 114 / 387 Beispiel Prim-Algorithmus Startknoten 1 3 6 8 2 4 13 3 6 115 / 387 7. Vorlesung 25.04.2016 Die Vorlesung schreitet “gefräßig” voran. 116 / 387 Korrektheit des Prim-Algorithmus Idee: Austauschsatz. (Ausführlicher Beweis an der Tafel) Bi−1 y′ Ri−1 ∈T y v (x) 6∈ T x 117 / 387 Huffman-Codes Thema einer Seminararbeit am MIT von 1951: Finde einen optimalen Präfixcode”. ” Das Ergebnis wurde 1952 von David A. Huffman publiziert: “A Method for the Construction of Minimum-Redundancy Codes” Die Methode von Huffman ist gierig. Die Zeichen mit der niedrigsten Häufigkeit haben die längsten Codewörter. 118 / 387 Präfixcodes P ⊆ Σ+ heißt Präfixcode, falls für alle u, v ∈ Σ∗ mit u, uv ∈ P gilt: u = uv . Kein Codewort ist also Präfix eines anderen Codeworts. Frage: Ist der Morsecode ein Präfixcode? Wenn ja, warum? Der SOS Ruf sollte so gesendet werden: ··· − − − ··· ··· − − − ··· ··· − − − ··· Ist jetzt w ∈ P ∗ eine Sequenz von Codewörtern, so lässt sich w eindeutig decodieren: Es gibt genau eine Sequenz (u1 , . . . , uk ) mit ui ∈ P und w = u1 · · · uk . Im Folgenden betrachten wir Präfixcodes über Σ = { 0, 1 }. Es gibt jetzt eine Eins-zu-eins Beziehung zwischen endlichen Binärbäumen und endlichen Präfixcodes: Ein Codewort entspricht einem nicht leerem 0-1-Pfad zum einem Blatt und jeder solche Pfad ist ein Codewort. Siehe Tafelbild 119 / 387 Datenkompression Sei s = s1 · · · sm ein Text mit sj ∈ A über einem Alphabet A = { a1 , . . . , an } . Jedes ai komme mit der Wahrscheinlichkeit pi in s vor: pi = |s|ai / |s| . Aufgabenstellung: Finde einen einen Huffman-Code, also einen Präfixcode P = { u1 , . . . , un } ⊆ Σ+ , der das folgende Gewicht” minimiert. ” γ(P) = n X i=1 pi |ui | . Mit einem Huffman-Code kann s mit |s| γ(P) Bit codiert werden. 120 / 387 Entropie von (p1 , . . . , pn ) als untere Schranke von γ(P) Jeder Präfixcode P = { u1 , . . . , un } ⊆ Σ+ definiert als Binärbaum eine Folge (2−|u1 | , . . . , 2−|un | ). P Lemma von Kraft sagt ni=1 2−|ui | ≤ 1. Lemma von Gibbs sagt jetzt: H(p1 , . . . , pn ) = n X i=1 pi log( 1 ) ≤ γ(P). pi Für eine obere Schranke benötigen wir eine Umkehrung des Lemmas von Kraft. 121 / 387 Umkehrung des Lemmas von Kraft Sei (b0 , . . . , bN ) eine Folge natürlicher Zahlen mit bN ≥ 1 und N X i=0 bi 2−i ≤ 1. Dann gibt es einen Binärbaum mit bi Blättern auf Tiefe i. Beweis. Für b0 = 1 gilt N = 0 und es ist nichts zu tun. Sei also N > 0. Für alle j ≤ N gilt j X i=0 −i bi 2 ≤ 1. Also: j X i=0 j−i bi 2 =( j−1 X i=0 bi 2j−i ) + bj 2j ≤ 2j ≤ 2N . Wir fügen in einer Phase j die bj Blätter auf Tiefe j ein. Jedes auf Tiefe i für i < j eingefügte Blatt genau 2j−i Blätter auf Tiefe j. Also sind insgesamt vor der Pj−1”blockiert” j−i Blätter der insgesamt 2j Blätter blockiert. Also ist genügend Phase j nur i=0 bi 2 Platz für die Phase j. 122 / 387 Obere Schranke für Huffman-Codes l m P P Wähle ti = , dann gilt ni=1 2−ti ≤ ni=1 pi = 1 Nach der Umkehrung des des Lemmas von Kraft gibt es einen Präfixcode P = { u1 , . . . , un } mit |ui | = ti . Also gilt für jeden Huffman-Code P die Aussage log( p1i ) H(p1 , . . . , pn ) = n X i=1 pi log( 1 ) ≤ γ(P) ≤ H(p1 , . . . , pn ) + 1. pi 123 / 387 Greedy-Berechnung eines Huffman-Codes Wir starten mit An = { a1 , . . . , an }, n ≥ 2 und 0 < p1 ≤ · · · ≤ pn sowie einem zunächst beliebigen Huffman-Code P als Binärbaum. Einige Beobachtungen: ◮ P ist saturiert, da optimal. Also mindestens zwei tiefste Blätter. ◮ a1 und a2 sind tiefste Blätter, da optimal. ◮ Austauscheigenschaft: Ohne Einschränkung sind a1 und a2 Geschwister. ◮ Betrachte An−1 = { a, a3 , . . . , an } mit p(a) = p1 + p2 . Dann können wir induktiv annehmen, dass wir einen Huffman-Code Pn−1 für An−1 kennen. Wir erhalten Pn , indem wir dem Blatt a die Kinder a1 und a2 geben. ◮ Behauptung: Pn ist ein Huffman-Code. ◮ Komplexität: O(n log n) unter Verwendung der Datenstruktur Heap. (Übungsaufgabe) 124 / 387 Beweis von Pn ist ein Huffman-Code” ” Nenne einen Präfixcode P ⊆ Σ+ saturiert, wenn der entsprechende Binärbaum saturiert ist. Z.B. ist ∅ saturiert. Expandieren wir in einem saturierten P ′ ein Blatt a durch zwei neue Kinder a1 und a2 mit p(a) = p(a1 ) + p(a2 ), so erhalten wir einen saturierten Präfixcode P mit der Beziehung γ(P) = γ(P ′ ) + p1 + p2 . Umgekehrt, streichen wir in einem saturierten P zwei Blätter a1 und a2 mit einem gemeinsamen Elternknoten a und setzen p(a) = p(a1 ) + p(a2 ), so erhalten wir einen saturierten Präfixcode P ′ . Erneut gilt γ(P) = γ(P ′ ) + p1 + p2 . Der Huffman-Algorithmus ist korrekt, denn wir können ihn wie folgt interpretieren. 1. Starte mit einem beliebigen saturierten P und streiche zwei Blätter wie eben. 2. Erhalte P ′ . Das neue Blatt heiße a. 3. Optimiere P ′ zu einem Huffman-Code. b 4. Expandiere a und erhalte den Huffman-Code P. 125 / 387 Code Verbesserung bei Zufallstexten Für A mit einer Verteilung (p1 , . . . , pn ) setze H(A) = (p1 , . . . , pn ). Idee: Fasse Buchstabenpaare (ai , aj ) zu einem neuen Hyperbuchstaben aij mit p(aij ) = pi pj zusammen. Dann gilt: X X pi pj log(pi pj ) = 2 pi log(pi ). i,j i Dann gilt H(A2 ) = 2H(p1 , . . . , pn ) = 2H(A) und allgemeiner H(Ad ) = dH(p1 , . . . , pn ) = dH(A). Damit reduziert sich unter Verwendung eines Huffman-Codes für An die mittlere Codewortlänge c(a) eines Zeichens a ∈ A mit auf 1 − log p(a) ≤ c(a) ≤ − log p(a) + . n Problem: Mehraufwand der Berechnung des Huffman-Codes; und die Verteilung der Buchstabenpaare ist in Texten s selten das Produkt aus den beteiligten Buchstaben. 126 / 387 Verschlechterung bei naiver Paarcodierung Betrachte das Wort s = ba ba aa Dann ist p(a) = 2/3 und p(b) = 1/3. Ein möglicher Huffman-Code liefert c(a) = 0 und c(b) = 1. Also c(s) = 101000 und 6 Bit, um s zu codieren. Ferner gilt für Zufallsfolgen: p(aa) = 4/9, p(ab) = 2/9, p(ba) = 2/9, p(bb) = 1/9. Ein Huffman-Code ist: cb(aa) = 0, cb(ab) = 10, cb(ba) = 110, cb(bb) = 111. Würde man jetzt mittels cb das Wort s codieren, so erhielte man Dies ist schlechter als vorher! cb(s) = 110 110 0. 127 / 387 Datenkompression Datenkompression ist ein wichtiges, spannendes und aktuelles Thema. In der Praxis sind für reale Daten (neben der Huffman-Codierung) viele andere Verfahren relevant(er). Einige Beispiele: ◮ Markov-Modelle: Nach einen weißen Pixel ist das nächste Pixel eher weiß als schwarz. ◮ Arithmetische Codierung: Ordne jedem Wort ein Intervall zu, zu Anfang dem leeren Wort das Intervall [0, 1] und verfeinere bei jedem neuen Buchstaben, der gelesen wird. ◮ Nehme Datenverlust in Kauf: jpeg. ◮ Lempel-Ziv Verfahren für Texte. ◮ Straight-line Programme: Kontext-freie Grammatiken, die genau ein Wort erzeugen. Entspricht Lempel-Ziv mit unbeschränkten Fenstergrößen. ◮ ... 128 / 387 8. Vorlesung 26.04.2016 Divide et impera Wikepedia sagt: Unter Teile und herrsche (Informatik) findet man ein wichtiges ” Grundprinzip der Algorithmik in der Informatik. Die lateinische Formulierung wird teilweise Machiavelli, der in seinem 1532 erschienenen Buch Der Fürst dem Fürsten Medici erklärt, wie er seine Herrschaft ausüben sollte, teilweise auch Ludwig XI. zugeschrieben. Abschließend konnte die Herkunft dieses Sprichwortes bisher nicht geklärt werden.” 129 / 387 Lösung einfacher Rekursionsgleichungen Satz 9.1 (Mastertheorem I) Seien a, b ∈ N und b > 1, g : N → N und es gelte die Rekursionsgleichung: t(1) = g (1) t(n) = a · t(n/b) + g (n) für n ≥ b. Dann gilt für n = b k (d.h. für k = logb (n)): t(n) = k X i=0 ai · g n bi . 130 / 387 Beweis des Satzes k = 0 : Es gilt n =b 0 = und t(1) = g(1). P1k−1 n ai · g bi+1 k > 0 : Daher t bn = i=0 mit Induktion, also t(n) = a · t = a n b k−1 X i=0 = = k X i=1 k X i=0 + g (n) ! n + g (n) ai · g b i+1 ai · g ai · g n bi n bi + a0 g n b0 . 131 / 387 Mastertheorem I, Fortsetzung Korollar 9.2 (Anwendung vom Mastertheorem I) Seien a, b ∈ N, mit b > 1 und es gelte die Rekursionsgleichung: t(n) ∈ a · t(n/b) + Θ(nc ) Dann gilt: Bemerkung: log a log b c ; falls a < b c Θ(n ) c Θ(n log n) ; falls a = b c t(n) ∈ log a Θ(n log b) ; falls a > b c = logb a. Falls a > b c , so ist logb a > c. 132 / 387 Beweis Sei g (n) = nc . Damit ist t(n) = nc · Pk a i i=0 ( b c ) nach dem Satz. ∞ X 1 a i = nc · 1. Fall a < b : t(n) ≤ n · ∈ O(nc ). bc 1 − bac c c i=0 Außerdem gilt t(n) ∈ Ω(nc ). Hieraus folgt t(n) ∈ Θ(nc ). 2. Fall a = b c : t(n) = (k + 1) · nc ∈ Θ(nc log n). 133 / 387 Beweis, Fortsetzung 3. Fall a > b c : k a k+1 X −1 a i c ( bc ) = n · a bc bc − 1 i=0 a logb (n) Θ nc · c b ! nc · alogb (n) Θ b c logb (n) Θ alogb (n) = Θ b logb (a)·logb (n) Θ nlogb (a) t(n) = nc · ∈ = = = Beachte: logb (a) = log(a) log(b) . 134 / 387 Beispiel Mergesort Algorithmus 9.1 Mergesort procedure mergesort(l, r ) var m : integer; begin if (l < r ) then m := (r + l) div 2; mergesort(l, m); mergesort(m + 1, r ); mische(l, m, r ); endif endprocedure 135 / 387 Mergesort 1. Laufzeit im schlechtesten, besten und mittleren Fall: Θ(n log n). 2. Es wird zusätzlicher Speicher benötigt, Mergesort ist im Gegensatz zu etwa Quicksort ein externes Sortierverfahren. 3. Geeignet für das Sortieren auf Sekundärspeichern. 4. Eine iterative Implementierung ist möglich und effizienter, da rekursive Aufrufe auch Speicher belegen. 136 / 387 Beispiele für Divide and Conquer Mergesort, Quicksort, Quickselect, . . . Weitere prominente Beispiele sind: 1. Multiplikation ganzer Zahlen 2. Matrixmultiplikation nach Strassen 137 / 387 9. und 10. Vorlesung, 02.05. und 03.05.2016 Divide et impera Teile-und-Beherrsche Divide and Conquer 138 / 387 Multiplikation ganzer Zahlen Schulmäßige Multiplikation von zwei Binärzahlen der Länge n erfordert O(n2 ) Operationen. Anderer Ansatz: r = A B s = C D Dabei sind A (C ) die ersten und B (D) die letzten k Bits von r (s). r = A 2k + B; s = C 2k + D r s = A C 22k + (A D + B C ) 2k + B D Mastertheorem I: tmult-ng (n) = 4 · tmult-ng (n/2) + O(n) ∈ O(n2 ) Nichts gewonnen! 139 / 387 Multiplikation ganzer Zahlen Berechne stattdessen besser rekursiv AC , (A − B)(D − C ) und BD. Aufwand: 3 · tmult (n/2) + O(n) Damit: rs = A C 22k + (A − B) (D − C ) 2k + (B D + A C ) 2k + B D Gesamtaufwand nach dem Mastertheorem I: log 3 tmult (n) = 3 · tmult (n/2) + O(n) ∈ O(n log 2 ) = O(n1.58496... ). Wir haben also durch den Teile-und-Beherrsche Ansatz den Exponenten des naiven Ansatzes von 2 auf 1.58496... heruntergesetzt. 140 / 387 Schnelle Multiplikation Nach einem Verfahren von Schönhage-Strassen von 1971 (diskrete FFT in geeigneten Restklassenringen) lassen sich zwei Binärzahlen der Länge n in der Zeit O(n log n log log n) multiplizieren. (Der log log n-Term lässt sich sogar noch weiter verkleinern.) Der “Weltrekord” wird seit 2007 von Martin Fürer gehalten: Fürer, M. (2007). “Faster Integer Multiplication” in Proceedings of the thirty-ninth annual ACM symposium on Theory of computing, June 11–13, 2007, San Diego, California, USA n log n · 2O(log ∗ n) . bzw. nach einer genaueren Analyse in 2014 ist die Zeitkomplexität: ∗ O(n log n24 log n ). 141 / 387 Matrixmultiplikation naiver Divide-and-Conquer P Die übliche Multiplikation zweier n × n Matrizen (ai,j ) (bi,j ) = ( nk=1 ai,k bk,j ) erfordert O(n3 ) skalare Multiplikationen. Divide-and-Conquer: A, B werden in 4 etwa gleichgroßen Untermatrizen unterteilt, wobei sich das Produkt AB = C wie folgt darstellen lässt: C12 B12 A12 C11 B11 A11 = C22 B22 A22 C21 B21 A21 142 / 387 Matrixmultiplikation naiver Divide-and-Conquer A11 A21 A12 A22 B11 B21 B12 B22 = C11 C21 C12 C22 Dabei ergeben sich folgende Beziehungen: C11 = A11 B11 + A12 B21 C12 = A11 B12 + A12 B22 C21 = A21 B11 + A22 B21 C22 = A21 B12 + A22 B22 Also: t(n) ∈ 8 · t(n/2) + Θ(n2 ) ∈ Θ(n3 ) Erneut keine Verbesserung. 143 / 387 Matrixmultiplikation nach Volker Strassen Berechne das Produkt von 2 × 2 Matrizen mit 7 Multiplikationen: M1 := (A12 − A22 )(B21 + B22 ) C11 = M1 + M2 − M 4 + M 6 M2 := (A11 + A22 )(B11 + B22 ) C12 = M3 := C21 = M6 + M7 M4 := (A11 − A21 )(B11 + B12 ) (A11 + A12 )B22 C22 = M5 := M2 − M3 + M 5 − M 7 M6 := A11 (B12 − B22 ) M7 := M4 + M5 A22 (B21 − B11 ) (A21 + A22 )B11 Laufzeit: t(n) ∈ 7t(n/2) + Θ(n2 ). Mastertheorem I (a = 7, b = 2, c = 2): t(n) ∈ Θ(nlog2 7 ) = Θ(n2,81... ) Theoretischer Durchbruch 1968. Die Schranke wurde mehrfach verbessert (auf Kosten sehr großer Konstanten). Zur Zeit (April 2016) liefert eine Variante des Coppersmith–Winograd-Algorithmus die folgende Schranke für die Matrixmultiplikation . O(n2,372... ). 144 / 387 Anwendung: Wortproblem für kontext-freie Sprachen Das Wortproblem für kontext-freie Sprachen lässt sich in der Zeit O(n3 ) lösen: Stichwort CYK. Eine Reduktion auf Multiplikation boolescher Matrizen liefert nach Strassen bzw. dessen Verbesserungen O(nlog2 7 ) bzw. O(n2,372... ). 145 / 387 Monte-Carlo-Algorithmus von Rusin Freivalds (1977) Eingabe A, B, C ∈ K n×n über einem Körper K . Aufgabe. Teste, ob A · B = C , also ob A · B − C die Nullmatrix ist. Monte-Carlo-Lösung. 1. Wähle n mal zufällig und unabhängig ri ∈ { 0, 1 } und setze r T = (r1 , . . . , rn ) ∈ { 0, 1 }n . Also ist r ein Spaltenvektor, da r T Zeilenvektor. P 2. Berechne s = (si ) = ( nk=1 bik rk ). Also s = B · r . Pn 3. Berechne t = (ti ) = ( k=1 aik sk ). Also t = A · s = A · B · r . P 4. Berechne p = (pi ) = (ti − nk=1 cik rk ). Also p = (A · B − C ) · r . 5. Falls p 6= 0, dann A · B 6= C . 6. Falls p = 0, dann Pr[A · B = C ] ≥ 1/2. Beweis der letzten Zeile: Sei A · B − C = (dij ) und (i, j) fest gewählt mit dij 6= 0. Es gilt dann X dik rk = dij rj + y . pi = dij rj + k6=j 146 / 387 Wahrscheinlichkeitsanalyse mit dem Ansatz P pi = dij rj + k6=j dik rk = dij rj + y und dij 6= 0 Es folgt Pr[pi = 0] = Pr[pi = 0 ∧ y = 0] + Pr[pi = 0 ∧ y 6= 0] = Pr[pi = 0 | y = 0] Pr[y = 0] + Pr[pi = 0 | y 6= 0] Pr[y 6= 0] = Pr[rj = 0] Pr[y = 0] + Pr[pi = 0 | y 6= 0] Pr[y 6= 0] ≤ Pr[rj = 0] Pr[y = 0] + Pr[rj = 1] Pr[y 6= 0] = Pr[y = 0] /2 + Pr[y 6= 0] /2 = Pr[y = 0] /2 + (1 − Pr[y = 0])/2 = 1/2 Beachte, ist dij der einzige Nicht-Null-Eintrag, so folgt Pr[pi = 0] = 1/2 wegen pi = dij rj . Durch k-fache Wiederholung kann die Fehlerwahrscheinlichtkeit unter 2−k gedrückt werden. Zeit: O(kn2 ). 147 / 387 Entwurfsstrategie: Dynamisches Programmieren Beim Verfahren der dynamischen Programmierung werden tabellarisch alle Teillösungen eines Problems bestimmt, bis schließlich die Gesamtlösung erreicht ist. Die Teillösungen werden dabei mit Hilfe der bereits existierenden Einträge berechnet. 148 / 387 Dynamisches Programmieren vs Backtracking Dynamischen Programmieren ist eng verwandt mit der Problemlösung durch Backtracking. Die zusätzliche Idee ist, Rekursion durch Iteration zu ersetzen und durch tabellarisches Festhalten von Teillösungen Mehrfachberechnungen zu vermeiden. BEISPIEL: Erinnerung an die Theorie-Vorlesung: Satz von Kleene. Bestimmung reguläre Ausdrücke: NEA A = (Q, Σ, δ ⊆ Q × Σ × Q, I , F ), Lk [i, j] = Sprache von i nach j über erlaubte Zwischenzustände aus der Menge {1, . . . , k}. L0 [i, j] = Kantenbeschriftung, (bzw. ε). Gesucht Ln [i, j] für alle i ∈ I und j ∈ F . Lk [i, j] := Lk−1 [i, j] + Lk−1 [i, k] · Lk−1 [k, k]∗ · Lk−1 [k, j] 149 / 387 Bestimmung reguläre Ausdrücke Algorithmus 10.1 Reguläre Ausdrücke aus einem endlichen Automaten Eingabe : NEA A = (Q, Σ, δ ⊆ Q × Σ × Q, I , F ) procedure NEA2REGEXP (Initialisiere: L[i, j] := {a | (i, a, j) ∈ δ ∨ (a = ε ∧ i = j)}) begin for k := 1 to n do for i := 1 to n do for j := 1 to n do L[i, j] := L[i, j] + L[i, k] · L[k, k]∗ · L[k, j] endfor endfor endfor end 150 / 387 Komplexitätsbetrachtung ◮ Auch wenn er der Algorithmus NEA nach REG” nur n3 Schleifen durchläuft kann ” die Ausgabekomplexität exponentiell in n sein. ◮ In jeder Schleife über k könnte sich die Länge des regulären Ausdrucks für L[i, j] vervierfachen. Die Ausgabelänge des Ausdrucks könnte also etwa bei 4n liegen. ◮ NEAs repräsentieren reguläre Sprachen kompakter als reguläre Ausdrücke. 151 / 387 Transitive Hülle Algorithmus 10.2 Warshall-Algorithmus: Berechnung der transitiver Hülle Eingabe : Graph als Adjazenzmatrix (A[i, j]) ∈ Booln×n procedure Warshall (var A : Adjazenzmatrix) begin for k := 1 to n do for i := 1 to n do for j := 1 to n do if (A[i, k] = 1) and (A[k, j] = 1) then A[i, j] := 1 endif endfor endfor endfor end 152 / 387 Korrektheit: Warshall Die Korrektheit des Warshall-Algorithmus folgt aus der Invarianten: 1. Nach dem k-ten Durchlauf der ersten for-Schleife gilt A[i, j] = 1, falls ein Pfad von i nach j über Zwischenknoten mit Nummern ≤ k existiert. – Beachte, k steht ganz außen! 2. Gilt A[i, j] = 1, so existiert ein Pfad von i nach j. 153 / 387 Transitive Hülle? Algorithmus 10.3 Ist dies Verfahren korrekt? Eingabe : Graph als Adjazenzmatrix (A[i, j]) ∈ Booln×n procedure Warshall’ (var A : Adjazenzmatrix) begin for i := 1 to n do for j := 1 to n do for k := 1 to n do if (A[i, k] = 1) and (A[k, j] = 1) then A[i, j] := 1 endif endfor endfor endfor end 154 / 387 Antwort Nein! 155 / 387 Von Warshall zu Floyd Trägt man in die Adjazenz-Matrix vom Warshall-Algorithmus Kantengewichte statt Boolesche Werte ein, so entsteht der Floyd-Algorithmus zur Berechnung kürzester Wege. 156 / 387 Floyd-Algorithmus Algorithmus 10.4 Floyd: Alle kürzesten Wege in einem Graphen Eingabe : Gewichteter Graph als Adjazenzmatrix A[i, j] ∈ (N ∪ ∞)n×n , wobei A[i, j] = ∞ bedeutet, dass es keine Kante von i nach j gibt. procedure Floyd (var A : Adjazenzmatrix) begin for k := 1 to n do for i := 1 to n do for j := 1 to n do A[i, j] := min{A[i, j], A[i, k] + A[k, j]}; endfor endfor endfor endprocedure 157 / 387 Floyd-Algorithmus Der Floyd-Algorithmus liefert ein korrektes Ergebnis auch wenn die Gewichte negativ sind, unter der Bedingung, dass keine negative Schleifen vorhanden sind. Zeitaufwand von Warshall und Floyd ist Θ(n3 ). Verbesserung“ dadurch, dass vor der ” j-Schleife zuerst getestet wird, ob A[i, k] = 1 (bzw. ob A[i, k] < ∞) gilt. Damit erreicht man den Aufwand O(n3 ): 158 / 387 Floyd-Algorithmus Algorithmus 10.5 Floyd-Algorithmus in O(n3 ) Eingabe : Adjazenzmatrix A[i, j] ∈ (N ∪ ∞)n×n procedure Floyd (var A : Adjazenzmatrix) begin for k := 1 to n do for i := 1 to n do if A[i, k] < ∞ then for j := 1 to n do A[i, j] := min{A[i, j], A[i, k] + A[k, j]}; endfor endif endfor endfor endprocedure 159 / 387 Floyd-Algorithmus Algorithmus 10.6 Floyd-Algorithmus mit negativen Zyklen Eingabe : Adjazenzmatrix A[i, j] ∈ (Z ∪ ∞ ∪ −∞)n×n procedure Floyd (var A : Adjazenzmatrix) begin for k := 1 to n do for i := 1 to n do if A[i, k] < ∞ then for j := 1 to n do if A[k, j] < ∞ then if A[k, k] < 0 then A[i, j] := −∞ else A[i, j] := min{A[i, j], A[i, k] + A[k, j]} endif endif endfor endif endfor endfor endprocedure 160 / 387 Transitive Hülle und Matrixmultiplikation Sei A = (aij ) die Adjazenzmatrix eines gerichteten Graphen mit n Knoten. Der Warshall-Algorithmus berechnet den reflexiven transitiven Abschluss A∗ in O(n3 ) Schritten. Hierbei ist X Ak mit A0 = In und ∨ als Addition boolescher Matrizen A∗ = k≥0 Mit Induktion ergibt sich leicht, dass Ak (i, j) = 1P genau dann gilt, wenn es von i nach j n−1 k einen Weg der Länge k gibt. Klar ist auch A∗ = k=0 A . 161 / 387 Transitive Hülle ≤ Matrixmultiplikation bis auf einen log-Faktor Setze B = In + A. Dann gilt A∗ = B m für alle m ≥ n − 1. Also reicht es, eine Matrix ⌈log2 (n − 1)⌉-mal zu quadrieren, um A∗ zu berechnen. Sei M(n) der Aufwand, zwei boolesche n × n-Matrizen zu multiplizieren, und sei T (n) der Aufwand, die reflexive transitive Hülle zu berechnen. Dann gilt also: T (n) ∈ O(M(n) · log n). Hieraus folgt für alle ε > 0 nach Strassen T (n) ∈ O(nε+log2 7 ). Ziel ist jedoch: T (n) ∈ O(M(n)). 162 / 387 Matrixmultiplikation ∼ Transitive Hülle Die Beziehung M(n) ∈ O(T (n)) gilt unter der plausiblen Annahme M(3n) ∈ O(M(n)). Denn seien A und B beliebige Matrizen, dann gilt: ∗ In A AB 0 A 0 0 0 B = 0 In B . 0 0 In 0 0 0 Unter den (ebenfalls plausiblen) Annahmen M(n) ∈ Ω(n2 ) und M(2n) ≥ (2 + ε)M(n) zeigen wir T (n) ∈ O(M(n)). Dies bedeutet: die Berechnung der transitiven Hülle ist bis auf konstante Faktoren genauso aufwendig wie die Matrixmultiplikation. 163 / 387 Berechnung der Transitive Hülle Eingabe: E ∈ Bool(n × n) 1. Teile E in vier Teilmatrizen A, B, C , D so, dass A und D quadratisch sind und jede Matrix ungefähr die Größe n/2 × n/2 hat: A B E= . C D 2. Berechne rekursiv D ∗ : Aufwand T (n/2). 3. Berechne F = A + BD ∗ C : Aufwand O(M(n/2)), da M(n) ∈ Ω(n2 ). 4. Berechne rekursiv F ∗ : Aufwand T (n/2). 5. Setze ∗ E = F∗ F ∗ BD ∗ D ∗ CF ∗ D ∗ + D ∗ CF ∗ BD ∗ . 164 / 387 Berechnung der Transitive Hülle Damit erhalten wir die Rekursionsgleichung T (n) ≤ 2T (n/2) + c · M(n) für ein c > 0. Dies ergibt i · M(n/2i ) 2 i≥0 P 2 i ≤ c · i≥0 2+ε · M(n) T (n) ≤ c · P (nach Mastertheorem) (da M(n/2) ≤ 1 2+ε M(n)) ∈ O(M(n)). 165 / 387 Matrizenmultiplikation Sei R ein (Semi-)Ring, etwa R = N, Z, Z/nZ, . . . und seien A, B Matrizen: A = (aik ) ∈ R p×q Dann gilt: A·B =( & q X k=1 B = (bkj ) ∈ R q×r . aik bkj ) ∈ R p×r . Aufwand: p · q · r Multiplikationen und p · (q − 1) · r Additionen. 166 / 387 Beispiel: Multiplikation einer Matrizenfolge Multiplikation von links (10 × 1) (1 × 10) (10 × 1) (1 × 10) (10 × 1) 167 / 387 Beispiel: Multiplikation einer Matrizenfolge Multiplikation von links (10 × 1) (1 × 10) (10 × 1) (1 × 10) (10 × 1) (10 × 1) (1 × 10) (10 × 1) 100 Multiplikationen (10 × 10) 168 / 387 Beispiel: Multiplikation einer Matrizenfolge Multiplikation von links (10 × 1) (1 × 10) (10 × 1) (1 × 10) (10 × 1) (10 × 1) (1 × 10) (10 × 1) (1 × 10) (10 × 1) 100 Multiplikationen (10 × 10) 100 Multiplikationen (10 × 1) 169 / 387 Beispiel: Multiplikation einer Matrizenfolge Multiplikation von links (10 × 1) (1 × 10) (10 × 1) (1 × 10) (10 × 1) (10 × 1) (1 × 10) (10 × 1) (1 × 10) (10 × 1) 100 Multiplikationen (10 × 10) 100 Multiplikationen (10 × 1) 100 Multiplikationen (10 × 10) (10 × 1) 170 / 387 Beispiel: Multiplikation einer Matrizenfolge Multiplikation von links (10 × 1) (1 × 10) (10 × 1) (1 × 10) (10 × 1) (10 × 1) (1 × 10) (10 × 1) (1 × 10) (10 × 1) 100 Multiplikationen (10 × 10) 100 Multiplikationen (10 × 1) 100 Multiplikationen (10 × 10) 100 Multiplikationen (10 × 1) (10 × 1) 171 / 387 Beispiel: Multiplikation einer Matrizenfolge Multiplikation von links Insgesamt: 400 Multiplikationen 172 / 387 Beispiel: Multiplikation einer Matrizenfolge Multiplikation von rechts (10 × 1) (1 × 10) (10 × 1) (1 × 10) (10 × 1) 173 / 387 Beispiel: Multiplikation einer Matrizenfolge Multiplikation von rechts (10 × 1) (1 × 10) (10 × 1) (10 × 1) (1 × 10) (10 × 1) (1 × 10) 10 Multiplikationen (10 × 1) (1 × 1) 174 / 387 Beispiel: Multiplikation einer Matrizenfolge Multiplikation von rechts (10 × 1) (1 × 10) (10 × 1) (10 × 1) (1 × 10) (10 × 1) (10 × 1) (1 × 10) (1 × 10) 10 Multiplikationen 10 Multiplikationen (10 × 1) (1 × 1) (10 × 1) 175 / 387 Beispiel: Multiplikation einer Matrizenfolge Multiplikation von rechts (10 × 1) (1 × 10) (10 × 1) (10 × 1) (1 × 10) (10 × 1) (10 × 1) (1 × 10) 10 Multiplikationen (10 × 1) (1 × 1) 10 Multiplikationen 10 Multiplikationen (10 × 1) (1 × 10) (10 × 1) (1 × 1) 176 / 387 Beispiel: Multiplikation einer Matrizenfolge Multiplikation von rechts (10 × 1) (1 × 10) (10 × 1) (10 × 1) (1 × 10) (10 × 1) (10 × 1) (1 × 10) 10 Multiplikationen (10 × 1) (1 × 1) 10 Multiplikationen (10 × 1) 10 Multiplikationen (10 × 1) (1 × 10) (1 × 1) 10 Multiplikationen (10 × 1) 177 / 387 Beispiel: Multiplikation einer Matrizenfolge Multiplikation von rechts Insgesamt: 40 Multiplikationen Also: 400 vs. 40 Multiplikationen bei Veränderung der Reihenfolge, aber die optimale Reihenfolge erfordert nur 31 Multiplikationen! 178 / 387 Beispiel: Multiplikation einer Matrizenfolge Multiplikation in optimaler Reihenfolge (10 × 1) (1 × 10) (10 × 1) (1 × 10) (10 × 1) 179 / 387 Beispiel: Multiplikation einer Matrizenfolge (10 × 1) (1 × 10) (10 × 1) (10 × 1) (1 × 10) (10 × 1) (1 × 10) 10 Multiplikationen (10 × 1) (1 × 1) 180 / 387 Beispiel: Multiplikation einer Matrizenfolge (10 × 1) (1 × 10) (10 × 1) (10 × 1) (1 × 10) (10 × 1) 10 Multiplikationen (10 × 1) (1 × 10) 10 Multiplikationen (1 × 1) (10 × 1) (1 × 1) (1 × 1) 181 / 387 Beispiel: Multiplikation einer Matrizenfolge (10 × 1) (1 × 10) (10 × 1) (10 × 1) (1 × 10) (10 × 1) 10 Multiplikationen (10 × 1) (10 × 1) (1 × 10) 10 Multiplikationen (1 × 1) (10 × 1) (1 × 1) (1 × 1) 1 Multiplikation (1 × 1) 182 / 387 Beispiel: Multiplikation einer Matrizenfolge (10 × 1) (1 × 10) (10 × 1) (10 × 1) (1 × 10) (10 × 1) 10 Multiplikationen (10 × 1) (10 × 1) (1 × 10) 10 Multiplikationen (1 × 1) (10 × 1) (1 × 1) (1 × 1) 1 Multiplikation (1 × 1) 10 Multiplikationen (10 × 1) 183 / 387 Multiplikation einer Matrizenfolge A(n,m) bezeichne eine Matrix A mit n Zeilen und m Spalten. Annahme: Wir berechnen C(p,r ) := A(p,q) · B(q,r ) mit p · q · r skalaren Multiplikationen. N 3 2 1 , . . . , M(n , M(n , M(n Aufgabe: Bestimme für eine Matrizenfolge M(n die 2 ,n3 ) 1 ,n2 ) 0 ,n1 ) N−1 ,nN ) minimale Zahl der skalaren Multiplikationen, um M[1, N] = M 1 · · · M N zu berechnen. Für die algorithmische Lösung ist die Eingabe eine Folge der Dimensionen: (n0 , n1 , . . . , nN ) Wir erhalten: cost(M 1 , . . . , M N ) = cost(1, . . . , N) Dynamisches Programmierung liefert: cost(i, . . . , j) = mink {cost(i, . . . , k) + cost(k + 1, . . . , j) + ni−1 · nk · nj }. 184 / 387 Multiplikation einer Matrizenfolge for i := 1 to N do cost[i, i] := 0; for j := i + 1 to N do cost[i, j] := ∞; endfor endfor for d := 1 to N − 1 do for i := 1 to N − d do j := i + d; for k := i to j − 1 do t := cost[i, k] + cost[k + 1, j] + n[i − 1] · n[k] · n[j]; if t < cost[i, j] then cost[i, j] := t; best[i, j] := k; endif endfor endfor endfor return cost[1, N] 185 / 387 Die Multiplikation nach der best-Tabelle cost[i, j], best[i, j] sind berechnet. Was nun? Um das Produkt M[1, N] zu berechnen, benötigen wir nur die best[i, j]-Werte. i und berechne M[1, N] rekursiv: Setze M[i, i] = M(n i−1 ,ni ) M[i, j] = M[i, best[i, j]] · M[best[i, j] + 1, j]. 186 / 387 11. Vorlesung, 09.05.2016 ◮ Fortsetzung: Dynamisches Programmieren 187 / 387 Erkennung kontext-freier Sprachen Kontext-freie Grammatik G = (V , Σ, P, S) heißt kontext-freie Grammatik, falls ◮ ◮ ◮ V = {A1 , A2 , . . . , Aq } eine Menge von Nichtterminalen, Σ = {a1 , a2 , . . . , ar } das Alphabet, P ⊆ V × (V ∪ Σ)∗ = { A → α | A → α ∈ P } eine Menge von Produktionen und ◮ S ∈ V das Startsymbol ist. Beispiel: Die Menge der Palindrome ist kontext-frei. Otto Tarne nie deinen Rat Tu erfreut A MAN A PLAN A CANAL PANAMA 188 / 387 Wiederholung Chomsky-Normalform (CNF) Jede kontext-freie Grammatik G kann in Chomsky-Normalform umgewandelt werden. In CNF hat jede Produktion entweder ◮ ◮ die Form A → BC (A, B, C ∈ V ) oder die Form A → a (A ∈ V , a ∈ Σ). Die neue Grammatik erzeugt L(G ) bis auf das leere Wort. CYK-Algorithmus Für eine Grammatik G in CNF kann mittels des CYK-Algorithmus in O(n3 ) Schritten entschieden werden, ob w ∈ L(G ) für ein gegebenes Wort w ∈ Σ∗ gilt. 189 / 387 CYK-Algorithmus for i := 1 to N do Var[i, i] := {A ∈ V | (A → ai ) ∈ P}; for j := i + 1 to N do Var[i, j] := ∅; endfor Eingabe: w = a1 · · · aN ∗ endfor Var[i, j] := {A ∈ V | A =⇒ ai · · · aj } for d := 1 to N − 1 do (1 ≤ i ≤ j ≤ N) for i := 1 to N − d do j := i + d; for k := i to j − 1 do Var[i, j] := Var[i, j] ∪ {A ∈ V | (A → BC ) ∈ P, B ∈ Var[i, k], C ∈ Var[k + 1, j]} endfor endfor endfor return Var[1, N] Es gilt w ∈ L(G ) ⇐⇒ S ∈ Var[1, N]. 190 / 387 Graphische Interpretation des CYK G = (V , Σ, P, S) kontext-frei ohne ǫ-Produktionen. Eingabe: a a a 1 2 3 0 −→ 1 −→ 2 −→ an−2 an−1 a n n −→ n − 2 −→ n − 1 −→ ··· Flute den Graphen mit Kanten: Regel Ist A → α ∈ P und ist ein Pfad von i nach j mit dem Wort α ∈ (V ∪ Σ)∗ beschriftet, A so füge eine mit A beschriftete Kante i → j ein. ◮ S a1 · · · an ∈ L(G ) ⇐⇒ Kante 0 → n wird erzeugt. 191 / 387 Vielleicht später. . . ◮ Valiants Algorithmus 192 / 387 Wortproblem für kontext-freie Sprachen Das Wortproblem für kontext-freie Sprachen lässt sich in der Zeit O(n3 ) lösen: Stichwort CYK. Leslie Valiant zeigte3 , dass man das Wortproblem einer kontext-freien Sprache L effizient auf die Multiplikation boolescher Matrizen reduzieren kann. Diese Reduktion auf Multiplikation boolescher Matrizen liefert dann nach Strassen: WP(L) ∈ O(nlog2 7 ). 3 General context-free recognition in less than cubic time. J. Computer and System Sciences, 10, (1975), pp.308-315 193 / 387 Ringoide Sei G = (V , Σ, P, S) eine kontext-freie Grammatik in CNF. Seien α, β ⊆ V . Definiere eine Multiplikation wie folgt: α · β := { C ∈ V | ∃A ∈ α, B ∈ β, C → AB ∈ P } Dann ist (P(V ), ∪, ·, ∅) ein Ringoid“ (R, +, ·, 0). ” Es gelten die Distributivgesetze, die Addition ∪ ist kommutativ, assoziativ und idempotent. Die leere Menge ∅ ist das Nullelement, d.h. x + ∅ = x und x · ∅ = ∅ für alle x. Beachte: Die Multiplikation · ist nicht assoziativ! Matrixmutiplikation wie üblich: A = (aik ) ∈ R p×q Dann: A·B =( & q X k=1 B = (bkj ) ∈ R q×r . aik bkj ) ∈ R p×r . 194 / 387 Transitive Hülle Sei R ein Ringoid, D ∈ R n×n eine echte obere Dreiecksmatrix (insbes. ist die Hauptdiagonale leer). D (1) := D D (t) := t−1 X D (s) D (t−s) s=1 D + := X für t ≥ 2 D (t) t≥1 D + heißt transitive Hülle von D. 195 / 387 Transitive Hülle in nicht-assoziativen Ringoiden Sei D̃ = D + . Dann gilt: D̃i,j = X alle versch. geklammerten Terme Di,k1 Dk1 ,k2 · · · Dks ,j Man beachte, dass s ≤ n gilt, da Dk,ℓ = 0 für k ≥ ℓ. 196 / 387 Erkennung kontext-freier Sprachen Sei G = (V , Σ, P, S) eine kontext-freie Grammatik in CNF. Algorithmus zur Erkennung von L(G ): Eingabe: w = a1 · · · an ∈ Σ∗ mit ai ∈ Σ. 1. Definiere eine Matrix D ∈ (P(V )){0,...,n}×{0,...,n} durch ( { A ∈ V | A → aj ∈ P } falls i = j − 1 Di,j := ∅ sonst 2. Berechne D + . + 3. w ∈ L(G ) ⇐⇒ S ∈ D0,n . Denn: + A ∈ Di,j Genauer: (t) A ∈ Di,j ⇐⇒ ⇐⇒ ∗ A =⇒ ai+1 · · · aj . j −i =t G & ∗ A =⇒ ai+1 · · · aj . G 197 / 387 Beispiel Sei G = (V , Σ, P, S) eine kontext-freie Grammatik mit V = { S, A, B }, Σ = { a, b } und P = { S → AB, A → AA | a, B → AB | b }: Sei w = aaab. ∅ {A} ∅ ∅ ∅ ∅ ∅ {A} ∅ ∅ ∅ ∅ {A} ∅ D= ∅ ∅ ∅ ∅ ∅ {B } ∅ ∅ ∅ ∅ ∅ 198 / 387 Beispiel: Erkennung kontext-freier Sprachen ∅ {A} {A} ∅ ∅ ∅ ∅ {A} {A} ∅ (1) (2) ∅ ∅ { A } { S, B } D +D = ∅ ∅ ∅ ∅ ∅ {B } ∅ ∅ ∅ ∅ ∅ ∅ {A} {A} {A} ∅ ∅ ∅ { A } { A } { S, B} (1) (2) (3) ∅ ∅ { A } { S, B } D +D +D = ∅ ∅ ∅ ∅ ∅ {B } ∅ ∅ ∅ ∅ ∅ 199 / 387 Beispiel: Erkennung kontext-freier Sprachen D + =D ⇒ w ∈ L(G ) (1) +D (2) +D (3) +D (4) = ∅ { A } { A } { A } { S, B } ∅ ∅ { A } { A } { S, B } ∅ ∅ ∅ { A } { S, B } ∅ ∅ ∅ ∅ {B } ∅ ∅ ∅ ∅ ∅ 200 / 387 Erkennung kontext-freier Sprachen in subkubischer Zeit Das Ziel ist, D + schnell (d.h. in subkubischer) Zeit auszurechnen, um damit das Wortproblem kontext-freier Sprachen in subkubischer Zeit zu lösen. Für eine assoziative Struktur wissen wir schon, wie Transitive Hülle“ auf ” Matrixmultiplikation“ reduziert werden kann. ” Valiants Lemma leistet diese Reduktion für nicht-assoziative Strukturen. 201 / 387 Valiants Lemma (Voraussetzung) Sei D ∈ R n×n eine echte obere Dreiecksmatrix und sei r ≥ n2 . (I ) (II ) (III ) D = ∅ (IV ) (V ) ∅ ∅ (VI ) Ferner gelte für r × r Teilmatrizen und (I ) (II ) ∅ (IV ) + (IV ) (V ) ∅ (VI ) + = (I ) (II ) ∅ (IV ) = (IV ) (V ) ∅ (VI ) . 202 / 387 Valiants Lemma Dann ist wobei g) (I ) (II ) (III D + = ∅ (IV ) (V ) , ∅ ∅ (VI ) ! + g) (I ) (III ) + (II ) · (V ) (I ) (III := . ∅ (VI ) ∅ (VI ) Zur Berechnung der transitiven Hülle von D ist unter diesen Voraussetzungen also nur die Multiplikation von (II ) mit (V ), sowie die Berechnung der transitiven Hülle einer 2(n − r ) × 2(n − r ) Matrix notwendig, bei der die transitive Hülle des linken oberen sowie des rechten unteren Blocks schon berechnet sind. 203 / 387 Beweis von Valiants Lemma Zunächst ist P(V ) mittels ⊆ geordnet. Die Addition und Multiplikation in (P(V ), ∪, ·, ∅) = (R, +, ·, 0) sind monoton. Für Matrizen schreibe D ≤ E falls Di,j ⊆ Ei,j für alle i, j. Beachte, 1) D ≤ D + und 2) D, D ′ ≤ E impliziert D + D ′ ≤ E . Angenommen, es gilt D + E · E ≤ E . Mit Induktion nach k folgt D (k) ≤ E und damit auch D + ≤ E . Sei jetzt g) (I ) (II ) (III E = ∅ (IV ) (V ) . ∅ ∅ (VI ) g)) und E · E ≤ E . Also folgt D + ≤ E . Dann gilt D ≤ E (da (III ) ≤ (III 204 / 387 Beweis von Valiants Lemma, Fortsetzung Klar ist auch F ≤ D + für (I ) ∅ (III ) + (II ) · (V ) . ∅ F = ∅ ∅ ∅ ∅ (VI ) Also gilt F + ≤ D + ≤ E mit F+ g) (I ) ∅ (III = ∅ ∅ ∅ . ∅ ∅ (VI ) g) steht und an allen anderen Stellen und D + Da rechts oben in F + und in E jeweils (III und E übereinstimmen, erhalten wir die Behauptung: D+ g) (I ) (II ) (III = ∅ (IV ) (V ) . ∅ ∅ (VI ) 205 / 387 Valiants Algorithmus Es sei T (n) die Laufzeit, die transitive Hülle einer n × n-Matrix zu berechnen. (I ) (II ) (III ) (IV ) (V ) (VI ) (VII ) D= (IX ) (X ) (XI ) Berechne in Zeit 2T (n/2) + O(n2 ). und (I ) (II ) (V ) (IX ) (X ) (XI ) + + = = (I ) (II ) (V ) (IX ) (X ) (XI ) 206 / 387 Valiants Algorithmus Betrachte jetzt P2 mit der Laufzeit T2 (n), wobei P2 die transitive Hülle berechnet, vorausgesetzt die transitive Hülle der Blöcke links oben und rechts unten der Größe bekannt. (Dies ist jetzt nach der ersten Phase der Fall.) n 2 sind (I ) (II ) (III ) (IV ) (V ) (VI ) (VII ) D= (IX ) (X ) (XI ) Berechne g) (V ) (VI (IX ) ! := (V ) (VI ) (IX ) + mittels P2 in der Zeit T2 (n/2) 207 / 387 Valiants Algorithmus Matrix-Multiplikation. Wir wissen M(n) ∈ Ω(n2 ). + g) (VII ) + (III ) (V ) (VI g) und (VI (IX ) (X ) (IX ) (XI ) g g mittels Multiplikationen (II ) · (VI ) und (VI ) · (X ) sowie Valiants Lemma in der Zeit 2(T2 (n/2) + M(n/4)). Sei M(n) die Laufzeit der (I ) (II ) P3 : Berechne (V ) 208 / 387 Valiants Algorithmus Wo stehen wir? In D + kann sich nur noch (IV ) verändern. (I ) (II ) (III ) (IV ) (V ) (VI ) (VII ) D= (IX ) (X ) (XI ) Hierfür berechne zunächst ((II ) (III )) · (VII ) (X ) = (II ) · (VII ) + (III ) · (X ) in Zeit 2M(n/4) + O(n2 ). g) mittels P2 sowie Valiants Lemma in Zeit T2 (n/2) + O(n2 ). Danach berechne (IV 209 / 387 Laufzeitananyse T2 (n) ∈ 4T2 n T (n) ∈ 2T 2 + 4M n 2 Mit dem Mastertheorem I folgt: n 4 + O(n2 ) ⊆ 4T2 + T2 (n) + O(n2 ) ⊆ 2T n 2 n 2 + O(M(n)). + O(T2 (n)). n X T (n) ∈ O 2i T2 i 2 i≥0 Da T2 (n/2) ≤ 14 T2 (n), folgt: T (n) ∈ T2 (n) · O( X i≥0 2−i ) ⊆ O(T2 (n)). Es verbleibt, T2 (n) zu analysieren. 210 / 387 Laufzeitananyse für T2 (n) T2 (n) ∈ 4T2 impliziert mit dem Mastertheorem I: n T2 (n) ∈ O 2 + O(M(n)) log2 n X i=0 4i M n 2i Es gilt: M(n) ∈ Ω(n2 ) ∩ o(n3 ). Annahme: Für ein κ ≥ 0 gilt: 1 M(n/2) ≤ M(n). 4+κ Hieraus folgt: Für κ > 0 gilt sogar: T2 (n) ∈ O (M(n) log n) . T2 (n) ∈ O (M(n)) . 211 / 387 Valiants Algorithmus, Zusammenfassung Sei M(n) die Zeit, zwei boolesche n × n Matrizen zu multiplizieren. Sei L = L(G ) kontext-frei und T (n) die Zeit, dass Wortproblem w ∈ L?“ zu entscheiden. Angenommen ” für ein κ ≥ 0 gilt: 1 M(n/2) ≤ M(n). 4+κ Dann gilt: T (n) ∈ O (M(n) log n) und für κ > 0 gilt: T (n) ∈ O (M(n)) . 212 / 387 12. Vorlesung, 10.05.2016 Thema: Optimale Suchbäume 213 / 387 Optimale Suchbäume Erzeugung von optimalen Suchbäumen: Die direkte Methode Θ(n3 ). Der Algorithmus von Donald E. Knuth hat einen Aufwand von Θ(n2 ). (Teleskopsumme) Interessant ist hier, wie man durch eine genaue Analyse des Problems den kubischen Algorithmus in einen quadratischen verwandeln kann. Der Algorithmus ist nicht komplizierter, sondern der Gewinn liegt im Auslassen überflüssiger Schritte. 214 / 387 Optimale Suchbäume Sei ein linear geordnetes Feld gegeben mit v1 < v2 < · · · < vn . Zugriffshäufigkeit auf Knoten v sei durch γ(v ) gegeben. Der Wert γ(v ) kann sowohl die relativen als auch die absoluten Häufigkeiten bezeichnen. 215 / 387 Optimale Suchbäume Binärer Suchbaum: knotenbeschrifteter Baum. Für jeden Knoten v mit linkem Unterbaum L und u ∈ L gilt: u < v (bzw. w ∈ R rechts und dann v < w ). Jeder Knoten v hat ein Level ℓ(v ): ℓ(v ) := 1 + Abstand des Knotens v zur Wurzel. Das Auffinden eines Knotens auf Level ℓ erfordert ℓ Vergleiche. Ziel: Finde einen binären Suchbaum, der die gewichtete innere Pfadlänge X P(B) := ℓ(v ) · γ(v ) v ∈V minimiert. 216 / 387 Optimale Suchbäume Optimaler Suchbaum für 1, 2, 22 , 23 , 24 , 25 mittels Greedy-Strategie. 25 24 23 22 2 1 Gewichtete innere Pfadlänge: 1 · 32 + 2 · 16 + 3 · 8 + 4 · 4 + 5 · 2 + 6 · 1 = 120 Mittlere Suchzeit: 120/63 < 2. 217 / 387 Optimale Suchbäume Optimaler Suchbaum für 1, 2, 3, 4, 5, 6, 7. 5 3 2 7 4 6 1 Gewichtete innere Pfadlänge: 1 · 5 + 2 · 10 + 3 · 12 + 4 · 1 = 65. Mittlere Suchzeit: 65/28 ≈ 2,3. 218 / 387 Optimale Suchbäume Suchbaum für 1, 2, 3, 4, 5, 6, 7 nach Greedy-Strategie: 7 6 5 4 3 2 1 Gewichtete innere Pfadlänge: 7 + 12 + 15 + 16 + 15 + 12 + 7 = 84. Mittlere Suchzeit: 84/28 = 3. 219 / 387 Optimale Suchbäume Die innere Pfadlänge bestimmt die durchschnittlichen Kosten einer Sequenz von Find-Operationen. Dynamische Programmierung möglich, da die Unterbäume eines optimalen Baums auch optimal sind. 220 / 387 Optimale Suchbäume Bezeichnungen: ◮ Knotenmenge = {1, . . . , n}, d.h. die Zahl i entspricht dem Knoten vi . Weiterhin wird ℓi (bzw. γi ) eine andere Schreibweise für ℓ(i) (bzw. γ(i)) sein. ◮ Pi,j : gewichtete innere Pfadlänge eines optimalen Suchbaumes der Knoten {i, . . . , j}. ◮ ◮ ◮ Ri,j : Wurzel eines optimalen Suchbaumes für {i, . . . , j}. Später: ri,j kleinstmögliche Wurzel, Ri,j größtmögliche Wurzel. P Γi,j := jk=i γ(k): Gewicht der Knotenmenge {i, . . . , j}. 221 / 387 Optimale Suchbäume Im dynamischen Ansatz sind nun Werte ri,j oder Ri,j gesucht, die einen optimalen Suchbaum B mit Kosten Pi,j realisieren. Man geht nun direkt vor und berechnet P(B) rekursiv (dabei bezeichnet BL bzw. BR den linken, bzw. rechten Unterbaum der Wurzel von B): P(B) := P(BL ) + P(BR ) + Γ(B) Wir realisieren diesen Ansatz zunächst in einem kubischen Algorithmus. Algorithmus: Berechnung eines optimalen Suchbaums ◮ ◮ Pi,j = Γi,j + mink∈{i,...,j} {Pi,k−1 + Pk+1,j } ri,j = k, für den minimalen Index Pi,k−1 + Pk+1,j das Minimum annimmt. 222 / 387 Optimale Suchbäume Lemma (Monotonie der Funktion P(B)) Sei B ′ ein optimaler Suchbaum für {1, . . . , n} und v ∈ {1, . . . , n}. Sei B ein optimaler Suchbaum für {1, . . . , n} \ {v }. Dann gilt P(B) ≤ P(B ′ ). Beweis: Entferne v aus B ′ . Fülle die Lücke von unten durch Rotationen. 223 / 387 Optimale Suchbäume Die folgende Beobachtung (von Knuth) ist entscheidend. Satz 11.1 (Monotonie der Wurzel) Sei r [i, j] (bzw. R[i, j]) die kleinste (bzw. größte) Wurzel eines optimalen Suchbaumes für die Knoten {i, . . . , j}. Dann gilt für n ≥ 2: r [i, j − 1] ≤ r [i, j], R[i, j − 1] ≤ R[i, j]. Die Anschauung ist klar, aber der Beweis ist schwierig. Wir stellen ihn zurück. 224 / 387 Optimale Suchbäume cost[n, n + 1] := 0; for i := 1 to n do cost[i, i − 1] := 0; cost[i, i] := γ(i); Γ[i, i] := γ(i); r[i, i] := i; endfor for d := 1 to n − 1 do for i := 1 to n − d do j := i + d; t := ∞; for k := r [i, j − 1] to r [i + 1, j] do if cost[i, k − 1] + cost[k + 1, j] < t then t := cost[i, k − 1] + cost[k + 1, j]; r := k; endif endfor Γ[i, j] := Γ[i, j − 1] + γ(j); cost[i, j] := t + Γ[i, j]; r [i, j] := r ; endfor endfor 225 / 387 Optimale Suchbäume – Teleskopsumme Beachte: Im Algorithmus war j = i + d. Daher Laufzeit: n−1 n−d X X d=1 i=1 (1 + r [i + 1, i + d] − r [i, i + d − 1]) = n−1 X 3 (n − d + r [n − d + 1, n] − r [1, d]) ≤ n2 ∈ Θ(n2 ). 2 d=1 Bemerkung 11.2 ◮ Ein linear geordnetes Feld v1 , . . . , vn kann aus einem ungeordneten Feld in O(n log n) Schritten erzeugt werden. Dies fällt aber bei Θ(n2 ) nicht ins Gewicht. Damit gilt: aus einem beliebigen Feld mit n Elementen kann ein optimaler Suchbaum in Θ(n2 ) Schritten erzeugt werden. 226 / 387 Monotonie der Wurzel. Zu zeigen ist noch: R[1, n − 1] ≤ R[1, n] und r [1, n − 1] ≤ r [1, n]. Es reicht zu zeigen (wegen Symmetrie) R[1, n − 1] ≤ R[1, n]. Mit Induktion ist Monotoniesatz von Knuth für j − i ≤ n − 2 bereits bewiesen. r [i, j − 1] ≤ r [i, j], R[i, j − 1] ≤ R[i, j]. Wegen Links-Rechts-Symmetrie folgt aus der ersten Zeile dann auch. R[i, j] ≤ R[i + 1, j]. Lemma: Sei {1, . . . , n} die Knotenmenge. Sei Bj ein optimaler Suchbaum mit minimalem Level j von Knoten n (also n möglichst hoch). Sei j1 die Wurzel von Bj . Sei Bi ein optimaler Suchbaum mit maximaler Wurzel i1 , also i1 ≥ j1 . Dann existiert ein optimaler Suchbaum B ′ mit Wurzel i1 und Knoten n auf Level j. 227 / 387 Kleines Level – große Wurzel Diese Verbindung der Eigenschaften minimales Level für n und große Wurzel ist für den Beweis des Satzes von Nutzen. Beweis des Lemmas: Wir betrachten die rechten Äste, wobei die Knoten von Bi mit ik und die Knoten von Bj mit jk bezeichnet sind: Beachte i1 ≥ j1 . Bj : j 1 Bi : j2 1 i1 i2 .. 2 .. . n . ij j n i 228 / 387 Kleines Level – große Wurzel Bei festem i1 maximieren wir i2 , dann maximieren wir i3 usw. Der neue Baum wird weiterhin mit Bi bezeichnet. Angenommen, in Bi und Bj liegt der Knoten n auf gleichem Level j. Dann sind wir fertig. Andernfalls können wir (zur Vereinheitlichung der Bezeichnung) annehmen, dass der Knoten n in Bi auf Level i liegt und i > j gilt, weil j minimal gewählt wurde. Sei k maximal mit ik > jk . Dann gilt 1 ≤ k < j. Setze m = k + 1. Es gilt {ik + 1, . . . , n} ( {jk + 1, . . . , n}, und mit Induktion und Links-Rechts-Symmetrie des Satzes gilt jm ≤ R[jk + 1, n] ≤ R[ik + 1, n] = im . Also folgt jm = im , da k maximal gewählt wurde. 229 / 387 Kleines Level – große Wurzel Sei nun Ri der rechte Unterbaum in Bi , der im als Wurzel hat, und Rj sei der rechte Unterbaum in Bj , der jm als Wurzel hat. Wegen im = jm haben Ri und Rj dieselbe Knotenmenge und sind optimale Suchbäume. Wir bilden einen Baum B ′ durch Ersetzen von Ri in Bi durch Rj . Da P(Ri ) = P(Rj ) gilt, ergibt sich auch P(B ′ ) = P(Bi ) = P(Bj ), d. h. B ′ ist optimal für {1, . . . , n}, hat i1 als Wurzel und den Knoten n auf Level j. 230 / 387 Kleines Level – große Wurzel Angenommen i2 = j2 , also m = 2. Wir erhalten das folgende Bild. Beachte i1 ≥ j1 . Bi : i1 1 B ′ : i1 i2 = j2 j2 i2 .. .. . ij . n n 2 j i 231 / 387 Kleines Level – große Wurzel Symmetrie ergibt: Lemma: Sei Bi ein optimaler Suchbaum für {1, . . . , n} mit maximalem Level i von Knoten n. Sei i1 die Wurzel von Bi . Sei Bj ein optimaler Suchbaum für {1, . . . , n} mit Wurzel j1 ≤ i1 . Dann existiert ein optimaler Suchbaum B ′ für {1, . . . , n} mit Wurzel j1 und Knoten n auf Level i. 232 / 387 Variation entlang α = γ(n) Es sei α = γ(n). Der Wert α variiert zwischen 0 und ∞. Mit rα (bzw. Rα ) bezeichnen wir die kleinste (bzw. größte) Wurzel eines optimalen Suchbaums für die Knoten {1, . . . , n}. Sei zunächst α = 0 und seien B ′ bzw. B ′′ optimale Suchbäume für die Knoten {1, . . . , n − 1} mit Wurzel r [1, n − 1] bzw. R[1, n − 1]. Nimmt man jeweils den Knoten n als rechtesten hinzu, so erhält man Suchbäume für {1, . . . , n}, ohne die gewichtete innere Pfadlänge zu erhöhen. Nach der Monotonie von P(B) sind diese Suchbäume optimal. Es folgt: r [1, n − 1] = r0 [1, n] und R[1, n − 1] = R0 [1, n]. Daher reicht es zu zeigen, dass rα und Rα monoton mit α steigen. Wegen der Symmetrie reicht es, Rα zu betrachten. 233 / 387 Variation entlang α = γ(n) Ab jetzt betrachten wir nur noch die Knotenmenge {1, . . . , n}. Bi sei ein optimaler Suchbaum unter der Nebenbedingung, dass der Knoten n auf dem Level i liegt. Dann gilt für eine gewisse Konstante c(i): Pα (Bi ) = α · i + c(i). Der Graph Pα (Bi ) ist eine Gerade mit Steigung i. Aufgrund der Linearität erhalten wir das folgende (vertikal gestauchte) Bild, bei der jede Steigung i = 1, . . . , n höchstens einmal vorkommt. 234 / 387 Variation entlang α = γ(n) Pα ✻ Pα (Bn ) Pα (Bℓ ) Pα (Bi ) Pα (Bk ) Pα (Bj ) ✲ α0 α 235 / 387 Monotoniebeweis Die Monotonie von rα oder Rα kann nur an einem Knick verletzt werden, wo sich Geraden mit verschiedenen Steigungen treffen. Um die Monotonie von rα zu zeigen, repräsentieren wir eine Gerade mit Steigung i durch ein Bi mit minimaler Wurzel, für Rα durch ein Bi mit maximaler Wurzel. Wir betrachten das Bild also in zwei Versionen“. ” 236 / 387 Monotoniebeweis für Rα Ein Schnittpunkt von Geraden sei bei α0 . Wenn wir α vergrößern, sind wir am Punkt α0 gezwungen, das Level von n zu verkleinern. (n kommt näher an die Wurzel.) Erinnerung: Die Verbindung der Eigenschaften minimales Level für n und große Wurzel ist von Nutzen. Sei Rα0 die maximale Wurzel, die bei den verschiedenen Geraden im Schnittpunkt α0 realisierbar ist. Dann kann Rα0 als Wurzel für die Gerade gewählt werden, die bei α0 die kleinste Steigung hat, denn dies entspricht dem minimalen Level von n. Daher können wir von links nach rechts den Baum wechseln und die maximale Wurzel wird nicht kleiner. Folglich steigt Rα monoton. 237 / 387 Rucksackproblem Eingabe: Eine Liste von n Objekten, die jeweils ein Gewicht gi und einen Wert wi haben sowie eine globale Schranke g , die dem maximalen Gewicht im Rucksack entspricht. Formal ist die Eingabe also: ((g1 , w1 ), . . . , (gn , wn ); g ) ∈ N2n+1 . Ziel: Maximiere P i∈I wi unter der Nebenbedingung P i∈I gi ≤ g . Sind die Zahlen binär gegeben, so ist das Problem schon in der folgenden Entscheidungsvariante NP-vollständig: X gi = g ? ∃I ⊆ { 1, . . . , n } : i∈I 238 / 387 Rucksackproblem: Dynamische Lösung Sind die Werte wi unär gegeben, so ist das Problem durch dynamisches Programmieren in polynomieller Zeit lösbar. Das Rucksackproblem ist also pseudo-polynomiell. 239 / 387 Das Rucksackproblem ist pseudo-polynomiell Sind die Werte wi (oder die Gewichte gi ) unär gegeben, so ist das Problem durch dynamisches Programmieren in polynomieller lösbar. Das Rucksackproblem ist also pseudo-polynomiell. Betrachte zunächst Pn den Fall, dass alle wi unär gegeben sind. Idee: Setze m = i=1 wi . Dies ist der maximale Wert. Fülle in n Runden ein Feld G der Länge m so, dass in der Runde k an Position j der Eintrag Gj steht mit der folgenden Bedingung: ) ( X X wi = j . gi I ⊆ { 1, . . . , k } ∧ Gj = inf i∈I i∈I Beachte: In Gj ist der Wert konstant j, aber das Gewicht wird minimiert. Wir berechnen also jeweils das kleinste Gewicht, um den Wert j zu erhalten. 240 / 387 Rechnung der k-ten Runde Initial ist G0 = 0 und Gj = ∞ für alle Werte j = 1, . . . , m. In der Runde k kann der Wert wk hinzukommen. Sei Gj (k − 1) der Wert Gj nach der (k − 1)-ten Runde. Wir erhalten Gj (k) = Gj (k − 1) für alle j < wk und für j ≥ wk : Gj (k) = min { Gj (k − 1), gk + Gj−wk (k − 1) } . Die Lösung ist das maximale j mit Gj (n) ≤ g . 241 / 387 Varianten Es ist nicht notwendig, alle Werte Gj für j = 1, . . . , m zu kennen. Es reicht, in P der Runde k die GP j (k) zu speichern, für die eine Teilmenge I ⊆ { 1, . . . , k } existiert mit i∈I gi ≤ g und i∈I wi = j. Wir erhalten eine Laufzeit, die polynomiell in n und W ist, wenn W die Anzahl der möglichen Werte ist, die angenommen werden können. ( ) X X W = gi ≤ g . wi I ⊆ { 1, . . . , n } ∧ i∈I i∈I 242 / 387 Dual: Rucksack mit unär codierten Gewichten Alle Werte wi sind binär gegeben und die Gewichte liegen in unärer Eingabe vor. P P Satz: Das Maximum i∈I wi unter der Nebenbedingung i∈I gi ≤ g kann in polynomieller Zeit berechnet werden. Lösung: Konstruiere eine Tabelle m[ℓ, j] ( X wi m[ℓ, j] = max i∈I für 0 ≤ ℓ ≤ g und 0 ≤ j ≤ n so, dass am Ende: ) X gi ≤ ℓ ∧ I ⊆ { 1, . . . , j } . i∈I Konventionen: 1. m[ℓ, 0] = m[0, j] = 0 für 0 ≤ ℓ und 0 ≤ j, 2. m[ℓ, j] = −∞ falls ℓ < 0. for ℓ := 1 to g do for j := 1 to n do m[ℓ, j] := max { m[ℓ, j − 1], m[ℓ − gj , j − 1] + wj } endfor endfor 243 / 387 13. Vorlesung, 23.05.2016 Thema: Mittlere Höhe in zufälligen binären Suchbäumen 244 / 387 Mittlere Höhe binärer Suchbäume Mittlere Höhe binärer Suchbäume: Wir nehmen an, dass binärer Suchbäume durch zufällig gewählte Permutationen erzeugt werden. 245 / 387 Bezeichnungen ◮ ◮ π: Permutation von {1, . . . , n} Schreibe π als Folge (π(1), π(2), π(3), . . . , π(n)) ◮ BI (π), I ⊆ {1, . . . , n}: Suchbaum mit den Elementen i ∈ I , eingefügt in der Reihenfolge (links nach rechts) von π. ◮ Zufallsvariablen: Wurzel von B(π) ist i“ ∈ {0, 1} ” XI (π) = Höhe von BI (π)“ ” YI (π) = 2XI (π) Ri (π) = Dies ist der Trick! Denn nach der Jensen’schen Ungleichung gilt 2E [XI ] ≤ E [2XI ] = E [YI ]. 246 / 387 Erwartungswerte XI (π) = Höhe von BI (π)“ ”X (π) YI (π) = 2 I Ziel: E [Xn ] ∈ O(log n). Wir zeigen hierfür: E [Yn ] ∈ O(n3 ). (bei Gleichverteilung der Permutationen.) 247 / 387 Berechnung von E [Yn ] n = 1: E [Y1 ] = 1. n ≥ 2: 1 E [Yn ] = 2 · n X i=1 E [Ri · max{Y{1,...,i−1} , Y{i+1,...,n} }] P Denn Yn (π) = 2 ni=1 (Ri (π) · max{Y{1,...,i−1} (π), Y{i+1,...,n} (π)}). Man beachte, dass Ri (π) = 1, falls π(1) = i ist, und Ri (π) = 0 andernfalls. 248 / 387 Berechnung von E [Yn ] Für i 6∈ I sind die Zufallsvariablen YI und Ri unabhängig. Also gilt: E [Yn ] = 2 n X i=1 Es gilt E [Ri ] = 1 n E [Ri ] · E [max{Y{1,...,i−1} , Y{i+1,...,n} }] und max{YI , YJ }(π) ≤ YI (π) + YJ (π). Also: n E [Yn ] ≤ 2X (E [Y{1,...,i−1} ] + E [Y{i+1,...,n} ]). n i=1 Aufgrund der Linearität der Erwartungswerte und der Eigenschaft E [YI ] = E [Y{1,...,|I |} ] = E [Y|I | ] gilt: E [Yn ] ≤ n n n−1 i=1 i=1 i=1 2X 4X 4X (E [Yi−1 ] + E [Yn−i ]) = E [Yi−1 ] = E [Yi ]. n n n 249 / 387 Berechnung von E [Yn ] Wir werden jetzt zeigen, dass E [Yn ] ≤ n = 1: E [Y1 ] = 1 = 1 4 n ≥ 2: 4 3 . n−1 1 4 4X E [Yi ] E [Yn ] ≤ n Induktion Obere Summation 1 = 4 i=1 = 1 n n+3 4 ≤ n+3 3 gilt. n−1 4X1 n 4 i=1 n+3 3 i +3 3 n−1 1X < n i=0 i +3 3 . 250 / 387 Nachtrag Zu zeigen verbleibt die Obere Summation n−1 X n+k i +k . = k +1 k i=0 ◮ ◮ ◮ Zähle die k + 1-elementigen Teilmengen mit größtem Element i + k + 1. . Deren Anzahl ist i+k k Der Index i läuft dabei von 0 bis n − 1. 251 / 387 Berechnung von E [Xn ] Jensen’sche Ungleichung für konvexe Funktionen: f (E [X ]) ≤ E [f (X )]. In unserem Fall ist die konvexe Funktion f (x) = 2x : 1 n+3 24n3 (n + 3)(n + 2)(n + 1) E [Xn ] Xn 2 ≤ E [2 ] = E [Yn ] ≤ ≤ . = 4 24 24 3 Ziel erreicht: E [Xn ] ≤ 3 log2 n ∈ O(log n). 252 / 387 Konvexe Funktionen f : R → R heißt konvex falls für alle x < y und 0 ≤ λ ≤ 1 gilt: f ((1 − λ)x + λy ) ≤ (1 − λ)f (x) + λf (y ) . Schaubild der konvexen Funktion f : (1 − λ)f (x) + λf (y ) x (1 − λ)x + λy y 253 / 387 Jensen’sche Ungleichung Sei Pk f : R → R eine konvexe Funktion und λi ≥ 0 für 1 ≤ i ≤ k mit i=1 λi = 1. Dann gilt f k X i=1 λ i xi ! ≤ k X λi f (xi ). i=1 Beweis: Durch Induktion nach k. k = 1: Dann ist λ1 = 1 und die Aussage trivial. 254 / 387 Jensen’sche Ungleichung Damit gilt jetzt (für k > 1 und damit ohne Einschränkung λ1 < 1): f k X i=1 λ i xi ! = f konvex ≤ Induktion ≤ = f k X λ1 x1 + (1 − λ1 ) i=2 λ1 f (x1 ) + (1 − λ1 )f λ1 f (x1 ) + (1 − λ1 ) k X λi xi 1 − λ1 k X i=2 k X i=2 ! λi xi 1 − λ1 ! λi f (xi ) 1 − λ1 λi f (xi ). i=1 255 / 387 Erwartungswerte diskreter Zufallsvariable Sei X : Ω → R eine diskrete Zufallsvariable. Dann berechnet sich der Erwartungswert durch X X E [X ] = Prob(i) · X (i) = λi xi mit xi = X (i), λi = Prob(i). i i Für eine konvexe Funktion f folgt dann aus der Jensen’schen Ungleichung: f (E [X ]) ≤ P i λi f (xi ) = E [f (X )]. 256 / 387 Exakte Lösungen NP-schwieriger Probleme Beispiel: Das Problem des Handlungsreisenden. Branch and Bound – Verzweigen und Beschränken 257 / 387 Das Problem des Handlungsreisenden: TSP Eingabe: Eine Menge V von Städten und für alle i, j ∈ V die Kosten“ oder ” Entfernungen“ d(i, j), um von i nach j zu reisen. ” Ziel: Finde eine Rundreise, die alle Städte genau einmal besucht und die Gesamtkosten minimiert. Das Problem ist schon in der Entscheidungsvarianten NP-vollständig (Hamiltonkreis): Existiert eine Rundreise, die alle Städte genau einmal besucht?“ ” 258 / 387 Rundreise = Permutation Gesucht ist für V = { 1, . . . , n } also eine Permutation π = (π(1), . . . , π(n)), die die folgende Summe minimiert: Dopt = X d(π(i), π(i + 1)). i∈Z/nZ Wir erlauben d(i, j) = ∞ und vereinbaren d(i, i) = ∞. Es reicht“ Dopt zu berechnen. (Warum?) ” Ohne Einschränkung gilt π(1) = 1, da wir eine Rundreise bei 1 starten können. Ein naiver Algorithmus durchsucht alle (n − 1)! Permutationen mit π(1) = 1. Die Funktion n! wächst etwa so schnell wie (n/e)n also schneller als jede einfach exponentielle Funktion k n , wenn k fest ist. Es ist möglich, TSP in der Zeit O(n2 2n ) zu lösen. 259 / 387 Einfache exponentielle TSP Lösung Dynamisches Programmieren: Berechne für alle (i, S) mit i = 1, . . . , n und S ⊆ { 1, . . . , n } \ { 1, i } die minimalen Kosten D(i, S) für einen Weg, der in i startet, alle Städte in S genau einmal besucht und in 1 endet. Dopt = D(1, { 2, . . . , n }). Initial ist: D(i, ∅) = d(i, 1). Für S 6= ∅ gilt: D(i, S) = min { d(i, k) + D(k, S \ { k }) | k ∈ S } . Wir minimieren über die k ∈ S, da die erste Stadt nach i eine Stadt k in der Menge S sein muss. Laufzeit: O(n2 2n ), um die ca. n2n Werte zu berechnen. 260 / 387 Matrixdarstellung des TSP ∞ 10 ∞ 20 5 ∞ 9 10 6 13 ∞ 12 Keine Kante von 1 nach 3. 8 8 9 ∞ ∞ 10 15 20 5 ∞ 9 10 6 13 ∞ 12 Eine Kante von 1 nach 3 mit Kosten 15. 8 8 9 ∞ ∞ 10 15 20 10 ∞ 9 10 15 9 ∞ 12 Keine Einbahnstraßen – symmetrische Matrix 20 10 12 ∞ 261 / 387 Branch and Bound Im Folgenden betrachten wir die folgende Matrix Schöning). ∞ 10 15 5 ∞ 9 6 13 ∞ 8 8 9 (aus dem Algorithmenbuch von Uwe 20 10 12 ∞ Jeder Rundweg verlässt 1 mit den Mindestkosten 10, also können wir 10 zur Lösung des folgenden Problems addieren. ∞ 0 5 10 5 ∞ 9 10 6 13 ∞ 12 8 8 9 ∞ 262 / 387 Reduktion: Bound = untere Schranke ∞ 10 15 20 5 ∞ 9 10 6 13 ∞ 12 8 8 9 ∞ Zeilenreduktion liefert untere Schranke bound = 29. ∞ 0 5 10 0 ∞ 4 5 0 7 ∞ 6 0 0 1 ∞ Spaltenreduktion liefert untere Schranke ∞ 0 0 0 bound = 29 + 1 + 5 = 35. 0 4 5 ∞ 3 0 7 ∞ 1 0 0 ∞ 263 / 387 Verzweigung ∞ 0 4 5 0 ∞ 3 0 0 7 ∞ 1 0 0 0 ∞ bound = 35 (= Übertrag nach der Reduktion) ¬(2, 1) ∞ 0 4 5 ∞ ∞ 3 0 0 7 ∞ 1 0 0 0 ∞ bound = 35 (2, 1) ∧ ¬(1, 2) ∞ ∞ 4 5 0 ∞ ∞ ∞ ∞ 7 ∞ 1 ∞ 0 0 ∞ bound = 35 + 4 + 1 = 40 264 / 387 Verzweigung mit ¬(2, 1) mit besserer bound“ ” ∞ 0 4 5 ∞ ∞ 3 0 0 7 ∞ 1 0 0 0 ∞ bound = 35 ¬(3, 1) ∞ 0 4 5 ∞ ∞ 3 0 ∞ 7 ∞ 1 0 0 0 ∞ bound = 35 + 1 = 36 (3, 1) ∧ ¬(1, 3) ∞ 0 ∞ 5 ∞ ∞ 3 0 0 ∞ ∞ ∞ ∞ 0 0 ∞ bound = 35 265 / 387 Verzweigung mit (3, 1) mit besserer bound“ ” ∞ 0 ∞ 5 ∞ ∞ 3 0 0 ∞ ∞ ∞ ∞ 0 0 ∞ bound = 35 ¬(4, 2) ∞ 0 ∞ 5 ∞ ∞ 3 0 0 ∞ ∞ ∞ ∞ ∞ 0 ∞ bound = 35 (4, 2) ∧ ¬(2, 4) ∞ 0 ∞ 5 ∞ ∞ 3 ∞ 0 ∞ ∞ ∞ ∞ 0 ∞ ∞ bound = 38 266 / 387 Verzweigung mit ¬(4, 2) mit besserer bound“ ” ∞ 0 ∞ 5 ∞ ∞ 3 0 0 ∞ ∞ ∞ ∞ ∞ 0 ∞ bound = 35 ¬(2, 4) ∞ 0 ∞ 5 ∞ ∞ 3 ∞ 0 ∞ ∞ ∞ ∞ ∞ 0 ∞ bound = 35 + 3 = 38 (2, 4) ∞ 0 ∞ ∞ ∞ ∞ ∞ 0 0 ∞ ∞ ∞ ∞ ∞ 0 ∞ bound = 35 Lösung: 1-2-4-3-1 267 / 387 Lösung: 1-2-4-3-1 Ausgangsmatrix: ∞ 10 15 20 5 ∞ 9 10 6 13 ∞ 12 8 8 9 ∞ Lösung: ∞ ∞ 6 ∞ 10 ∞ ∞ ∞ ∞ 10 ∞ ∞ ∞ ∞ 9 ∞ 268 / 387 14. Vorlesung am 24.05.16 Thema: Verwaltung von Mengen Union – Find 269 / 387 Verwaltung von Mengen Union-Find-Algorithmen Definition: Eine Partition P einer Menge M ist eine Zerlegung von M in disjunkte, nicht-leere Teilmengen: m M = [ ˙ Pi i=1 P = {Pi | Pi ∩ Pj = ∅, Pi 6= ∅, 1 ≤ i < j ≤ m} Beispiel: Sei M = {1, 2, . . . , 12}. Dann ist P = {Q, R, S} mit Q = {i ∈ M | i ungerade}, R = {i ∈ M | i ≡ 0 mod 4} und S = {i ∈ M | i ≡ 2 mod 4} eine Partition von M. 270 / 387 Union-Find ◮ ◮ ◮ Find ist eine Funktion, die jedem i ∈ M die Menge Pj zuordnet, für die i ∈ Pj gilt. Benutzt wird Find(x) = Find(y )?“ ” Nur nach einem Find-Aufruf erfolgt u.U. ein Union-Aufruf. ◮ Union verändert die Partition wie folgt: Union(A, B) bedeutet, dass die Partitionselemente A, B ∈ P zu einer neuen Menge mit dem Namen C vereinigt werden. Der neue Name kann explizit in Form eines Union(A, B, C ) oder implizit sein. ◮ Nach Union(A, B) ist die neue Partition (P \ {A, B}) ∪ {A ∪ B}. 271 / 387 Anwendung auf DEA 1.) Äquivalenztest deterministischer endlicher Automaten nach Hopcroft und Karp 1971: A linear algorithm for testing equivalence of finite automata. ◮ Tatsächlich ist der Algorithmus nur linear in der Zahl der Union-Find-Operationen. Die Laufzeit ist daher nur fast linear”. ” 272 / 387 Äquivalenz endlicher Automaten nach Hopcroft und Karp 1971 Definition 14.1 Ein endlicher, deterministischer Automat über dem Alphabet Σ ist ein 5-Tupel A = (Q, Σ, δ, q0 , F ) wobei: ◮ Q Zustände, ◮ q0 ∈ Q Startzustand, ◮ ◮ δ : Q × Σ → Q Übergangsfunktion, F ⊆ Q Endzustände. Erweiterung auf δ : Q × Σ∗ → Q durch δ(q, ε) = q und δ(q, ua) = δ(δ(q, u), a) für q ∈ Q, u ∈ Σ∗ und a ∈ Σ. 273 / 387 Äquivalenz endlicher Automaten Schreibe statt δ(q, w ) für q ∈ Q und w ∈ Σ∗ , vereinfacht qw . L(A) := {w ∈ Σ∗ | q0 w ∈ F } L(q) := {w ∈ Σ∗ | qw ∈ F }. Gegeben: A = (Q, Σ, δ, q0 , F ) und A′ = (Q ′ , Σ, δ ′ , q0′ , F ′ ). Frage: L(A) = L(A′ )? 274 / 387 Äquivalenztest DEA Algorithmus 14.1 function Äquivalenztest-DFA(A, A′ : DFA) : boolean begin L := {(q0 , q0′ )}; (∗ z.B. FIFO Queue ∗) while L = 6 ∅ do wähle ein (p, q) ∈ L; L := L \ {(p, q)}; if not (p ∈ F ⇐⇒ q ∈ F ′ ) then return false EXIT endif (∗ L(q0 ) 6= L(q0′ ) ∗) if Find(p) 6= Find(q) then Union(p, q); forall a ∈ Σ do L := L ∪ {(p · a, q · a)} endfor endif endwhile return true endfunction 275 / 387 Korrektheit Siehe Tafel Kurzmitschrift Wird das Programm mit EXIT“ beendet so gilt L(q0 ) 6= L(q0′ ). ” Wir können daher annehmen, dass das Programm nicht über EXIT“ beendet wird, ” sondern den Wert true“ zurückgibt. Zu zeigen ist: L(q0 ) = L(q0′ ). ” 276 / 387 Korrektheit Zeige: Am Ende, also nach korrekter Beendigung mit L = ∅, gilt: Find(p) = Find(q) =⇒ L(p) = L(q). Beachte, ist zu irgendeinem Zeitpunkt (p, q) ∈ L, so gilt Find(p) = Find(q). Wir zeigen, dass dann auch Find(p · a) = Find(q · a) für alle a ∈ Σ gilt. Man beweist jetzt mit Induktion nach der Zeit die folgenden beiden Aussagen für alle Zustände p ∈ Q, q ∈ Q ′ und alle a ∈ Σ: ◮ Ist Find(p) = Find(q), so gilt p ∈ F ⇐⇒ q ∈ F ′ . Trivial. ◮ Ist Find(p) = Find(q), so gilt Find(p · a) = Find(q · a). Für den Beweis beachte, dass Find(p) = Find(q) zwei Ursachen haben kann: 1. (p, q) ∈ L, oder 2. es gibt ein (r , s) ∈ L, welches über Find(p) = Find(x), Find(q) = Find(y ) mit { x, y } = { r , s } und Union(r , s) die Bedingung Find(p) = Find(q) liefert. Wegen (q0 , q0′ ) ∈ L folgt jetzt mit Induktion nach k, dass q0 · a1 · · · ak ∈ F ⇐⇒ q0′ · a1 · · · ak ∈ F ′ . 277 / 387 Zeitanalyse Terminierung Es sind maximal n := |Q| + |Q ′ | = |Q̃| Union-Operationen möglich. Damit werden maximal |Σ| · n Elemente zu L hinzugefügt. In jedem Schleifendurchlauf wird ein Element aus L entfernt. Daher ergibt sich die Termination nach maximal |Σ| · n Schleifendurchläufen. ◮ n Union-Operationen ◮ |Σ| · n Find-Operationen 278 / 387 15./16. Vorlesung am 30./31.05.16 Thema: Kruskal-Algorithmus zur Union-Find-Berechnung” eines minimalen Spannbaums ” Zeitanalyse von Union – Find 279 / 387 Minimale Aufspannende Bäume Definition 15.1 Ein Graph G = (V , E ) heißt zusammenhängend, wenn je zwei Knoten durch einen Pfad verbunden sind. Definition 15.2 Ein Baum ist ein zusammenhängender, kreisfreier, ungerichteter Graph. Bemerkung 15.3 Jeder Baum mit n Knoten besitzt genau n − 1 Kanten. Definition 15.4 Ein minimaler aufspannender Baum (minimal spanning tree, MSB) zu einem gewichteten Graphen P G = (V , E , γ) ist ein Baum B = (V , F , γ|F ) mit F ⊆ E mit minimalem Gewicht γ(B) := e∈F γ(e). 280 / 387 Algorithmus 15.1 Kruskal-Algorithmus zur Bestimmung des MSB function kruskal(G = (V , E , γ): kantengew. Graph): Kantenmenge; (∗ G sei zusammenhängend ∗) (∗ E = {e1 , e2 , . . . , em } sei nach Gewichten aufsteigend sortiert. ∗) var m, i: integer; x, y : Knoten; T : Kantenmenge; (∗ des MSB ∗) begin m := |E |; T := ∅; forall v ∈ V do [v ] := {v } endfor; (∗ Init. des Waldes ∗) for i := 1 to m do xy := ei ; if Find(x) 6= Find(y ) then Union(x, y ); T := T ∪ {xy } endif endfor return T endfunction 281 / 387 Mögliche Prüfungsfragen ◮ ◮ Wie groß können m = |E | und |T | werden? (Allgemeine Graphen, planare Graphen?) Müssen alle Kanten vorsortiert werden? ◮ Was sind geeignete Datenstrukturen, um die Kanten zu verwalten? ◮ Wenn man die for-schleife durch eine while Schleife ersetzt, was ist dann die geeignete Abbruchbedingung? ◮ Was sind geeignete Datenstrukturen für Union-Find-Realisierungen? 282 / 387 Feld von Paaren 1 Q 2 S 3 Q 4 R 5 Q 6 S 7 Q 8 R 9 Q 10 S 11 Q 12 R Hier gilt z.B. Find(5) = Q Union(Q, R, T ) ergibt (d.h. Q und R werden zu einer Klasse mit Namen T vereinigt): 1 T 2 S 3 T 4 T 5 T 6 S 7 T 8 T 9 T 10 S 11 T 12 T 283 / 387 Feld: Quadratische Kosten ◮ ◮ ◮ ◮ Kosten: Find-Operation O(1). Kosten: Union-Operation Θ(n). In den Anwendungen werden häufig m Union-Find-Operationen hintereinander durchgeführt, mit m ∈ Ω(n). Damit insgesamt: Ω(n2 ). Ziel: m Union-Find-Operationen in fast linearer“ Zeit. ” 284 / 387 Knotenbeschriftete Bäume Klasse = knotenbeschrifteter Baum, Wurzel = Name der Klasse. Elemente der Grundmenge: 1, . . . , n. Knoten = {v1 , . . . , vn } Zugriffsmöglichkeiten: element: {1, . . . , n} → Knoten pred: Knoten → Knoten count: Wurzelknoten → Zahl name: Wurzelknoten → Klasse root: Menge → Wurzelknoten zugehöriger Knoten im Baum Vorgänger im Baum Anzahl der Elemente Name der Klasse Wurzel des Baumes 285 / 387 Union Die Initialisierung ist dann: name(vi ) := i root(i) := vi pred(vi ) := nil count(vi ) := 1 Die Union-Operation Union(i, j) wird dann so realisiert, dass der kleinere der beiden Bäume i, j an die Wurzel des größeren angehängt wird: 286 / 387 Union Realisierung Hänge den kleineren Baum unter die Wurzel des größeren Baumes. L Union R L R 287 / 387 Logarithmische Find-Kosten Lemma 15.5 Sei B ein Baum der durch Union-Find Operationen entsteht und n = |B|. Hat B die Höhe r , so gilt r ≤ log2 n und n ≥ 2r . Beweis: Für r = 0 ist die Behauptung klar. Seien L und R Bäume, die zu einem Baum B mittels Union zusammengefügt werden und |R| ≥ |L|. Hat B weiterhin die Höhe von R, so gilt n ≥ |R| ≥ 2r mit Induktion. Ist die Höhe von B größer geworden, so gilt r = ℓ + 1, wenn ℓ die Höhe von L ist. Damit gilt nach Induktion: n = |L| + |R| ≥ 2 |L| ≥ 2 · 2ℓ = 2ℓ+1 = 2r . 288 / 387 Union Satz 15.6 Sei m ∈ Ω(n). Dann lassen sich bei einer n-elementigen Grundmenge m Union-Find-Operationen (ohne Pfadverkürzung) in der Zeit O(m log n) realisieren. Eine weitere Idee zur Verkürzung der Suchpfade (= benötigte Find-Zeit) besteht darin, bei einem Aufruf von Find alle Knoten auf dem Pfad, den man zur Wurzel hin durchläuft, direkt unter die Wurzel anzuhängen. 289 / 387 Find mit Pfadverkürzung p p s q q r r s Baum nach Find(s) Baum vor Find(s) 290 / 387 Find-Implementierung mit Pfadverkürzung Algorithmus 15.2 function Find(i: Element): Element; var u, v , root: Knoten; begin u := element[i]; while pred(u) 6= nil do u := pred(u); endwhile root := u; u := element[i]; while pred(u) 6= nil do v := pred(u); pred(u) := root; u := v endwhile return name(root); endfunction 291 / 387 Zeitanalyse für Union-Find Dieser Abschnitt beschreibt die Analyse nach Robert E. Tarjan (1983) für m Union-Find-Operationen. Wir verwenden die folgende Ackermannfunktion: A0 (r ) = r + 1, Ak+1 (r ) = Ark (r ). (Hierbei bezeichnet Ark (r ) die r -fache Anwendung von Ak auf r .) Es ist Ak (1) = 2 für alle k ∈ N; daher ist sinnvoll: α(n) = min{k | Ak (2) ≥ n}. A1 (x) = 2x, A2 (x) = x2x , A3 (2) = 2048, also (2048): ein Turm von mehr als 2000 Potenzen der 2. A4 (2) = A23 (2) = A3 (2048) = A2048 2 2 ·· Es ist α(n) ≤ 4 = α(2049) für alle denkbaren Werte von n (etwa n ≤ 2| 2{z } ). Turm von 2000 2ern 292 / 387 Der Rang eines Knotens Definition 15.7 Der Rang eines Knotens x, Rang(x), ist die Höhe des Knotens in dem Wald, der ohne Pfadverkürzung erzeugt wurde. Lemma 15.8 Sei x ein Knoten mit Rang(x) = r . Dann hat der Teilbaum mit der Wurzel x mindestens 2r Elemente. Beweis: Lemma von eben. Korollar 15.9 Es gibt höchstens n/2r Knoten mit Rang r . Beweis: Zwei Knoten mit gleichem Rang sind nicht Vorgänger voneinander. 293 / 387 Analyse von m Union-Find-Operationen Wir betrachten n Knoten und die folgende zeitabhängige Funktion part (x): Definition 15.10 Sei x ein Knoten mit Rang r . Dann bezeichnet part (x) seinen Vorgänger (englisch: parent) zum Zeitpunkt t. Definition 15.11 Ein Knoten x mit Rang r ≥ 2 gehört zur Zeit t zur Klasse (oder Ranggruppe) k, falls k maximal ist mit r (part (x)) ≥ Ak (r (x)). Beachte: n ≥ 2r (part (x)) >r (part (x)) ≥ Ak (r (x)) ≥ Ak (2). Also gilt für existierende Ranggruppen k stets: 0 ≤ k < α(n). 294 / 387 Analyse von m Union-Find-Operationen ◮ Wurzeln oder Knoten vom Rang 0 oder 1 gehören in keine Klasse. Ein innerer Knoten mit Rang 2 gehört mindestens in die Klasse 0. ◮ Es gibt höchstens α(n) verschiedene Klassen. ◮ Realistisch: nur die Klassen 0, 1, 2 und 3. ◮ Eine Klasse kann als Maß für den Abstand eines Knotens zu seinem Vaterknoten angesehen werden. Damit ist auch klar: Die Klassennummern, die man auf dem Pfad zur Wurzel antrifft, müssen nicht wie die Ränge monoton steigen. 295 / 387 Die Lebensgeschichte eines Knotens Erinnerung: Es gibt höchstens α(n) Rangklassen. ◮ Ein Knoten x beginnt als Wurzel. ◮ Wenn er den Wurzelstatus verliert, erhält er seinen Rang r (x). ◮ Bei Rang 0 oder 1 bleibt x für immer klassenlos. ◮ Bei Rang 2 oder mehr betritt x eine Klasse k ≥ 0. ◮ ◮ Ab jetzt geht es in der Klassengesellschaft nur aufwärts. Realistischerweise sollte man nur auf Klasse 3 hoffen. 296 / 387 Analyse von m Union-Find-Operationen Erinnerung: Teuer sind nur die Find-Operationen. Bei einem Find(i) verteilen wir auf dem Pfad Gold- und Eisenstücke auf die Knoten. Wir unterscheiden α(n) Klassen von Eisenstücken, so dass es insgesamt 1 + α(n) verschiedene Währungen gibt. Goldverteilung: Wenn x auf dem Pfad zur Wurzel besucht wird, gibt es ein Goldstück, falls x keiner Klasse angehört (d.h. x ist Wurzel oder vom Rang 0 oder 1) oder x letzter seiner Klasse ist. Korollar 15.12 Insgesamt werden nicht mehr als (3 + α(n))m Goldstücke verteilt. 297 / 387 Analyse von m Union-Find-Operationen Eisenverteilung: Wenn x zur Zeit t auf dem Pfad zur Wurzel besucht wird, erhält x ein Eisenstück der Klasse k, falls x zu dieser Zeit zur Klasse k gehört und nicht letzter seiner Klasse ist. Beobachtung: Erhält x zur Zeit t ein Eisenstück der Klasse k, so gibt es auf dem Pfad zur Wurzel Knoten x, part (x), y , part (y ) mit: Ak (r (x)) ≤ r (part (x)) ≤ r (y ), Ak (r (y )) ≤ r (part (y )). Satz 15.13 Sei i ≥ 1 mit r (part (x)) ≥ Aik (r (x)). Dann gilt zur Zeit t + 1 die Beziehung: r (part+1 (x)) ≥ Ai+1 k (r (x)). r (x) Konsequenz. Nach r (x) − 1 Besuchen von x gilt r (par(x)) ≥ Ak (r (x)) = Ak+1 (r (x)). 298 / 387 Beweis Wähle auf dem Pfad x, part (x), y , part (y ) mit: Aik (r (x)) ≤ r (part (x)) ≤ r (y ), Ak (r (y )) ≤ r (part (y )). Dann folgt: r (part+1 (x)) ≥ ≥ ≥ ≥ = r (part (y )) Ak (r (y )) Ak (r (part (x))) Ak (Aik (r (x))) Ai+1 k (r (x)). 299 / 387 Korollare Ein Knoten vom Rang r erhält maximal r − 1 Eisenstücke der Klasse k. (Erinnerung r ≥ 2.) Beweis: Nach r Find-Operationen in der Klasse k gilt: r (pars (x)) ≥ Ark (r ) = Ak+1 (r ) und der Knoten steigt in die Klasse k + 1 auf. Korollar 15.14 Es werden insgesamt maximal 3n 2 ≤ 2n Eisenstücke der Klasse k verteilt. r Beweis: Es gibt höchstens n/2 Knoten mit Rang r und jeder erhält höchstens r − 1 Eisenstücke der Klasse k. Damit: X (r − 1)n =n 2r r ≥2 Korollar 15.15 Es werden insgesamt maximal α(n)n Eisenstücke verteilt. Beweis: α(n) Klassen und pro Klasse n Eisenstücke. 300 / 387 Abschätzung für die Gesamtkosten Alle Finds zusammen kosten O ((3 + α(n))m + α(n)n) Zeit. Beweis: (3 + α(n))m Gold + α(n)n Eisen. Übung: Für α(n) < 4 dominiert die Konstante 6m im O-Term, da m > n. Wie erreicht man 5m? Lösung steht etwa bei Kozen oder Tarjan. 301 / 387 Gemessene Laufzeitkosten Die folgenden Diagramme zeigen experimentell gemessene Werte für die Laufzeitkosten, die die Union-Find-Implementierung mit Pfadverkürzung beim Kruskal-Algorithmus verursacht. Gemessen wurde jeweils, wie viele Knoten alle Find-Operationen zusammen besuchen mussten. Der zugrunde gelegte Graph wurde stets zufällig erstellt und hatte n Knoten sowie m Kanten, wie es in den Diagrammen jeweils zu sehen ist. Die Diagramme zeigen die Ergebnisse jeweils für drei verschiedene Strategien der Implementierung: Normal Die normale Strategie, bei einem Union stets den kleineren Baum unter den größeren zu hängen Invers Die umgekehrte Strategie, bei einem Union stets den größeren Baum unter den kleineren zu hängen Zufall Bei jedem Union wird gewürfelt, ob nun der kleinere Baum unter den größeren gehängt werden soll oder umgekehrt 302 / 387 Experimente 303 / 387 Experimente 304 / 387 17. Vorlesung am 06.06.16 Themen: 1. Fibonacci-Heaps 2. Amortisierte Zeitanalyse Anwendungen: 1. Dijkstra/Prim 2. Berechnung minimaler Schnitte nach Stoer/Wagner. (Siehe den nächsten Abschnitt.) 305 / 387 Fibonacci-Heaps Fibonacci-Heap H = Liste von Bäumen (also ein Wald): Die Bäume sind knotenbeschriftet. Alle Knoten, bis auf die Wurzel, können zusätzlich eine Marke tragen. V = Knotenmenge. key : V → N Beschriftung. root bezeichnet stets eine der Wurzeln. Heap-Bedingung: ∀x ∈ V : ist y ein Kind von x, so gilt: key (x) ≤ key (y ) 306 / 387 Fibonacci-Heaps ◮ Die Eltern-Kind-Beziehung wird durch Zeiger realisiert, da die Bäume unbalanciert sein werden. ◮ Im Gegensatz zu einem Standard-Heap müssen Indexrechnungen also durch aufwendige Zeigeroperationen ersetzt werden. ◮ Operationen: ◮ 1. merge, ◮ 2. insert, ◮ 3. delete min, ◮ 4. decrease key. 307 / 387 Fibonacci-Heaps ◮ merge: Konkatenation zweier Listen — konstante Zeit. ◮ insert: Spezialfall von merge — konstante Zeit. ◮ merge und insert können (eventuell sehr lange) Listen einelementiger Bäume erzeugen. ◮ Jede solche Liste ist ein Fibonacci-Heap. 308 / 387 delete min ◮ Sei H ein Fibonacci-Heap aus T Bäumen und n Elementen. ◮ Für einen Knoten x sei rank (x) = die Anzahl der Kinder von x. ◮ Für einen Baum B sei rank (B) = Rang der Wurzel von B. ◮ Sei rmax (n) der maximale Rang, der in einem Fibonacci-Heap mit n Elementen auftreten kann. ◮ rmax (n) < n. ◮ Später zeigen wir rmax (n) ∈ O(log n). 309 / 387 procedure delete min 1. Suche minimalen Schlüssel als Wurzel in einem Baum. Sei r der Rang dieses Baumes. Zeit: O(T ). Alternativ gibt es einen Zeiger auf das kleinste Element. 2. Trenne die Wurzel ab und ersetze den Baum durch die r Teilbäume. Evtl. Marken entfernen. Zeit: O(T + r ). 3. Definiere Feld L[0, . . . , rmax (n)] mit L[i] = die Liste der Bäume von Rang i. Zeit: O(T + rmax (n)). 4. for i := 0 to rmax (n) − 1 do while |L[i]| ≥ 2 do Entnehme zwei Bäume aus L[i]. Hänge den Baum mit dem größeren Schlüsselwert an der Wurzel direkt unter die Wurzel des anderen Baumes und füge diesen neuen Baum in L[i + 1] an. endwhile endfor delete min erfordert also die Zeit O(T + rmax (n)). 310 / 387 Bemerkung Am Ende der Prozedur delete min gibt es für jeden möglichen Rang höchstens einen Baum. Insbesondere ist die Zahl der Bäume durch rmax (n) beschränkt. Beachte, wir nehmen hier als Definition von rmax (n) mindestens den Wert an, der nie dazu führt, dass bei delete min die Liste L[rmax (n)] mehr als einen Baum erhalten kann. Wegen der naiven Abschätzung rmax (n) ≤ n − 1, existiert rmax (n). Später zeigen wir: n ≥ Frmax (n)+2 . 311 / 387 decrease key Kaskadenartige Schnitte: Sei x der Knoten, dessen Schlüssel verkleinert werden soll. 1. Ist x die Wurzel, so kann der Schlüsselwert verkleinert werden. Sei also x keine Wurzel und x = y0 , y1 , . . . , yk , . . . , root der Pfad von x zur Wurzel. Für ein k ≥ 1 sei yk der erste (von x verschiedene) Knoten, der keine Marke trägt. 2. Für 0 ≤ i < k trenne jetzt yi vom Elternknoten yi+1 ab und entferne dabei die Marke von yi . (Für y0 = x ist evtl. eine Marke vorhanden gewesen.) Damit wird yi für 0 ≤ i < k zu einer unmarkierten Wurzel eines eigenen Baumes. 3. Falls yk keine Wurzel ist, markiere yk . (Kind verloren!) 312 / 387 decrease key Es wird O(k + 1) Zeit benötigt. Beachte: Die Zahl der Marken hat sich mindestens um k − 2 verringert für k ≥ 2. Für k = 1 kann maximal eine Marke hinzugekommen sein. Dies passiert wenn, x und y1 vorher unmarkiert waren. Sei M die Zahl der Marken vor decrease key und M ′ danach. Dann gilt immer M ′ ≤ M + 2 − k. Die Anzahl der Bäume ist nach der Prozedur decrease key durch T + k begrenzt. 313 / 387 decrease key Definition 16.1 Ein Fibonacci-Heap ist eine Liste von Bäumen wie eingangs beschrieben, die aus der leeren Liste unter Anwendung der Operationen merge, insert, delete min und decrease key entstanden ist. Fibonacci-Heaps-Lemma 1. Sei x ein Knoten in einem Fibonacci-Heap, und ci das i-t älteste Kind von x (d.h., c1 ist der erste Knoten, der Kind von x geworden ist). Dann hat ci mindestens den Rang i − 2. 2. Hat x mindestens den Rang k, k ≥ 0, so enthält die Teilmenge der Wurzel x zusammen mit den Teilbäumen von k Kindern mindestens Fk+2 Knoten. Hierbei ist Fk+2 die (k + 2)-te Fibonacci-Zahl (F0 = 0, F1 = 1, Fk+2 = Fk + Fk+1 für k ≥ 0). 314 / 387 Beweis Lemma 1. Sei c1 , c2 , . . . , ck die dem Alter nach absteigend geordnete Folge der Kinder von x, und 1 ≤ i ≤ k. Dann ist c1 älter als c2 , c2 älter als c3 , u.s.w. Zu dem Zeitpunkt, als ci unter den Knoten x (der zu diesem Zeitpunkt eine Wurzel war) gehängt wurde, existierten also bereits die Kinder c1 , . . . , ci−1 . Der Rang von x war also mindestens i − 1. Da nur Bäume vom gleichen Rang zu einem Baum vereinigt werden, hatte ci zu diesem Zeitpunkt mindestens den Rang i − 1. Der Knoten ci kann inzwischen maximal ein Kind verloren haben. (In diesem Fall wäre ci markiert.) Der Verlust eines weiteren Kindes hätte die Abtrennung ci von x zur Folge gehabt. Es folgt die erste Behauptung rank (ci ) ≥ i − 2 . Die zweite Behauptung folgt dann mit Induktion und einem Bild. 315 / 387 Fibonacci-Zahlen √ x k+1 = x k + x k−1 ⇐⇒ x k−1 (x 2 − x − 1) = 0 √ Die Zahlen 1+2 5 , 1−2 5 sind die beiden Lösungen der quadratischen Gleichung x 2 − x − 1 = 0. Dies führt zu dem Ansatz: Fk = a √ !k 1+ 5 +b 2 √ !k 1− 5 2 Wegen F0 = 0 und F1 = 1 muss für a, b gelten: a Es folgt a = √1 , 5 b= −1 √ . 5 √ 1+ 5 2 +b a + b = 0, √ 1− 5 2 = 1. 316 / 387 Fibonacci-Zahlen √ !k 1 1+ 5 Fk = √ − 2 5 Die Fibonacci-Zahlen wachsen exponentiell. Also rmax (n) ∈ O(log n). √ !k 1− 5 2 317 / 387 Zusammenfassung der Zeitabschätzungen 1,2. merge, insert: in konstanter Zeit 3. delete min: O(T + log n), wobei T die Zahl der Bäume ist. Der Summand log n ergibt sich aus rmax (n) ∈ O(log n). 4. decrease key: O(1) + O(k), wobei k ≥ 0 die Zahl der Marken sei, um die sich der Fibonacci-Heap verringert hat. 318 / 387 Amortisierte Zeiten Für die weitere Analyse einer Sequenz von Operationen betrachten wir die gegen eine Potentialfunktion amortisierte Zeit. Definition 16.2 Für einen Fibonacci-Heap H sei das Potential pot (H) gegeben durch pot (H) := T + 2M , wobei T die Zahl der Bäume und M die Zahl der Marken seien. Für eine Operation op sei ∆pot (op ) die Differenz des Potentials vor und nach der Ausführung: ∆pot (op ) = pot (Heap nach op ) − pot (Heap vor op ) . Die amortisierte Zeit einer Operation op sei tamort (op ) = t(op ) + ∆pot (op ) . 319 / 387 Potentialfunktion Die Potentialfunktion erfüllt: ◮ pot (H) ≥ 0, ◮ pot (∅) = 0. Sei jetzt op 1 , op 2 , op 3 , . . . , op m eine Sequenz von m Operationen auf einem zunächst leeren Fibonacci-Heap. Dann gilt: m m X X tamort (op i ) . t(op i ) ≤ i=1 i=1 Bemerkung: Die Differenz ist gerade das Potential des erzeugten Heaps. Wegen pot (H) ∈ O(|H|) gilt m X i=1 tamort (op i ) ∈ m X t(op i ) + θ(|H|). i=1 Es genügt also eine Schranke für tamort (op ) zu bestimmen. 320 / 387 Bequemlichkeit Für die weitere Rechnung ist es bequemer, sich bei der tatsächlich verbrauchten Zeit zunächst von der O-Notation zu befreien. Durch die Multiplikation mit einer geeigneten Konstanten können wir annehmen, dass sich merge und insert in einem Schritt realisieren lassen. Die Operation delete min benötigt höchstens T + log n und die Operation decrease key höchstens k + 1 Zeitschritte. Die Wahl der Basis für den Logarithmus ist in der Zeitanalyse unerheblich. 321 / 387 delete min ◮ tamort (merge) = t(merge) = 1. Denn das Potential der konkatenierten Liste ist die Summe der Potentiale der Einzellisten. ◮ tamort (insert) = t(insert)+∆pot (op ) = 1 + 1 = 2. ◮ Für delete min gilt t(delete min) ≤ T + log n, wobei T die Zahl der Bäume zuvor und rmax (n) bis auf einen konstanten Faktor die maximale Zahl der Bäume danach ist. Die Zahl der Marken kann nur kleiner werden. Aus ∆pot (op ) ≤ −T + rmax (n) folgt daher tamort (delete min) ≤ T + log n − T + rmax (n) ∈ O(log n) . 322 / 387 delete min ◮ Für decrease key gilt nach der obigen Bemerkung t(decrease key) ≤ k + 1. Dabei verliert der Heap mindestens k − 2 Marken, k ≥ 1, und erhält höchstens k neue Bäume. ∆pot (op ) = ∆(T ) + 2∆(M) ≤ k + 2 · (2 − k) = 4−k Also gilt tamort (decrease key) ≤ k + 1 + 4 − k = 5 ∈ O(1). 323 / 387 delete min Satz 16.3 Für einen Fibonacci-Heap gelten die folgenden amortisierten Zeiten: tamort (merge) ∈ O(1) tamort (insert) ∈ O(1) tamort (delete min) ∈ O(log n) tamort (decrease key) ∈ O(1) 324 / 387 Anwendungen Anwendung auf den Dijkstra- oder Prim-Algorithmus: Für den Dijkstra-Algorithmus sei V die Randmenge und key die ermittelte Distanz der Randknoten zum Quellknoten u (entsprechend für Prim). Sei n die Zahl der Knoten und e die Zahl der Kanten. Maximal werden n insert-, e decrease key- und n delete min-Operationen durchgeführt. 325 / 387 Anwendungen tDijkstra ≤ n · tamort (insert) + e · tamort (decrease key) + n · tamort (delete min) ∈ O(n + e + n log n) = O(e + n log n) Man beachte, dass sich für die Analyse des schlechtesten Falles keine Verbesserung ergibt. Asymptotisch ist O(e + n log n) jedoch mindestens genauso gut wie min(e · log n, n2 ). In n2 vielen Fällen (n log n ≤ e ≤ log n ) ist O(e + n log n) um den Faktor log n besser. 326 / 387 18. Vorlesung am 07.06.16 Berechnung eines minimalen Schnittes nach M. Stoer und F. Wagner (Konferenz 1994, Zeitschrift 1997). Ausblick: 1. Las Vegas (Quicksort) vs Monte Carlo (Primzahlerkennung, Fermat-Test). 2. Monte Carlo für minimale Schnitte. Literatur zum Thema Minimale Schnitte: STOER, MECHTHILD und WAGNER, FRANK A simple Min-Cut Algorithm. Journal of the ACM (1997) 585-591. KARGER, DAVID und STEIN, CLIFFORD A New Approach to the Minimum Cut Problem. Journal of the ACM (1996) 601-640. 327 / 387 Minimale Schnitte Sei G = (V , E , γ) ein ungerichteter Graph γ : E → N das Kantengewicht, durch Null fortgesetzt. Ein Schnitt C = (C1 , C2 ) ist eine Partition der Knoten. Ein s-t-Schnitt ist ein Schnitt (C1 , C2 ) mit s ∈ C1 und t ∈ C2 . Das Gewicht g (C ) von C ist die Summe: g (C ) = X γ(vw ) v ∈C1 ,w ∈C2 P Für A ⊆ V , v ∈ V setze g (A, v ) = a∈A γ(av ). Oder einheitlich: X g (A, B) = γ(ab) a∈A,b∈B 328 / 387 Stoer-Wagner-Algorithmus Der Algorithmus arbeitet in Phasen. 1) Berechne analog zum Prim-Algorithmus für zwei Punkte s, t ∈ V , s 6= t einen minimalen s-t-Schnitt Cphase . Achtung: Die Punkte s und t werden erst durch den Algorithmus bestimmt. 2) Verschmelze s und t zu einem neuen Punkt {s, t}: Die Kanten zwischen s und t werden gelöscht und für x ∈ / {s, t} setzt man γ({s, t}x) = γ(sx) + γ(tx). Der neue Graph heiße G /(s = t). 3) Rekursion: Sei C ′ der rekursiv berechnete Schnitt in G /(s = t). Dann ist C ′ ein minimaler Schnitt von G unter der Nebenbedingung, dass C ′ die Knoten s und t nicht trennt. Der minimale Schnitt ist das Minimum von g (Cphase ) und g (C ′ ). 329 / 387 Minimale s-t-Schnitte Es kommt also im Wesentlichen darauf an, den minimalen s-t-Schnitt für gewisse Knoten s, t ∈ V , s 6= t zu berechnen. Diese Phase verläuft analog zum Prim-Algorithmus. Zu Beginn der Phase gelte B = {v1 } und R = V \ {v1 }. Die Knoten aus B werden Baumknoten und die Knoten aus R Randknoten P genannt. Für einen Randknoten v ∈ R sei stets g (v ) = x∈B γ(xv ). (Gibt es keine Kante zwischen B und v , so hat diese Summe den Wert Null. Damit ist der Wert g (v ) = γ(v1 v ) in der Zeit O(|R|) für den Rand initialisiert.) 330 / 387 while |R| > 1 do Zu Beginn jeder Schleife wird ein delete max ausgeführt. Dies bestimmt einen Knoten v ∈ R mit g (v ) ≥ g (w ) ∀w ∈ R und entfernt v aus R. Es wird B um v ergänzt (v wird also ein Baumknoten) und die Schlüsselwerte werden mit increase key vergrößert: Für w ∈ R \ {v } setzt man g (w ) := g (w ) + γ(vw ). Eine Invariante ist also ∀w ∈ R : g (w ) = g (B, w ) 331 / 387 Termination Die Schleife wird solange durchlaufen, bis der Rand nur noch einen Knoten t enthält. P Dann gilt g (t) = vt∈E γ(vt), d.h. g (t) ist die Summe der Gewichte aller von t ausgehenden Kanten. Sei s der Knoten, der unmittelbar vor t zum Baumknoten wurde. Dann definiert die Zerlegung (V \ {t}, {t}) einen s-t-Schnitt Cphase mit dem Gewicht g (t). 332 / 387 Korrektheitslemma Lemma 16.4 Der Schnitt Cphase ist ein minimaler s-t-Schnitt im Eingabegraphen der Phase. Beweis: Sei v1 , v2 , . . . , vn eine Anordnung der Knoten in der Reihenfolge, in der sie zu Baumknoten wurden. Es gilt vn−1 = s, vn = t. Sei C = (C1 , C2 ) ein minimaler s-t-Schnitt mit s ∈ C1 , t ∈ C2 . Wir zeigen: g (Cphase ) ≤ g (C ) 333 / 387 g (Cphase ) ≤ g (C ) In der Folge v1 , . . . , vn−1 , vn wird ein Knoten vi aktiv genannt, falls C ein vi−1 -vi -Schnitt ist. Da C ein s-t-Schnitt ist, ist insbesondere vn = t aktiv. Sei vi aktiv; setze B(i) = {v1 , . . . , vi−1 } und betrachte den durch B(i) ∪ {vi } induzierten Untergraphen. Durch Einschränkung definiert C auf diesem Untergraphen einen Schnitt. Diesen bezeichnen wir mit C (i) und das Gewicht mit g (C (i)). Da t = vn aktiv ist und g (Cphase ) = g (B(n), t) sowie C (n) = C gelten, genügt es, die Behauptung g (B(i), vi ) ≤ g (C (i)) für alle aktiven Knoten vi zu zeigen. Für den bzgl. der obigen Folge ersten aktiven Knoten vi gilt g (B(i), vi ) = g (C (i)), denn die durch C induzierte Partition ist ({v1 , . . . , vi−1 }, {vi }). Dies ist die Induktionsverankerung. 334 / 387 Fortsetzung: Beweis Sei jetzt vi ein aktiver Knoten für den die Behauptung richtig ist und vj der nächste auf vi folgende aktive Knoten. Dann gilt 1 < i < j ≤ n. Zu zeigen ist: g (B(j), vj ) ≤ g (C (j)). Es gilt zunächst: g (B(j), vj ) = g (B(i), vj ) + g ({vi , . . . , vj−1 }, vj ) Da der Knoten vi vor vj gewählt wurde, gilt g (B(i), vj ) ≤ g (B(i), vi ) und nach Induktion gilt g (B(i), vi ) ≤ g (C (i)). Alle Kanten zwischen {vi , . . . , vj−1 } und vj sind Schnittkanten und tragen somit zum Gewicht von C (j) bei. Daher g (C (i)) + g ({vi , . . . , vj−1 }, vj ) ≤ g (C (j)), und insgesamt g (B(j), vj ) ≤ g (C (j)). 335 / 387 Laufzeit Phase In jeder Phase wird also ein minimaler s-t-Schnitt berechnet. Die Laufzeitanalyse einer Phase ist identisch zum Prim-Algorithmus: Wird der Rand R als ein Feld oder als eine Liste verwaltet, so ergibt sich die Zeit n · O(n) + e · O(1) = O(n2 ). Bei Verwendung eines Heaps erhalten wir n · O(log n) + e · O(log n) = O(e log n). Mit Fibonacci-Heaps ergibt die beste Abschätzung: n · O(log n) + e · O(1) = O(e + n log n) 336 / 387 Gesamtlaufzeit Nach jeder Phase wird der Graph durch Verschmelzen der beiden Knoten s und t verkleinert. Dies ist eine O(e)-Operation. Das Gewicht des jeweils aktuellen minimalen Schnittes ergibt sich in O(1) durch einen direkten Gewichtsvergleich. Die Aktualisierung der Partition (C1 , C2 ) kostet dann O(n) Schritte. Der Algorithmus terminiert, wenn der Graph nur noch einen Punkt enthält, d. h., es werden (n − 1) Phasen durchlaufen. Dies ergibt die Gesamtzeit O(n3 ) für Felder oder Listen, O(ne log n) für Heaps und O(ne + n2 log n) für Fibonacci-Heaps. 337 / 387 Phase Algorithmus 16.1 function Phase (G = (V , E , γ) || |V | ≥ 2; v1 ∈ V ); Die Ausgabe besteht aus zwei Knoten s, t mit dem Gewicht gphase eines minimalen s-t-Schnittes. *) var B : Knotenmenge; R : Knotenmenge; s, t, v , w : V ; begin B := {v1 }; R := V \ {v1 }; forall v ∈ R do g (v ) := γ(v1 v ); endfor s := v1 ; (∗ Baumknoten ∗) (∗ Randknoten ∗) (∗ Initialisierungen ∗) 338 / 387 Berechnung eines minimalen Schnittes Algorithmus 16.2 Fortsetzung while |R| > 1 do s := Knoten v ∈ R mit g (v ) ≥ g (w )∀w ∈ R; R := R \ {s}; B := B ∪ {s}; forall sw ∈ E , w ∈ R do g (w ) := g (w ) + γ(sw ) endfor endwhile t := der letzte Knoten in R return (s, t, g (t)) endfunction (∗ begin delete max ∗) (∗ end delete max ∗) (∗ increase key ∗) 339 / 387 Berechnung eines minimalen Schnittes Algorithmus 16.3 function Min Cut( G = (V , E , γ), |V | ≥ 2) (Partition C1 , C2 mit minimalem Schnitt g ); var C1 , C2 : Knotenmenge; (∗ Partition von V ∗) s, t : V ; g , gphase : integer; begin wähle ein v1 ∈ V ; (s, t, gphase ) := Phase(G , v1 ); verschmelze s und t; der neue Graph sei G /(s = t); if |V | = 2 then C1 := {s}; C2 := {t}; g := gphase ; else (C1 , C2 , g ) := Min Cut (G /(s = t)); endif (∗ Die Partition (C1 , C2 ) von G /(s = t) ist auch ein Schnitt von G . ∗) 340 / 387 Berechnung eines minimalen Schnittes Algorithmus 16.4 Fortsetzung und Ende von Min Cut if gphase ≤ g then C1 := V \ {t}; C2 := {t}; g := gphase ; endif return (C1 , C2 , g ) endfunction 341 / 387 Beispiel: Berechnung eines minimalen Schnittes 2 1 3 2 5 3 2 2 3 6 2 1 4 3 4 2 7 2 3 8 Abbildung: Ein Graph G = (V , E ) mit Kantengewichten γ : E → N. Der Startknoten ist Knoten 2. 342 / 387 Beispiel: Berechnung eines minimalen Schnittes t 2 1 3 a 2 2 5 s 2 3 6 f b 3 3 2 1 4 c 4 2 7 d 2 3 8 e Abbildung: Der Graph nach der ersten Phase mit Startknoten 2. Die Knoten wurden in der Reihenfolge a, b, c, d, e, f , s, t besucht. Der gefundene Schnitt ist die Partition {1} , {2, 3, 4, 5, 6, 7, 8} mit Gewicht g = 5. 343 / 387 Beispiel: Berechnung eines minimalen Schnittes a 2 4 1,5 b 2 3 6 c d 3 3 2 1 4 e 4 2 7 s 2 3 8 t Abbildung: Der Graph nach der zweiten Phase. Die Knoten wurden in der Reihenfolge a, b, c, d, e, s, t besucht. Der gefundene Schnitt ist die Partition {8} , {1, 2, 3, 4, 5, 6, 7} mit Gewicht g = 5. 344 / 387 Beispiel: Berechnung eines minimalen Schnittes a 2 4 1,5 b 6 c 3 2 2 3 d 3 1 4 s 4 4 7,8 t Abbildung: Nach der dritten Phase. Der gefundene Schnitt ist die Partition {7, 8} , {1, 2, 3, 4, 5, 6} mit Gewicht g = 7. 345 / 387 Beispiel: Berechnung eines minimalen Schnittes a 3 2 4 1,5 b s 3 6 2 3 6 c 1 4,7,8 t Abbildung: Nach der vierten Phase. Der gefundene Schnitt ist die Partition {4, 7, 8} , {1, 2, 3, 5, 6} mit Gewicht g = 7. 346 / 387 Beispiel: Berechnung eines minimalen Schnittes t a 3 2 4 1,5 b 2 3 3,4,7,8 1 6 s Abbildung: Nach der fünften Phase. Der gefundene Schnitt ist die Partition {3, 4, 7, 8} , {1, 2, 5, 6} mit Gewicht g = 4. 347 / 387 Beispiel: Berechnung eines minimalen Schnittes a 2 5 4 1,5 t 3 3,4,6,7,8 s Abbildung: Nach der sechsten Phase. Der gefundene Schnitt ist die Partition {1, 5} , {2, 3, 4, 6, 7, 8} mit Gewicht g = 7. 348 / 387 Beispiel: Berechnung eines minimalen Schnittes s 2 9 V \2 t Abbildung: Nach der siebten Phase. Der gefundene Schnitt ist die Partition {2} , {1, 3, 4, 5, 6, 7, 8} mit Gewicht g = 9. 349 / 387 Übung: Wie verhält sich der Algorithmus bei negativen Kantengewichten, bleibt er korrekt? 350 / 387 Antwort: Bei negativen Kantengewichten arbeitet der Algorithmus im Allgemeinen nicht korrekt: 1 3 2 −2 2 4 1 5 3 Abbildung: Beispiel für einen Graphen, bei dem der Algorithmus mit Startknoten 1 kein korrektes Ergebnis erzielt: In der ersten Phase werden die Knoten in der Reihenfolge 1, 2, 3, 4 besucht und es wird der Schnitt {4} , {1, 2, 3} gefunden (g = 3). Dann werden die Knoten 3 und 4 verschmolzen. Der minimale Schnitt (g = 2) ist jedoch {1, 4} , {2, 3}. 351 / 387 Monte Carlo für Minimale Schnitte 1. Las Vegas (Quicksort) vs Monte Carlo (Primzahlerkennung, Freivalds Matrixprodukt-Erkennung). 2. Monte Carlo für minimale Schnitte nach Karger und Stein: A New Approach to the Minimum Cut Problem Journal of the ACM (1996) 601-640. 352 / 387 19. Vorlesung am 13.06.16 Monte-Carlo-Algorithmen sind randomisierte Algorithmen, die bei beschränkter Laufzeit mit einer kleinen Wahrscheinlichkeit ein falsches Ergebnis liefern dürfen: Mostly Correct Durch Wiederholen des Algorithmus kann die Fehlerwahrscheinlichkeit gesenkt werden. Im Gegensatz zu Monte-Carlo-Algorithmen dürfen Las-Vegas-Algorithmen nur korrekte Lösungen berechnen, aber mit einer gewissen Wahrscheinlichkeit ist die Laufzeit lang. Verified. Kann man die Richtigkeit eines Ergebnisses effizient überprüfen, so kann man Monte-Carlo-Algorithmen in Las-Vegas-Algorithmen überführen, indem man sie solange wiederholt, bis ein richtiges Ergebnis gefunden wird. Las Vegas nach Monte Carlo: Bricht man nach einer gewissen Laufzeit ab, so ist man automatisch in Monte Carlo. 353 / 387 Monte-Carlo Methode zur Berechnung minimaler Schnitte 1. Wähle eine Kante zufällig. 2. Kontrahiere. 3. Wiederhole. Analyse: Zur Vereinfachung der Rechnung sei das Gewicht einer Kante stets 1. (Wir erlauben Mehrfachkanten.) Sei k das Gewicht des minimalen Schnitts, dann gilt: k ≤ min { deg(v ) | v ∈ V } . Die Anzahl (das Gewicht) aller Kanten ist |E | ≥ kn/2. Wähle Kante e zufällig, dann wird nur mit W’keit ≤ 2k/(kn) = 2/n eine Schnittkante getroffen. Also ist die W’keit keine Schnittkante zu treffen ≥ 1 − 2/n = n−2 n . Es ist also im Prinzip eine gute Idee, die gewählte Kante e zu kontrahieren. 354 / 387 Monte-Carlo-Ansatz Wiederholen wir das Experiment c-mal, so haben wir immer noch die W’keit keine Schnittkante zu treffen: ≥ n−2 n−3 n−c n−c −1 (n − c)(n − c − 1) · ··· · = . n n−1 n−c +2 n−c +1 n(n − 1) Für c = n − 2 ist die W’keit allerdings ziemlich klein geworden, aber immerhin: ≥ 2 . n(n − 1) Seien C1 , . . . Cℓ die minimalen Schnitte und Ei das Ereignis, dass für c = n − 2 der Schnitt Ci gefunden wurde. Dann sind die Ereignisse disjunkt und Pr[Ei ] ≥ 1/ n2 . Daher gilt n ℓ≤ 2 . Es gibt also höchstens n 2 minimale Schnitte. 355 / 387 Naiver Monte-Carlo Ansatz Wiederhole das Experiment mehr als n2 -mal und behalte das beste Ergebnis. Dann ist die W’keit groß, einen fest gewählten minimalen Schnitt zu finden. Problem: Zu langsam! 356 / 387 Karger-Stein-Monte-Carlo-Ansatz Nächste Idee: Die Chancen, einen minimalen Schnitt zu treffen, sind zu Anfang gering und nehmen dann zu. Erfolg ist ab jetzt keine Schnittkante zu treffen. Misserfolg ist, eine zu treffen (und daher nicht den gewünschten Schnitt zu finden). Für c = n/2 ist die Erfolgs-W’keit noch mindestens ≥ (2n − n)(2n − n − 1) = 1/4. 4n(n − 1) √ Für n − c = n/ 2 ist die Erfolgs-W’keit mindestens 1/2. Dies ist daher unser Cut-Off-Point. 357 / 387 Karger-Stein-Algorithmus √ Sei G der Eingabegraph mit n Knoten, n = ( 2)k . (Wir vernachlässigen bewusst Rundungsfehler und kleine n.) Sei C ein fester minimaler Schnitt. Berechnung von C : 1.) Wiederhole zweimal: √ ◮ Wähle n − n/ 2-mal eine Zufallskante und kontrahiere jeweils die entsprechende Kante. ◮ ◮ ◮ ◮ ◮ Zeit für alle Kantenkontraktionen O(n2 ). Wir behandeln nicht, wie man effizient zufällige Kanten wählt, die ein Gewicht haben. (Die ist durchaus nicht trivial!) W’keit, Schnitt C nicht √ getroffen zu haben, ist ≥ 1/2. Restgraph G ′ hat ( 2)k−1 Knoten. Starte rekursiv den ganzen Algorithmus für G ′ . 2.) Behalte das bessere Ergebnis, also den kleineren Schnitt. Laufzeit: Mastertheorem I : √ t(n) = 2t(n/ 2) + O(n2 ). t(n) ∈ O(n2 log n). 358 / 387 Erfolgswahrscheinlichkeit: Ω(1/log n) Es sei pk die (Mindest-)Erfolgswahrscheinlichkeit. Wir können pk = 1 für kleine Werte von √ k ansetzen. Betrachte n = ( 2)k+1 . 1. Schnitt C wird bei den initialen Kantenkontraktionen mit W’keit 1/2 nicht getroffen. 2. Erfolg beim rekursiven Aufruf auf G ′ ist ≥ pk . 3. Erfolg beim ersten Durchlauf insgesamt ≥ p2k , Misserfolg also ≤ 1 − p2k . 4. Misserfolg bei beiden Durchläufen auf G ist ≤ (1 − p2k )2 . 5. Erfolg insgesamt bei G ist pk 2 ) 2 p2 = 1 − 1 + pk − k 4 pk2 = pk − 4 pk+1 ≥ 1 − (1 − 359 / 387 Lösung der Rekursion pk+1 ≥ pk − pk2 /4 Ansatz, definiere eine reelle Zahl zk ≥ 3 durch: pk = 4 . zk + 1 Also: 1 1 1 − zk+1 + 1 zk + 1 (zk + 1)2 zk = (zk + 1)2 zk = 2 zk + 2zk + 1 ≥ Damit folgt für die Kehrbrüche: zk2 + 2zk + 1 1 = zk + 2 + zk zk 1 ≤ zk + 1 + zk zk+1 + 1 ≤ zk+1 360 / 387 Zack zack. Wegen zk > 1 folgt zk+1 ≤ zk + 1 + 1 < zk + 2 zk Also wegen z2 = 3 mit Induktion zk ≤ 2k − 1 für k ≥ 2: zk ≤ 2k − 1 ∈ O(k) 1 2 pk ≥ ∈ Ω( ) k k Wegen k = log√2 n = 2 log2 n folgt für die Erfolgswahrscheinlichkeit P(n) des Karger-Stein-Algorithmus: 1 1 P(n) ≥ ∈Ω . log2 n log n 361 / 387 Finde minimale Schnitte mit hoher W’keit Satz 17.1 Wiederholen wir den Karger-Stein-Algorithmus 3 · ln n · log2 n-mal, so finden wir alle minimalen Schnitte in der Zeit O(n2 log3 n) mit einer Fehlerwahrscheinlichkeit kleiner als 1 2n . Beweis. Sei C zunächst ein fester minimaler Schnitt: 1 3·ln n·log2 n Pr(C wird nicht gefunden) ≤ (1 − ) log2 n ≤e Es gibt höchstens n 2 −3·ln n·log2 n log2 n ≤ e −3 ln n = 1 n3 minimale Schnitte. Also 1 n 1 < Pr(Nicht alle gefunden) ≤ 3 2n 2 n 362 / 387 21. Vorlesung, 27. Juni 2016 Thema: Kuchenschneide-Algorithmen Folien stammen (teilweise) von Ulrich Hertrampf! Literatur: Cake-Cutting Algorithms Jack Robertson / William Webb (AK Peters Natick, Massachusetts 1998) Be Fair If You Can. 363 / 387 Turings Kuchen 364 / 387 Grundvoraussetzungen ◮ Alle Beteiligten haben eine Bewertungsfunktion, die jedem beliebigen Teilstück des Kuchens einen Wert zwischen 0 und 1 so zuordnet, dass bei jeder Aufteilung die Gesamtsumme 1 herauskommt. ◮ Jeder ist in der Lage, einen Schnitt so anzusetzen, dass eine beliebige gewünschte Aufteilung entsteht. ◮ Alle Beteiligten kennen ihre eigene Bewertungsfunktion, aber nicht unbedingt die der anderen. ◮ Alle Beteiligten handeln vernünftig in dem Sinn, dass sie ihren worst-case-Anteil maximieren. (Je mehr je besser — ohne Risiko-Spiele) ◮ Eigentlich ist es egal, aus der Sicht jeder Person handelt jede andere nach Belieben. 365 / 387 Erste Algorithmen – als die Kinder noch klein waren Es war einmal ein großes Stück Kuchen da, auf das nur Lukas (11 Jahre) und Isabel (9 Jahre) Anspruch erhoben (- armer Jonas). UH war als Aufsicht dabei. Es ergaben sich verschiedene mögliche Algorithmen: ◮ UH teilt den Kuchen in zwei Teile. Dann gibt er ein Teil Lukas, das andere Isabel. ◮ UH teilt den Kuchen in zwei Teile. Lukas und Isabel werfen eine Münze, um zu entscheiden, wer zuerst wählen darf. ◮ Lukas teilt den Kuchen und nimmt sich dann ein Teil. Isabel bekommt das andere. ◮ Lukas teilt den Kuchen. Dann wählt Isabel ein Teil, Lukas bekommt das andere. ◮ Du teilst, ich wähle“ ” 366 / 387 Eine Person teilt, die andere wählt ◮ Lukas schneidet den Kuchen in zwei Stücke. ◮ Isabel wählt eines der beiden Stücke. ◮ Lukas bekommt das übrige Stück. Faire Analyse: Jede der beiden Kinder erhält nach eigener Einschätzung mindestens die Hälfte des Wertes. Neidfreie Analyse: Jede der beiden Kinder erhält nach eigener Einschätzung mindestens soviel wie die andere! 367 / 387 Drei Personen - erster Versuch ◮ Jonas möchte auch Kuchen ◮ Lukas teilt den Kuchen X in zwei Stücke, X1 und X2 , wobei nach seiner Einschätzung X1 ein Drittel des gesamten Kuchens ist. ◮ Isabel teilt X2 in zwei Stücke, X21 und X22 , die nach seiner Einschätzung gleich groß sind. ◮ Jonas wählt das nach seiner Ansicht größte der drei Stücke, dann wählt Lukas sich das größere der verbleibenden Stücke. Isabel bekommt, was übrigbleibt. Analyse: ◮ Jonas wählt als erster: Glück gehabt. . . ◮ Lukas bekommt auch mindestens sein Drittel! ◮ Was is mit Isabel? ◮ Lassen wir UH eingreifen! 368 / 387 Neid - eine schwerwiegende Komplikation Eine neue Situation: Auf dem Tisch liegen 9 Euro, und zwar: ◮ Zwei 2-Euro-Stücke ◮ Drei 1-Euro-Stücke ◮ Zwei 50-Cent-Stücke ◮ Zehn 10-Cent-Stücke UH gibt Lukas drei 1-Euros und einen 50er. Lukas freut sich (noch)! UH gibt Jonas die zehn Zehner. Jonas strahlt! (Soviele Münzen!) UH gibt Isabel zwei 2-Euros und einen 50er. Sie freut sich! Und was sagt Lukas jetzt??? 369 / 387 Neid - Definition der Neidfreiheit Eine Kuchenverteilung heißt neidfrei, wenn jede der teilenden Personen nach ihrem eigenen Maßstab mindestens so viel Kuchen bekommen hat, wie jede andere. Ein Algorithmus heißt neidfrei, wenn er immer eine neidfreie Verteilung ergibt. Ist Du teilst, ich wähle“ ein neidfreier Algorithmus? ” Ist die n-Personen-Verallgemeinerung neidfrei? 370 / 387 Successive-Pairs-Algorithmus Du teilst, ich wähle“-Algorithmus für n Personen: ” Wir entwerfen den Algorithmus sukzessive für steigende n. Bei n = 2 nehmen wir Du teilst, ich wähle“. ” ◮ Benutze (n − 1)-Version zwischen P1 und Pn−1 . ◮ ◮ Jeder Pi (1 ≤ i ≤ n − 1) teilt seinen Haufen durch weitere Schnitte in n gleiche Teile. Pn darf von jedem anderen Pi ein Teil wählen. Analyse: Korrektheit (für was?) ist klar. Aber was für ein Gekrümel? Ist das Gekrümel fair? Ist es neidfrei? 371 / 387 Aber was für ein Gekrümel? ◮ ◮ Habe ich bereits ein Gekrümel von x Stücken und will ich n gleichgroße Haufen erhalten, so benötige ich bis zu n − 1 weitere Schnitte. Rekursionsgleichung für die Anzahl der Schnitte: ◮ S(1) = 0, ◮ S(n) = (n − 1)2 + S(n − 1). Pn−1 2 (n−1)n(2n−1) ∈ Θ(n3 ) Schnitte und 1 Krümel mehr. i=1 i = 6 ◮ Maximale Schnittzahl ist also kubisch. Beispiel: S(8) = 140 372 / 387 Trimming ◮ P1 meldet Interesse und teilt möglicherweise ein Stück X des Kuchens ab. ◮ Nacheinander dürfen P2 bis Pn Interesse anmelden und bei Interesse das Stück X möglicherweise noch verkleinern. ◮ Der letzte, der Interesse angemeldet hat, bekommt das Stück. ◮ Die übrigen n − 1 Personen teilen den Rest rekursiv unter sich auf. Analyse: Einer bekommt ein n-tel des Kuchens. Die übrigen meinen, er hätte höchstens ein n-tel. Ergo: Es klappt! Die maximale Schnittanzahl quadratisch! S(n) = n(n − 1) 2 Beispiel: S(8) = 28 373 / 387 Moving Knife – Algorithmus n Personen wollen einen Kuchen teilen. ◮ Ein Messer fährt kontinuierlich von links nach rechts. ◮ Irgendwann ruft eine Person STOPP. ◮ Nun wird geschnitten, die Person bekommt den Teil links des Schnitts. ◮ Die übrigen n − 1 Personen teilen den Rest rekursiv unter sich auf. Wie realisiert man kontinuierliche Algorithmen? Analyse: Einer bekommt ein n-tel des Kuchens. Die übrigen meinen, er hätte höchstens ein n-tel. Ergo: Es klappt! Ist der Algorithmus neidfrei? 374 / 387 Untere Schranken Übung: 3 Personen, zwei Schnitte kann nicht fair sein. Denn: ? Trimming ist quadratisch, Das Gekrümel ist kubisch. Geht es besser? 375 / 387 Divide and Conquer Ziel: Θ(n log n) Algorithmus. Sei n > 1: P1 bis Pn−1 machen n − 1 vertikale Schnitte und jeder ist bereit, sein Stück links mit ⌊n/2⌋ Personen oder rechts vom Schnitt mit ⌈n/2⌉ Personen zu teilen. Beispiel: n = 5, dann mache sinnvollerweise einen 2 : 3-Schnitt Der wirkliche Schnitt ist der ⌊n/2⌋-te Schnitt von links. Wir haben also wieder zwei Stücke und Pn sucht sich einen Teil aus, von dem er ein Stück erhalten will. Die anderen werden dem Teil zugeordnet, in dem sich ihr Schnitt befindet. Die Person, die den Schnitt ⌊n/2⌋ verursacht hat, wird der anderen Seite als Pn zugeordnet. ⌊n/2⌋ bzw. ⌈n/2⌉ Personen teilen sich jeweils ein Stück, das jeder als genügend groß ansieht. Abbruch bei n = 1. 376 / 387 Zeit/Schnitt-Analyse ◮ Rekursionsgleichung für die Zeit bzw. Anzahl der Schnitte: ◮ S(1) = 0, ◮ S(n) = n − 1 + S(⌊n/2⌋) + S(⌈n/2⌉). ◮ ◮ ◮ ◮ Mastertheorem: S(n) ∈ O(n log n). Genauer: S(n) = nk − 2k + 1 mit k = ⌈log2 n⌉. Beweis folgt aus ⌈log2 ⌈n/2⌉⌉ = ⌈log2 ⌊n/2⌋⌉ = k − 1. Beispiel: n = 7, 8, 9, 10, . . . , 15, 16. ◮ S(7) = 14, S(8) = 17, S(9) = 20, S(10) = 23, . . . ◮ S(15) = 38, S(16) = 49. 377 / 387 Variationen ◮ Eigene Vorschläge für Erbengemeinschaften? ◮ oder zum Geburtstagskuchen teilen? ◮ Divide-and-Conquer-Moving-Knife ◮ Praktische Anwendungen? 378 / 387 Neidfrei für drei Personen, die ersten drei Schnitte Runde 1: ◮ P1 schneidet X in drei Teile. X = X1 + X2 + X3 ◮ Für P2 sei X1 das größte dieser Teile, X2 das zweitgrößte. ◮ P2 schneidet ein Stück E von X1 ab, und zwar so, dass Y = X1 − E für ihn gerade so groß ist wie X2 . ◮ Aus X1 − E , X2 und X3 wählen nacheinander P3 , P2 und P1 je eines aus, wobei P2 auf jeden Fall X1 − E nehmen muss, wenn es noch da ist. P1 erhält also ein unversehrtes Stück X1 , X2 oder X3 . Sicht von P1 : X2 = X3 ≥ Y + E ≥ Y . Sicht von P2 : Y = X2 ≥ X3 . Die erste Runde endet neidfrei! 379 / 387 Neidfrei für drei Personen, die beiden letzten Schnitte Runde 2: ◮ Die Person, die Y genommen hat, heisse nun R (Reststück). Das heißt, R ist entweder P2 oder P3 . Die andere dieser beiden Personen heiße Q. ◮ Die Akteure sind also R, P1 und Q. ◮ Q teilt E in drei Teile, von denen in der Reihenfolge R, P1 , Q gewählt wird. ◮ Q bleibt neidfrei, da sie geteilt hat. ◮ R bleibt neidfrei, da sie als erste ausgesucht hat. ◮ P1 hat vor Q gewählt, kann also höchstens auf R neidisch sein. Aber der der maximale Kuchenanteil ist Y + E ≤ X1 und schon die erste Runde ergab den Anteil X2 oder X3 für P1 . 380 / 387 22. Vorlesung, 28. Juni 2016 Thema: Mustererkennung in Texten Matiyasevich-Knuth-Morris-Pratt-Algorithmus (1971 / 1977) Üblicherweise nach Knuth-Morris-Pratt 1977 einfach KMP-Algorithmus genannt. MKMP wurde schon 1971 Yuri Matiyasevich entdeckt: Real-Time Recognition of the ” Inclusion Relation“ 1971 (russisch), 1973 (englische Übersetzung) 381 / 387 Problemstellung Bezeichnungen:Σ endliches Alphabet, u ≤ v Präfixrelation. Sei T = a0 a1 · · · an ein Text und M = b1 b2 · · · bm ein Muster mit ai , bj ∈ Σ für ein endliches Alphabet. Stets 0 < m und 1 ≤ n. Problem: ◮ ◮ ◮ Gilt T ∈ Σ∗ MΣ∗ ? Finde ein erstes Vorkommen von M in T . Finde alle Vorkommen von M in T . Lösungen: 1. Naive Lösungen sind quadratisch. 2. Man kann “automatisch” O(n + m · |Σ|) erreichen. Für |Σ| ∈ O(1) (also klein) ist dies ausreichend. 3. MKMP erreicht O(n + m). (Beachte, ohne Einschränkung |Σ| ≤ m.) 382 / 387 Endliche Automaten für Σ∗ MΣ∗ Die Sprache Σ∗ MΣ∗ ist regulär. Ein NEA hat nur m + 1 Zustände. Zustände sind die Präfixe p ∈ Q = { b1 · · · bj | j = 0, . . . , m } . Startzustand ist das leere Wort λ; wir raten das erste Vorkommen von M, laufen durch M, und akzeptieren im Endzustand M ∈ Q. IDEE: Bilde den zugehörigen DEA direkt. Wir behaupten, Q ist auch die Zustandsmenge des DEA zu Σ∗ MΣ∗ . Konstruktion vom DEA in der (Preprocessing-)Zeit O(m · |Σ|). Trick, da etwas übersichtlicher: Frage nur, ob T ∈ Σ+ MΣ∗ (bzw. T ∈ Σ+ M) ? (Denn M ≤ T ist trivial zu testen!) Dies führt auf die folgende Suffixfunktion für u ∈ Σ+ : s(u) = maximaler echter Suffix von u, der ein Präfix von M ist. Es gilt also immer u = vs(u), |s(u)| < |u| und s(u) ≤ M. 383 / 387 Konstruktion vom DEA mittels s(u) Vorbemerkung: s(u) wird als Index |s(u)| ∈ { 0, . . . , m − 1 } gespeichert. Dynamisches Programmieren: Bilde Tabelle S(p, a) = s(pa) für M 6= p ≤ M, also p = b1 · · · bj mit 0 ≤ j < m und a ∈ Σ. j = 0: Dann ist S(λ, a) = s(a) = λ. 0 < j: Den Suffix q = s(p) können wir der schon berechneten Tabelle entnehmen: Schreibe p = p ′ a′ , dann ist q = S(p ′ , a′ ). Ist qa ≤ M, dann gilt S(p, a) = qa, sonst gilt S(p, a) = S(q, a). Die Tabelle definiert einen DEA mit Zuständen { −1, 0, . . . , m } und (m + 1) |Σ| Kanten. Dies ist der minimale DEA für Σ+ M, wenn wir in −1 starten und mit m akzeptieren, aber er hat zu viele Kanten. 384 / 387 MKMP mit DEA und ε-Kanten DEA und ε-Kanten sind nicht üblich, aber wir betrachten sie trotzdem! Konvention: Für jeden Zustand p ∈ Q und Buchstaben a ist höchstens ein Folgezustand q = p · a definiert. Gibt es für ein p ein a, ohne dass p · a definiert ist, so ist zusätzlich genau eine ε-Kante (p, ε, q) definiert. Damit das Verfahren terminiert, sei Q linear geordnet mittels <. Wir verlangen, dass aus (p, ε, q) stets q < p folgt. Die ε-Kanten sind also Rückwärtskanten Die deterministische Übergangsregel ist jetzt wie folgt festgelegt: Annahme: Wir sind in Zustand p ∈ Q und a ist das nächste Eingabezeichen. 1.) Ist q = p · a definiert, so lese a und wechsle in den Zustand q. 2.) Ist p · a nicht definiert, so wechsle ohne a zu lesen in Zustand q, indem man der Rückwärtskante (p, ε, q) folgt. Besonderheit bei uns: Es wird nur |Σ| + 2m + 1 Kanten geben. 385 / 387 Konstruktion des MKMP-ε DEA ◮ ◮ ◮ ◮ ◮ Zustände: { −1, 0, . . . , m } = { −1 } ∪ { p ∈ Σ∗ | p ≤ M }. (−1) · a = 0 = λ für alle a ∈ Σ. p · a = pa, falls pa ≤ M. (0, ε, −1). (p, ε, s(p)) für alle λ 6= p ≤ M. On-the-fly Konstruktion der ε-Kanten (p, ε, s(p)). Für p = −1 gibt es keine ε-Kanten. Für p = λ gibt es (0, ε, −1). Sei jetzt λ 6= p ≤ M und (r , ε, s(r )) für alle 0 ≤ r < p schon definiert. Schreibe p = ra für ein a ∈ Σ. Folge jetzt solange wie möglich ε-Kanten s(r ), ss(r ), . . . bis schließlich für ein k ≥ 1 gilt, dass s k (r ) · a definiert ist. Dies definiert die Kante (pa, ε, s k (r ) · a). Definiere ein Gewicht durch 2(m − p) + q falls (p, ε, q) existiert. Wir starten mit dem Gewicht 2(m + 1) und jedes Durchlaufen einer Kante verringert das Gewicht. Also kann der MKMP-ε DEA in der Zeit O(m + |Σ|) konstruiert werden. 386 / 387 MKMP mit DEA und ε-Kanten Korrektheit: Beachte, wenn wir a0 a1 · · · an lesen, sind wir nach dem Lesen von Zeichen an im Zustand s(a0 a1 · · · an ). Laufzeit: Sei a0 a1 · · · an die Eingabe; eine Konfiguration besteht aus der Resteingabe aj · · · an und einem Zustand q mit 0 ≤ q ≤ m. Vergebe das Gewicht 2(n − j) + q. Jedes Durchlaufen einer Kante verringert das Gewicht. Initial ist es 2n + 2. Maximale Laufzeit daher 2n + 2. Zeitanalyse bei Konstruktion vom DEA in der Zeit O(m) war analog. 387 / 387