Modul: Algorithmik SS 2016 - Institut für Formale Methoden der

Werbung
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
Herunterladen