Skript, Version 0.6 - Parallel Computing

Werbung
Graphenalgorithmen und
lineare Algebra Hand in Hand
Henning Meyerhenke
1. September 2014
iii
Inhaltsverzeichnis
1. Grundlegende Graphenalgorithmen
1.1. Dualität zwischen Graphen und Matrizen . . . . . . . . .
1.2. Starke Zusammenhangskomponenten . . . . . . . . . . . .
1.2.1. Definition . . . . . . . . . . . . . . . . . . . . . . .
1.2.2. Algorithmus . . . . . . . . . . . . . . . . . . . . . .
1.2.3. Konvergenz . . . . . . . . . . . . . . . . . . . . . .
1.3. Kürzeste Wege . . . . . . . . . . . . . . . . . . . . . . . .
1.3.1. Definitionen . . . . . . . . . . . . . . . . . . . . . .
1.3.2. Algorithmus von Bellman und Ford . . . . . . . . .
1.3.3. Paarweise kürzeste Distanzen . . . . . . . . . . . .
1.3.4. Paarweise kürzeste Wege mit dem Algorithmus von
1.4. Nicht erweiterbare unabhängige Mengen . . . . . . . . . .
1.5. Weiterführende Literatur . . . . . . . . . . . . . . . . . . .
.
.
.
.
.
.
.
.
.
.
.
.
1
2
4
4
5
6
6
6
7
9
14
20
24
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
25
25
25
26
26
26
26
27
27
27
29
29
30
30
32
32
32
33
34
35
35
36
38
39
3. Clusteranalyse von Graphen
3.1. Label Propagation . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
3.1.1. Der Algorithmus . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
41
41
41
. . . .
. . . .
. . . .
. . . .
. . . .
. . . .
. . . .
. . . .
. . . .
Seidel
. . . .
. . . .
2. Datenstrukturen für dünn besetzte Matrizen
2.1. Cache-Effizienz . . . . . . . . . . . . . . . . . . . . . . . . . . .
2.1.1. I/O-Modell . . . . . . . . . . . . . . . . . . . . . . . . .
2.1.2. Modell-Annahmen . . . . . . . . . . . . . . . . . . . . .
2.1.3. Grundlegende Algorithmen im I/O-Modell . . . . . . . .
2.2. Grundlegende Matrix-Operationen . . . . . . . . . . . . . . . .
2.2.1. Teilmatrizen addressieren (SpRef/SpAsgn) . . . . . . . .
2.2.2. Matrix-/Vektormultiplikation (SpMV) . . . . . . . . . .
2.2.3. Addition dünner Matrizen (SpAdd) . . . . . . . . . . . .
2.2.4. Sparse matrix-sparse matrix multiplication (SpGEMM)
2.3. Tripel . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
2.3.1. Ungeordnete Tripel . . . . . . . . . . . . . . . . . . . . .
2.3.2. Zeilenweise geordnete Tripel . . . . . . . . . . . . . . . .
2.3.3. Zeilendominant geordnete Tripel . . . . . . . . . . . . .
2.4. CSR/CSC . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
2.4.1. CSR und Adjazenzlisten . . . . . . . . . . . . . . . . . .
2.4.2. Grundoperationen mit CSR . . . . . . . . . . . . . . . .
2.5. Multiplikation dünn besetzter Matrizen . . . . . . . . . . . . .
2.5.1. Der Sparse Accumulator . . . . . . . . . . . . . . . . . .
2.5.2. SpGEMM mit CSR . . . . . . . . . . . . . . . . . . . . .
2.6. Hyperdünne Matrizen . . . . . . . . . . . . . . . . . . . . . . .
2.7. DCSC . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
2.8. Multiplikation hyperdünner Matrizen . . . . . . . . . . . . . . .
2.9. Weiterführende Literatur . . . . . . . . . . . . . . . . . . . . . .
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
iv
Inhaltsverzeichnis
3.2.
3.3.
3.4.
3.5.
3.1.2. Probleme . . . . . . . . . . . . . . . . . . . . . . . .
3.1.3. Komplexität . . . . . . . . . . . . . . . . . . . . . . .
3.1.4. Algebraische Formulierung . . . . . . . . . . . . . . .
Markov Clustering . . . . . . . . . . . . . . . . . . . . . . .
3.2.1. Konvergenz des Markov Clustering Algorithmus . . .
3.2.2. Zusammenhänge zwischen Graphen und Eigenwerten
Random Walks als Analysewerkzeug . . . . . . . . . . . . .
Bildsegmentierung mit spektraler Clusteranalyse . . . . . .
3.4.1. Graphrepräsentation von Bildern . . . . . . . . . . .
3.4.2. Optimierungsproblem . . . . . . . . . . . . . . . . .
3.4.3. Relaxiertes Optimierungsproblem . . . . . . . . . . .
3.4.4. Laufzeit des NCut-Algorithmus . . . . . . . . . . . .
3.4.5. Verallgemeinerung auf k Segmente . . . . . . . . . .
Weiterführende Literatur . . . . . . . . . . . . . . . . . . . .
4. Visualisierung von Graphen
4.1. Spektrales Zeichnen . . . . . . . . . . . . . . . . . . . . .
4.2. Kräftegesteuertes Zeichnen . . . . . . . . . . . . . . . . . .
4.2.1. Quadtree-Datenstruktur . . . . . . . . . . . . . . .
4.2.2. Multilevel-Verfahren für kräftegesteuertes Zeichnen
4.3. Weiterführende Literatur . . . . . . . . . . . . . . . . . . .
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
42
43
44
46
47
49
51
51
52
52
53
53
54
55
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
57
57
58
60
61
62
5. Lastbalancierung paralleler Berechnungen
5.1. Parallelität . . . . . . . . . . . . . . . . . . . . . . . . . . . .
5.2. Dynamische Balancierung unabhängiger Lasten . . . . . . . .
5.2.1. Das Diffusionsverfahren erster Ordnung (FOS) . . . .
5.2.2. Weitere Verfahren zur dynamischen Lastbalancierung .
5.3. Balancierung abhängiger Lasten mittels Graphpartitionierung
5.3.1. Bubble-Framework . . . . . . . . . . . . . . . . . . . .
5.3.2. Gestörte Diffusion (FOS/C) . . . . . . . . . . . . . . .
5.3.3. Bubble-FOS/C . . . . . . . . . . . . . . . . . . . . . .
5.3.4. Theoretische Ergebnisse zu Bubble-FOS/C . . . . . .
5.3.5. DibaP . . . . . . . . . . . . . . . . . . . . . . . . . . .
5.4. Weiterführende Literatur . . . . . . . . . . . . . . . . . . . . .
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
63
63
63
63
66
67
68
69
70
71
74
74
6. Ausdünnung von Graphen und Laplace-Löser
6.1. Schnitterhaltende Ausdünnung von Graphen . . . .
6.1.1. Definitionen . . . . . . . . . . . . . . . . . .
6.1.2. Der Sampling-Prozess . . . . . . . . . . . .
6.1.3. Konzentration um den Erwartungswert . . .
6.1.4. Das Hauptresultat . . . . . . . . . . . . . .
6.2. Spektrale Approximation . . . . . . . . . . . . . . .
6.2.1. Definitionen . . . . . . . . . . . . . . . . . .
6.2.2. Graphen und elektrische Netzwerke . . . . .
6.2.3. Algorithmus und Beweis des Haupttheorems
6.3. Kombinatorische Löser für Laplace-Systeme . . . .
6.3.1. Grundidee . . . . . . . . . . . . . . . . . . .
6.3.2. Flüsse, Energie und Baumzyklen . . . . . .
6.3.3. Der Algorithmus SimpleSolver . . . . . . . .
6.3.4. Konvergenz des Algorithmus . . . . . . . . .
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
75
75
75
76
77
79
81
81
82
83
86
86
86
89
90
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
Inhaltsverzeichnis
6.3.5. Beweis des Haupttheorems . . . . . . . . . . . . . . . . . . . . . . . . . . .
6.4. Weiterführende Literatur . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
v
93
94
Literaturverzeichnis
94
A. Anhang
A.1. Grundlagen der linearen Algebra . . . . . . . . . . . . . . . . . . . . . . . . . . .
A.1.1. Spektrale Zerlegung einer symmetrischen Matrix . . . . . . . . . . . . . .
97
97
99
vii
Vorwort
Dieses Skript basiert im Wesentlichen auf der Vorlesung Graphenalgorithmen und lineare Algebra
Hand in Hand, die ich im Sommersemester 2014 am Karlsruher Institut für Technologie (KIT)
gehalten habe. Es sind jedoch teilweise zusätzlich Inhalte aus meinen anderen Vorlesungen bearbeitet worden und hier eingeflossen, u. a. aus Vorläuferskripten zu Vorlesungen von Robert
Elsässer bzw. von Burkhard Monien an der Universität Paderborn.
Das Skript erhebt keinen Anspruch auf Vollständigkeit, es ergänzt lediglich die
Folien zur Vorlesung. Nehmen Sie zur Prüfungsvorbereitung auf jeden Fall sowohl
Skript als auch Folien zur Hand. Beides zusammen ist wiederum nicht als Ersatz
zum Besuch der Vorlesung gedacht, sondern als Hilfestellung bei der notwendigen
Vor- und Nachbereitung. Sollten Sie auf Fehler stoßen, bitte ich um einen entsprechenden
Hinweis. Auch für Verbesserungsvorschläge bin ich sehr dankbar.
Mein großer Dank gilt den studentischen Hilfskräften Lukas Hartmann und Michael Wegner.
Beide waren maßgeblich an der Anfertigung des Skriptes beteiligt.
Karlsruhe, im Sommer 2014
Henning Meyerhenke
ix
Versionen
Version 0.1
• Allgemein: Struktur der Vorlesung im Skript nachvollziehbar, auch wenn Inhalte fehlen
• Kapitel 1 im Wesentlichen vollständig, beinhaltet auch den Algorithmus von Seidel, der
nicht Teil der aktuellen Vorlesung (SS 2014) ist
• Kapitel 1: Algorithmus von Seidel vorhanden, aber noch nicht gründlich auf Fehler überprüft
• Kapitel 5: Dynamische Lastbalancierung mit Diffusion im Wesentlichen vollständig
• Kapitel 5: Diffusionsbasierte Partitionierung nur in Ansätzen vorhanden (mehr folgt in
Version 0.2.1)
Versionen 0.2, 0.2.1. und 0.2.2 (15. bis 17. Juli 2014)
• Kapitel 5: Enthält eine leicht erweiterte Fassung zur Diffusion
• Kapitel 5: Diffusionsbasierte Partitionierung deutlich erweitert
• Kapitel 6: Schnitterhaltende Ausdünnung
Version 0.3 (23. Juli 2014)
• Kapitel 6: Spektrale Ausdünnung, kombinatorischer Laplace-Löser sind nun enthalten. Weitere Verbesserungen in der Darstellung sind erst für spätere Versionen geplant.
Version 0.4 und 0.4.1 (31. Juli und 4. August 2014)
• Kapitel 2
Version 0.5 (6. August 2014)
• Kapitel 3
Version 0.6 (1. September 2014)
• Kapitel 4
Version 0.6.1 (Mitte/Ende September 2014)
• Verbesserungen, Korrekturen der eingereichten Fehler
1
1. Grundlegende Graphenalgorithmen
In dieser Vorlesung werden Sie eine Reihe von Algorithmen kennenlernen, die auf Graphen operieren. Ein Graph modelliert allgemein gesprochen eine Menge von Entitäten (dargestellt als
Knoten) und die Beziehungen der Entitäten (dargestellt durch Kanten).
Definition. Ein Algorithmus ist eine eindeutige Beschreibung eines Verfahrens zur Lösung einer
bestimmten Klasse von Problemen.
Genauer gesagt ist ein Algorithmus eine Menge von Regeln für ein Verfahren, um aus gewissen
Eingabegrößen bestimmte Ausgabegrößen herzuleiten. Dabei muss dass Verfahren in einem endlichen Text beschreibbar sein. Jeder Schritt dieses Verfahrens muss auch tatsächlich ausführbar
sein und darüber hinaus muss der Ablauf des Verfahrens zu jedem Zeitpunkt eindeutig definiert
sein.
Hier einige typische Beispielprobleme, in denen Graphenalgorithmen eine wichtige Rolle spielen:
• Wie findet ein Navigationssystem gute Verbindungen zwischen zwei Orten?
• Wie werden im Internet Informationen geroutet?
• Wie berechnet ein Unternehmen eine möglichst gute Aufteilung seiner Ressourcen, um
seinen Gewinn zu maximieren?
• Wie finden Suchmaschinen Informationen schnell wieder?
Um über die Qualität eines Algorithmus urteilen zu können, bedarf es bestimmter Kriterien, um
entsprechende Urteile treffen zu können.
1. Algorithmen müssen korrekt sein. D.h. zu jedem Algorithmus gehört ein Korrektheitsbeweis, der in allgemeiner Form die Korrektheit der Berechnung der Ausgabegröße zu einer
gegebenen Eingabegröße zeigt.
2. Algorithmen sollen zeit- und speichereffizient sein. Hierzu bedarf es Analysemethoden für
den Zeit- und Speicherbedarf eines Algorithmus. Diese Analyse basiert in der klassischen
Algorithmik nicht auf empirischen Untersuchungen, sondern auf mathematischen Analysen.
Wir nutzen hierfür Pseudocode und Basisoperationen.
Zum Entwurf eines Algorithmus gehören im Allgemeinen grundsätzlich drei Dinge:
1. Die Beschreibung des Algorithmus selbst in Pseudocode.
2. Ein vollständiger Korrektheitsbeweis.
3. Die Analyse des Zeit- und Speicherbedarfs des Algorithmus.
In dieser Vorlesung (und somit auch in diesem Skript) wird aus Zeitgründen bei einigen Inhalten
teilweise auf eine detaillierte Darstellung der obigen drei Punkte verzichtet. Diese Darstellung
ist dann üblicherweise in der angegebenen Literatur zu finden.
2
1. Grundlegende Graphenalgorithmen
1.1. Dualität zwischen Graphen und Matrizen
Für viele Graphenalgorithmen ist es vorteilhaft, die Dualität zwischen Graphen und ihren dazugehörigen Matrizen auszunutzen. Graphenalgorithmen können so zu Sequenzen von einfachen
algebraischen Operationen umgeschrieben werden, meist Multiplikationen einer Matrix mit einem Vektor. In diesem Abschnitt werden die wichtigsten Verbindungen der beiden Konzepte
vorgestellt.
Grundlegend ist die Darstellung eines Graphen durch seine Adjazenzmatrix.
Definition 1.1. Sei G = (V, E) ein ungewichteter Graph mit |V | = n. Die Adjazenzmatrix A
ist eine n × n-Matrix, definiert durch:
(
1, die Knoten i und j sind adjazent
Aij =
0, sonst.
Betrachte als Beispiel den ungerichteten Graphen G aus Abbildung 1.1.1 und die zugehörige
Adjazenzmatrix A.

0
1
A= 
0
1
1
0
1
1
0
1
0
1

1
1

1
0
Abbildung 1.1.1.: Ungerichteter Graph G = (V, E) und die zugehörige Adjazenzmatrix A
Eine weitere wichtige Verbindung besteht zwischen der Matrix-Vektor-Multiplikation und der
Breitensuche (BFS). Sei ek ∈ Rn der k-te Einheitsvektor (d.h. alle Einträge bis auf die k-te Stelle
haben den Wert null). Dann gilt: (AT ek )i = 1 genau dann, wenn der Knoten i vom Knoten k
durch einen Schritt der Breitensuche erreichbar ist. Beachten Sie dabei, dass die transponierte
Adjanzenzmatrix verwendet werden muss. Die Multiplikation mit ek „wählt” die Einträge der
k-ten Spalte von AT , also die Einträge der k-ten Zeile von A aus. Ein Eintrag aki in der k-ten
Zeile von A ist nach Definition genau dann 1, wenn k und i durch eine Kante verbunden sind,
also der Knoten i in einem Breitensuchschritt von k erreichbar ist.
Wir werden nun die Prinzipien der gewöhnlichen Matrix-Vektor-Multiplikation auf einen Halbring erweitern.
Definition 1.2. Ein Halbring ist eine Menge M mit zwei binären Verknüpfungen + und ∗,
genannt Addition und Multiplikation, sodass für alle x, y, z ∈ M gilt:
• Addition und Multiplikation besitzen je ein neutrales Element 0 bzw. 1.
• x + (y + z) = (x + y) + z (Addition ist assoziativ)
• x ∗ (y ∗ z) = (x ∗ y) ∗ z (Multiplikation ist assoziativ)
• x + y = y + x (Addition ist kommutativ)
• x ∗ (y + z) = x ∗ y + x ∗ z und (x + y) ∗ z = x ∗ z + y ∗ z (Distributivität)
• 0∗x=x∗0=0
1.1. Dualität zwischen Graphen und Matrizen
3
Die ganzen Zahlen Z und die reellen Zahlen R bilden bezüglich der gewöhnlichen Addition
und Multiplikation einen Halbring. Fügen wir +∞ zu Z oder zu R hinzu, so erhalten wir einen
Halbring bezüglich der Verknüpfungen ” min ” als Addition und ” + ”als Multiplikation. Lineare
Algebra über diesem Halbring ist oft nützlich, um Kürzeste-Wege-Probleme zu lösen. Wir werden
nun Vektor- und Matrix-Operationen auf einem allgemeinen Halbring (Rn , +, ∗) definieren.
Definition 1.3. Seien c ∈ R, v ∈ Rm , w ∈ Rn und A = (aij )ij ∈ Rm×n .
• Die Addition mit einem Skalar c + v wird punktweise ausgeführt, d.h.
c + v = (c + v1, . . . , c + vn ).
• Das dyadische ( manchmal: äußere) Produkt v ◦ w ist eine m × n-Matrix definiert durch
(v ◦ w)ij = vi ∗ wj .
• Ist m = n, so ist das innere Produkt oder Skalarprodukt v · w definiert durch
X
v·w =
vi ∗ wi = (v1 ∗ w1 ) + · · · + (vn ∗ wn ).
i
• Das Matrix-Vektor-Produkte v T A ∈ Rn und Aw ∈ Rm ist gegeben durch
X
X
(v T A)k =
vi ∗ aik bzw. (Aw)k =
aki ∗ wi .
i
i
.
In einem gegebenen Halbring, der nicht die gewöhnliche Addition und Multiplikation besitzt,
werden wir die Matrix-Vektor-Multiplikation Aw auch als A + . ∗ w darstellen, z. B. A min . + w
für die Multiplikation bezüglich ” min ” und ” + ”. A min . + w ist dann ein n-dimensionaler
Vektor, dessen i-ter Eintrag gerade min(Aij + wj ; 1 ≤ j ≤ n) ist.
Definition 1.4. Seien A = (aij )ij und B = (bij )ij Matrizen.
• Die Addition mit einem Skalar c + A wird punktweise ausgeführt, d.h.
(c + A)ij = c + aij .
• Seien A ∈ Rm×n ,v ∈ Rm und w ∈ Rn , so sind die punktweisen Matrix-Vektor-Produkte v.∗A
und A. ∗ w Matrizen in Rm×n gegeben durch
(v. ∗ A)ij = vi ∗ aij bzw. (A. ∗ w)ij = wj ∗ aij .
• Sind A, B ∈ Rm×n , so ist das punktweise Matrizenprodukt A. ∗ B von A und B eine Matrix
in Rm×n mit (A. ∗ B)ij = aij ∗ bij . Analog definiere auch andere punktweise Operationen,
wie A. + B.
m×n und B ∈ Rn×p , dann ist das Matrizenprodukt AB ∈ Rm×p definiert durch
• Sind A ∈ R
P
(AB)ij = k aik ∗ bkj .
Auch beim Matrizenprodukt werden wir die Schreibweise A + . ∗ B benutzen, wenn wir die
gegebenen Verknüpfungen explizit nennen möchten.
4
1. Grundlegende Graphenalgorithmen
Mit Hilfe eines Halbrings lassen sich nun viele Graphenalgorithmen einfach durch Matrizen
darstellen. So kann im Bellman-Ford-Algorithmus (siehe Abschnitt 1.3.2) für kürzeste Wege die
Aktualisierung des Distanzvektors d als Multiplikation mit der Adjazenzmatrix A als
d ← d min . + A
geschrieben werden. Ein weiteres Anwendungsbeispiel ist die Bestimmung von Teilgraphen, welches sich mit Hilfe der Adjazenzmatrix auf ein Zeilen- und Spalten-Auswahlproblem zurückführen
lässt. Sei dazu v ∈ Rn und diag(v) die Diagonalmatrix mit Dimension n × n, deren Einträge
gerade die Werte von v sind. Dann können wir eine (gewichtete) Zeilen- oder Spaltenauswahl
durch Matrizenmultiplikationen, bezüglich der gewöhnlichen Addition und Multiplikation, folgendermaßen darstellen:
• Zeile auswählen: diag(u) A
• Spalte auswählen: A diag(v)
• Zeile und Spalte auswählen: diag(u) A diag(v)
Als letztes Beispiel geben wir die Berechnung der Zeilen- und der Spaltensumme einer Matrix an.
Sei A = (aij )ij ∈ Rm×n eine Matrix und u = (1, . . . , 1) ∈ Rm und v = (1, . . . , 1) ∈ Rn Vektoren
mit Einträgen 1. Dann ist Av ein Vektor und es gilt
X
X
(Av)i =
aik vk =
aik ,
k
k
d.h. der Eintrag (Av)i ist die Summe der Einträge der i-ten Zeile von A. Analog folgt, dass (uA)j
gerade die Summe der Einträge der j-ten Spalte von A ist.
1.2. Starke Zusammenhangskomponenten
1.2.1. Definition
Definition 1.5. Ein (möglicherweise) gerichteter Multigraph ist ein Paar G = (V, E) aus einer
endlichen Menge V von Knoten und einer Multimenge E ⊆ V × V von Kanten.
Eine Kante e ∈ {(v, v)|v ∈ V } heißt Schleife. Kanten e ∈ E mit #e = k > 1 (Mehrfachauftreten) heißen Multikanten. Einen Multigraphen, der weder Schleifen noch Multikanten besitzt,
nennen wir schlicht.
Wir werden nun den Zusammenhang und darauf aufbauend Zusammenhangskomponenten
eines Graphen definieren.
Definition 1.6. Sei G = (V, E) ein Multigraph.
• G heißt stark zusammenhängend, wenn für jedes Paar (u, v) ∈ V ×V sowohl ein (gerichteter)
(u, v)-Weg, als auch ein (v, u)-Weg in G existiert.
• G heißt (schwach) zusammenhängend, wenn der zu G gehörige Multigraph stark zusammenhängend ist.
Sei G nun ein ungerichteter Multigraph.
• G heißt k-fach zusammenhängend, falls jeder durch Entfernen von höchstens k − 1 Knoten
(und aller inzidenten Kanten) aus G entstehende Teilgraph zusammenhängend ist.
1.2. Starke Zusammenhangskomponenten
5
• G heißt k-fach kantenzusammenhängend, falls jeder durch das Entfernen von höchstens
k − 1 beliebigen Kanten aus G entstehende Teilgraph zusammenhängend ist.
Definition 1.7. Zu einem schlichten Multigraphen G heißt ein maximaler stark zusammenhängender Teilgraph starke Zusammenhangskomponente.
Analog definieren wir eine schwache, k-fach zusammenhängende bzw. k-fach kantenzusammenhängende Zusammenhangskomponente.
Ein Beispiel für starke Zusammenhangskomponenten kann unter folgender Adresse gefunden
werden: http://www.cs.berkeley.edu/~vazirani/s99cs170/notes/lec12.pdf
1.2.2. Algorithmus
Wir möchten nun einen Algorithmus entwickeln, um starke Zusammenhangskomponenten in
einem gegebenen Graphen zu finden. Als Grundidee benutzen wir das nachfolgende Resultat:
Theorem 1.8. Sei A die Adjazenzmatrix des Graphen G. Dann ist (Ak )ij die Anzahl der Wege
der Länge k zwischen den Knoten i und j.
Beweis. Wir beweisen das Theorem mittels Induktion über k. Für k = 1 ist ein Weg der Länge
1 genau eine Kante und damit gilt die Aussage nach Definition der Adjazenzmatrix. Sei nun die
Aussage für ein k bewiesen. Dann gilt:
X
(Ak+1 )ij =
Ail (Ak )lj .
l
Also ist (Ak+1 )ij die Summe aus der Zahl der Kanten von i nach l und dann (nach Induktionsvoraussetzung) der Wege der Länge k von l nach j. Die Kante von i nach l verlängert somit
den Weg um 1, also gibt (Ak+1 )ij die Anzahl der Wege der Länge k + 1 von i nach j an.
Sei nun die Matrix C mittels punktweiser oder-Funktion definiert als
C = I ∨ A ∨ A2 ∨ A3 ∨ A4 ∨ . . .
Nach Theorem 1.8 ist Cij genau dann 6= 0, wenn ein Pfad beliebiger Länge zwischen den
Knoten i und j existiert. Beachten Sie dabei, dass wir hier auch triviale Wege der Länge 0
zulassen. Analog enthält C T somit einen Eintrag (C T )ij 6= 0 genau dann, wenn ein Pfad zwischen
j und i existiert. Für C ∧ C T gilt folglich, dass (C ∧ C T )ij genau dann 6= 0 ist, wenn die Knoten
i und j in der gleichen starken Zusammenhangskomponente liegen. Ist die Adjazenzmatrix A
symmetrisch, so gilt auch C = C T und somit liefert uns die Matrix C bereits alle benötigten
Informationen.
Wir verwenden allerdings im Folgenden statt der Oder-Verknüpfung die Addition und definieren die Matrix D als
D = I + A + A2 + A3 + A4 + . . . .
Der Grund für die Verwendung der Addition statt der Oder-Verknüpfung liegt in der einfacheren Umformbarkeit und wird nachfolgend klar. Es gilt nun Dij = 0 ⇔ Cij = 0 und somit auch
Dij 6= 0 genau dann, wenn die Knoten i und j durch einen Pfad verbunden sind. Weiterhin gilt
mit F = (I − A)D:
F = D −AD
=
=
I
I
+A + A2 + A3 + A4 + . . .
−A − A2 − A3 − A4 − . . .
6
1. Grundlegende Graphenalgorithmen
Das bedeutet, dass D = (I − A)−1 gilt und sich so die benötigte Matrix D berechnen lässt.
Allerdings konvergiert die Reihe D häufig nicht.
1.2.3. Konvergenz
Um die Konvergenz der Reihe D zu erhalten, wandeln wir die Reihe etwas ab. Sei α > 0 und
definiere D0 als
D0 = I + (αA) + (αA)2 + (αA)3 + (αA)4 + . . .
Die Matrix D0 besitzt noch immer die gewünschten Eigenschaften und für hinreichend kleines
α konvergiert die Reihe. Wie α gewählt werden muss, wird in der nachfolgenden Aufgabe geklärt.
Aufgabe 1.9. Die Zeilensummennorm einer Matrix A ist definiert als
kAk∞ = max
i=1,...,n
n
X
k=1
|aik |.
Es gilt: kBAk∞ ≤ kBk∞ kAk∞ für Matrizen A und B ∈ Rn×n (sogar noch allgemeiner). Außerdem gilt kα · Ak∞ = |α| · kAk∞ für α ∈ R.
Leiten Sie eine passende Wahl von α her, so dass die Reihe limk→∞
Sie können z. B. das Quotientenkriterium von d’Alembert anwenden.
Pk
i=0 α
i Ai
konvergiert!
2
kAk∞
1
Beweis. Wenn α < kAk
, dann folgt: kα2 A2 k∞ = |α|2 kAk2∞ < kAk
= 1. Dies gilt auch für
2
∞
∞
alle weiteren Reihenglieder. Also folgt nach dem Quotientenkriterium von d’Alembert, dass die
Reihe konvergiert.
Sei daher nun 0 < α <
1
kAk∞ .
Setzen wir F 0 = (I − αA)D0 , dann ergibt sich:
F 0 = D0 −αAD0
=
=
I
I
+(αA) + (αA)2 + (αA)3 + (αA)4 + . . .
−(αA) − (αA)2 − (αA)3 − (αA)4 + . . .
Also gilt D0 = (I − αA)−1 , wobei D0 konvergiert. Wir können nun D0 berechnen und zusammenfassend gilt (D0 + D0T )ij 6= 0 genau dann, wenn die Knoten i und j in der selben starken
Zusammenhangskomponente liegen.
1.3. Kürzeste Wege
1.3.1. Definitionen
In diesem Abschnitt betrachten wir das Problem kürzester Wege in gerichteten Graphen mit
Kantengewichten. In einem unidirektionalen, zusammenhängenden Graphen G = (V, E) mit
V = {1, . . . , n} und |E| = m als Eingabegrößen soll als Ausgabegröße für jedes Paar von Knoten
u, v ∈ V die Distanz von u nach v, sowie ein kürzester Weg zwischen den beiden Knoten im
Graphen G berechnet werden.
Definition 1.10. Sei ein gerichteter und gewichteter Graph G = (V, E) mit der Gewichtsfunktion w : E → R gegeben. Das Gewicht eines Weges P = hv0 , v1 , . . . , vk i ist die Summe der
1.3. Kürzeste Wege
7
Abbildung 1.3.1.: Unidirektionaler, gewichteter Graph G = (V, E)
Gewichte seiner Kanten:
w(P ) =
k
X
w(vi−1 , vi ).
i=1
Definition 1.11. Das Gewicht eines kürzesten Weges P in einem gerichteten und gewichteten
Graphen G = (V, E) zwischen den Knoten u, v ∈ V ist definiert als:
(
min{w(P ) : v ist von u über P erreichbar},
δ(u, v) =
∞, falls v von u nicht erreichbar ist.
Ein kürzester Weg zwischen u, v ∈ V ist dann ein Weg P mit w(P ) = δ(u, v).
Die Eingabe wird als Gewichtsmatrix W = (wij )ij
Die Matrix-Einträge wij sind wie folgt definiert:


0
wij = Gewicht der ger. Kante (i, j)


∞
dargestellt, die den Graphen repräsentiert.
, wenn i = j
, wenn i 6= jund (i, j) ∈ E
, wenn i =
6 jund (i, j) ∈
/E
Aus dieser Definition folgt für den Graphen G aus Abbildung 1.11 die Gewichtsmatrix wij ,
abgebildet in der nachfolgenden Tabelle.
Tabelle 1.1.: Gewichtsmatrix W
a
b
a 0
2
b ∞ 0
c ∞ ∞
d ∞ -4
e ∞ ∞
f ∞ ∞
zum
c
∞
4
0
6
8
∞
Graphen
d
e
5 ∞
∞ ∞
1 ∞
0
5
∞ 0
∞ ∞
G aus Abbildung 1.11
f
∞
∞
7
∞
-1
0
1.3.2. Algorithmus von Bellman und Ford
Der Algorithmus von Bellman und Ford berechnet von einem gegebenen Startknoten s ∈ V
die kürzesten Wege in G (single-source shortest paths). Dabei wird auch erkannt, ob in G ein
negativer Kreis existiert. In diesem Fall ist eine Berechnung nicht möglich und der Algorithmus
bricht mit einer Fehlermeldung ab. Somit ist dieser Algorithmus im Gegensatz zu Dijkstras Algorithmus auch verwendbar, wenn der Eingabegraph negative Kantengewichte hat. Der komplette
Algorithmus ist in Algorithmus 1 darstellt.
8
1. Grundlegende Graphenalgorithmen
Für jeden Knoten v ∈ V wird in d(v) das Gewicht des bisher gefundenen kürzesten Weges von
s nach v gespeichert. Initial setzen wir d(v) = ∞ für v ∈ V \ {s} und d(s) = 0. Der Algorithmus
führt nun eine Reihe von Kantenrelaxierungen aus. Wird eine Kante e = (u, v) relaxiert, so wird
überprüft, ob durch e ein besserer, d.h. kürzerer, Weg von s nach v verläuft. Wir setzen also
d(v) ← min {d(v), d(u) + wuv } .
Der Algorithmus besteht aus n − 1 Runden, in denen jeweils alle Kanten (in einer beliebigen
Reihenfolge) relaxiert werden. Können die bis jetzt berechneten Distanzen nochmals verbessert
werden, so existiert ein negativer Kreis im Graphen. Andernfalls gilt nach Berechnung die gewünschte Eigenschaft δ(s, v) = d(v).
Um nicht nur das Gewicht des kürzesten Weges von s nach v zu erhalten, wird zusätzlich der
Vaterknoten π(v) von v gespeichert, der vor v auf dem kürzesten Weg von s nach v liegt. Somit
kann der kürzeste Weg rekonstruiert werden.
Algorithmus 1 : Bellman-Ford
Input : Graph G = (V, E), Gewichtsfunktion w, Startknoten s
Output : Distanz des kürzesten Wegs d(v), Vaterknoten π(v) (für v ∈ V )
1 foreach v ∈ V do
2
d(v) ← ∞
3
π(v) ← N IL
4
5
6
7
8
9
10
11
12
d(s) ← 0
for k = 1 to n-1 do
foreach (u, v) ∈ E do
if d(v) > d(u) + wij then
d(v) ← d(u) + wij
π(v) ← u
// Relaxierung der Kante (u, v)
foreach (u, v) ∈ E do
if d(v) > d(u) + wij then
return Negativer Kreis existiert!
Wir möchten nun den Algorithmus mit algebraischen Mitteln formulieren. Wir definieren dazu
(
min {w(P ) : P ist Pfad von unach vmit |P | ≤ k}
δk (u, v) =
∞,
sonst
als die Länge des kürzesten Weges zwischen u und v, der höchstens k Kanten benutzt. Falls
δn (s, v) < δn−1 (s, v) für einen beliebingen Knoten v ∈ V gilt, dann gibt es einen Zyklus negativer
Länge. Andernfalls gilt δ(s, v) = δn−1 (s, v) . Die Berechnung von δk (s, v) mittels δk−1 (s, v) ist
äquivalent zur Relaxierung aller zu v inzidenten Kanten. Insbesondere gilt somit
δk (s, v) = min {δk−1 (s, u) + wuv } .
u∈N (v)
Wir stellen ferner fest, dass δk alleine mit Hilfe von δk−1 und der gegebenen Gewichtsmatrix W
berechnet werden kann. Alle vorher berechneten δi können folglich gelöscht werden. Sei dk ∈ Rn
nun ein Vektor zum Speichern der Informationen von δk , d.h. es gilt dk (v) = δk (s, v). Dann lässt
1.3. Kürzeste Wege
9
sich dk und somit δk mittels Matrix-Vektor-Multiplikation berechnen durch
dk = dk−1 min . + W,
wobei wir initial d0 setzen als
(
0, v = s
d0 (v) =
.
∞, sonst
Da wir nach obiger Überlegung δk−1 nach der Berechnung von δk nicht mehr benötigen, können
wir die Informationen in einem einzigen Vektor d speichern und verwenden somit
d ← d min . + W.
Sofern der Graph keinen negativen Kreis besitzt, gilt folglich nach n − 1 Runden δ(s, v) = d(v).
Zusammengefasst ergibt sich Algorithmus 2.
Algorithmus 2 : Algebraischer Bellman-Ford-Algorithmus
Input : Adjazenzmatrix A, Startknoten s
Output : Distanzvektor d
1 d←∞
2 ds ← 0
3 for k = 1 to n − 1 do
4
d ← d min . + A
6
if d 6= d min . + A then
return Negativer Kreis existiert!
7
return d
5
1.3.3. Paarweise kürzeste Distanzen
1.3.3.1. Der Floyd-Warshall-Algorithmus
Der Floyd-Warshall-Algorithmus basiert auf der Idee, das Problem schrittweise zu vergrößern. In
Iteration k werden alle Wege berücksichtigt, die über Knoten aus der Menge {1, . . . , k} verlaufen
(direkte Kanten des Graphen eingeschlossen). Nach Ende der äußersten Schleife hat k den Wert
n überschritten, so dass alle möglichen Wege berücksichtigt worden sind.
Algorithmus 3 : Floyd-Warshall-APSP
Input : Graph G = (V, E)
Output : Distanzmatrix
1 D (0) ← W
2 for k ← 1 to n do
3
for i ← 1 to n do
4
for j ← 1 to n do
(k)
(k−1) (k−1)
(k−1)
5
dij ← min(dij , dik
+ dkj )
6
return D(n)
10
1. Grundlegende Graphenalgorithmen
Lemma 1.12. Sei G ein Graph ohne negative Zyklen und sei j von i aus erreichbar. Dann gibt
es einen kürzesten i − j-Weg, der keinen Knoten doppelt benutzt.
Theorem 1.13. Sei G = (V, E) ein Graph mit nicht-negativen Zyklen. Dann berechnet der Algorithmus von Floyd-Warshall die Entfernung zwischen jedem Knotenpaar in O(|V |3 ) Schritten.
Die Beweise von Lemma 1.12 und Theorem 1.13 werdem dem Leser anhand der obigen Erläuterungen als Übung empfohlen.
Bemerkung 1.14. Das als Algorithmus 3 angegebene Verfahren löst nur das Problem All-PairsDistances (APD), d.h. es werden die paarweisen Distanzen und nicht auch die zugehörigen kürzesten Wege berechnet. Eine entsprechende Erweiterung des Algorithmus für APSP wird dem
Leser ebenfalls als Übungsaufgabe empfohlen.
1.3.3.2. Matrix-Multiplikation
Wir betrachten nun ungerichtete Graphen G = (V, E) mit der Knotenmenge V = {1, ..., n}. Ein
Graph G = (V, E) ist gegeben durch seine Adjazenzmatrix A.
Im Folgenden betrachten wir zunächst das Problem der Matrixmultiplikation. Es seien D, W ∈
(R ∪ {∞})n×n quadratische Matrizen. Verwenden wir die Verknüpfungen (min, +) bei der Matrizenmultiplikation, so gilt bekanntlich:
(DW )ij = min {Dik + Wkj }
1≤k≤n
Diese Tatsache setzen wir nun ein, um mit Hilfe eines modifizierten Algorithmus zur Matrixmultiplikation die Distanzen aller paarweise kürzesten Wege zu berechnen. Die wichtige Idee dabei
ist, D(n−1) = δn−1 (i, j) durch fortgesetzte Matrixmultiplikation zu berechnen:
D(1) = W, D(2) = W 2 = W ∗ W, D(4) = W 4 = W 2 ∗ W 2 , ...
D(2dlog n−1e) = D2dlog n−1e = Ddlog n−1e−1 ∗ Ddlog n−1e−1
Algorithmus 5 namens mmAPD zeigt nun, wie man durch fortgesetzte Aufrufe an eine Subroutine
zur modifizierten Matrixmultiplikation die Distanzen der paarweise kürzesten Wege berechnen
kann.
Algorithmus 4 : MatrixMultiply
Input : Matrizen A, B
Output : Matrizenprodukt AB
1 for i = 1 to n do
2
for j = 1 to n do
3
Cij ← ∞
4
for k = 1 to n do
5
Cij ← min{Cij , Aik + Bkj }
6
return C
Momentan liegt die beste bekannte Laufzeit eines Algorithmus für Matrixmultiplikation bei
O(n2.373 ) [LG14]. Eine bessere untere Schranke als Ω(n2 ) ist nicht bekannt, so dass hier eine
noch nicht geschlossene Lücke zwischen unterer und oberer Laufzeitschranke klafft.
Die obere Laufzeitschranke kann auf die Multiplikation von boolschen Matrizen angewandt
werden, wie wir in Kürze sehen werden. Bedauerlicherweise folgt aus dieser Beobachtung aber
1.3. Kürzeste Wege
11
Algorithmus 5 : mmAPD
Input : Gewichtsmatrix W
Output : Distanzmatrix
1 D (1) ← W
2 m←1
3 while m < n − 1 do
4
D(2m) ← M atrixM ultiply(D(m) , D(m) )
5
m ← 2m
6
return D(m)
auch eine Laufzeit für das APD Problem, die größer als O(n2 ) ist (jedenfalls solange man über
keinen Algorithmus mit quadratischer Zeitkomplexität zur Matrixmultiplikation verfïügt).
Die Laufzeit des Algorithmus mmAPD ist O(mm(n) · log n), wobei mm(n) die Zeit ist, um
zwei n × n Matrizen miteinander zu multiplizieren. Es gibt allerdings einen Nachteil, denn es
gibt keine implizite Darstellung der kürzesten Wege, denn dazu wären alle Matrizen D1 , . . . , Dm
notwendig und die Laufzeit würde auf O(mm(n) · n) ansteigen.
1.3.3.3. Distanzberechnung mit dem Algorithmus von Seidel
Wir betrachten nun das Problem Distanzberechnungen in ungerichteten und ungewichteten Graphen.
Problem APD:
• Gegeben: Ungerichteter, ungewichteter Graph G = (V, E).
• Gesucht: Matrix D = (δ(i, j))ij , wobei δ(i, j) die Distanz von i nach j in G ist.
Wir werden zunächst einen alternativen Algorithmus kennenlernen, der das APD-Problem
in Zeit O(mm(n) · log n) für ungewichtete, ungerichtete Graphen löst. Dieser Algorithmus wird
anschließend so erweitert, dass auch die kürzesten Wege zu den Distanzen schnell berechnet
werden können.
Bemerkung 1.15. Es sei G(V, E) ein ungerichteter, ungewichteter Graph mit Adjazenzmatrix A.
Ist Z = A2 , so ist Zij > 0 genau dann, wenn es einen Weg der Länge 2 von i nach j gibt. Zij
gibt die Anzahl der verschiedenen Wege der Länge 2 von i nach j an, was aus Theorem 1.8 folgt.
Damit können wir durch eine einfache Matrixmultiplikation eine Matrix Z berechnen, die
es erlaubt, schnell einen Graphen G0 zu berechnen, in dem zwei Knoten i und j genau dann
miteinander verbunden sind, wenn δ(i, j) ≤ 2 in G ist:
2
Z = A
(
1, falls i 6= j und (Aij = 1 oder Zij > 0)
A0ij =
0, sonst
G0 =
0
der durch A induzierte Graph
Lemma 1.16. Es sei G = (V, E) ein ungerichteter, ungewichteter Graph mit Adjazenzmatrix
0
0
A. Ist A derart, dass Aij = 1 genau dann gilt, wenn i 6= j und (Aij = 1 oder Zij > 0), und ist
0
0
0
D die Distanzmatrix des durch A gegebenen Graphen G , so gilt:
12
1. Grundlegende Graphenalgorithmen
0
1. Dij = 2Dij , wenn Dij gerade ist und
0
2. Dij = 2Dij − 1, wenn Dij ungerade ist.
Beweis. Wir betrachten die beiden Fälle:
• Fall Dij = 2k ist gerade:
⇒ ∃ kürrzester Weg P = hi = i0 , i1 , ..., i2k−1 , i2k = ji von i nach j in G.
0
0
⇒ P = hi = i0 , i2 , ..., i2k−2 , i2k = ji ist Weg von i nach j in G .
0
⇒ Dij ≤ k
0
Wäre Dij = l < k, so existierte ein Weg Q von i nach j in G der Länge ≤ 2l (Widerspruch,
0
da Dij = 2k). Daraus folgt Dij = k.
0
Also Dij = 2k = 2Dij .
• Fall Dij = 2k + 1 ungerade:
⇒ ∃ kürrzester Weg P = hi = i0 , i1 , ..., i2k , i2k+1 = ji von i nach j in G.
0
0
⇒ P = hi = i0 , i2 , ..., i2k , i2k+1 = ji ist Weg von i nach j in G .
0
⇒ Dij ≤ k + 1
0
Wäre Dij = l ≤ k, so existierte ein Weg Q von i nach j in G der Länge ≤ 2k (Widerspruch,
0
da Dij = 2k + 1). Daraus folgt Dij = k + 1.
0
Also Dij = 2k + 1 = 2Dij − 1.
Die Idee für einen Algorithmus beläuft sich auf drei hauptsächliche Schritte:
0
0
1. Berechne die Distanzen D für G (rekursiv).
2. Berechne die Parität der Distanzen in G.
3. Dann liefert Lemma 1.16 eine Berechnungsvorschrift für die Distanzen D in G.
Lemma 1.17. Betrachte ein beliebiges Paar disjunkter Knoten i, j ∈ V des Graphen G.
1. Für alle Nachbarn k ∈ Γ(i) gilt Dij − 1 ≤ Dkj ≤ Dij + 1.
2. Es existiert ein Nachbar k ∈ Γ(i) mit Dkj = Dij − 1.
Beweis. Sei P = hi = i1 , i2 , ..., ip+1 = ji kürzester Weg von i nach j in G, also Dij = p.
1. Sei k ∈ Γ(i), d. h. {i, k} ∈ E.
a) k = i2 ⇒ P1 = hk = i2 , ..., ip+1 = ji ist Weg von k nach j
⇒ Dkj ≤ p + 1
b) k 6= i2 ⇒ P2 = hk = i0 , i1 , ..., ip+1 = ji ist Weg von k nach j
⇒ Dkj ≤ p + 1
In jedem Fall: Dkj ≤ p + 1 = Dij + 1
c) Annahme: Dkj = q < Dij − 1.
Dann existiert P3 = hk = k1 , k2 , ..., kq+1 = ji von k nach j ⇒ P4 = hi = k0 , k1 , k2 , ..., kq+1 =
ji ist ein Weg der Länge q + 1 < Dij von i nach j (Widerspruch zur Definition von
Dij ).
2. Folgt aus 1 (a) und (c).
Lemma 1.18. Betrachte ein beliebiges Paar disjunkter Knoten i, j ∈ V des Graphen G.
1.3. Kürzeste Wege
0
13
0
1. Ist Dij gerade, so ist Dkj ≥ Dij für alle Nachbarn k ∈ Γ(i).
0
0
2. Ist Dij ungerade, so ist Dkj ≤ Dij für alle Nachbarn k ∈ Γ(i). Außerdem existiert ein
0
0
k ∈ Γ(i) derart, dass Dkj < Dij .
Beweis. Wir betrachten die beiden Fälle:
• Fall 1. Dij = 2l ist gerade.
⇒
∀ Nachbarn k ∈ Γ(i): Dkj ≥ 2l − 1
|{z}
Lemma 1.17
0
Dann ist Dij = l nach Lemma 1.16 a).
0
Weiter folgt aus Lemma 1.16 a,b), dass Dkj ≥ Dkj /2 ≥ l −
0
0
0
Dkj ist ganzzahlig ⇒ Dkj ≥ l = Dij
1
2
• Fall 2. Dij = 2l − 1 ist ungerade.
∀ Nachbarn k ∈ Γ(i): Dkj ≤ 2l
⇒
|{z}
Lemma 1.17
0
Dann ist Dij = l nach Lemma 1.16 b).
0
Weiter folgt aus Lemma 1.16 a,b), dass Dkj ≤ (Dkj + 1)/2 ≤ l + 12
0
0
0
Dkj ist ganzzahlig ⇒ Dkj ≤ l = Dij
0
Weiter gilt, dass ein k ∈ Γ(i) mit Dkj = Dij − 1 = 2l − 2 existiert, also gilt Dkj = l − 1 <
0
l = Dij nach Lemma 1.16 a).
Lemma 1.19. Betrachte ein beliebiges Paar disjunkter Knoten i, j ∈ V des Graphen G.
P
0
0
1. Dij ist gerade genau dann, wenn k∈Γ(i) Dkj ≥ Dij · deg (i).
P
0
0
2. D ist ungerade genau dann, wenn k∈Γ(i) Dkj < Dij · deg (i).
Beweis. Es gilt:
• Fall 1. Dij ist
P
Pgerade 0
0
0
⇒
k∈Γ(i) Dij = deg(i)Dij .
k∈Γ(i) Dkj ≥
|{z}
Lemma 1.18 a)
• Fall 2. Dij ist
Pungerade0
P
0
0
⇒
k∈Γ(i) Dkj ≤
k∈Γ(i) Dij − 1 = deg(i)Dij − 1.
|{z}
Lemma 1.18 b)
Die jeweilige Rückrichtung ergibt sich durch die Betrachtung der beiden komplementären Fälle.
Wir betrachten nun den Algorithmus APD, der die Distanzen Dij für alle Knotenpaare (i, j) für
einen gegebenen ungerichteten Graphen G berechnet. Der Graph wird durch seine Adjazenzmatrix A repräsentiert.
Theorem 1.20. Der Algorithmus APD berechnet die Distanzmatrix D eines n-Knoten Graphen
G in Zeit O(mm(n) · log n) mit Hilfe der ganzzahligen Matrixmultiplikation, wobei die Einträge
der Matrix nicht größer als O(n2 ) sind.
0
0
Beweis. Sei δ der Durchmesser von G. Dann hat G Durchmesser δ = dδ/2e. Sei T (n, δ) die Zeit,
die APD auf Graphen mit n Knoten und Durchmesser δ benötigt. Ist δ = 1, so ist G vollständig.
Ist δ = 2, so ist T (n, δ) = mm(n) + O(n2 ). Wegen δ < n, mm(n) = Ω(n2 ) und Rekursionstiefe
0
log n folgt die Laufzeit O(mm(n) log n). Wegen Dij < n und somit Dij < n sind die Einträge von
S durch n2 nach oben beschränkt.
14
1. Grundlegende Graphenalgorithmen
Algorithmus 6 : APD
Input : Adjazenzmatrix A
Output : Distanzmatrix D
1 Z ← A2
0
0
2 Berechne A mit Aij = 1 ⇔ i 6= j und (Aij = 1 oder Zij > 0)
0
// Aij = 1 ⇔ es ex. Weg der Länge 1 od. 2 v. i nach j
0
3 if Aij = 1 ∀i 6= j then
0
4
return D ← 2A − A
// Rekursionsabbruch
0
5
6
7
0
D ← AP D(A )
0
S ←A·D
( 0
2Dij ,
return D mit Dij =
0
2Dij − 1,
0
falls Sij ≥ Dij Zii
0
falls Sij < Dij Zii
// Rekursion
P
0
// Sij = k∈Γ(i) Dkj
// Zii = deg(i)
1.3.4. Paarweise kürzeste Wege mit dem Algorithmus von Seidel
Wir werden nun den Algorithmus von Seidel für das Problem APD so erweitern, dass nicht nur
die Distanzen Dij , sondern auch für jedes Knotenpaar (i, j) ein kürzester Weg berechnet wird.
Der erweiterte Algorithmus löst somit das Problem APSP :
Problem APSP:
• Gegeben: Ungerichteter, ungewichteter Graph G = (V, E).
• Gesucht: Matrix D = (δ(i, j))ij wie bei APD und eine implizite Darstellung der kürzesten
Wege.
Dabei soll die Laufzeit des neuen Algorithmus subkubisch sein. Wir werden zeigen, dass das
APSP-Problem in erwarteter Zeit O(mm(n) · log2 n) durch einen randomisierten Algorithmus
lösbar ist. Das Problem ist jedoch, dass es Graphen G = (V, E) von der Gestalt gibt, dass Ω(n2 )
Knotenpaare Distanz Ω(n) haben.
Beispiel 1.21. G = (V, E) ist eine „Linie”: V = {1, ..., n}, E = {(i, i + 1)|1 ≤ i < n}. Setze
δ = n2 = Ω(n), dann haben
n−δ
X
k=1
k=
(n − δ + 1)(n − δ)
n2
>
= Ω(n2 )
2
8
Knotenpaare mindestens den Abstand δ zueinander.
Explizites Speichern der kürzesten Wege würde daher Platzbedarf Ω(n3 ), also auch Zeitaufwand Ω(n3 ), bedeuten. Daher werden die kürzesten Wege nur implizit gespeichert, indem zu
jedem Knotenpaar (i, j) der Nachfolger Sij von i auf einem kürzesten Weg nach j gespeichert
wird.
S = (Sij ) hat O(n2 ) Einträge und ein kürzester Weg von i nach j kann in Zeit proportional
zu seiner Länge bestimmt werden:
Wir bezeichnen im Folgenden:
• die boolsche1 Matrixmultiplikation mit ∧ als Multiplikation und ∨ als Addition durch "‘∗"’
1
Da diese Bezeichnung auf George Boole (1815-1864) zurückgeht, findet man auch häufig die Schreibweise boolesche Matrixmultiplikation.
1.3. Kürzeste Wege
15
Algorithmus 7 : SPN
Input : S, i, j
1 x0 ← i
2 k ←0
3 repeat
4
xk+1 ← Sxk j
5
k + +;
6 until xk = j
7 return {x0 , . . . , xk }
und
• die ganzzahlige Matrixmultiplikation mit "‘·"’.
Definition 1.22. Es seien A, B ∈ {0, 1}n×n boolsche Matrizen, P = A ∗ B ∈ {0, 1}n×n das
boolsche Produkt von A und B. Ein Zeuge für Pij ist ein Index k ∈ {1, ..., n} derart, dass
Aik = 1 = Bkj .
Bemerkung 1.23. Es gilt:
1. Pij = 1 ⇔ es gibt einen Zeugen k für Pij .
2. Ist C = A · B, so ist Cij die Anzahl der Zeugen für Pij .
3. Ist A Adjazenzmatrix eines Graphen G = (V, E), P = A ∗ A und C = AA, so ist Pij = 1
genau dann, wenn ein Weg der Länge 2 zwischen i und j existiert. Cij ist die Anzahl dieser
Wege (vgl. Lemma 1.15).
4. Für P = A ∗ A ist ein Zeuge k für Pij = 1 Zwischenknoten auf einem Weg der Länge 2 von
i nach j.
5. Für jedes Pij bzgl. P = A ∗ B kann es bis zu n Zeugen geben.
Zeugen sind interessant, wenn man den APD-Algorithmus so erweitern will, dass er kürzeste
Wege berechnet. Da Zeugen Zwischenknoten auf Wegen der Länge 2 darstellen, helfen sie bei der
Konstruktion einer Nachfolgermatrix. Wie genau dies funktioniert, wird nachfolgend erläutert.
Definition 1.24. Es seien A, B ∈ {0, 1}n×n boolsche Matrizen, P = A∗B ∈ {0, 1}n×n . Eine Zeugenmatrix (Bpwm = Boolean Product Witness Matrix) für P ist eine Matrix W ∈ {0, ..., n}n×n
mit
(
0, wenn Pij = 0
Wij =
k, k ist Zeuge für P {ij} = 1
Problem Bpwm:
• gegeben: boolsche Matrizen A und B.
• gesucht: eine Zeugenmatrix W für P = A ∗ B.
Ein trivialer Algorithmus für Bpwm, der für alle (i, j) ∈ {1, ..., n}2 alle k ∈ {1, ..., n} testet,
hat Zeitaufwand O(n3 ). Da wir einen niedrigeren Aufwand anstreben, vereinfachen wir zunächst
das Problem Bpwm:
16
1. Grundlegende Graphenalgorithmen
Problem UniqueBpwm:
• gegeben: boolsche Matrizen A und B, so dass jeder Eintrag in P = A∗B einen eindeutigen
Zeugen hat.
• gesucht: die Zeugenmatrix W für P = A ∗ B.
Lemma 1.25. Es seien A, B ∈ {0, 1}n×n boolsche Matrizen und die Matrizen  und W gegeben
durch Âik = kAik und W = ÂB. Dann gilt:
1. Wij ist Zeuge für Pij , wenn Pij einen eindeutigen Zeugen hat.
2. Hat jeder Eintrag von Pij einen eindeutigen Zeugen, so ist W die Lösung von UniqueBpwm.
Beweis. Es ist
W =
n
X
k=1
Beispiel 1.26.
Âik Bkj
=
n
X
k=1
k · Aik Bkj


falls genau ein Aik Bkj = 1
k,
=
0,
falls Aik Bkj = 0 ∀k


> k, falls Aik Bkj = 1 und Ail Blj = 1 für ein l 6= k.




1 1 0
1 0 0
A = 1 0 0 , B = 1 1 0 , P
0 0 0
0 0 0



1 2 0
3
 = 1 0 0 und W = 1
0 0 0
0


1 1 0
= 1 0 0 .
0 0 0

2 0
0 0 .
0 0
Die grünen und blauen Einträge von W sind schon korrekte Einträge für eine Zeugenmatrix, der
rote jedoch nicht.
Bemerkung 1.27. Das Problem UniqueBpwm kann durch eine ganzzahlige Matrixmultiplikation,
also in Zeit O(mm(n)), gelöst werden.
Problematisch ist nun, dass wir eine Zeugenmatrix W für P = A ∗ A mit einer Adjazenzmatrix
A berechnen wollen. Dabei ist natïrlich nicht garantiert, dass die Zeugen immer eindeutig sind.
Die Idee zur Lösung des Problems lässt sich so beschreiben:
• Randomisierung liefert den gleichen Effekt wie eindeutige Zeugen für genügend viele Einträge Pij , denn bei einer zufälligen Auswahl von Kandidatenmengen trifft man wahrscheinlich
auf eine Menge mit genau einem Zeugen.
• Die wenigen verbleibenden Einträge werden dann mit dem trivialen Algorithmus berechnet.
1.3. Kürzeste Wege
17
1.3.4.1. Nicht eindeutige Zeugen
Wir betrachten boolsche Matrizen A, B ∈ {0, 1}n×n , P = A ∗ B, C = AB und einen festen
Eintrag Pij von P . Es sei w = Cij die Anzahl der Zeugen für Pij (OE w ≥ 2, denn nach den
Vorbetrachtungen ist es einfach, einen eindeutigen Zeugen zu finden). Außerdem sei r ∈ N mit
n
2 ≤ wr ≤ n.
Ziel ist es, eine Menge R ⊂ {1, ..., n} mit |R| zu finden, die den eindeutigen Zeugen k für Pij
enthält.
Lemma 1.28. Es sei n ∈ N, w ∈ {1, ..., n}, r ∈ N mit n2 ≤ wr ≤ n. Eine Urne enthalte n Bälle,
von denen w weiß und n − w schwarz sind. Zieht man zufällig r Bälle aus der Urne, ohne diese
zwischendurch zurückzulegen, so ist:
P r(genau ein weißer Ball wurde gezogen) ≥
1
.
2e
Beweis. Durch elementare Rechenoperationen kann die gesuchte Wahrscheinlichkeit wie folgt
beschränkt werden:
w n−w
r! (n − w)!
(n − r)!
1
r−1
= w
n
(r − 1)!
n!
(n − w − r + 1)!
r


!
w−1
w−2
Y 1
Y

= wr
(n − r − j)
n−i
i=0
j=0


w−2
wr  Y n − r − j 
=
n
n−1−j
j=0


w−2
Y
wr 
n − r − j − (w − j − 1) 
≥
siehe (*)
n
n − 1 − j − (w − j − 1)
j=0


w−2
Y
n − w − (r − 1) 
wr 
=
n
n−w
j=0
wr
r − 1 w−1
=
1−
n
n−w
1 w−1
1
≥
1−
siehe (**)
2
w
(*) Gilt faktorweise: a = n − r − j, b = n − 1 − j, c = w − j − 1. Dann ist a(b − c) ≥ b(a − c) ⇔
ac ≤ bc ⇔ a ≤ b.
r−1
(**) n−w
≤ w1 ⇔ (r − 1)w ≤ n − w ⇔ rw ≤ n.
Die letzte Ungleichung folgt von den Beobachtungen, dass wr/n ≥ 1/2 und (r−1)/(n−w) ≤ 1/w,
was aus der Annahme, dass n/2 ≤ wr ≤ n, folgt.
Beispiel 1.29. n = 8, w = 3, n − w = 5. Einzig mögliche Wahl für r mit
• 3 Möglichkeiten, genau 2 weiße Bälle zu ziehen
• 10 Möglichkeiten, genau 2 schwarze Bälle zu ziehen
• 15 Möglichkeiten, genau 1 weißen und 1 schwarzen Ball zu ziehen
n
2
≤ wr ≤ n ist r = 2:
18
1. Grundlegende Graphenalgorithmen
• 28 Möglichkeiten insgesamt.
Damit ist P r(genau ein weißer Ball wurde gezogen) =
28−13
28
=
15
28
>
1
2
>
1
2e
≈ 0.184.
Sei jetzt R ⊂ {1, ..., n} derart, dass R einen eindeutigen Zeugen für Pij enthällt. R sei gegeben
durch einen Vektor R ∈ {0, 1}n mit Rk = 1 genau dann, wenn k ∈ R. Definiere:
• eine Matrix AR ∈ Nn×n
durch AR
0
ik = kRk Aik und
R =R B
• eine Matrix B R ∈ Nn×n
durch Bkj
k kj
0
Weiterhin sind die Matrizen  mit Âik = kAik sowie B und W =  · B so wie bereits weiter oben
verwendet. AR ist die Matrix, die aus  entsteht, indem jede Spalte von Â, die zu einem Element
k ∈
/ R gehört, durch eine Nullspalte ersetzt wird und jede andere Spalte k mit k multipliziert
wird. B R ist die Matrix, die aus B entsteht, indem jede Zeile von B, die zu einem Element k ∈
/R
gehört, durch eine Nullzeile ersetzt wird.
Lemma 1.30. Es seien A, B ∈ {0, 1}n×n boolsche Matrizen, AR und B R wie oben, W = AR ·B R .
Wenn Pij einen eindeutigen Zeugen in R hat, so ist Wij Zeuge für Pij .
P
Pn
P
R
Beweis. Wij = (AR ·B R )ij = nk=1 AR
k∈R k ·Aik ·Bkj . Wenn
k=1 k ·Rk ·Aik ·Rk Bkj =
ik Bkj =
R nur einen einzigen Zeugen enthält, folgt aus der Zeugeneigenschaft: Wij = k · Aik · Bkj = k,
wobei k der eindeutige Zeuge ist.
Die weiteren Ideen, die zum fertigen Algorithmus führen, lassen sich so umschreiben:
• W = AR B R liefert Zeugen für alle Einträge in P = A ∗ B, die einen eindeutigen Zeugen in
R haben.
• Nach Lemma 1.28 ist die Wahrscheinlichkeit dafür, dass eine zufällig gewählte Menge R der
Größe |R| = r einen eindeutigen Zeugen für einen Eintrag von P mit w Zeugen enthällt,
1
größer oder gleich der Konstanten 2e
, wenn n2 ≤ wr ≤ n ist.
• Wir wählen O(log n) Mengen R zufällig aus. Damit wird es sehr unwahrscheinlich, dass für
einen Eintrag von P kein Zeuge identifiziert wird.
• Zeugen für die Einträge, für die kein Zeuge identifiziert wird, werden mit dem trivialen
Algorithmus berechnet.
• Da nicht alle Einträge von P die gleiche Anzahl Zeugen haben, müssen Mengen R mit
verschiedenen Kardinalitäten r benutzt werden. Es reicht jedoch, für r die Zweierpotenzen
zwischen 1 und n zu benutzen, da nur die Bedingung n2 ≤ wr ≤ n erfüllt sein muss.
Theorem 1.31. Der Algorithmus Bpwm ist ein Las-Vegas-Algorithmus für das Problem Bpwm
mit erwarteter Laufzeit O(mm(n) log2 n).
Beweis. Die Initialisierung benötigt O(mm(n)) Zeit. Der Algorithmus durchläuft die innere Schleife O(log2 n)-mal und führt jedes Mal eine ganzzahlige Matrixmultiplikation von n × n Matrizen durch. Die anderen Operationen in der Schleife sind weniger zeitaufwändig. Die Laufzeit
O(mm(n) log2 n) folgt, wenn nicht zu oft der triviale Algorithmus aufgerufen werden muss.
• Beh.: Ist Pij = 1, so wird im randomisierten Teil des Algorithmus ein Zeuge mit Wahrscheinlichkeit ≥ 1 − n1 gefunden.
1.3. Kürzeste Wege
19
Algorithmus 8 : BPWM
Input : Boolsche Matrizen A, B ∈ {0, 1}n×n
Output : Zeuge für P
1 W ← −AB
// Wij < 0 ⇔ Zeuge für Pij muss noch gefunden werden
2 for t = 0, ..., blog nc do
// teste alle Zweierpot. r = 2t zwischen 1 und n
3
r ← 2t
4
repeat d3.77 log ne times
5
Wähle R ⊆ {1, ..., n} mit |R| = r
6
Berechne AR und B R
// vgl. Lemma 1.28
7
Z ← AR B R
8
forall the (i, j) do
// teste, ob neuer Zeuge für Pij gefunden wurde
9
if Wij < 0 und Zij ist Zeuge für Pij then
10
Wij ← Zij
11
12
13
forall the (i, j) do
if Wij < 0 then
Berechne Wij mit dem trivialen Algorithmus
// kein Zeuge für Pij gefunden
• Bew.: Sei w die Anzahl der Zeugen für Pij . Die äußere Schleife wird mindestens einmal mit
einem Wert r mit n2 ≤ wr ≤ n durchlaufen. In diesem Durchlauf ist die Wahrscheinlichkeit,
1
dass R keinen eindeutigen Zeugen für Pij enthällt, höchstens 1 − 2e
nach Lemma 1.28.
Damit ist die Wahrscheinlichkeit, dass kein Zeuge für Pij identifiziert wird höchstens (1 −
1 3.77 log n
≤ n1 .
2e )
Damit ist die erwartete Anzahl der nicht gefundenen Zeugen begrenzt durch n, anstelle der
ursprïnglichen n2 . Somit benötigen alle Aufrufe des trivialen Algorithmus zusammen Zeit O(n2 ).
1.3.4.2. Randomisierter Algorithmus
Wir schließen das Thema in diesem Abschnitt mit der Beschreibung des randomisierten Algorithmus ab, der anhand einer Zeugenmatrix eine Nachfolgermatrix berechnet. Zuvor muss noch
festgelegt werden, wie genau diese Nachfolgermatrix berechnet wird.
Definition 1.32. Es sei G = (V, E) ein Graph mit n Knoten. Eine Nachfolgermatrix S für G
ist eine n × n-Matrix, so dass für alle i 6= j Sij ein Nachfolger von i ist, der auf einem kürzesten
Weg von i nach j liegt. Weiter ist Sii = 0.
Sei nun A die Adjazenzmatrix eines Graphen G = (V, E), D die Distanzmatrix von G. Seien
i, j ∈ {1, ..., n}, i 6= j beliebig mit Dij = d. Sij = k ist genau dann möglich, wenn Dik = 1 und
d = 1 genau dann, wenn D
d
Dkj = d − 1. Sei B d ∈ {0, 1}n×n mit Bkj
kj = d − 1 (B kann aus D in
Zeit O(n2 ) berechnet werden).
Lemma 1.33. Es sei A Adjazenzmatrix eines Graphen G = (V, E) und B d ∈ {0, 1}n×n wie
oben definiert. Der Aufruf Bpwm(A, B d ) liefert für alle i, j mit Dij = d Einträge Sij einer
Nachfolgermatrix S für G.
Der Beweis von Lemma 1.33 ist dem Leser zur Übung empfohlen.
Das Problem ist, dass es n mögliche Werte für d gibt. Damit wäre die Laufzeit eines Algorithmus mindestens Ω(nmm(n)) und somit superkubisch. Aber es reichen drei Berechnungen von
Zeugenmatrizen aus, denn:
20
1. Grundlegende Graphenalgorithmen
• Für alle i, j und alle Nachfolger k von i gilt Dij − 1 ≤ Dkj ≤ Dij + 1.
• Jeder Nachfolger k von i mit Dkj = Dij − 1 ist ein möglicher Eintrag für Sij .
• Also: Jedes k mit Aik = 1 und Dkj ≡ Dij − 1 (mod 3) ist ein möglicher Eintrag für Sij .
(s)
• Für s = 0, 1, 2 definiere D(s) durch Dkj = 1 genau dann, wenn Dkj + 1 ≡ s (mod 3).
• Eine Nachfolgermatrix S von A kann dann aus den Zeugenmatrizen für A ∗ D(s) , s = 0, 1, 2
berechnet werden.
Algorithmus 9 : Apsp
Input : Adjazenzmatrix A für G = (V, E)
Output : Nachfolgematrix von G
1 Berechne Distanzmatrix D ← AP D(A)
2 for s = 0, 1, 2 do
(s)
3
Berechne D(s) ∈ {0, 1}n×n derart, dass Dkj = 1 gdw. Dkj + 1 ≡ s (mod 3)
4
Berechne Zeugenmatrix W (s) ← BP W M (A, D(s) )
5
(Dij (mod 3))
Berechne Nachfolgematrix S mit Sij = Wij
Theorem 1.34. Der Algorithmus Apsp berechnet eine Nachfolgermatrix eines Graphen G mit
n Knoten in erwarteter Zeit O(mm(n) log2 n).
1.4. Nicht erweiterbare unabhängige Mengen
Definition 1.35. Sei G = (V, E) ein Graph. Eine Menge I ⊆ V heißt unabhängig, wenn je zwei
beliebige Knoten aus V nicht adjazent sind. Eine unabhängige Menge I heißt nicht erweiterbar
(engl.: maximal ), falls keine unabhängige Menge J existiert mit I ⊆ J und |I| < |J|.
Der von einer unabhängigen Menge induzierte Subgraph besitzt folglich keine Kanten. Beachten Sie, dass eine nicht erweiterbare unabhängige Menge nicht notwendigerweise kardinalitätsmaximal unter allen unabhänigen Mengen ist!
Ein sehr einfacher Algorithmus zur Berechnung einer nicht erweiterbaren unabhängigen Menge nimmt einen beliebigen Knoten v ∈ V , fügt ihn zu I hinzu und löscht v und N (v) aus dem
Graphen. Dieses Vorgehen wird dann iteriert, bis der Graph leer ist. Zwar bekommt man auf
diese Weise eine nicht erweiterbare unabhängige Menge. Aber das Verfahren ist inhärent sequentiell. Ein bekannter Algorithmus, der Parallelität nutzt, geht zurück auf Luby. Auch Lubys
Algorithmus (Algorithmus 10) operiert in Phasen, aber in jeder Phase werden mehrere Knoten
gleichzeitig in I eingefügt. Wir folgen hier der Darstellung von D. C. Kozen [Koz91].
Beachten Sie, dass wir im Schritt 1 des Algorithmus Knoten mit niedrigem Knotengrad bevorzugen. Hingegen werden in Schritt 2 Knoten mit hohem Knotengrad bessergestellt. Wir wollen
nun das folgende Theorem beweisen.
Theorem 1.36. Die erwartete Anzahl von Runden in Lubys Algorithmus ist O(log m).
Wir werden dieses Theorem jedoch nicht vollständig beweisen. Vielmehr werden wir ein Hauptlemma zeigen, das besagt, dass in jeder Runde ein konstanter Anteil von Kanten aus dem aktuellen Graphen gelöscht wird. Wie man sich dann überlegen kann (was wir hier nicht tun), folgt
daraus die logarithmische Rundenanzahl. Zum Beweis des Hauptlemmas benötigen wir zunächst
einige Hilfsresultate.
1.4. Nicht erweiterbare unabhängige Mengen
21
Algorithmus 10 : Lubys MIS-Algorithmus
1. Berechne eine Menge S ⊆ V von Kandidaten für I, indem jeder Knoten v ∈ V parallel
1
mit Wahrscheinlichkeit 2d(v)
in S eingefügt wird.
2. Prüfe für jede Kante e ∈ E, ob beide Endpunkte in S sind. Ist dies der Fall, lösche den
Endknoten mit kleinerem Grad aus S. Löse evtl. Konflikte beliebig auf, z. B. gemäß
Knotennummer. Füge die resultierende Menge zu I hinzu.
3. Lösche S und N (S) aus G und gehe zu 1., falls G nicht leer ist.
Lemma 1.37. Für jeden Knoten u ∈ V gilt: P r(u ∈ I | u ∈ S) ≥ 12 .
Beweis. Zum Beweis der Aussage werden wir das Gegenereignis P r(u ∈
/ I | u ∈ S) von oben
beschränken. Ein Knoten u ∈ S wird genau dann nicht in I aufgenommen, wenn ein Nachbar
mit mindestens gleich großem Grad in S aufgenommen wird. Es gilt:
P r(u ∈
/ I | u ∈ S) = P r(∃v ∈ N (u) ∩ S, d(v) ≥ d(u) | u ∈ S)
X
≤
P r(v ∈ S | u ∈ S)
v∈N (u), d(v)≥d(u)
≤
≤
≤
X
v∈N (u), d(v)≥d(u)
X
v∈N (u), d(v)≥d(u)
X
v∈N (u), d(v)≥d(u)
≤ d(u) ·
P r(v ∈ S)
1
2d(v)
1
2d(u)
(da d(v) ≥ d(u))
1
1
= .
2d(u)
2
Ein Knoten, der in S landet, wird also mindestens mit Wahrscheinlichkeit 21 auch in I in
derselben Runde aufgenommen. Daraus ergibt sich eine weitere Abschätzung, wie wahrscheinlich
es ist, dass ein Knoten in I aufgenommen wird.
Lemma 1.38. Für jeden Knoten u ∈ V gilt P r(u ∈ I) ≥
1
4d(u) .
Beweis. Nach Definition der bedingten Wahrscheinlichkeit und mit Lemma 1.37 ergibt sich:
P r(u ∈ I) = P r(u ∈ I | u ∈ S) · P r(u ∈ S)
1
1
≥
·
2 2d(u)
1
≥
.
4d(u)
Für den Rest des Beweises benötigen wir zunächst eine weitere Definition.
Definition 1.39. Wir sagen, dass ein Knoten u ∈ V gut ist, falls
X
v∈N (u)
1
1
≥ .
2d(v)
6
22
1. Grundlegende Graphenalgorithmen
Eine Kante ist gut, falls mindestens einer ihrer Endpunkte gut ist. Ein Knoten oder eine Kante
sind schlecht, wenn sie nicht gut sind.
Damit lässt sich ein weiteres Hilfsresultat folgern.
Lemma 1.40. Falls u gut ist, dann gilt P r(u ∈ N (I)) ≥
1
36 .
Beweis. Wir betrachten zwei Fälle. Im ersten Fall existiere ein Knoten v ∈ N (u) mit d(v) ≤ 2.
Nach Lemma 1.38 folgt
P r(u ∈ N (I)) ≥ P r(v ∈ I)
1
≥
4d(v)
1
≥
.
8
Der zweite Fall ist das Komplement und muss detaillierter untersucht werden. Es gilt also d(v) ≥ 3
1
für alle v ∈ N (u) und somit 2d(v)
≤ 61 . Da der Knoten u gut ist, gilt nach Definition 1.39
X
v∈N (u)
1
1
≥ .
2d(v)
6
(1.4.1)
Da jeder Summand einzeln kleiner als 1/6 ist, lässt sich immer eine Teilmenge M (u) ⊆ N (u)
derart finden, dass
X
1
1
1
≤
≤ .
6
2d(v)
3
v∈M (u)
Da nach dem Prinzip
P des Ein- undPAusschließens für eine Menge von Ereignissen A die Ungleichung P r(∪A) ≥ A∈A P r(A) − A,B∈A, A6=B P r(A ∩ B) gilt, folgt in unserem Fall:
P r(∃v ∈ M (u) ∩ I) ≥
Insgesamt ergibt sich somit:
X
v∈M (u)
P r(v ∈ I) −
X
v,w∈M (u), v6=w
P r(v ∈ I∧w ∈ I)
(1.4.2)
1.4. Nicht erweiterbare unabhängige Mengen
P r(u ∈ N (I)) ≥ P r(∃v ∈ M (u) ∩ I)
X
P r(v ∈ I) −
≥
v∈M (u)
(nach 1.4.2)
X
1
≥
−
4d(v)
v∈M (u)
X
v,w∈M (u), v6=w
X
v,w∈M (u), v6=w
(nach Lemma 1.38)
X
X
1
≥
−
4d(v)
v∈M (u)
v,w∈M (u), v6=w
23
P r(v ∈ I∧w ∈ I)
P r(v ∈ S ∧ w ∈ S)
P r(v ∈ S) · P r(w ∈ S)
(wegen paarweiser Unabhänigkeit)
X
X
X
1
1
1
≥
−
·
4d(v)
2d(v) 2d(w)
v∈M (u)
v∈M (u) w∈M (u)

 

X
X
1  1
1 
≥ 
−
·
2d(v)
2
2d(w)
v∈M (u)
≥
w∈M (u)
1
1 1
· =
6 6
36
(nach 1.4.1)
Jetzt zeigen wir, dass mindestens die Hälfte aller Kanten gut sind.
Lemma 1.41. Mindestens die Hälfte der Kanten in G sind gut.
Beweis. Richte jede Kante zu ihrem Endpunkt mit höherem Knotengrad. Dabei werden die
Konflikte so wie im Algorithmus aufgelöst. Jeder schlechte Knoten hat dabei mindestens doppelt
so viele Kanten, die ihn verlassen, wie Kanten, die in ihn hineinführen. Wäre dies nicht der Fall,
hätte mindestens ein Drittel der zu v adjazenten Knoten Grad d(v) oder niedriger. Das würde
implizieren, dass v gut ist.
Indem wir diese Tatsache nutzen, weisen wir jede schlechte Kante e, die in einen schlechten
Knoten v hineinführt, einem Paar von Kanten (gut oder schlecht) zu, die aus v hinausführen.
Dies geschieht derart, dass jede schlechte Kante an ein eindeutiges Paar zugewiesen wird. Dies
impliziert, dass es mindestens doppelt so viele Kanten insgesamt wie schlechte Kanten gibt.
Anders gesagt ist mindestens die Hälfte aller Kanten gut.
Wir können nun das Hauptlemma beweisen.
Lemma 1.42. Bezeichne die Zufallsvariable X die Zahl der Kanten, die in der aktuellen Phase
gelöscht werden. Dann gilt:
|E|
E(X) ≥
.
72
Beweis. Sei EG die Menge der guten Kanten. Für e ∈ E definiere die Zufallsvariable
(
1, falls e gelöscht wird
Xe =
0, sonst.
24
1. Grundlegende Graphenalgorithmen
Dann folgt X =
P
e∈E
Xe und wegen der Linearität des Erwartungswertes,
E(X) =
X
E(Xe )
e∈E
≥
≥
≥
≥
X
E(Xe )
e∈EG
X 1
36
(nach Lemma 1.40)
e∈EG
|EG |
36
|E|
72
(nach Lemma 1.41)
Wir haben also gezeigt, dass in jeder Runde des Algorithmus ein konstanter Anteil der Kanten
des jeweils aktuellen Graphen entfernt wird. Diese Feststellung impliziert, dass man nach erwartet
logarithmisch vielen Runden fertig ist.
1.5. Weiterführende Literatur
Eine ausführliche Darstellung zur Dualität von Matrizen und Graphen findet sich im Buch Graph
Algorithms in the Language of Linear Algebra von Kepner und Gilbert (Hrsg.) [KG11]. Besonders in den ersten beiden Kapiteln dieses Buches wird verstärkt auf allgemeine Halbringe und
Matrizenmultiplikationen und ihre Verwendung in Graphenalgorithmen eingegangen.
Die Darstellung von Lubys Algorithmus sowie dessen Analyse folgt im Wesentlichen dem Lehrbuch von Kozen [Koz91].
25
2. Datenstrukturen für dünn besetzte
Matrizen
Beim Entwurf und der Implementierung von Algorithmen spielt die Wahl der Datenstruktur
eine zentrale Rolle. Hier bilden Algorithmen für dünn besetzte Matrizen (bzw. Graphen ohne
reichhaltige semantische Informationen) keine Ausnahme, denn die Darstellung dünner Matrizen
bestimmt nicht nur die Effizienz der eingesetzten Algorithmen. Sie wirkt sich auch auf den
gesamten Entwurfsprozess aus. Aus softwaretechnischer Sicht ist zu beachten, dass die Details der
Datenstruktur von den Algorithmen abgekapselt werden. In dem Fall lässt sich die Datenstruktur
intern ändern, ohne dass man die Algorithmen anpassen muss.
In diesem Kapitel werden wir die bekanntesten Datenstrukturen für dünn besetzte Matrizen kennenlernen. Für die grundlegenden Matrizenoperationen werden wir spezielle Algorithmen
vorstellen, wobei der zusätzliche Speicherbedarf und die zusätzlichen Berechnungskosten berücksichtigt werden.
2.1. Cache-Effizienz
Aufgrund der unregelmäßigen Verteilung von Einträgen und der verhältnismäßig hohen Speicherzugriffszeit auf den Hauptspeicher (RAM) ist die Cache-Effizienz bei Berechnungen auf dünn besetzten Matrizen besonders wichtig, insbesondere bei iterativen Algorithmen mit vielen Schleifendurchläufen. Deshalb wird in diesem Kapitel nicht nur auf die Berechnungskomplexität, sondern
auch auf die Komplexität im I/O-Modell eingegangen, das je nach wissenschaftlicher Community
auch EM-Modell (EM für external memory) genannt wird.
2.1.1. I/O-Modell
Das I/O-Modell beschreibt ein hierarchisches Speichermodell, bei dem grundlegend zwischen
zwei Arten von Speicher unterschieden wird, einem schnellen und einem langsamen. Der schnelle
Speicher wird Cache genannt, der langsame Speicher normalerweise Disk. Manchmal findet man
auch die Bezeichnungen Cache vs. RAM bzw. RAM vs. Disk. Wichtig ist eigentlich nur, dass die
Einsichten meist für zwei beliebige aufeinanderfolgende Ebenen der Speicherhierarchie gelten.
Wir wollen daher in unserem Fall beim schnellen Speicher vom Cache und beim langsamen
Speicher vom Arbeitsspeicher oder RAM sprechen.
Dabei sind beide Speicher in Blöcke derselben Größe L unterteilt. Benötigt der Prozessor
Daten, die sich nicht im Cache befinden, tritt ein Cache miss auf und der ganze Speicherblock,
der die benötigten Daten enthält, muss vom langsamen RAM geladen werden. Deshalb ist es
wichtig, die Daten blockweise unter Ausnutzung von Lokalität abzuarbeiten, um die Anzahl der
Cache misses zu minimieren.
Definition. Unter der I/O-Komplexität eines Algorithmus versteht man die Anzahl der nötigen
Speichertransfers zwischen dem schnellen und dem langsamen Speicher.
Beispiel. Bei einer angenommenen Blockgröße von L hat das Lesen eines Speichers der Größe
N eine I/O-Komplexität von N/L.
26
2. Datenstrukturen für dünn besetzte Matrizen
Definition. Wir definieren scan(A) = nnz(A)/L als Abkürzung für die I/O-Komplexität, um
alle Nichtnull-Einträge einer Matrix A zu lesen.
2.1.2. Modell-Annahmen
Für das restliche Kapitel gelten die folgenden beiden Annahmen:
Annahme: Für die Anzahl der Nichtnull-Einträge (nnz ) einer dünn besetzten Matrix der Dimensionen M × N gilt: nnz = Ω(N, M ).
Dies vereinfacht die asymptotische Analyse der Algorithmen in diesem Kapitel, da wir nun bei
Komplexitäten, die die Dimension der Matrix enthalten, auf diese verzichten und stattdessen
stets nnz verwenden können.
Annahme: Der schnelle Speicher ist nicht groß genug, um eine Datenstruktur der Größe O(N )
zu halten, wobei N die Dimension der Matrix ist.
Ein Beispiel soll zeigen, dass die zweite Annahme gerechtfertigt ist: Bei der kleinsten Repräsentation einer dünn besetzten Matrix haben die Nichtnull-Einträge eine Größe von 16 Byte (8 Byte
zur Indizierung, 8 Byte für die Daten). Das ergibt 230 /16 = 226 Nichtnull-Einträge pro GB. Eine
quadratische, dünn besetzte Matrix mit 8 Einträgen pro Zeile füllt demnach ein GB RAM, wenn
sie die Dimension 223 ×223 besitzt. Ein dichter double-Vektor der Dimension 223 würde demnach
64 MB L2 Cache pro GB benötigen, was üblicherweise deutlich größer als ein typischer L2 Cache
ist.
2.1.3. Grundlegende Algorithmen im I/O-Modell
2.1.3.1. Sortieren
Folgt.
2.1.3.2. Minimaler Spannbaum
Folgt.
2.2. Grundlegende Matrix-Operationen
In diesem Abschnitt werden die grundlegenden Operationen auf dünn besetzten Matrizen und
ihre Entsprechungen bei Graphen beschrieben. Die meisten Operationen auf dünn besetzten
Matrizen sind durch die numerische lineare Algebra motiviert, einige sind aber auch für Graphenalgorithmen nützlich:
2.2.1. Teilmatrizen addressieren (SpRef/SpAsgn)
Die Abkürzung bezieht sich auf die englischen Ausdrücke sparse matrix indexing and assignment.
Diese Operationen entsprechen der Auswahl eines Teilgraphen.
• SpRef: B = A(p, q) : Speichert eine Teilmatrix von A in B.
• SpAsgn: B(p, q) = A : Zuweisung einer Matrix an eine Teilmatrix B.
Diese Operatoren können recht mächtig aber auch kompliziert sein, wenn p und q beliebige
Vektoren von Indizes sein können. Deshalb beschränken wir uns in diesem Kapitel auf zeilenweise
(A(i, :)), spaltenweise (A(:, i)) und elementweise (A(i, j)) Indizierung, welche auch am häufigsten
Gebrauch finden.
2.2. Grundlegende Matrix-Operationen
27
Abbildung 2.2.1.: Links die Operation SpRef, rechts SpAsgn
2.2.2. Matrix-/Vektormultiplikation (SpMV)
Die Abkürzung bezieht sich auf den englischen Ausdruck sparse matrix dense vector multiplication. Wie wir bereits in Kapitel 1 gesehen haben, entspricht SpMV einem Schritt einer Breitensuche
im Graphen.
Eine dünn besetzte Matrix kann von rechts (y = Ax) oder von links (y 0 = x0 A) mit einem
dichten Vektor multipliziert werden. In diesem Skript beschränken wir uns auf die Multiplikation
von rechts. Es ist im Allgemeinen einfach, die entsprechenden Algorithmen für die Matrixmultiplikation von links umzuformulieren. Einige Vertreter von Graphalgorithmen, die SpMV nutzen,
sind PageRank, BFS, Bellman-Ford und Prim’s MST-Algorithmus.
2.2.3. Addition dünner Matrizen (SpAdd)
Die Abkürzung bezieht sich auf den englischen Ausdruck sparse matrix addition. Die Operation
entspricht der Vereinigung von Graphen und berechnet C = A ⊕ B. Dabei steht die Operation
für einen beliebigen punktweisen, binären Operator ⊕ zwischen zwei Matrizen. Beispiele sind
Addition, Subtraktion, MIN & MAX (Minimum bzw. Maximum der Operanden), logisches UND
und logisches ODER.
2.2.4. Sparse matrix-sparse matrix multiplication (SpGEMM)
Die Abkürzung bezieht sich auf den englischen Ausdruck generalized sparse matrix-matrix multiplication. Diese Operation entspricht aus Graphen-Sicht einem Schritt einer Breitensuche von
mehreren Startknoten gleichzeitig aus bzw. APSP. Sie berechnet C = AB, wobei die Eingabematrizen A ∈ RM ×K und B ∈ RK×N beide dünn besetzt sind. SpGEMM findet häufig Verwendung
beim Arbeiten auf großen Graphen, z.B. bei der Graphenkontrakion, bei der algebraischen Formulierung von Peer Pressure Clustering (das wir in Kapitel 3 in der Variante Label Propagation
behandeln) oder Markov-Clustering sowie bei iterativen APD-Formulierungen (siehe z.B. Abschnitt 1.3.3.3).
Für die Berechnung der Matrixmulitplikation gibt es mehrere Möglichkeiten. Eine übliche
Methode berechnet den Eintrag C(i, j) mit Hilfe des Skalarproduktes der Zeile i von A und der
Spalte j von B (siehe Algorithmus 11). Angelehnt an das Skalarprodukt, wird dieser Ansatz
auch als inner product matrix multiply bezeichnet. Eine andere Möglichkeit besteht darin, das
Matrixprodukt als Summe von n Matrizen mit Rang eins zu berechnen. Jede dieser Matrizen
mit Rang eins ist das dyadische Produkt (outer product) einer Spalte k von A und einer Zeile k
von B (siehe Algorithmus 12 und Abbildung 2.2.2).
Eine weitere Möglichkeit ist die zeilen- bzw. spaltenweise Berechnung des Matrixprodukts.
Algorithmus 13 zeigt die spaltenweise Formulierung, hierbei wird die Spalte j von C als Linearkombination aus Spalten von A und den Nichtnull-Einträgen der Spalte j von B berechnet.
Abbildung 2.2.3 veranschaulicht dieses Konzept. Analog wird bei der zeilenweisen Formulierung
28
2. Datenstrukturen für dünn besetzte Matrizen
Algorithmus 11 : Matrixmultiplikation mit Hilfe des Skalarprodukts
Input : A : RM ×K , B : RK×N
Output : C : RM ×N
1 for i = 1 to M
2
for j = 1 to N
3
C(i, j) ← A(i, :) · B(:, j);
4
return C
Algorithmus 12 : Matrixmultiplikation mit Hilfe des dyadischen Produkts
Input : A : RM ×K , B : RK×N
Output : C : RS(M ×N )
1 C ←0
2 for k = 1 to K
3
C ← C + A(:, k) · B(k, :);
4
return C
Abbildung 2.2.2.: Schematische Matrixmultiplikation mit Hilfe des dyadischen Produkts
2.3. Tripel
29
Abbildung 2.2.3.: Schematische Darstellung der spaltenweisen Matrixmultiplikation
die Zeile i von C als Linearkombination aus Zeilen von B und Nichtnull-Einträgen der Zeile i
von A berechnet.
Algorithmus 13 : Spaltenweise Matrixmultiplikation
Input : A : RM ×K , B : RK×N
Output : C : RM ×N
1 C ←0
2 for j = 1 to N
3
for k where B(k, j) 6= 0
4
C(:, j) ← C(:, j) + A(:, k) · B(k, j);
5
return C
2.3. Tripel
Das Tripel- oder Koordinatenformat ist die einfachste Art, dünn besetzte Matrizen darzustellen. Hierbei wird für jeden Nichtnull-Eintrag A(i, j) 6= 0 ein Tripel (i, j, A(i, j)) gespeichert.
Jeder Eintrag eines Tripels wird üblicherweise in einem der drei Arrays A.I (Zeilenindizes), A.J
(Spaltenindizes) oder A.V (Werte) gespeichert, die die komplette§ Matrix A repräsentieren. Der
Speicherverbrauch pro Tripel beträgt bei 8-Byte-Integers 8 + 8 + 8 = 24 Byte pro NichtnullEintrag. In modernen Programmiersprachen ist die Repräsentation von Tupeln als Struktur in
einem Array einfacher und kann auch den Cache besser ausnutzen, da oft alle Werte eines Tripels
von Interesse sind und so nicht aus drei unterschiedlichen Arrays gelesen werden muss. Bei drei
unterschiedlichen Arrays kann es nämlich passieren, dass alle drei in dieselbe Cachezeile geladen
werden und sich gegenseitig verdrängen. Diese Cache-Optimierung wird auch als array merging
bezeichnet.
In diesem Kapitel werden wir das Tripelformat mit unterschiedlichen Ordnungen der Einträge
kennenlernen.
2.3.1. Ungeordnete Tripel
Die Tripel werden nicht sortiert, der Verwaltungsaufwand der Tripel ist somit sehr gering. Allerdings besteht daher beim Zugriff auf die Einträge einer Zeile oder Spalte keinerlei Lokalität,
d.h. im schlechtesten Fall müssen alle Tripel durchsucht werden, um einen bestimmten Eintrag
zu finden. Ein Beispiel einer Matrix in ungeordneter Tripeldarstellung zeigt Abbildung 2.3.1.
Bei der Berechunng von SpMV (y = Ax) spielt die Ordnung der Einträge aus theoretischer
Sicht keine Rolle, d.h. die RAM-Komplexität ist schon bei ungeordneten Tripeln optimal. Wenn
der Cache zuvor keine Einträge von A enthält, treten O(scan(A)) Cache-Fehlzugriffe auf. Zusätzlich wird für jedes Tripel (i, j, A(i, j)) ein Zugriff auf den j-ten Eintrag von x benötigt und
30
2. Datenstrukturen für dünn besetzte Matrizen
das Ergebnis dieser Multiplikation muss nach y(i) geschrieben werden. Nach unserer ModellAnnahme passen die dichten Vektoren x und y allerdings nicht in den Cache. Pro Tripel treten
also bis zu zwei zusätzliche Cache-Fehlzugriffe auf, d.h. die I/O-Komplexität von SpMV ist
nnz(A)/L + 2 · nnz(A) = O(nnz(A)).


19 0 11 0
 0 43 0 0 

A=
 0 0 0 0 
0 27 0 35
A.I
1
4
2
4
1
A.J
1
2
2
4
3
A.V
19
27
43
35
11
Abbildung 2.3.1.: Matrix in ungeordneter Tripeldarstellung
2.3.2. Zeilenweise geordnete Tripel
Falls die Tripel nach ihrer Zeilenzugehörigkeit geordnet werden, bleibt die Indizierung ineffizient. Ein schneller Zeilenzugriff ist ohne die Kenntnis des Startindex nicht möglich. Um auf die
Einträge einer Zeile i zuzugreifen, wird zunächst eine binäre Suche auf A.I verwendet. Diese
findet einen (beliebigen) Eintrag der Zeile i, von dem aus anschließend in beide Richtungen in
den restlichen Nichtnull-Einträgen dieser Zeile gesucht wird. Analog zu zeilenweise geordneten
Tripeln funktionieren auch spaltenweise geordnete Tripel. Falls die Einträge einer Zeile Spaltenindizes mit großem Abstand zueinander haben, kann sich die fehlende Sortierung auch hier
negativ auswirken, etwa bei SpMV.
2.3.3. Zeilendominant geordnete Tripel
Die dritte Möglichkeit der Tripeldarstellung ist die der zeilendominant geordneten Tripel. Hierbei
werden die Einträge zunächst wie bei zeilenweise geordneten Tripeln nach der Zeile sortiert und
anschließend innerhalb jeder Zeile noch nach der Spalte. Der Zugriff auf eine komplette Zeile
erfolgt wie bei den zeilenweise geordneten Tripeln, jedoch ist die Referenzierung eines einzelnen
Eintrags A(i, j) schneller. Hierfür reicht eine gewöhnliche Binärsuche allerdings nicht aus, da
Anfang und Ende der i-ten Zeile im Voraus nicht bekannt sind. Deshalb wird wie folgt verfahren:
1. Finde mittels binärer Suche ein Tripel das zur i-ten Zeile der Matrix gehört.
2. Führe von diesem Tripel eine unbeschränkte binäre Suche in beide Richtungen aus. Dabei
wird die Schrittgröße nach jeder Iteration verdoppelt. Die Suche terminiert, wenn in der
entsprechenden Richtung ein Tripel gefunden wird, das nicht zur i-ten Zeile gehört. Diese
beiden Tripel (eines aus jeder Richtung) bilden die Grenze.
3. Führe eine normale binäre Suche zwischen den beiden Grenztripeln aus.
Abbildung 2.3.2 veranschaulicht das Verfahren.
Die RAM-Komplexität für die Referenzierung beträgt O(log nnz(A) + log nnz(A(i, :)). Im
I/O-Modell kann eine einfache lineare Suche auf einem sortierten Array schneller sein als die
unbeschränkte binäre Suche. Das Suchen eines Elements in einer geordneten Menge mit N Elementen im I/O-Modell kostet mit Hilfe von B-Bäumen (siehe [BM72]) Θ(logL N ). Wird dafür
2.3. TripelSparse Matrices for Graph Algorithms
Chapter 13. Implementing
304
31
Step 3
A.I
10 11 11 12 12 12 12 12 12 12 12 12 13 13 13
A.J 18
5
12
2
3
4
7
10 11 13 16 18
2
9
11
A.V
90
76
57
89
19
96
65
21
11
54
31
44
34
28
28
Step 2
Abbildung 2.3.2.: Referenzierung
vonIndexing
A(i, j) im
zeilendominant
geordneten Tripelformat
Figure 13.4.
row-major
triples.
Element-wise indexing of A(12, 16) on row-major ordered triples.
values. Accesses to x are also with increasing indices, which is an improvement over
row ordered triples. However, memory strides when accessing x can still be high,
depending on the number of nonzeros in each row and the bandwidth of the matrix.
In the worst case, each access to x might incur a cache miss.
Bender et al. came up with cache-efficient algorithms for SpMV, using the
column-major layout, that have an optimal number of cache misses [Bender et al. 2007].
From a high-level view, their method first generates all the intermediate triples of
y, possibly with repeating indices. Then, the algorithm sorts those intermediate
triples with respect to their row indices, performing additions on the triples with
same row index as they occur. I/O optimality of their SpMV algorithm relies on the
existence of an I/O optimal sorting algorithm. Their complexity measure assumes
a fixed k number of nonzeros per column, leading to I/O complexity of
!
"
Abbildung 2.3.3.: Schematische Darstellung
von SpAdd auf zeilendominant
geordneten Tripeln
N
O scan(A) logZ/L
(13.10)
max{Z, k}
SpAdd is now more efficient even without using any auxiliary data structure.
A scanning-based array-merging algorithm is sufficient as long as we do not forget
allerdings ein normales Array verwendet, so treten bei der Suche im schlechtesten Fall log N
to sum duplicates while merging. Such an implementation has O(nnz (A)+nnz (B))
Cache-Fehlzugriffe
auf, was mehr sein kann als scan(N ). Deshalb werden die Kosten der Suche
RAM complexity and O(scan (A) + scan(B)) I/O complexity.*
in einer geordneten
Zeile einer
Matrix
folgt
definiert:
Row-major
ordered
tripleswie
allow
outer
product and row wise SpGEMM implementations at least as efficiently as row ordered triples. Indeed, some finer imsearch(A(i,
= min {log
:)), scan(A(i,
:))}In the case of
provements are
possibly by:))exploiting
the nnz(A(i,
more specialized
structure.
row wise SpGEMM, a technique called finger search [Brodal 2005] can be used to
improve the RAM complexity. While enumerating all triples (i, k, A) ∈ A(i, :), they
Für denare
Spaltenzugriff
sowie
ergibt sich
gegenüber
genaturally sorted
withSpAsgn-Operationen
increasing k values. Therefore,
accesses
to B(k,dem
:) arezeilenweise
also
ordneten Tripelformat
Verbesserung.
Bei SpMV
= Ax)
wirdfrom
sowohl
auf A als auch auf
with increasingkeine
k values.
Instead of restarting
the(y
binary
search
the beginning
of B, one can
use fingers and
only search the
yet zugegriffen.
unexplored subsequence.
y mit überwiegend
konsekutivem,
aufsteigendem
Index
Auch auf x Note
wird mit auf-
steigendem Index
zugegriffen, was eine Verbesserung gegenüber zeilenweise geordneten Tripeln
* These bounds
are optimal only if nnz (A) = Θ(nnz (B)); see [Brown & Tarjan 1979].
darstellt. Jedoch kann die Anzahl der Cache-Fehlzugriffe trotzdem hoch sein, abhängig von der
Anzahl der Nichtnull-Einträge in jeder Zeile und der Bandbreite der Matrix. Im schlimmsten Fall
kann jeder Zugriff auf x ein Cache-Fehlzugriff sein.
SpAdd mit zeilendominanten Tripeln ist ohne zusätzliche Hilfsdatenstruktur effizienter als
SpAdd auf
zeilenweise geordneten Tripeln. Das Scannen und Verschmelzen der sortierten Arrays
Downloaded 09 Dec 2011 to 129.174.55.245. Redistribution subject to SIAM license or copyright; see http://www.siam.org/journals/ojsa.php
genügt, wobei Duplikate addiert werden (siehe Abbildung 2.3.3). Daraus ergibt sich eine RAMKomplexität von O(nnz(A) + nnz(B)) und eine I/O-Komplexität von O(scan(A) + scan(B)).
Die dyadische und zeilenweise Matrix-Matrix-Multiplkation SpGEMM ist bei zeilendominant
geordneten Tripeln mindestens so effizient wie bei zeilenweise geordneten Tripeln.
32
2. Datenstrukturen für dünn besetzte Matrizen
2.4. CSR/CSC
Die populärsten und am häufigsten eingesetzten Formate dünn besetzter Matrizen sind Compressed Sparse Row (CSR) und Compressed Sparse Column (CSC). Beispielsweise verwendet
MATLAB das CSC-Format, um dünn besetzte Matrizen zu speichern [GMS92]. Wir beschränken
uns in diesem Skript auf das CSR-Format, das Gustavson 1972 als sparse row wise representation
eingeführt hat [Gus72]. Das CSC-Format ist symmetrisch zum CSR-Format. Das CSC-Format
schauen wir uns dann in verallgemeinerter Form für hyperdünne Matrizen genauer an.
2.4.1. CSR und Adjazenzlisten
Im Prinzip ist das CSR-Format fast identisch zur Adjazentlisten-Darstellung gerichteter Graphen.
Man spricht daher auch manchmal von Adjazenz-Arrays. Allerdings hat das CSR-Format in
der Praxis eine deutlich bessere Cache-Effizienz als Adjazenzlisten. Denn CSR verwendet statt
verketteter Listen insgesamt drei Arrays. Wegen des kontinuierlichem Speicherlayouts der Arrays
ist dies cacheeffizienter als N verkettete Listen. Die drei Arrays von CSR sorgen dafür, dass die
Einträge der Adjazenzlisten einer Matrix A ∈ RN×M kontinuierlich hintereinander gespeichert
werden:
• JC der Größe nnz speichert die Spaltenindizes der Nichtnull-Einträge
• NUM der Größe nnz speichert die Werte der Nichtnull-Einträge
• IR der Größe N +1 speichert für jede Zeile den Index des Zeilenstarts in den beiden anderen
Arrays
Im Sinne der Dualität zwischen dünn besetzter Matrix und Graphen ist es sinnvoll, bei IR
vom Knoten-Array zu sprechen und bei JC vom Kanten-Array. Das Knoten-Array speichert für
jeden Knoten den Offset (also die Startposition) im Kanten-Array. Demnach sind die NichtnullEinträge der i-ten Zeile in NUM(IR(i)) bis NUM(IR(i + 1) - 1) gespeichert und die entsprechenden Spaltenpositionen in dieser Zeile sind in JC(IR(i)) bis JC(IR(i + 1) - 1) gespeichert. In
Abbildung 2.4.1 ist die CSR-Darstellung der Matrix A von Abschnitt 2.3.1 angegeben. Die Pfeile
in der Adjazenzliste repräsentieren Zeiger auf die Speicherstellen während sie im CSR-Format
Indirektionen über die Offset-Indizierung des IR Arrays darstellen.
Die bessere Cache-Effizienz gegenüber Adjazenzlisten ist durch die moderne Computer-Architektur
zu erklären. Um auf alle Nichtnull-Einträge einer gegebenen Zeile i zuzugreifen, entstehen im
CSR-Format maximal dnnz(A(i, :))/Le Cache-Fehlzugriffe. Ein gleicher Zugriff auf das AdjazenzlistenFormat erzeugt im worst-case nnz(A(i, :)) Cache-Fehlzugriffe. Die gesteigerte Cache-Effizienz
kommt allerdings zu einem Preis: Das Einfügen und Löschen von Nichtnull-Einträgen ist ineffizient und sollte möglichst vermieden werden. Daher ist das CSR-Format am besten für statische
Graphen geeignet. Dies stellt aber keine große Einschränkung dar, da außer SpAsgn alle grundlegenden Operationen aus Abschnitt 2.2 mit statischen Graphen arbeiten.
2.4.2. Grundoperationen mit CSR
Im Gegensatz zum Tripel-Format ermöglicht das CSR-Format eine Zeilenindizierung in konstanter Zeit. Das Iterieren über alle Einträge einer Zeile i hat im RAM-Modell eine Komplexität von
O(nnz(A(i, :)) und im I/O-Modell O(scan(A(i, :)). Diese Eigenschaft macht das CSR-Format zu
einer sehr guten Datenstruktur für zeilenweises SpRef. Der Zugriff auf einen einzelnen NichtnullEintrag A(i, j) benötigt mit Hilfe einer binären Suche sowohl im RAM- als auch im I/O-Modell
maximal O(log nnz(A(i, :))) Zeit, jedoch kann eine lineare Suche in der Praxis, insbesondere bei
2.5. Multiplikation dünn besetzter Matrizen
33
Abbildung 2.4.1.: Matrix A als Adjazenzliste (links) und im CSR-Format (rechts)
Knoten mit kleinem Grad, bezüglich der Cache-Performance besser sein. Beim spaltenweisen Zugriff ist das CSR-Format hingegen ineffizient. Ein solcher Zugriff sollte daher vermieden werden.
Hier bietet CSR gegenüber dem Tripel-Format keinerlei Vorteile.
Für manche Algorithmen ist ein schneller Zugriff auf das Diagonalelement wichtig. Hierfür
existieren unterschiedliche Abwandlungen des CSR-Formats, z.B. können die Diagonaleinträge
zusätzlich in einem separaten Array gespeichert werden oder es wird das normale CSR-Format
genutzt, wobei das erste Element jeder Zeile immer den Diagonaleintrag repräsentiert (auch wenn
dieser 0 ist).
2.4.2.1. SpMV
Algorithmus 14 zeigt, wie SpMV bei einer dünn besetzten Matrix A im CSR Format ausgeführt
werden kann. SpMV im CSR-Format bietet im Vergleich zum zeilendominant geordneten Tripelformat ähnliche Performance. Wenn N nnz gilt, dann hat das CSR-Format einen Vorteil,
da innerhalb einer Zeile nur ein Index (A.JC(k)) pro Iteration ausgewertet werden muss und
beim Tripelformat zwei Indizes (A.I(k) und A.J(k)). Daher hat das CSR-Format bis zu Faktor
2 weniger Cache-Fehlzugriffe als das zeilendominant geordnete Tripelformat. Außerdem benötigt
es weniger Speicher, wenn die Zahl der Nichtnull-Einträge deutlich größer ist als die Zahl der
Zeilen bzw. Knoten.
Algorithmus 14 : SpMV (y = Ax) im CSR-Format
1
2
3
4
5
Input : A : RM ×N , x : RN
Output : y : RM
y←0
for i = 1 to M do
for k = A.IR(i) to A.IR(i) − 1 do
y(i) ← y(i) + A.N U M (k) · x(A.JC(k))
return y
2.5. Multiplikation dünn besetzter Matrizen
In diesem Abschnitt wollen wir die Matrixmultiplikation auf dünn besetzten Matrizen (SpGEMM)
im CSR-Format genauer betrachten. Dabei wird eine Hilfsdatenstruktur eingeführt, die zur Berechnung der Zwischenergebnisse dient. Hinsichtlich des Produkts von zwei dünn besetzten Matrizen C = A · B ist zu erwähnen, dass C nicht wieder dünn besetzt sein muss. Außerdem muss
das Produkt zweier symmetrischer Matrizen A und B nicht symmetrisch sein.
34
2. Datenstrukturen für dünn besetzte Matrizen
Da der Zugriff auf eine Zeile und die Iteration über eine Zeile im CSR-Format sehr effizient
möglich sind, ist die zeilenweise Matrixmultiplikation die beste Wahl.
2.5.1. Der Sparse Accumulator
Die meisten Algorithmen zur Ausführung von Matrixoperationen, die als Ergebnis wieder eine
Matrix liefern, berechnen diese Zeile für Zeile. Daher ist es sinnvoll, die gerade zu berechnende
Zeile in einer geeigneten Datenstruktur abzuspeichern, die das Indizieren einer Spalte in dieser
Zeile in konstanter Zeit erlaubt, um Einträge schnell einfügen zu können. Die Sparse Accumulator
(SPA) Datenstruktur erfüllt diese Anforderung und speichert temporär die jeweils aktive Zeile.
Da es ein abstrakter Datentyp ist, existieren unterschiedliche Varianten des SPA. Für diese
Vorlesung verwenden wir die folgende Definition: w ist der dichte Vektor der Werte, b ist der
dichte, boolesche Vektor für „Besetzt”-Einträge und LS ist die Liste, welche eine ungeordnete Liste
von Indizes der Nichtnull-Einträge speichert. Abbildung 2.5.1 veranschaulicht die Datenstruktur.
Die Accumulate-SPA Funktion, die in Algorithmus 15 definiert ist, addiert einen Skalar (value)
zu einer bestimmten Position (pos) des SPA. Diese Funktion arbeitet in konstanter Zeit. Um die
Nichtnull-Einträge des SPA auszugeben, wird O(nnz(SP A)) Zeit benötigt. Der Pseudocode für
Output-SPA ist in Algorithmus 16 beschrieben. Dabei greift der SPA nur auf Werte zu, die auch
tatsächlich vorhanden sind. Es ist wichtig, den Sparse Accumulator nur einmal am Anfang zu
initialisieren, da dies O(M ) Zeit benötigt. Das Zurücksetzen des SPA für eine neue Zeile geht
in O(nnz(SP A)), da hierfür die Einträge in LS verwendet werden können, um alle NichtnullEinträge der vorherigen Zeile zu erreichen und nur diese Indizes von w und b zu löschen.
In der Praxis treten bei dieser Datenstruktur allerdings häufig Cache-Fehlzugriffe auf. Da
der SPA Arrays der Größe N speichert (bei einer M × N Matrix) passt die Datenstruktur
nach der zweiten Modell-Annahme in Abschnitt 2.1.2 nicht komplett in den Speicher weshalb im
worst-case pro flop ein Cache-Fehlzugriff auftritt. Zusätzlich treten bis zu scan(A) weitere CacheFehlzugriffe beim Zugriff auf die Nichtnull-Einträge von A auf, also insgesamt O(scan(A)+f lops)
Cache-Fehlzugriffe im worst-case.
Abbildung 2.5.1.: SPA Datenstruktur
Algorithmus 15 : AccumulateSPA
Input : SPA, value, pos
1 if SPA.b(pos) then
2
SP A.w(pos) ← SP A.w(pos) + value
3 else
4
SP A.w(pos) ← value
5
SP A.b(pos) ← true
6
Insert(SP A.LS, pos)
2.6. Hyperdünne Matrizen
Algorithmus 16 : OutputSPA
Input : SPA, val, col, nzcur
Output : nzi
1 cptr ← head(SP A.LS)
2 nzi ← 0
3 while cptr 6= N IL do
4
5
6
7
35
// number of nonzeros in the current row of C
col(nzcur + nzi) ← element(cptr)
val(nzcur + nzi) ← SP A.w(element(cptr))
nzi ← nzi + 1
Advance(cptr)
// for all entries in SPA.LS
// set column index
// set value
2.5.2. SpGEMM mit CSR
Die zeilenweise Matrixmultiplikation im CSR-Format erfolgt mit Hilfe des Sparse Accumulators
und ist in Algorithmus 17 dargestellt, Abbildung 2.5.2 stellt eine Iteration der äußersten Schleife
dar und Abbildung 2.5.3 zeigt ein Beispiel mit Zahlen.
Algorithmus 17 : CSR-SpGEMM
Input : A : RN ×K , B : RK×N
Output : C = AB
1 SetSPA(SP A)
// set w = 0, b = 0 and create empty list LS
2 C.IR(1) ← 1
3 for i ← 1 to M do
4
for k ← A.IR(i) to A.IR(i + 1) − 1 do
5
for j ← B.IR(A.JC(k)) to B.IR(A.JC(k) + 1) − 1 do
6
value ← A.N U M (k) · B.N U M (j)
7
AccumulateSPA(SP A, value, B.JC(j))
8
9
10
nznew ← OutputSPA(SP A, C.N U M, C.JC, C.IR(i))
C.IR(i + 1) ← C.IR(i) + nznew
ResetSPA(SP A)
// reset w = 0, b = 0 and empty LS
2.6. Hyperdünne Matrizen
Definition. Eine Matrix A ∈ RN×M ist hyperdünn (engl.: hypersparse), wenn nnz(A) < N gilt.
Hyperdünne Matrizen kommen im Bereich der linearen Algebra – zumindest in sequentiellen
Algorithmen – eher selten vor, da eine Matrix mit vollem Rang bereits nnz ≥ N erfüllt. Bei
Graphen sind hyperdünne Matrizen allerdings ein häufiges Muster. So bilden beispielsweise unzusammenhängende Graphen mit vielen Einzelknoten hyperdünne Matrizen. Aber auch bei der
2D-Partitionierung eines Graphen bzw. einer Matrix für die Parallelverarbeitung ergeben sich
häufig hyperdünne Matrizen. Große Matrizen müssen häufig verteilt gespeichert werden, da sie
entweder zu groß für den Hauptspeicher eines einzelnen Rechners sind oder sie sind zu groß, um
eine ausreichend schnelle Berechnung auf einem einzelnen Rechner zu gewährleisten. Dabei sind
zwei verschiedene Partitionierungsvarianten üblich:
36
2. Datenstrukturen für dünn besetzte Matrizen
Abbildung 2.5.2.: Ein Iterationsschritt des CSR-SpGEMM Algorithmus
• 1D-Partitionierung: Jeder Prozessor erhält bestimmte Zeilen der Matrix. Dies entspricht
einer Knotenpartitionierung des Graphen.
• 2D-Paritionierung: Jeder Prozessor erhält einen Block der Matrix. Dies entspricht einer
Kantenpartitionierung des Graphen.
Wie bereits erwähnt, ergeben sich insbesondere bei der 2D-Partitionierung häufig Blöcke mit
sehr wenigen Nichtnull-Elementen. Obwohl CSR bzw. CSC recht effiziente Speicherformate für
dünn besetzte Matrizen mit nnz = Ω(N ) sind, eignen sie sich weniger gut für solche hyperdünne
Matrizen. Betrachten wir beispielsweise das CSC-Format bei einer 2D-Partitionierung. Nehmen
√
√
wir dafür an, dass jeder Prozessor einen quadratischen Block der Größe (N/ p) × (N/ p)
der Matrix erhält (p :=# Prozessoren). Wenn nun jede dieser Teilmatrizen im CSC-Format
√
gespeichert wird, beläuft sich der parallele Gesamtspeicherverbrauch auf O((N/ p) · p + nnz) =
√
O(N p + nnz). Speichert man die Matrix hingegen sequentiell auf einem einzigen Prozessor,
beträgt der Gesamtspeicherverbrauch im CSC-Format nur O(N + nnz). Wenn die Anzahl der
√
Prozessoren steigt, so wird der N p Term dominant und der Speicherverbrauch im parallelen
Fall steigt. Es ist allerdings sehr wünschenswert, dass der Speicherverbrauch unabhängig von der
Zahl der Prozessoren ist. Neben der Skalierbarkeit der Problemgröße hat diese Ineffizienz von
CSC nämlich auch Einfluss auf die Skalierbarkeit von Algorithmen. Darum definieren wir im
folgenden Abschnitt eine neue Datenstruktur für hyperdünne Matrizen.
2.7. DCSC
Die DCSC-Datenstruktur (DCSC steht für doubly compressed sparse columns) hat die folgenden
Eigenschaften:
• Speicherverbrauch von O(nnz), d.h. unabhängig von der Anzahl der Prozessoren und der
Matrixdimension
• Schneller Zugriff auf die Spalten der Matrix
• SpGEMM skaliert mit zunehmender Anzahl von Null-Einträgen
2.7. DCSC
37
Abbildung 2.5.3.: Zeilenweise Matrix-Matrix-Multiplikation (SpGEMM)
Als Beispiel betrachten wir die 9×9 Matrix A mit 4 Nichtnull-Einträgen, die in der Tripeldarstellung in Abbildung 2.7.1 zu sehen ist. Abbildung 2.7.2 zeigt die Matrix im CSC-Format; hier gibt
es redundate Einträge im Array JC. Die wesentliche Idee des DCSC-Formats ist die Verwendung
der von CSC bekannten Arrays IR und NUM und der Komprimierung des JC-Arrays, um Wiederholungen zu vermeiden. Dafür braucht es zusätzlich ein Array CP, welches die Startindizes für
IR und NUM der Spalten mit Nichtnull-Einträgen bzw. die kumulierte Anzahl aller NichtnullEinträge bis zur jeweiligen Spalte angibt (Indizes beginnen bei 1). Die Matrix A im DCSC-Format
ist in Abbildung 2.7.3 zu sehen. Das AUX-Array wird nur bei Bedarf angelegt, um eine schnelle
Spaltenindizierung zu ermöglichen. Es speichert Zeiger auf Nichtnull-Spalten (also Spalten, die
mindestens einen Nichtnull-Eintrag enthalten). Die Gesamtanzahl der Nichtnull-Spalten wollen
wir mit nzc bezeichnen. Jeder Eintrag im AUX-Array bezieht sich auf einen Spaltenblock der
Größe d(N + 1)/nzce und zeigt auf die erste Nichnull-Spalte in diesem Block. Das DCSC-Format
hat somit einen Speicherverbrauch von O(nnz), da für die Größen der verwendeten Arrays gilt:
|NUM| = |IR| = nnz, |JC| = nzc, |CP| = nzc und |AUX| ≈ nzc.
A.I
6
8
4
2
A.J
1
1
7
8
A.V
0.1
0.2
0.3
0.4
Abbildung 2.7.1.: Matrix A im Tripel Format
38
2. Datenstrukturen für dünn besetzte Matrizen
JC =
1
3
IR =
6
0.1
NUM =
3
3
3
3
3
4
8
4
2
0.2
0.3
0.4
5
5
Abbildung 2.7.2.: Matrix A im CSC Format
AUX =
JC =
CP =
IR =
NUM =
1
1
1
6
0.1
2
7
3
8
0.2
4
8
4
4
0.3
4
5
2
0.4
Abbildung 2.7.3.: Matrix A im DCSC Format
2.8. Multiplikation hyperdünner Matrizen
In diesem Abschnitt wollen wir die sequentielle Matrixmultiplikation C = A · B auf hyperdünnen
Matrizen (HypSpGEMM) kennen lernen. Diese basiert auf der Summierung von dyadischen Produkten, weshalb die Operation schnellen Zugriff auf die Zeilen von B benötigt. Hierfür könnte
man jede Eingabematrix sowohl im DCSC- als auch im DCSR-Format (entspricht der Transponierten im DCSC-Format) speichern, was allerdings den Speicherverbrauch verdoppelt. Hier
verwenden wir eine Lösung, bei der B in einem Vorverarbeitungsschritt transponiert wird (Kosten: trans(B)). Die tatsächliche Laufzeit für das Transponieren beträgt je nach Implementierung
O(N + nnz(B)) oder O(nnz(B) · log nnz(B)).
Als erste Beobachtung fällt uns beim DCSC-Format auf, dass das JC-Array bereits sortiert ist,
d.h. A.JC gibt uns die sortierten Indizes der Nichnull-Spalten und B T .JC gibt uns die sortierten
Indizes der Nichtnull-Zeilen. Der naive Algorithmus berechnet jeweils das dyadische Produkt Ck
der k-ten Spalte von A und der k-ten Zeile von B für alle k ∈ N und summiert die so erhaltenen
N Rang-1 Matrizen zu C auf. Um nur die Indizes zu berücksichtigen, deren dyadisches Produkt
nichttrivial ist, wird ein Vorverarbeitungsschritt benötigt, der Isect := A.JC ∩B T .JC berechnet.
Dieser Schritt benötigt O(nzc(A) + nzr(B)) Zeit, da |A.JC| = nzc(A) und |B T .JC| = nzr(B).
Abbildung 2.8.1 veranschaulicht die Bestimmung der Menge Isect.
Für die Nichtnull-Einträge der Matrix Ck gilt: (Ck )ij = Aik · Bkj 6= 0 ⇐⇒ Aik 6= 0 ∧ Bkj 6= 0.
Daher werden im nächsten Schritt |Isect| kartesische Produkte gebildet und in fiktiven Listen der
Größe nnz(A(:, k)) · nnz(B(k, :)) gespeichert. In Abbildung 2.8.2 ist dieser Schritt anhand eines
Beispiels zu sehen. Die Listen sind fiktiv, da sie nicht explizit gespeichert werden. Sie können
sortiert erstellt werden, da die Nichtnull-Einträge in einer Spalte bzw. Zeile aufsteigend nach dem
Zeilen- bzw. Spaltenindex sortiert sind. Nun verschmilzt der Algorithmus die sortierten Listen,
wobei die Einträge mit gleicher Position (i, j) in C aufsummiert werden. Diese Phase entspricht
dem k-fachen Verschmelzen (k-way multiway merge) sortierter Liste, wie es etwa aus MergeSort
bekannt ist. Der einzige Unterschied besteht darin, dass die Listen nie explizit erstellt werden,
sondern jeder Eintrag auf Anforderung berechnet wird.
Das Verschmelzen benutzt eine Prioritätswarteschlange mit binärem Heap der Größe ni :=
|Isect|. Der Wert eines Eintrags ist der NUM-Wert und der Schlüssel das Indexpaar (i, j) in
spaltendominanter Reihenfolge. Die Idee besteht darin, wiederholt das Minimum min aus der
Warteschlange zu entfernen und das nächste Element aus der fiktiven Liste von min einzufügen.
Mehrere Elemente mit demselben Schlüssel werden dabei akkumuliert. Für jede arithmetische
Operation pro Eintrag in C wird eine Extract-Min Operation
benötigt, d.h. die Zeitkomplexität
P
dieser Phase beträgt O(f lops · log ni ), wobei f lops = k∈Isect nnz(A(:, k)) · nnz(B(k, :)). Die
2.9. Weiterführende Literatur
39
Abbildung 2.8.1.: Bestimmung der Menge Isect
Speicherkomplexität beträgt O(nnz(C) + ni) - nnz(C) für die Ausgabematrix und ni für die
Prioritätswarteschlange. Die Ausgabe dieser Phase ist eine Warteschlange mit NUM-Werten in
spaltendominanter Sortierung.
Als letzter Schritt erstellt der Algorithmus aus der Warteschlange der vorherigen Phase die
DCSC-Datenstruktur für die Matrix C, was noch einmal O(nnz(C)) Zeit und Speicher benötigt.
Die Gesamtzeitkomplexität beträgt O(trans(B) + nzc(A) + nzr(B) + f lops · log ni). Der Term
nnz(C) taucht hier nicht auf, da nnz(C) ≤ f lops gilt. Es ist noch zu erwähnen, dass die Kosten
für das Transponieren der Matrix B (trans(B)) in der Praxis bei Amortisierung vernachlässigbar sind. Algorithmus 18 zeigt den kompletten Pseudocode der HypSpGEMM-Operation. Die
Funktion CartM ultInsert generiert das nächste Element der j-ten fiktiven Liste und fügt es
in die Prioritätswarteschlange ein. Die Funktion IncrementList verschiebt den Zeiger auf das
nächste Element der j-ten fiktiven Liste oder löscht die Liste, wenn sie leer ist.
2.9. Weiterführende Literatur
Dieses Vorlesungskapitel basiert vor allem auf den Kapiteln 13 und 14 im Buch Graph Algorithms
in the Language of Linear Algebra [KG11]. Dort finden Sie auch eine ausführlichere Betrachtung
zur parallelen Multiplikation von dünn besetzten Matrizen.
40
2. Datenstrukturen für dünn besetzte Matrizen
Abbildung 2.8.2.: Bestimmung der kartesischen Produkte und Speicherung in fiktiven Listen
Algorithmus 18 : HypSpGEMM
Input : A : RN ×K , B : RK×M
Output : C = AB
1 isect ← Intersection(A.JC, B T .JC)
// intersection of sorted column arrays
2 for j ← 1 to |isect| do
// create first element of fictitious list and insert it into PQ
3
CartMultInsert(A, B T , P Q, isect, j)
4
IncrementList(isect, j)
5
6
7
8
9
10
11
12
13
14
15
while IsNotFinished(isect) do
(key, value) ← ExtractMin(P Q)
(product, j) ← Unpair(value)
if key 6= Back(Q) then
Enqueue(Q, key, product)
else
UpdateBack(Q, product)
// extract next element from PQ
// insert non-existing element
// update existing element on the fly
if ISN OT EM P T Y (isect(j)) then
// insert appropriate list element into PQ
CartMultInsert(A, B T , P Q, lists, isect, j)
IncrementList(isect, j)
ConstructDCSC(Q)
41
3. Clusteranalyse von Graphen
In diesem Kapitel wollen wir uns mit der Clusteranalyse in Graphen beschäftigen. Dabei handelt
es sich um die Problemstellung, „natürliche” Gruppen in Graphen zu bestimmen. Salopp könnte
man dazu auch „Strukturierung des Chaos” im Graphen sagen. Das Bestimmen von Clustern
ist eine weitverbreitete Analysemethode, sie findet unter anderem Anwendung in den Bereichen
Marketing und Werbung, in der Strukturvorhersage, im Maschinellen Lernen und im Data Mining, bei der Bildsegmentierung sowie in vielen weiteren Gebieten.
In der Forschung werden die Begriffe Clusteranalyse, Clustering und Community Detection oft
anhand verschiedener Eigenschaften der Problemstellung und/oder der eingesetzten Algorithmen
unterschieden. Der Einfachheit halber wollen wir das in diesem Kapitel nicht tun und die Begriffe synonym verwenden, was auch nicht selten in Forschungsarbeiten zum Thema geschieht.
Clustering-Algorithmen lassen sich in zahlreiche Algorithmenklassen einteilen, einige dieser Algorithmen wollen wir in diesem Kapitel kennen lernen.
Bevor wir uns mit den Algorithmen zur Clusteranalyse beschäftigen können, benötigen wir
zunächst eine formale Definition einer Clusterung bzw. eines Clusters.
Definition 3.1. Sei G = (V, E) ein ungerichteter, einfacher (schlichter) Graph. Eine Clusterung C = (C1 , . . . , Ck ) ist eine Partitionierung der Knotenmenge V in nicht-leere, disjunkte
Teilmengen, deren Vereinigung V überdeckt. Eine solche Teilmenge Ci heißt Cluster.
Korollar 3.2. Jede Clusterung C kann eindeutig durch die Äquivalenzrelation (reflexiv, symmetrisch, transitiv)
u ∼C v :⇔ ∃Ci ∈ C : u, v ∈ Ci
beschrieben werden. Die Cluster Ci entsprechen genau den Äquivalenzklassen.
3.1. Label Propagation
Die Idee des Label-Propagation-Algorithmus (LPA) besteht darin, jedem Knoten bereits von
Anfang an eine Clusternummer (Label ) zuzuordnen. Iterativ übernimmt jeder Knoten dann das
Label, das die meisten seiner direkten Nachbarn haben. Ein Beispiel davon ist in Abbildung 3.1.1
zu sehen, bei dem Knoten 4 noch zum falschen Cluster (blau) gehört.
3.1.1. Der Algorithmus
Gegeben ist also ein Graph G = (V, E) mit einer initialen Clusterung C. Als initiale Clusterung
wird, wie im klassischen Label Propagation Algorithmus, jeder Knoten einem eigenen Cluster
zugeordnet (Ein-Knoten-Clusterung), oder sie kann von einem anderen Algorithmus stammen,
z.B.:
• Ausführung einer Runde des Luby-Algorithmus zur Berechnung einer maximal unabhängigen Menge (Maximum Independent Set). Die Zuordnung der restlichen Knoten, die nicht
zur unabhängigen Menge gehören, erfolgt an den nächstgelegenen Knoten, der in der unabhängigen Menge enthalten ist.
42
3. Clusteranalyse von Graphen
6
8
7
4
2
1
5
3
Abbildung 3.1.1.: Beispielgraph mit Clusterung
• Berechnung einer Startlösung durch ein Multilevel-Verfahren. Hierbei wird der Graph zunächst rekursiv vergröbert um dann auf der gröbsten Ebene eine Startlösung zu berechnen.
Während der Rückkehr aus der Rekursion wird die Lösung stufenweise verbessert.
Die experimentelle Erfahrung zeigt allerdings, dass LPA auf einem Graphen mit guter ClusterStruktur robust gegenüber der initialen Clusterung ist.
Gesucht ist nun eine bessere Clusterung C 0 . Der Algorithmus geht dabei iterativ (oder rekursiv)
wie folgt vor:
• Stimmabgabe: Jeder Knoten stimmt dafür, dass seine Nachbarn zum eigenen Cluster gehören.
• Zuweisung: Jeder Knoten wird nach der Berechnung aller Stimmabgaben dem benachbarten
Cluster mit den meisten Stimmabgaben zugeordnet, dies kann natürlich auch das eigene
Cluster sein.
Ist der Einfluss bzw. die Stimmanzahl verschiedener benachbarter Cluster gleich hoch, so wird
dieser Konflikt beliebig aufgelöst, bspw. indem der Cluster mit der kleinsten Clusternummer
gewählt wird.
Der Pseudocode ist in Algorithmus 19 abgebildet und Abbildung 3.1.2 zeigt einen Schritt
des Algorithmus mit der Ausgangssituation von Abbildung 3.1.1. Dabei wurden die Anzahl der
Kanten von jedem Cluster zu jedem Knoten gezählt. Für jeden Knoten wurde dabei implizit eine
Schleife mitgezählt.
3.1.2. Probleme
Ein Problem des Algorithmus liegt in den unterschiedlichen Knotengraden, die im Graphen vorkommen können. Besonders bei Netzwerken der realen Welt wie beispielsweise sozialen Netzwerken oder manchen Transportnetzwerken treten stark unterschiedliche Knotengrade auf. Besonders wichtig ist dies bei gerichteten Netzwerken bzw. Graphen (Ein- und Ausgangsgrad können
hier sehr unterschiedlich sein). Dieses Problem hat zur Folge, dass einige Knoten sehr starken
Einfluss bei der Stimmabgabe haben. Eine mögliche Lösung besteht darin, eine Normalisierung
der Abstimmung durchzuführen. Hierfür werden beispielsweise die Kantengewichte der ausgehenden Kanten jedes Knotens durch die Summe aller ausgehenden Kantengewichte geteilt um
die Stimmen jedes Knotens auf 1 zu normalisieren.
Ein weiteres Problem stellen Knoten mit Grad 1 dar. Hier ist nicht klar, ob diese einen eigenen
Cluster bilden sollen oder beser zum Cluster des Nachbarn hinzugefügt werden sollten.
3.1. Label Propagation
Algorithmus 19 : Label Propagation
Input : G = (V, E) : Graph, θ : Konvergenz-Schranke
Output : ζ : V → N : Communities
1 for v ∈ V do
2
ζ(v) ← id(v)
3
4
5
6
7
8
9
10
11
12
13
14
15
updated ← |V |
Vactive ← V
while updated > θ do
updated ← 0
for v ∈ {u ∈ VactiveP: deg(u) > 0} do
l∗ ← argmaxl { u∈N (v):ζ(u)=l ω(v, u)}
43
// Initiale Clusterung
// Stimmabgabe
// Zuweisung
if ζ(v) 6= l∗ then
ζ(v) ← l∗
updated ← updated + 1
Vactive = Vactive ∪ N (v)
else
Vactive ← Vactive \ {v}
return ζ
Bei einem kleinen Cluster ist es wahrscheinlich, dass dieser von einem anderen Cluster “aufgesogen” wird, wenn zu diesem mehrere Kanten existieren. Es ist in diesem Fall anwendungsabhängig, ob man diesen Effekt verhindern will oder nicht. Eine Möglichkeit, dieses Phänomen zu
verhindern, besteht wiederum in der Normalisierung der Abstimmung, allerdings unter Berücksichtigung der Clustergröße. Dafür wird der Einfluss bzw. die Anzahl der Stimmen mit einem
Stärkeexponenten skaliert, genauer werden die ausgehenden Kantengewichte jedes Knotens durch
die Größe seines Clusters, potenziert um einen Wert 0 ≤ p ≤ 1, geteilt. Der Exponent p kann
während der Laufzeit verändert werden um die Änderungen in Anzahl und Größe der Cluster
widerzuspiegeln.
3.1.3. Komplexität
3.1.3.1. Raumkomplexität
Werden die Stimmen als Liste an jedem Knoten verwaltet, so reichen insgesamt |E| Listeneinträge
über alle Kanten gesehen, da jede Kante in jeder Iteration einmal Einfluss nehmen kann.
3.1.3.2. Zeitkomplexität
Der Vorteil des LPA liegt in der Laufzeit. Jede Iteration benötigt O(|E|) Zeit und es konnte
empirisch gezeigt werden, dass der Algorithmus bereits nach wenigen Iterationen, typischerweise
O(1), einen stabilen Zustand erreicht, wenngleich dies bisher noch nicht mathematisch bewiesen
wurde. In der Praxis hat sich gezeigt, dass die Anzahl der Iterationen eher von der Struktur des
Graphen abhängt und weniger von dessen Größe. Wenn der Graph eine gute Cluster-Struktur
besitzt, so ergibt sich (zumindest aus empirischer Sicht) eine Gesamtlaufzeit von O(|E|).
44
3. Clusteranalyse von Graphen
B: 1
R: 2
B: 0
R: 3
B: 4
R: 1
B: 5
R: 0
B: 2
R: 3
B: 3
R: 0
B: 1
R: 3
B: 3
R: 1
B: 0
R: 3
B: 4
R: 1
B: 1
R: 4
B: 0
R: 3
B: 3
R: 0
B: 4
R: 1
B: 3
R: 1
B: 0
R: 4
Abbildung 3.1.2.: Iterationsschritt des Algorithmus
3.1.4. Algebraische Formulierung
|V |×|V |
Definition 3.3. Sei C ∈ F2
die Matrix, für die gilt: Cij = 1 gdw. Knoten j befindet sich
in Cluster i. C repräsentiert also die Clusterung des Graphen.
Bemerkung. Als Startlösung wird C = I gewählt.
Definition 3.4. Sei A die gewichtete Adjazenzmatrix des Graphen. Dann definieren wir T = CA
als die Stimmauszählungsmatrix (engl.: tally matrix ).
Bemerkung. Es gilt Tij = k gdw. es k Stimmen für den Knoten j in Cluster i gibt.
Ist die Stimmabgabe abgeschlossen, erfolgt die Zuweisung der Clusterung wie folgt:
m = T max.
C = m . == T
|V |
Hier wird für jeden Knoten in m ∈ R+ die maximale Anzahl Stimmen, die er in einem der
Cluster besitzt, gespeichert und anschließend daraus die neue Clusterung C generiert. Algorithmus 20 zeigt den Pseudocode für die algebraische Formulierung des LPA.
Weitere Operationen sind:
• Normalisierung 1 (Entschärfung verschiedener Knotengrade):
3.1. Label Propagation
45
Algorithmus 20 : Algebraische Formulierung des Label Propagation Algorithmus
|V |×|V |
1
2
3
4
5
6
7
|V |×|V |
Input : G = A : R+
, Ci : F2
|V |×|V |
Output : Cf : F2
T ← Ci A
m ← T max.
Cf ← m . == T
if Ci == Cf then
return Cf
else
return LabelPropagation(G, Cf )
w = A +.
A = 1/w .x A
• Normalisierung 2 (kleine Cluster und Einzelknoten erhalten):
w = C +.
A = (1/w .ˆp) .x A
• Konflikte:
Finde in jeder Spalte von T das erste Maximum
3.1.4.1. Raumkomplexität
Algorithmus 20 verwendet die folgenden Variablen:
Name
Typ
Anzahl Elemente
A
T
Ci
Cf
m
|V |×|V |
R+
|V |×|V |
R+
|V |×|V |
F2
|V |×|V |
F2
|V |
R+
O(|E|)
O(|E|)
O(|V |)
O(|V |)
O(|V |)
T benötigt nur O(|E|) Einträge, da jede Kante einer Stimme entspricht und es demnach nicht
mehr Stimmen als Kanten im Graphen geben kann. Der Gesamtspeicherverbauch der algebraischen Formulierung beläuft sich demnach auf O(|E|).
3.1.4.2. Zeitkomplexität
Da jede Kante genau einer Stimme entspricht benötigt die Stimmabgabe O(|E|) Operationen,
gleiches gilt für die Auszählung. Wenn der Algorithmus p Durchläufe benötigt, beträgt die Gesamtlaufzeit O(p·|E|). Wird wie beim normalen Label Propagation Algorithmus davon ausgegange, dass nur wenige Iterationen nötig sind (also p eine Konstante ist), so hat auch die algebraische
Formulierung eine Laufzeit von O(|E|).
46
3. Clusteranalyse von Graphen
3.2. Markov Clustering
Ein alternativer Ansatz ist das sogennante Markov-Clustering. In diesem Abschnitt wollen wir
diesen Ansatz vorstellen und ihn mit dem LPA vergleichen.
Definition 3.5. Ein Random Walk ist ein Pfad, der auf einem beliebigen Knoten j startet
und dann zufällig und gleichverteilt über einen Nachbarn i von j verläuft. Von Knoten i wird
dieser Prozess fortgesetzt.
Abbildung 3.2.1.: Schematische Darstellung eines Random Walks in einem Graphen
Abbildung 3.2.1 zeigt schematisch einen Random Walk in einem Graphen. Der Markov-ClusteringAlgorithmus (MCL) basiert auf Random Walks. Die Idee dabei ist, dass ein Random Walk mit
hoher Wahrscheinlichkeit lange in einem dichten Gebiet (also einem Cluster) verweilt, bevor er
eine der wenigen externen Kanten findet, über die er das Gebiet verlassen kann.
Definition 3.6. Eine n × n Matrix M heißt Markov-Matrix, wenn alle Einträge nichtnegativ
sind und die Summe jeder Spalte 1 ergibt. Man nennt M dann auch spaltenstochastisch.
Definition 3.7. Sei G ein gewichteter Graph und A die gewichtete Adjazenzmatrix von G.
Weiter sei D die Diagonalmatrix der Spaltensummen von A. Dann definieren wir M := AD−1
als Transitionsmatrix von G.
Bemerkung 3.8. Die Transitionsmatrix M von G ist eine Markov-Matrix.
Beweis. Betrachte die j-te Spalte von M . Es gilt:
Mij =
n
X
−1
−1
Aik Dkj
= Aij Djj
k=1
und damit:
n
X
i=1
Mij =
n
X
i=1
Pn
Aij
−1
Aij Djj
= Pni=1
=1
A
i=1 ij
3.2. Markov Clustering
47
Demnach definiert Mij die Wahrscheinlichkeit des Übergangs von Knoten j nach Knoten i. Die
e-fache Matrix-Matrix-Multiplikation der Matrix M mit sich selbst liefert uns also die Matrix
M e , wobei Mije die Wahrscheinlichkeit ausdrückt, einen Pfad der Länge e von Knoten j nach
Knoten i zu gehen.
Algorithmus 21 zeigt das Markov Clustering Verfahren. Der Algorithmus besteht im Wesentlichen aus zwei Schritten. Zunächst wird eine Expansion durchgeführt, d.h. es wird mit Hilfe von
Random Walks der Graph erkundet. Dies geschieht durch die Potenzierung der Markovmatrix
mit einem Exponenten e ≥ 2. Anschließend werden die Einträge der Matrix punktweise mit einem
Skalar r > 0 potenziert. Dies führt zu einer Verstärkung guter und zur Abschwächung schwacher
Bindungen zwischen den Knoten. Dieser Schritt wird auch als Inflation bezeichnet. Da durch den
Infaltionsschritt die Matrix nicht mehr spaltenstochastisch ist, folgt in einem letzten Schritt noch
eine Normalisierung der Spalten, um wieder eine Markovmatrix zu erhalten. Dieser Prozess wird
bis zur Konvergenz wiederholt. Der MCL Algorithmus wird beim Start mit der Markovmatrix
Ci := M = AD−1 aufgerufen, bei der die Schleifenwahrscheinlichkeit optional größer Null sein
kann.
Algorithmus 21 : Markov Clustering
Input : Ci : Markovmatrix, e : Expansionsexponent, r : Inflationsexponent
1 Cf ← Cie
// Expansion: Matrix-Matrix-Multiplikation
2 Cf ← Cf . ∧ r
// Inflation: Punktweise Potenzierung
3 w ← Cf .+
// Spaltensummen
4 Cf ← Cf . × 1/w
// Spaltennormalisierung
5 if Ci == Cf then
6
return Cf
7 else
8
return MarkovClustering(Cf , e, r)
Es bleibt zu zeigen, dass der Algorithmus konvergiert. Das wollen wir im nächsten Abschnitt
mit Hilfe der Eigenwerte und Eigenvektoren der Markovmatrix beweisen. Eigenwerte und Eigenvektoren bieten uns eine Möglichkeit zur Analyse der wiederholten Anwendung eines Operators
auf einen Vektor. Im Anschluss an den Beweis der Konvergenz des MCL Algorithmus wollen
wir noch einige weitere Eigenschaften eines Graphen anhand der Eigenwerte bzw. Eigenvektoren
kennen lernen.
3.2.1. Konvergenz des Markov Clustering Algorithmus
Wir müssen zeigen, dass sich die Einträge der iterativ berechneten Markovmatrix ab einem bestimmten Zeitpunkt nicht mehr ändern. Da die Markovmatrix eine Wahrscheinlichkeitsverteilung
für einen Random Walk auf dem Graphen beschreibt, ist die Konvergenz des Random Walks gegen eine bestimmte Wahrscheinlichkeitsverteilung damit äquivalent.
Die Eigenvektoren und Eigenwerte der Markovmatrix M = AD−1 geben uns dafür wichtige
Informationen über die Struktur von G. Aus der linearen Algebra ist bekannt, dass die Eigenvektoren einer symmetrischen Matrix eine orthonormale Basis bilden (siehe Anhang A.1). Allerdings
ist M im Allgemeinen nicht symmetrisch.
Wir verwenden deshalb die Matrix S := D−1/2 AD−1/2 = D−1/2 M D1/2 . Demnach besitzt S
die spektralen Zerlegung
S=
n
X
i=1
λi vi viT ,
48
3. Clusteranalyse von Graphen
wobei ω1 ≥ ω2 ≥ · · · ≥ ωn die Eigenwerte von S und z1 , . . . , zn die zugehörigen und normierten
Eigenvektoren sind.
Dann gilt für alle i = 1, . . . , n
M (D1/2 zi ) = D1/2 SD−1/2 D1/2 zi = D1/2 Szi = D1/2 ωi zi = ωi (D1/2 zi ).
Daraus folgt, dass M dieselben n Eigenwerte ωi besitzt wie S und D1/2 zi die zugehörigen
Eigenvektoren sind.
Theorem 3.9. Ist G zusammenhängend und ungerichtet, dann hat der größte Eigenwert ω1 von
M = AD−1
• die Vielfachheit 1,
• den Wert 1 und
• Eigenvektor d = (d(1), . . . , d(n).
Beweis. Zunächst werden wir durch einfaches Nachrechnen überprüfen, dass d ein Eigenvektor
von M zum Eigenwert 1 ist.
Ist d ein Eigenvektor von M , so existiert ein Eigenwert z von S mit
√
D1/2 z = d ⇔ z = d.
Dann gilt:
√
√
√
Sz = S d = D−1/2 AD−1/2 d = D−1/2 A = d = 1 · z.
Somit ist d ein Eigenvektor von M zum Eigenwert ω1 = 1. Weiter gilt für einen bel. Eigenvektor
ω und den korrespondierenden Eigenvektor v von M :
||M || = sup
x6=0
||M x||
||wv||
||v||
≥
= |w|
= |w|.
||x||
||v||
||v||
Da M eine Markovmatrix ist, gilt ||M ||1 = 1 und damit |w| ≤ 1, daher ist ω1 der größte
Eigenwert von M .
Es bleibt noch zu zeigen, dass ω1 die Vielfachheit 1 besitzt. Hierfür verwenden wir den Satz
von Perron-Frobenius, der besagt, dass der größte Eigenwert einer positiven Matrix (alle Einträge
sind positiv) ein einfacher Eigenwert ist.
Folgerung 3.10. Sei G wie in Theorem 3.9 definiert und sei ωn > −1. Dann konvergiert der
Random Walk auf G gegen die Verteilung
d
.
v d(v)
π=P
Der Beweis von Folgerung 3.10 kann in der einschlägigen Literatur nachgelesen werden, zur
Übung kann die Aussage aber durch das Nachrechnen von M π = π überprüft werden.
Nun wissen wir, dass der Markov Clustering Algorithmus konvergiert, allerdings würden wir
noch gerne eine Aussage über die Konvergenzgeschwindigkeit machen.
Sei dazu pt ∈ Rn die Wahrscheinlichkeitsverteilung, die für jeden Knoten j die Wahrscheinlichkeit angibt, dass der Pfad des Random Walks nach t Schritten an j endet. Der Wahrscheinlichkeitsverteilung p0 wird dabei meist auf einen Startknoten a gesetzt, also p0 (a) = 1. Für t > 0
gilt dann pt = M pt−1 .
3.2. Markov Clustering
49
Theorem 3.11. Sei der Startknoten des Random Walks Knoten a. Dann gilt für jeden Knoten
b:
s
d(b)
|pt (b) − π(b)| ≤
(max{|ω2 |, |ωn |})t
d(a)
Beweis. Der Beweis funktioniert auf ähnliche Weise wie der Beweis von Theorem 5.6.
Damit konvergiert der MCL Algorithmus eher langsam. Der Grund dafür ist zugleich der
Ansatz des gesamten Algorithmus, die Random Walks überwinden Flaschenhälse nur schlecht.
3.2.2. Zusammenhänge zwischen Graphen und Eigenwerten
In diesem Abschnitt wollen wir noch einige weitere interessante Zusammenhänge zwischen einem
Graphen bzw. der Matrixrepräsentation des Graphen und den Eigenwerten erwähnen.
3.2.2.1. Eigenwerte und Zusammenhang des Graphen
Theorem 3.12. Sei L die Laplacematrix eines ungerichteten Graphs G. Dann enspricht die Zahl
der Zusammenhangskomponenten von G der Häufigkeit des Eigenwerts 0 von L.
Beweisskizze. Wir führen eine vollständige Induktion über die Zahl k der Zusammenhangskomponenten von G.
• Fall 1. k = 1:
P P
Sei v ein Eigenvektor zum Eigenwert 0. Dann gilt: 0 = v T ·0 = v T Lv = 21 ni=1 nj=1 wij (v(i)−
v(j))2 . Knoten derselben Zusammenhangskomponente haben den gleichen Wert in v. Da
nach Voraussetzung nur eine Zusammenhangskomponente existiert, ist demnach v ein konstanter Vektor.
• Fall 2. k > 1:
Da die Reihenfolge der Knoten keinen Einfluss auf die Eigenvektoren bzw. die Eigenwerte hat, können wir L in eine Blockmatrix überführen. Dabei entspricht jeder Block einer
Zusammenhangskomponente und stellt für diese eine Laplacematrix dar. Nun sind wir für
jeden Block in Fall 1 und (0, . . . , 0, vi (1), . . . , vi (ni ), 0, . . . , 0)T ist ein Eigenvektor des i-ten
Blocks (mit der korrekten Anzahl Nullen an den Stellen der anderen Blöcke). Insgesamt
haben wir also k solcher Blöcke mit linear unabhängigen Eigenvektoren, weshalb der Eigenwert 0 von L die Vielfachheit k besitzt.
3.2.2.2. Eigenwerte und Konnektivität
Definition 3.13. Partition
Sei G = (V, E) ein ungerichteter Graph. Dann ist (V1 , V2 ) mit
• V1 , V2 ⊂ V ,
• V1 ∩ V2 = ∅ und
• V1 ∪ V2 = V
eine Partition von G. Dabei müssen V1 und V2 nicht zwingend zusammenhängend sein. Eine
Partition (V1 , V2 ) heißt balanciert, wenn ||V1 | − |V2 || ≤ 1 gilt.
50
3. Clusteranalyse von Graphen
Bei einer Partitionierung in zwei Teile spricht man auch von einer Bipartition.
Definition 3.14. Schnitt
Die Menge Ext(V1 , V2 ) = {{u, v} ∈ E; u ∈ V1 , v ∈ V2 } beschreibt die Kanten, die zwischen V1
und V2 verlaufen und wird Schnitt der Partition genannt.
Abbildung 3.2.2 zeigt den Schnitt eines Graphen.
Abbildung 3.2.2.: Schnitt in einem ungerichteten Graphen
Definition 3.15. Bisektionsweite
Sei G = (V, E) ein ungerichteter Graph. Die Bisektionsweite σ(G) ist definiert als:
σ(G) := min{|Ext(V1 , V2 )|; (V1 , V2 ) ist eine balancierte P artition von G}
Theorem 3.16. Untere Schranke für σ
Sei G = (V, E) ein ungerichteter Graph mit gerader Knotenanzahl n = |V | und λ2 der zweitkleinse Eigenwert der Laplacematrix L von G. Für die Bisektionsweite von G gilt dann:
σ(G) ≥ n ·
λ2
4
Beweis. Da (1 . . . 1) ein Eigenvektor zum kleinsten Eigenwert 0 der Laplacematrix ist, müssen
folglich alle Eigenvektoren von λ2 orthogonal
zu diesem Vektor sein, d.h. ist x ein Eigenvektor
Pn
zu λ2 , so gilt hx, (1 . . . 1)i = 0, also i=1 xi = 0. Mit Hilfe des Rayleigh-Quatienten und des
Courant-Fisher Theorems folgt dann, dass
λ2 = min
Px6=0
xi =0
hLx, xi
.
hx, xi
Nun sei V1 , V2 eine minimale, balancierte Partition von G, also |V1 | = |V2 | = n/2 und
|Ext(V )1 , V2 )| = σ(G). Weiterhin sei y ∈ Zn ein Indikatorvektor für den gilt:
(
−1, falls vi ∈ V1
yi =
+1, falls vi ∈ V2
Damit gilt offensichtlich
Pn
i=1 yi
= 0 und darum gilt auch:
3.3. Random Walks als Analysewerkzeug
λ2 ≤
51
hLy, yi
hy, yi
P
wobei hy, yi = ni=1 yi2 = n. Im Folgenden bezeichne N (i) die Nachbarschaft von Knoten vi .
Für einen beliebigen Vektor x ∈ Zn gilt dann:
hLx, xi =
=
n X
n
X
(
Lij xj )xi
i=1 j=1
n X
n
X
(
i=1 j=1
=
n
X
i=1
=
n
X
liixi −
X
xj )xi
vj ∈N (i)
(|N (i)| · xi −
(
X
X
xj )xi
vj ∈N (i)
(xi − xj ))xi
i=1 vj ∈N (i)
X
=
{vi ,vj }∈E
=
X
{vi ,vj }∈E
((xi − xj )xi + (xj − xi )xj )
(xi − xj )2
Es ist yi = yj für alle Kanten, die nicht zum Schnitt der Partitionen V1 , V2 gehören. Für die
Schnittkanten gilt: |yi − yj | = 2 und somit:
X
X
hLy, yi =
(yi − yj )2 =
22 = 4 · σ(G).
{vi ,vj }∈E
{vi ,vj }∈
Ext(V1 ,V2 )
Insgesamt erhalten wir also:
λ2 ≤
4 · σ(G)
n
hLy, yi
=
=⇒ σ(G) ≥ λ2 ·
hy, yi
n
4
3.3. Random Walks als Analysewerkzeug
Folgt.
3.4. Bildsegmentierung mit spektraler Clusteranalyse
Eine sehr anschauliche Anwendung des Graphclusterings ist die Segmentierung von Bildern.
Hierbei besteht die Aufgabe darin, ein Bild in inhaltlich zusammenhängende, homogene Bereiche
zu zerlegen. Die graphbasierte Bildsegmentierung ist nur eine von vielen Algorithmenklassen, die
zur Lösung dieses weitverbreiteten Problems in der Bildverarbeitung verwendet wird. Die Wahl
des „richtigen” Algorithmus ist dabei stark anwendungsabhängig. In diesem Abschnitt wollen wir
am Beispiel der Bildsegmentierung die spektrale Clusteranalyse kennenlernen.
52
3. Clusteranalyse von Graphen
Abbildung 3.4.1.: Minimaler Schnitt einer schlechten Clusterung
3.4.1. Graphrepräsentation von Bildern
Zunächst müssen wir definieren, wie ein Bild als Graph repräsentiert werden kann. Die Idee
dabei ist, jeden Pixel (i, j) des Bildes durch einen Knoten darzustellen. Kanten existieren dann
von jedem Knoten zu seiner lokalen Nachbarschaft im Bild. Oft wird dabei die 8-Nachbarschaft
jedes Pixels gewählt, es können aber auch noch größere Nachbarschaften definiert werden. Die
Kantengewichte berücksichtigen dabei die Distanz des jeweiligen Pixels zu seinem Nachbarn sowie
den Farbunterschied.
Definition 3.17. Wir definieren das Kantengewicht einer Kante (u, v) des Bildgraphen G =
(V, E) wie folgt:
−||F (u) − F (v)||22
w(u, v) := exp
·
σI2
(
2
exp −d(u,v)
σ2
X
0
falls v in Nachbarschaft von u
sonst
wobei F : V → [0, 255]3 den RGB-Farbwert eines Pixels und d(u, v) die Distanz von Pixel
u zu Pixel v angibt. Mit Hilfe der beiden Konstanten σI und σX können die beiden Faktoren
zusätzlich gewichtet werden. Für F sind auch andere Funktionen wie beispielsweise die Helligkeit
eines Pixels denkbar, dies ist selbstverständlich anwendungsabhängig.
Damit repräsentiert das Kantengewicht w(u, v) die Wahrscheinlichkeit, dass Pixel u zum selben
Objekt wie Pixel v gehört. Die Aufgabe eines Clusteringalgorithmus besteht nun darin, eine
geeignete Partitionierung der Knotenmenge zu finden, sodass die Objekte eines Bildes jeweils
eine Partition bilden.
3.4.2. Optimierungsproblem
Nach der Definition der Kantengewichtsfunktion sollten in einer Partitionierung möglichst wenige schwere Kanten, d.h. Kanten mit hohem Gewicht, geschnitten werden. Dies entspricht dem
Finden eines minimalen Schnitts zwischen den Partitionen. Allerdings schneidet der Algorithmus
mit dieser Zielfunktion bevorzugt kleine Mengen isolierter Knoten. Abbildung 3.4.1 zeigt ein Beispiel, in dem im Falle einer Bisektionierung stets ein einzelner isolierter Knoten der rechten Hälfte
einen kleineren minimalen Schnitt ergibt, als der eigentlich für ein Clustering bessere Schnitt,
der hier gestrichelt gekennzeichnet ist. Dieses Verhalten wollen wir bei der Bildsegmentierung
vermeiden, denn sehr kleine Cluster decken meist einzelne Objekte eines Bildes nicht vollständig
ab.
Um diese Bedingungen zu berücksichtigen, definieren wir den normalisierten Kantenschnitt
Ncut (A, B) nach Shi und Malik [SM00] wie folgt:
3.4. Bildsegmentierung mit spektraler Clusteranalyse
Definition 3.18. (Normalisierter Kantenschnitt) Sei vol(X) :=
der gewichteten Knotengrade der Knoten in X. Dann ist
Ncut (A, B) :=
P
u∈X,v∈V
53
w(u, v) die Summe
cut(A, B) cut(A, B)
+
.
vol(A)
vol(B)
Wir wollen nun mit Hilfe von spektralem Clustering auf dem Bildgraphen G = (V, E) Partitionen A und B finden, für die V = A ∪ B und A ∩ B = ∅ gilt, sodass die Funktion Ncut (A, B)
annähernd minimal ist.
Definition 3.19. Sei n = |V | und x ∈ {−1, 1}n der Indikatorvektor, für den xi = 1 gilt, wenn
Knoten i in A enthalten ist und analog xi = −1 gilt, wenn Knoten i in B liegt. Weiter sei 1 der
n × 1 dimensionale Einsvektor und b ∈ R, sowie y ∈ {1, −b}n ein weiterer Indikatorvektor. Sei
außerdem D die Gradmatrix von G und L die Laplacematrix, also L = D − W , wobei W die
gewichtete Adjazenzmatrix ist.
Lemma 3.20. (Minimaler, normalisierter Kantenschnitt in algebraischer Form) Unter der Bedingung y T D1 = 0 gilt für den minimalen, normalisierten Kantenschnitt:
minx Ncut (x) = miny
y T Ly
y T Dy
(3.4.1)
Die Herleitung dieses Ergebnisses kann in der Publikation von Shi und Malik nachgelesen
werden [SM00]. Man beachte, dass der Quotient in 3.4.1 dem Rayleigh-Quotienten entspricht.
3.4.3. Relaxiertes Optimierungsproblem
Die Lösung des Optimierungsproblems aus 3.4.2 unter den Bedingungen b ∈ R, y ∈ {1, −b}n
(diskret!) und y T D1 = 0 ist NP-schwer. Deshalb nehmen wir eine Relaxierung des Problems
vor, indem wir y ∈ [−b, 1]n erlauben. Dies führt mit Hilfe des Courant-Fischer-Theorems auf das
verallgemeinerte Eigenwertproblem:
Ly = λDy.
Dieses Problem kann mit Hilfe eines Eigenlösers wie zum Beispiel dem Lanczos-Verfahren
approximativ gelöst werden. Da wir in diesem Fall meist nur am Vorzeichen der Einträge in den
Eigenvektoren interessiert sind, muss die benötigte Präzision des Eigenlösers nicht sonderlich
hoch sein [SM00]. Algorithmus 22 zeigt den kompletten NCut-Algorithmus nach Shi und Malik.
3.4.4. Laufzeit des NCut-Algorithmus
Die Laufzeit wird vom Lösen des Eigenwertproblems dominiert. Das Lösen mit einem Standardverfahren wie beispielsweise dem QR-Verfahren benötigt O(n3 ) Operationen. Allerdings berechnet dieses Verfahren alle Eigenvektoren, was wir im NCut-Algorithmus nicht benötigen –
wir sind lediglich an einem Eigenvektor interessiert. Zudem spielt die Genauigkeit nur eine untergeordnete Rolle. Hinzu kommt, dass die Bildgraphen aufgrund der Konstruktion meist dünn
besetzt sind. Darum bietet sich das bereits erwähnte Lanczos-Verfahren an, das eine Laufzeit von
O(tn + t · M V M ult(n)) besitzt. Hierbei bezeichnet t die maximale Anzahl benötigter Matrix√
Vektor-Multiplikationen (t ≈ O( n)) und M V M ult die dabei anfallenden Kosten pro Aufruf
(= O(n)). Demnach beträgt die Gesamtlaufzeit typischerweise O(n1.5 ).
54
3. Clusteranalyse von Graphen
Algorithmus 22 : NCut-Algorithmus nach Shi und Malik [SM00]
Input : G = (V, E, w) : ungerichteter Graph mit wij ≥ 0
Output : C : Clusterung von G
1 D ← DegreeMatrix(G)
2 L ← LaplacianMatrix(G)
3 v2 ← SolveEigenProblem(L, D)
// Eigenvektor v2 zum zweitkleinsten EW
4 p ← FindSplitPoint(v2 )
// Finde guten Splitting-Punkt
5 foreach i in V do
6
if v2 (i) ≥ p then
7
C1 ← C1 ∪ {i}
8
else
9
C2 ← C2 ∪ {i}
10
11
12
13
if recursivePartition then
// Falls nötig, partitioniere rekursiv weiter
else
C ← C ∪ C1 ∪ C2
return C
3.4.5. Verallgemeinerung auf k Segmente
Im vorangegangenen Abschnitt haben wir den NCut-Algorithmus kennen gelernt, der mit Hilfe
von spektralem Clustering rekursiv 2-Partitionierungen eines Graphen berechnet, der aus einem
Bild generiert wird. Der Nachteil des rekursiven Vorgehens ist, dass er sehr rechenaufwändig
ist. Zudem enthalten die nächsten Eigenvektoren nach dem zweitkleinsten ebenfalls hilfreiche
Partitionierungsinformationen, die ungenutzt bleiben. In diesem Abschnitt möchten wir dieses
Verfahren deshalb auf eine k-Partitionierung verallgemeinern, indem nicht nur ein Eigenvektor,
sondern k Eigenvektoren verwendet werden.
Um für jedes Pixel zu entscheiden, welcher der k Eigenvektoren als Indikator für dieses Pixel
dienen soll, wird im Raum der Eigenvektoren ein geometrisches Clustering angewandt. Shi und
Malik verwenden dafür den k-means-Algorithmus, der auch als Lloyds Algorithmus bekannt ist.
3.4.5.1. k-means Algorithmus von Lloyd
Die Idee des k-means-Algorithmus ist die folgende: Gegeben eine Menge von Beobachtungspunkten (p1 , . . . , pn ), wobei jeder der Punkte d-dimensional ist, teilt der k-means Algorithmus die n
Punkte in k Cluster C = {C1 , . . . , Ck } ein, wobei die Summe der quadratischen Abstände zum
Zentrum innerhalb eines Clusters minimiert wird:
min
C
k X
X
i=1 pj ∈Ci
||pj − µi ||2 ,
wobei µi das Zentrum bzw. der Schwerpunkt der Punkte in Ci ist.
Der Algorithmus wird dazu mit einer initialen Belegung der Zentren µi aufgerufen. Diese kann
zufällig gewählt werden, es existieren aber auch bessere Methoden. Anschließend werden folgende
Schritte iterativ ausgeführt:
• Zuweisung jedes Punktes pi zu einem der Cluster Cj , bei dem der quadratische Abstand
zum Zentrum µi des Clusters (||pj −µi ||2 ) minimiert wird. Dieser Schritt entspricht der Par-
3.5. Weiterführende Literatur
55
titionierung der Punkte anhand des Voronoi-Diagramms, das von den Zentren der Cluster
induziert wird.
• Neuberechnung der Zentren als Schwerpunkt jedes einzelnen Clusters anhand der Punkte,
die im vorigen Schritt in jedes Cluster eingeteilt wurden.
Abbildung 3.4.2 veranschaulicht die Schritte des Algorithmus. Die Iteration wird beendet, sobald
sich keine neuen Änderungen mehr ergeben. Der Algorithmus konvergiert, da in jedem Schritt
die Zielfunktion optimiert wird und es nur eine endliche Anzahl solcher Partitionen gibt. Es ist
allerdings nicht sichergestellt, dass der Algorithmus in ein globales Optimum konvergiert.
Abbildung 3.4.2.: Schematische Darstellung des k-means Algorithmus von Lloyd
Algorithmus 23 zeigt den KWay-NCut-Algorithmus.
Algorithmus 23 : KWay-NCut-Algorithmus
Input : G = (V, E, w) : ungerichteter Graph mit wij ≥ 0
Output : C : Clusterung von G
1 D ← DegreeMatrix(G)
2 L ← LaplacianMatrix(G)
3
4
5
6
// Berechne generalisierte Eigenvektoren v2 , . . . , vk+1
{v2 , . . . , vk+1 } ← SolveEigenProblem(L, D)
U ← (v2 v3 . . . vk+1 )
// Fasse Eigenvektoren als Spalten v. U auf
// Interpretiere Zeilen v. U als k-dim. Punkte und wende geom. Algorithmus an
// Übertrage das Ergebnis auf Knoten des Graphen
C ← k-means(U (1, :), . . . , U (n, :))
return C
3.5. Weiterführende Literatur
Der Abschnitt zur Bildsegmentierung basiert auf einem Paper von Shi und Malik [SM00]. Mehr
folgt.
57
4. Visualisierung von Graphen
In diesem Kapitel möchten wir nun für einen Graphen ohne Koordinateninformationen eine gute
visuelle Repräsentation finden, durch die die Struktur des Graphen für einen Menschen schnell
ersichtlich wird. Die Visualisierung soll also übersichtlich sein und je nach Anwendungsfall bspw.
wenige Überschneidungen oder wenige Knicke besitzen. Typische Anwendungsgebiete sind UBahn-Pläne und technische Zeichnungen, aber auch die Darstellung von Datenrelationen, wie
z.B. von sozialen Netzwerken oder das Debugging von Graphenalgorithmen. In jedem Fall suchen
wir somit für jeden Knoten i ∈ V eine Koordinate xi im R2 oder R3 , sodass die davon induzierte
Zeichnung die gewünschten Eigenschaften besitzt.
Welcher Algorithmus zur Visualisierung eingesetzt werden sollte, hängt stark von der Klasse
des Eingabegraphen ab. So lassen sich Graphen mit einem geringen Durchmesser oft schlecht
darstellen. Für sehr große Graphen hingegen benötigt man eine hierarchische Auflösung, da eine
sinnvolle Zeichnung des kompletten Graphen viel zu viel Platz einnehmen würde. Der FacebookFreundschaftsgraph würde auf normalen Bildschirmen mehrere zehntausend Kanten pro Pixel
benötigen!
4.1. Spektrales Zeichnen
In diesem Abschnitt stellen wir eine Methode vor, die mit dem spektralen Clustering des letzten Kapitels verwandt ist. Grundidee ist hierbei eine Erkenntnis von Hall: Es lassen sich viele
Abfolge- und Platzierungsprobleme durch Minimierung der quadrierten Distanzen zwischen den
Koordinaten charakterisieren. Sei LG die gewichtete Laplace-Matrix des Graphen G. Dann ist in
unserem Szenario das Minimierungsproblem gegeben durch
X
minn
w(i, j)||xi − xj ||2 = minn xT LG x
x∈R
unter der Nebenbedingung
x∈R
(i,j)∈E
n
X
x2l = 1.
l=1
Die Nebenbedingung impliziert hierbei x 6= 0. Dies ist wichtig, da in der trivialen Lösung alle
Knoten auf den gleichen Punkt abgebildet würden. Nach dem letzten Kapitel müssen wir somit diejenigen Eigenvektoren als Koordinaten verwenden, die zu den zwei kleinsten positiven
Eigenwerten gehören. Bezeichnen wir diese mit v1 und v2 , so setzen wir also xi = ((v1 )i , (v2 )i ).
Wir betrachten nun allgemein, warum die Eigenvektoren der betragsmäßig größten Eigenwerte
besonders nützlich sind. Sei A ∈ Rn×n eine symmetrische Matrix mit den Eigenwerten α1 ≥ α2 ≥
. . . ≥ αn und (v1 , . . . , vn ) eine Orthonormalbasis aus dazugehörigen Eigenvektoren. Dann lässt
sich A darstellen durch seine spektrale Zerlegung:
A=
n
X
αi vi viT .
i=1
Wir möchten nun mit Hilfe der Eigenwerte eine möglichst gute Approximation B von A erstellen,
58
4. Visualisierung von Graphen
für die die Operatornorm ||A − B|| bzw. die Frobeniusnorm ||A − B||F klein ist. Dabei sind die
Normen gegeben durch
sX
||M x||
||M || = maxn
||M ||F =
Mij2 .
x∈R
||x||
i,j
Als Hilfsmittel dient uns dabei das Courant-Fischer-Theorem, das wir hier nicht beweisen:
Theorem 4.1. Sei A eine symmetrische Matrix mit Eigenwerten α1 ≥ α2 ≥ . . . ≥ αn . Dann
gilt:
αk =
=
max
S⊆Rn ,dim(S)=k
xT Ax
x∈S,x6=0 xT x
min
xT Ax
T ⊆Rn ,dim(T )=n−k+1 x∈T,x6=0 xT x
min
max
Da wir nur nichttriviale Lösungen betrachten wollen, werden wir die Forderung x 6= 0 nicht
mehr explizit erwähnen. Nach dem Courant-Fischer-Theorem gilt somit für die extremen Eigenwerte α1 und αn :
xT Ax
xT Ax
α1 = maxn T
αn = minn T
x∈R
x∈R
x x
x x
Als für uns wichtige Folgerung aus dem Courant-Fischer-Theorem P
erhalten wir, dass die beste
(k)
Approximation von A durch eine Matrix mit Rang k gerade A := ki=1 αi vi viT ist. Der Beweis
dieser Folgerung sei dem Leser als Selbstübung überlassen. Der Approximationsfehler ||A − A(k) ||
ist daher so klein wie möglich und dies erklärt, warum die k betragsmäßig größten Eigenwerte
und ihre Eigenvektoren bereits sehr viel Information über A enthalten.
4.2. Kräftegesteuertes Zeichnen
In diesem Abschnitt werden wir für das Zeichnen eines großen ungerichteten Graphen G = (V, E)
einen weiteren Ansatz vorstellen. Wir modellieren dazu G als ein physikalisches System, auf das
bestimmte Kräfte wirken und für das wir einen stabilen Gleichgewichtszustand (Äquilibrium)
finden möchten. Wir gehen dazu wie folgt vor:
1. Berechnung von Kräften, die auf die Knoten wirken.
2. Bewegung der Knoten entlang der Richtung der Kräfte.
3. Wiederholung der beiden Operationen, bis ein Äquilibrium erreicht ist.
Zur Modellierung der Kräfte benutzen wir das Feder-elektrische Modell. Dabei stellen wir uns
die Knoten als elektrisch geladen vor sowie die Kanten als Federn, durch die die Endknoten einer
Kante gegenseitig angezogen werden. Gleichzeitig wirken die elektrischen Kräfte auf jedes Paar
von Knoten, gleichgültig ob durch eine Kante verbunden oder nicht, voneinander abstoßend.
Die anziehende Kraft Fa zwischen Nachbarn i und j soll hierbei proportional zur quadratischen
Distanz zwischen i und j sein. Wir setzen daher
Fa (i, j) = −
||xi − xj ||2
xi − xj
·
,
K
||xi − xj ||
wobei K ein Skalierungsparameter ist, abhängig von der gewünschten Größe der endgültigen
Zeichnung. Die abstoßende Kraft Fr (r für engl. repulsive) zwischen allen Knotenpaaren (i, j)
4.2. Kräftegesteuertes Zeichnen
59
soll hingegen invers proportional zur Distanz zwischen i und j sein, sodass wir
Fr (i, j) =
xi − xj
K2
·
||xi − xj || ||xi − xj ||
setzen. Hierbei ist K erneut der eingeführte Skalierungsparameter. Die Energie E in unserem
Feder-elektrischen Modell ist gegeben durch:
X
X
E(x) =
||xi − xj ||3 /3K −
K 2 ln(||xi − xj ||)
i6=j
ij∈E
Beispiel 4.2. Sei xi = (5; 1) die Koordinate von Knoten i und xj = (2; 5) die Koordinate von
Knoten j. Als Skalierungsparameter wählen wir K = 10. Wir möchten nun die auf das Tupel
(i, j) wirkenden Kräfte berechnen. Es ergibt sich:
25 (3, −4)
·
= (−1.5, 2)
10
5
100 (3, −4)
·
= (12, −16)
5
5
Fa (i, j) = −
Fr (i, j) =
Die anziehende Kraft Fa (i, j) entspricht somit einer Translation um −1.5 in x-Richtung und
2 in y-Richtung, während Fr (i, j) einer Translation um 12 in x-Richtung und −16 in y-Richtung
entspricht.
Für unseren Algorithmus können wir grundsätzlich ein beliebiges initiales Layout der Knoten wählen, z.B. eine zufällige Platzierung der Knoten in der Ebene. Dann werden wiederholt
die verschiedenen Kräfte berechnet und eine Verschiebung durchgeführt, bis der Algorithmus
konvergiert. Die Verschiebung wird dabei durch eine abnehmende Schrittlänge skaliert. Zusammengefasst ergibt sich Algorithmus 24.
Algorithmus 24 : Algorithmus ForceDirected
Input : Graph G = (V, E), Skalierungsparameter K, iniatiales Layout x, Toleranz tol
Output : Kräftebasiertes Layout x
1 converged ← f alse
2 step ← initialStepLength
3 while converged 6= true do
4
x(0) ← x
5
for i ∈ V do
6
f ←0
// berechne Kraftvektor f
7
foreach j ∈ N (i) do
8
f ← f + Fa (i, j)
9
10
11
12
13
14
for j 6= i, j ∈ V do
f ← f + Fr (i, j)
xi ← xi + step · (f /||f ||)
// Normalisierung wird nur einmal ausgeführt!
step ← updateStepLength(step, x, x0 )
if kx − x(0) k < tol · K then
converged ← true
Der angegebene Algorithmus funktioniert auf kleineren Graphen recht gut. Eine mögliche
Verbesserung wäre die adaptive Aktualisierung der Schrittgröße. Für große Graphen ergeben sich
60
4. Visualisierung von Graphen
Abbildung 4.2.1.: Beispiel für einen Quadtree, http://upload.wikimedia.org/wikipedia/de/a/
a7/Quadtree.png
dann allerdings noch immer einige Probleme: Zum einen können viele lokale Minima auftreten.
Der Algorithmus läuft dann häufig in ein schlechtes lokales Minimum. Dies könnte mit einem
Multilevel-Ansatz umgangen werden, dessen Prinzip wir in Abschnitt 4.2.2 vorstellen werden.
Zum anderen tritt bei der Berechnung von Fr quadratische Zeitkomplexität auf. Um dies zu
umgehen, werden wir nachfolgend eine geometrische Datenstruktur zur Approximation von Fr
benutzen. Für weit entfernte Knoten berechnen wir dann nur einen Näherungswert. Die Laufzeit
kann dann auf O(n log n + m) gedrückt werden.
4.2.1. Quadtree-Datenstruktur
Wie bereits erwähnt, besitzt die Berechnung von Fr eine quadratische Laufzeit. Dies kommt
daher, dass Algorithmus 24 eine verschachtelte Schleife ist, bei der außen über jeden Knoten
iteriert wird und im Inneren für Fr über alle anderen Knoten iteriert wird. Ähnlich dem nKörper-Problem in der Physik verwenden wir zur Approximation den Ansatz, dass wir weit
entfernte Knoten in der gleichen Region als einen Superknoten auffassen. Wir realisieren dies
mit Hilfe eines Quadtrees im zweidimensionalen bzw. mit einem Octree im dreidimensionalen
Fall. Ein Quadtree ist eine rekursive Baum-Datenstruktur, die wie folgt aufgebaut wird:
• Der Wurzelknoten repräsentiert die gesamte Ebene (bzw. den gesamten zu betrachtenden
Ausschnitt).
• Falls das zum aktuellen Knoten gehörende Rechteck zu viele Punkte (Schwellwert als Parameter) enthält, dann teile die zu einem Knoten v im Baum gehörige Fläche wird in vier
gleich große Rechtecke, die jeweils einem der vier Kinder von v zugeordnet werden.
• Verfahre rekursiv so lange weiter, bis die gewünschte Auflösung erreicht ist, also z.B. die
Anzahl der Punkte pro Rechteck unter dem Schwellwert liegt.
In Abbildung 4.2.1 ist beispielhaft die Aufteilung eines Rechtecks und der dazugehörige Quadtree
dargestellt.
Falls ein Knoten j in unserem Ausgangsgraphen G weit weg ist für die Kraftberechnung Fr (i, j),
so genügt zur Approximation schon ein innerer Baumknoten des Quadtrees, es muss kein Blatt
oder j selbst sein. Ein innerer Baumknoten
repräsentiert dabei eine Menge S von Knoten des
P
Graphen G am Schwerpunkt xS = j∈S xj /|S| von S. Die abstoßende Kraft von Knoten i zum
Superknoten S ist dann
K2
xi − xS
Fr (i, S) =
·
.
||xi − xS || ||xi − xS ||
Eine Möglichkeit, um das Kriterium „weit weg” zu formalisieren, besteht in dem Barnes-HutKriterium: Ein Superknoten S ist weit weg von Knoten i, wenn die Breite ds des Rechtecks, das
4.2. Kräftegesteuertes Zeichnen
61
zu S gehört, klein ist im Vergleich zum Abstand von xS und xi . Dies bedeutet, es gibt ein θ ≥ 0,
sodass gilt
dS /||xi − xS || ≤ θ.
Je kleiner dabei θ gewählt wird, umso genauer ist die Näherung. In der Praxis haben sich hierfür
die Werte θ = 1 und θ = 2 bewährt.
Betrachten wir nun, wie sich die Verwendung eines Quadtrees in Algorithmus 24 auf die Berechnung der abstoßenden Kraft Fr auswirkt. Dabei nehmen wir an, dass die Punkte im Quadtree
geeignet verteilt sind. Die Konstruktion des Quadtrees benötigt O(n log n) Zeit. Die Bestimmung
aller Superknoten für einen Knoten im Ausgangsgraphen G kann in O(log n) durchgeführt werden. Die Laufzeit der Bestimmung der abstoßenden Kraft reduziert sich somit von O(n2 ) auf
O(n log n). Weitere Verbesserungen sind sogar noch möglich, wenn wir nicht nur zwischen einem
Blatt und einem Superknoten approximieren, sondern jeweils zwischen Paaren von Superknoten. Mit Hilfe der Datenstruktur des Quadtrees haben wir somit das Problem der quadratischen
Zeitkomplexität pro Iteration umgangen. Allerdings können noch immer viele lokale Minima
der Energiefunktion existieren. Hierfür werden wir im nächsten Abschnitt den Multilevel-Ansatz
kennenlernen.
4.2.2. Multilevel-Verfahren für kräftegesteuertes Zeichnen
Ein Mehrebenen- oder Multilevel-Verfahren besteht aus drei Phasen. In einem ersten Schritt
wird der Eingabegraph G rekursiv vergröbert, d. h. es entsteht eine Hierarchie von Graphen
G = G0 , G1 , . . . , Gk , den k + 1 Ebenen des Verfahrens. Je höher der Index einer Ebene, desto
weniger Knoten und Kanten soll der zugehörige Graph besitzen. Trotz Vergröberung soll dabei die
Struktur des Eingabegraphen weitgehend erhalten bleiben. Auf der stärksten Vergröberungsstufe
Gk wird dann eine initiale Lösung berechnet. Abschließend wird durch Interpolation der initialen
Lösung und lokaler Optimierung auf jeder Ebene eine Lösung für den Eingabegraphen errechnet.
In unserem Szenario laufen die drei Phasen folgendermaßen ab:
1. Rekursive Vergröberung:
Zur Vergröberung des ungerichteten Graphen Gi existieren verschiedene Möglichkeiten. Oft
wird dazu ein nicht erweiterbares Matching benutzt. Die Kanten des Matchings und deren
Endknoten werden dabei zu einem neuen Knoten verschmolzen. Sei e = uv eine solche
Kante. Wir bilden dann einen neuen Superknoten x in Gi+1 mit w(x) = w(u) + w(v) und
entfernen die Kante e. Kanten von einem Knoten y ∈
/ {u, v, x} zu u oder v werden in
Gi+1 auf den Superknoten x „umgebogen”. Dabei verschmelzen wir parallele Kanten und
addieren ihre Gewichte: w(yx) = w(yu) + w(yv).
Eine alternative Möglichkeit zur Vergröberung besteht in der Berechnung einer unabhängigen Knotenmenge U mit geeignet gewichteten Kanten zwischen den Knoten in U .
2. Initiales Layout:
Durch die Vergröberung in Phase 1 ist der resultierende Graph Gk sehr klein. Es kann
somit ein beliebiger Algorithmus zur Berechnung eines initialen Layouts gewählt werden.
Der im vorherigen Abschnitt vorgestellte ForceDirected-Algorithmus bietet sich hierfür an,
da er auf kleinen Graphen gute Lösungen erreicht. Wegen der kleinen Größe von Gk ist die
Wahrscheinlichkeit groß, dass der Algorithmus das globale Optimum für Gk erreicht.
3. Interpolation und Verbesserung:
In dieser Phase wird die Rekursion aus Phase 1 wieder rückabgewickelt. Im Graphen Gi
expandieren wir die in Gi+1 verschmolzene Kante e = uv wieder, indem die alte Adjazenzinformation wiederhergestellt wird. Die beiden Endknoten u und v erhalten im Layout für
62
4. Visualisierung von Graphen
Gi zunächst die Position ihres Superknotens. Lokale Verbesserungen können nun, z.B. mit
dem ForceDirected-Algorithmus, durchgeführt werden. Bei letzterem Algorithmus muss beachtet werden, dass sich die relative Position von u und v zueinander nicht mehr ändert,
falls die Nachbarschaften der beiden Knoten gleich sind. In diesem Fall sollten alternative
Platzierungen bei der Expansion von e erwogen werden.
Verwenden wir den Algorithmus ForceDirected in einem Multilevel-Verfahren, so können wir
durch die lokalen Verfeinerungen in Phase 3 auch weitgehend das Problem umgehen, dass viele
lokale Minima im Graphen auftreten können. Das Multilevel-Verfahren bietet somit sowohl eine
globale Sicht (durch Phase 2), als auch eine lokale Sicht (durch Phase 3) auf das Problem.
Nichtsdestotrotz bleibt es eine Heuristik, die nicht garantiert, dass wir die global optimale Lösung
finden. Für viele kombinatorische Optimierungsprobleme sind Multilevel-Verfahren jedoch sehr
effektiv.
4.3. Weiterführende Literatur
Eine ausführlichere Darstellung des spektralen Zeichnens und zu spektralen Methoden findet sich
im Kapitel Spectral Graph Theory von Spielman im Buch Combinatorial Scientific Computing
[NS12] von Naumann und Schenk (Hrsg.).
Weitere Erklärungen zum DirectedForce-Algorithmus und Vergleiche mit anderen Visualisierungsalgorithmen sind ebenfalls im Buch Combinatorial Scientific Computing, im Kapitel Algorithms for Visualizing Large Networks von Hu zu finden.
63
5. Lastbalancierung paralleler Berechnungen
5.1. Parallelität
Abschnitt folgt.
5.2. Dynamische Balancierung unabhängiger Lasten
Gegeben sei ein Rechnernetz mit vielen Prozessoren. Jeder Prozessor hat gewisse Arbeitsaufgaben, die abzuarbeiten sind und die wir in der Folge als Last bezeichnen. Bis zur gemeinsamen
Lösung eines Problems muss man immer auf den am längsten rechnenden Prozessor warten. Daher ist es für eine effiziente Nutzung eines Parallelrechners entscheidend, dass alle Prozessoren
gleich stark ausgelastet sind. Algorithmisch stellen wir uns daher die Frage, wie eine möglichst
schnelle Balancierung der Lasten erreicht werden kann.
Unsere Modellannahme in diesem Abschnitt bezüglich des parallelen Systems und der Arbeitsaufträge ist, dass die Prozessoren in jedem Schritt nur ihre eigene Last und die ihrer Nachbarn
kennen und mit ihnen in einer Runde Last austauschen können. Dies geschieht ohne zentrale
Steuerung und nur über die Kommunikationskanäle, die Prozessoren direkt miteinander verbinden. Weiterhin sind die Lasten beliebig aufteilbar (also durch reelle Zahlen repräsentierbar).
Ein entsprechendes Rechnersystem repräsentieren wir durch einen ungerichteten Graphen, in
dem die Knoten die Prozessoren darstellen und die Kanten Kommunikationskanäle zwischen den
Prozessoren.
5.2.1. Das Diffusionsverfahren erster Ordnung (FOS)
Gegeben sei ein Graph G = (V, E) mit n Knoten und m Kanten und seiner Adjazenzmatrix A. Sei
w der Vektor (w1 , . . . , wn )T , der die Arbeitslasten der Prozessoren (= Knoten) beschreibt, d. h.,
wi bezeichnet die Last des Knotens vi ∈ V . Setze den Diffusionsparameter α ∈ (0, maxi 1deg(i) ).
(k)
Weiter sei w(k) der Lastvektor nach k Iterationsschritten und sei yij der Fluss entlang der
Kante (vi , vj ) im Schritt k. Dann führt das Diffusionsverfahren erster Ordnung (engl.: first order
diffusion scheme, FOS) in Iteration k + 1 folgende Operationen aus:
(k+1)
yij
(k+1)
wi
(k)
(k)
− wj )
X (k+1)
(k)
= wi −
yij
= α(wi
j∈N (i)
=w−
In Matrixform:
X
j∈N (i)
(k)
α(wi
(k)
(k)
− wj ) = (1 − di α)wi
+
X
j∈N (i)
(k)
αwj
64
5. Lastbalancierung paralleler Berechnungen
Abbildung 5.2.1.: 3 × 3-Torus aus Beispiel 5.2 (links) mit initialer Lastverteilung und dem Fluss,
der durch das Diffusionsverfahren entsteht (rechts).






(k+1)
w1
(k+1)
w2
..
.
(k+1)
wn


 
 
=
 

1 − d1 α
0
0
1 − d2 α 0
..
.
α
|
α
α
0
0 ···
···
α
α ···
0 ···
···
0 α
{z
0
0
···
···
0
···
0
n×n-Matrix M
  (k)
w1
(k)
 
w2
 

·
  .
  ..
(k)
1 − dn α
wn
}
α
α
..
.






Bemerkung 5.1. Es gilt also w(k+1) = M w(k) , wobei M ∈ Rn×n mit M = I − αL und w(k) ∈ Rn .
Es folgt w(k+1) = M k+1 w(0) . Weiterhin besitzt M nur reelle Eigenwerte und es gibt n aufeinander
stehende Eigenvektoren z1 , . . . , zn , die eine Orthonormalbasis im Rn bilden.
Beispiel 5.2. Der Graph in Abbildung 5.2.1 links ist ein 3 × 3-Torus. Die initiale Lastverteilung
w(0) der Knoten sei in der Abbildung 5.2.1 rechts dargestellt. Dann liefert das Diffusionsverfahren
denjenigen Fluss, der auf den Kanten dargestellt ist.
(0)
Lemma 5.3. Sei wn die initiale Lastverteilung in einem Graphen G = (V, E) und sei
w=
n
X
wj
j=1
n
(1, . . . , 1)
die zugehörige balancierte Lastsituation. Sei w(0) =
Pn
j=1 βj zj ,
dann gilt:
w = β1 · z1 .
Beweis. Es gilt λ1 = 1 > λ2 (falls G zusammenhängend), und z1 = a · (1, . . . , 1), wobei a ∈ R.
5.2. Dynamische Balancierung unabhängiger Lasten
65
Dann gilt:
D
w(0) , w
E
=
* n
X
βj zj , w
j=1
=
=
* n
X
*
βj zj ,
j=1
+
n
X
wj
j=1
β 1 z1 ,
n
X
j=1
n
+
(1, . . . , 1)
+
wj
(1, . . . , 1)
n
(da (1, . . . , 1)zu allen Eigenvektoren außer z1 senkrecht steht)
*
+
n
X
wj
=
β1 a(1, . . . , 1),
(1, . . . , 1)
n
j=1
Nehmen wir nun die Gleichheit
an, wobei w = b · β1 · z1 . Dann folgt:
D
w
(0)
,w
E
=
D
E 1
w(0) , w = hw, wi
b
P
j=1 wj
(1, . . . , 1)
(w1 , . . . , wn ),
n
P
Pn
n
X
( nj=1 wj )2
j=1 wj
=
=
wj ·
n
n
j=1
P
P
j=1 wj
j=1 wj
(1, . . . , 1),
(1, . . . , 1)
hw, wi =
n
n
P
P
X j=1 wj 2
( nj=1 wj )2
=
=n·
n
n2
i=1
⇒b = 1
Insgesamt gilt also w = β1 · z1 .
Seien µ1 ≥ µ2 ≥ . . . ≥ µn die Eigenwerte von M und λ1 ≤ λ2 ≤ . . . ≤ λn die Eigenwerte der
Laplace-Matrix L. Sei zi der Eigenvektor der Matrix L zum Eigenwert λi . Dann folgt:
M · zi = (I − αL)zi = Izi − αLzi = zi − αλi zi = (1 − αλi )zi .
Der Vektor zi ist daher auch Eigenvektor von M zum Eigenwert 1 − αλi . Da die Eigenwerte
von L alle nicht-negativ sind, ist L positiv semidefinit. Wie bereits festgestellt, gilt λ1 = 0 und
der zugehörige Eigenwert ist z1 = (1, . . . , 1). Wir haben bereits im Zusammenhang mit spektraler
Clusteranalyse gezeigt, dass 0 ein einfacher (d.h. einfach vorkommender) Eigenwert von 0 genau
dann ist, wenn G zusammenhängend ist.
Definition 5.4. Sei (k) = w(k) − w der Fehler nach k Iterationsschritten.
Lemma 5.5. Sei G =P(V, E) ein Graph und sei w(0) die initiale Lastsituation in G. Seien
β1 , . . . , βn ∈ R: w(0) = ni=1 βi zi . Dann gilt:
(0)
=
n
X
i=2
βi zi .
66
5. Lastbalancierung paralleler Berechnungen
Beweis. Es gilt:
(0)
=w
(0)
−w =
n
X
i=1
βi · zi − w =
n
X
i=1
βi zi − β1 z1
(k) = w(k) − w = M k w(0) − M k w = M k (w(0) − w) = M k · (0)
Theorem 5.6. Sei G = (V, E) ein Graph, sei w(0) die initiale Lastsituation und führe Diffusion
mittels der Diffusionsmatrix M durch. Dann gilt:
k(k) k2 ≤ max{|µ2 |, |µn |}k · k(0) k2
Beweis. Zunächst gilt M w̄ = w̄, da mit Lemma 5.3 folgt M w̄ = M β1 z1 = β1 z1 = w̄. Setze
γ := max {|µ2 |, |µn |}. Nach Definition von (k) gilt
||(k) ||2 = ||w(k) − w̄||2 = ||M k w(0) − w̄||2 = ||M k w(0) − M k w̄||2
= ||M k (w(0) − w̄)||2 = ||M k (0) ||2
Weiterhin gelten die Zusammenhänge
M
(0)
n
n
X
X
= M(
βj zj ) =
β j µj z j
j=2
n
X
M k (0) = M k (
j=2
j=2
n
X
β j zj ) =
βj µkj zj
j=2
Insgesamt folgt somit die Behauptung durch
||(k) ||2 = ||
≤ ||
n
X
j=2
n
X
j=2
βj µkj zj ||2
βj γ k zj ||2 = ||γ k
n
X
j=1
βj zj ||2 = ||γ k (0) ||2 = γ k ||(k) ||2
Definition 5.7. Ein Fluss-Vektor y heißt `2 -minimal, wenn
kyk2 = min{kxk2 | x balanciert die Last in G mit initialem Lastvektor w(0) }.
Theorem 5.8. Das Diffusionsverfahren FOS berechnet einen `2 -minimalen Fluss y ∈ Rm .
Bemerkung 5.9. Das Diffusionsverfahren kann durch Berücksichtigung der vorletzten Iteration
√
auf einfache Weise so abgewandelt werden, dass die Lastsituation bereits nach O( log(1/)
) Schrit1−γ
ten -balanciert ist. Darüber hinaus gibt es weitere Diffusionsverfahren mit noch deutlich besserem Konvergenzverhalten. Dazu benötigt man unter anderem die Eigenwerte der Laplace-Matrix
des Graphen.
5.2.2. Weitere Verfahren zur dynamischen Lastbalancierung
Es gibt eine Reihe weiterer Verfahren für das oben beschriebene Szenario (beispielsweise Dimension Exchange oder Work Stealing), auf die hier (zunächst) nicht genauer eingegangen werden
soll.
5.3. Balancierung abhängiger Lasten mittels Graphpartitionierung
67
Abbildung 5.3.1.: Veranschaulichung zur Balancierung abhängiger Lasten und ihre Entsprechung
bei der Partitionierung eines Graphen.
5.3. Balancierung abhängiger Lasten mittels Graphpartitionierung
Im vorigen Abschnitt sind wir davon ausgegangen, dass die Arbeitslasten des parallelen Systems
unabhängig voneinander waren. Nun ändern wir das Szenario in dieser Hinsicht. Die Arbeitslasten und deren Abhängigkeiten repräsentieren wir dabei als Graphen, dessen Knoten (Lasten)
durch eine Kante verbunden sind, wenn zwischen ihnen eine Abhängigkeit besteht. Eine typische
Anwendung sind iterative Algorithmen, die bei der Berechnung des Wertes an einem Knoten v in
Iteration i auf die Werte der Nachbarn von v in Iteration i−1 zurückgreifen muss. Will man diese
Algorithmen parallelisieren, muss man sich im Allgemeinen überlegen, wie man die Daten auf
die verschiedenen Prozessoren aufteilt, um möglichst wenig zwischen Prozessoren kommunizieren
zu müssen. Dies führt uns zum Graphpartitionierungsproblem.
Bei der Partitionierung eines Graphen G = (V, E) soll die Knotenmenge V in fast gleich große,
zusammenhängende Teilmengen aufgeteilt werden. Typische Anwendungsbereiche sind Teile-undHerrsche-Algorithmen oder auch Lastbalancierung für verteilte parallele Graphenalgoirthmen,
wie z.B. beim wissenschaftlichen Rechnen oder der Analyse riesiger Netzwerke.
In Abbildung 5.3.1 Mitte ist ein Graph dargestellt, der die Abhhänigkeiten in einem System
repräsentieren soll. Die Werte in den Knoten sind dabei die initialen Lasten. Der auf den Kanten
aufgeführte Fluss (Werte gerundet) balanciert das System so, dass jeder Knoten genau 92 Einheiten Last erhält. Interessant dabei ist, dass der Knoten links unten als initiale Last 67 < 92
besitzt und für den balancierten Fluss dennoch Last abgeben muss. Der Fluss könnte mittels
Diffusion ausgerechnet werden. Allerdings ist dies auch durch Partitrionierungen möglich, die
dem Lastproblem entsprechen: In Abbildung 5.3.1 links ist die dem initialen Zustand entsprechende Partitionierung dargestellt und rechts die Partitionierung, die den balancierten Zustand
induziert.
Definition 5.10. Eine Abbildung Π : V → {1, . . . , k} induziert eine disjunkte Aufteilung V =
π1 ∪π2 ∪. . .∪πk mit πi = {v ∈ V | Π(v) = i}. Eine solche Abbildung Π nennen wir Partitionierung
und die π Blöcke von Π. Sie heißt -balancierte Partitionierung, wenn |πi | ≤ (1 + )d|V |/ke gilt.
Definition 5.11. Der Kantenschnitt cut(Π) einer Partitionierung Π eines ungerichteten Graphen
G = (V, E, ω) ist definiert als:
X
cut(Π) :=
ω({u, v}).
{u,v}∈E: π(u)6=π(v)
Der Kantenschnitt cut(Π) einer Partitionierung Π ist beispielhaft in Abbildung 5.3.2 dargestellt.
68
5. Lastbalancierung paralleler Berechnungen
π2
π1
π3
Abbildung 5.3.2.: Ein Graph mit Partitionierung Π = π1 ∪ π2 ∪ π3 . Wir nehmen an, dass alle
Kantengewichte 1 sind. Dann gilt für den von Π induzierten Kantenschnitt:
cut(Π) = 7. Die Kanten, die dabei gezählt werden, sind rot dargestellt.
Problem 5.12. Das Graphpartitionierungsproblem besteht in der Berechnung einer -balancierten
Partitionierung mit minimalem Kantenschnitt.
Bemerkung 5.13. Wird ein dynamischer Graph betrachtet, bei dem sich die Struktur über die
Zeit ändert, so sprechen wir von einem Repartionierungsproblem. In diesem Fall möchten wir bei
Eingabe von G und Π1 das Problem 5.12 lösen und Π2 berechnen. Dabei fordern wir zusätzlich,
dass die Migrationskosten zwischen Π1 und Π2 minimiert werden sollen. Diese ergeben sich
üblicherweise aus der Zahl der Knoten, die in Π2 einem anderen Block zugewiesen sind als in Π1 .
Im Allgemeinen sind beide Probleme N P-schwer, sodass in der Praxis Heuristiken eingesetzt
werden. Die Schwierigkeit des Optimierungsproblems liegt interessanterweise nicht in der Zielfunktion des minimalen Schnitts, sondern in der Nebenbedingung der Balancierung der Blöcke.
Falls diese Nebenbedingung entfällt, können wir das bekannte MaxFlow-MinCut-Theorem anwenden und mit effizienten Flusslösern eine (im Allgemeinen natürlich unbalancierte) Lösung
mit minimalem Schnitt in Polynomialzeit berechnen.
5.3.1. Bubble-Framework
Eine Partitonierungsidee, die wir nachfolgend benutzen wollen, basiert auf der Idee von Lloyds kmeans Algorithmus: Gegeben sei eine Punktmenge in der Ebene. Wir wollen diese in k Bereiche
zerlegen und für jeden Bereich ein Zentrum bestimmen, sodass die Summe über den quadratischen Abstand zu den Zentren minimal wird. Initial werden dabei k Zentren beliebig, z.B.
zufällig, gewählt. Dann wird jeder Punkt dem nächstgelegenen Zentrum zugeordnet. Anschließend wird der jeweilige geometrische Schwerpunkt der entstandenen Bereiche neues Zentrum und
ein weiterer Iterationsschritt beginnt. Dieses Verfahren ist schematisch in Abbildung 5.3.3 links
dargestellt.
Das Bubble-Framework überträgt diese Idee nun auf Graphen, indem der Abstand durch ein
geeignetes Distanz- bzw. Ähnlichkeitsmaß ersetzt wird (siehe Abbildung 5.3.3 rechts). Dieses
Ähnlichkeitsmaß soll zum Ausdruck bringen, wie gut zwei Knoten (oder allgemeiner: zwei Regionen) im Graphen miteinander verbunden sind. „Gut verbunden” wird hier nicht streng definiert,
in der Literatur gibt es dazu verschiedene Ansätze. Im Allgemeinen versteht man darunter, dass
zwischen den Knoten eine Vielzahl kurzer Pfade existieren. Letztlich nutzen wir hier wie bereits
im Abschnitt zu MCL (Abschnitt 3.2) aus, dass geeignete Techniken auf Basis von Random Walks
5.3. Balancierung abhängiger Lasten mittels Graphpartitionierung
69
Abbildung 5.3.3.: Schematische Darstellung des k-means Algorithmus von Lloyd (links) und seine
Übertragung auf Graphen durch das Bubble-Framework (rechts).
Abbildung 5.3.4.: Schematische Darstellung des Abflusses bei der gestörten Diffusion.
(oder auf Diffusion als speziellem Random Walk) in der Lage sind, dichte Gebiete in Graphen
von dünnen zu unterscheiden.
Das Bubble-Framework besteht aus der anfänglichen Prozedur DetermineInitialCenters und
den beiden Prozeduren AssignPartition und ComputeCenters, die in jedem Iterationsschritt
ausgeführt werden. Diese folgen, wie an den Namen zu erkennen ist, der generischen Struktur des
k-means-Algorithmus. Bevor wir seine Details anschauen, führen wir zunächst das verwendete
Distanz- bzw. Ähnlichkeitsmaß ein.
5.3.2. Gestörte Diffusion (FOS/C)
In diesem Abschnitt ändern wir das FOS-Verfahren so ab, dass ein balancierter Zustand bei
Konvergenz vermieden wird. Dazu fließt in jeder FOS-Iteration von jedem Knoten δ > 0 Last ab
und anschließend wird der Gesamtabfluss auf die Menge der Quellknoten gleichmäßig verteilt,
wie in Abbildung 5.3.4 dargestellt ist. Dabei geht keine Last im Graphen verloren, da sie nur
umverteilt wird! Dieses Verfahren nennen wir gestörte Diffusion oder kurz FOS/C (engl.: f irst
order diffusion scheme with constant drain).
Definition 5.14. (Abflussvektor) Sei S ⊂ V die Quellmenge. Dann ist der Abflussvektor d
gegeben durch:
(
−δ,
falls i ∈
/S
di = n·δ
|S| − δ, falls i ∈ S
Definition 5.15. (Gestörte Diffusion FOS/C) Gegeben seien G = (V, E), eine Quellmenge
∅=
6 S⊂V von Knoten sowie der Diffusionsparameter 0 < α < max deg(G)−1 . Seien der Abfluss-
70
5. Lastbalancierung paralleler Berechnungen
vektor d wie in Def. 5.14 sowie der initiale Lastvektor w(0) definiert durch:
(
0,
falls i ∈
/S
(0)
wi = n
|S| , falls i ∈ S
Das gestörte Diffusionsverfahren FOS/C führt dann in Iteration k (i ≥ 1) die Berechnung
w(k) = M w(k−1) + d aus.
Hierbeit ist M = I − αL die bereits bekannte Diffusionsmatrix und L die Laplace-Matrix von
G. Wie FOS konvergiert das FOS/C-Verfahren ebenfalls, sogar unabhängig vom (aus anderen
Gründen) oben gewählten initialen Lastvektor. Allerdings erreicht es dabei im Unterschied zu
FOS wie gewünscht keinen balancierten Zustand.
Theorem 5.16. Sei G = (V, E) ein zusammenhängender, schlichter und ungerichteter Graph.
Das FOS/C-Verfahren konvergiert auf G für jeden initialen Vektor w(0) .
Betrachten wir die beiden ersten Iterationen:
w(1) = M w(0) + d
w(2) = M w(1) + d = M 2 w(0) + M d + d = M 2 w(0) + M (I + d).
Wenn wir dies iterativ fortführen, so ergibt sich
w(k) = M w(0) + (M k−1 + . . . + M + I)d
und somit durch die geometrische Reihe für Matrizen
w(∞) = M ∞ w(0) + (I − M )† d = w̄ + (αL)† d.
Im obigen Beweis ist L† die Pseudoinverse der Laplace-Matrix und w̄ der stationäre Zustand,
also der balancierte Lastvektor, von FOS. Wäre L regulär, könnte man dort die echte Inverse
einsetzen.
Statt mit der oben dargestellten und im Beweis genutzten Form der Iteration kann der stationäre Zustand w(∞) folglich auch durch das Lösen eines linearen Gleichungssystems Lw = d mit
w = αw(∞) bestimmt werden. Löser für lineare Gleichungssysteme wie CG (konjugierte Gradienten) konvergieren meist deutlich schneller als das iterative FOS/C-Verfahren. Letzteres ist
daher eher als Mittel zum Verständnis und zur Analyse zu sehen, nicht als Basis einer effizienten
Implementierung von FOS/C.
5.3.3. Bubble-FOS/C
Wir werden nun das FOS/C-Verfahren mit dem Bubble-Framework verbinden, um mit dieser
Kombination namens Bubble-FOS/C Graphen zu partitionieren. Wir betrachten zunächst, wie
wir die einzelnen Methoden des Bubble-Frameworks mit Hilfe von FOS/C-Prozeduren implementieren. Unter einer FOS/C-Prozedur verstehen wir dabei den Lösungsvektor w im stationären
Zustand eines konkreten FOS/C-Systems mit einer bestimmten Quellmenge S. Dabei sei C[i]
das Zentrum von Block i. Wir führen zusätzlich zu AssignPartition und ComputeCenters die
optionale Methode Consolidation ein, die in gewisser Weise die beiden vorigen Methoden kombiniert und oft zu einer besseren Balancierung und einer höheren Qualität der Partitionierung
führt.
1. DetermineInitialCenters:
Wir wählen k verschiedene, beliebige Knoten v1 , . . . , vk aus und setzen C[i] ← vi für
5.3. Balancierung abhängiger Lasten mittels Graphpartitionierung
71
i = 1, . . . , k. Alternativ kann auch ein anderes Verfahren gewählt werden, das k verschiedene Zentren bestimmt. Man kann bspw. nur ein Zentrum zufällig wählen und die übrigen
Zentren möglichst weit weg von den bisherigen Zentren wählen. „Möglichst weit weg” gilt
dabei in Bezug auf das Ähnlichkeitsmaß FOS/C.
2. AssignPartition:
Zur Zuweisung eines Knotens an das nächstgelegene Zentrum lösen wir k FOS/C-Prozeduren.
Die Quellmenge für Verfahren i ist dabei {C[i]}. Ein Knoten wird dem Zentrum zugeordnet,
dessen System die meiste Last sendet. Algorithmisch wird dabei ausgeführt:
• Löse das Gleichungssystem Lwi = di für i = 1, . . . , k
• Π(v) ← argmaxi wi (v)
3. ComputeCenters:
Die Berechnung neuer Zentren aus der bisheriger Partitionierung wird ebenfalls durch Lösen
von k FOS/C-Prozeduren erreicht. Dabei ist die Quellmenge für Verfahren i der gesamte
Block i. Neues Zentrum des Blocks i wird der Knoten mit höchster Last in System i.
Algorithmisch bedeutet dies:
• Löse das Gleichungssystem Lwi = di für i = 1, . . . , k. (nun andere Abflussvektoren!)
• C[i] ← argmaxv wi (v)
4. Consolidation (optional):
Diese Prozedur wird verwendet, um aus einer bestehenden Partitonierung eine neue zu
berechnen. Dazu werden erneut k FOS/C-Verfahren berechnet. Die Quellmenge in System
i ist der gesamte Block i. Ein Knoten wird zu dem Zentrum hinzugefügt, dessen Partition die meiste Last sendet. Diese Prozedur ist somit ein Mischung aus den Prozeduren
AssignPartition und ComputeCenters.
Um die Balancierung weiter zu verbessern, können zusätzliche Balancierungsschritte eingeführt
werden. Beim ScaleBalance wird Last aus Systemen mit zu großen Partitionen entfernt und im
Gegenzug Last zu Systemen mit zu kleinen Partitionen hinzugefügt. Dabei wird ein passender
Skalierungsfakor βi berechnet, der die Menge der Last im System geeignet skaliert.
Eine andere Möglichkeit ist FlowBalance. Hierbei wird mittels Diffusion ein balancierender
Fluss bestimmt, der berechnet, wie viele Knoten von Block i nach Block j (1 ≤ i 6= j ≤ k)
müssen, um die Balancebedingung einzuhalten. Unklar ist hingegen zunächst weiterhin, welche
Knoten dies genau sind. Hierfür können jedoch die Lasten aus der Prozedur AssignPartition
benutzt werden. Letzlich werden diejenigen Knoten verschoben, die die höchste Affinität zum
Zielblock besitzen.
Nachfolgend ist der Algorithmus Bubble-FOS/C dargestellt, der die oben beschriebenen Methoden benutzt. Passend dazu kann Konsolidierung oder Balancierung eingebaut werden. Dabei wird die Konsolodierung üblicherweise als letzte Methode in der Schleife integriert, die
Balancierungs-Methoden noch dahinter in der Schleife oder – um Zeit zu sparen – nur hinter
der Schleife.
5.3.4. Theoretische Ergebnisse zu Bubble-FOS/C
In diesem Abschnitt zeigen wir zunächst, dass Bubble-FOS/C auf zusammenhängenden ungerichteten Graphen konvergiert. Der Beweis basiert auf Lastsymmetrie und einer Potentialfunktion,
die es erlaubt, die Lösung des Algorithmus zu charakterisieren. Mit Hilfe dieser Charakterisierung können wir dann zeigen, dass Bubble-FOS/C den Kantenschnitt auf relaxierte Weise global
optimiert.
72
5. Lastbalancierung paralleler Berechnungen
Algorithmus 25 : Bubble-FOS/C
Input : Graph G, Zahl der Partitionen k
Output : Partitionierung Π
1 C ← DetermineInitialCenters(G, k)
2 Π ← AssignP artition(G, C, k)
3 for τ = 1 until convergence
4
C ← ComputeCenters(G, Π, k)
5
Π ← AssignP artition(G, C, k)
6
return Π
Definition 5.17. Die Potentialfunktion F (Π, Z, τ ) zum Zeitpunkt τ ist wie folgt definiert:
F (Π, Z, τ ) :=
k
X
X
[w]zvc (τ ) ,
c=1 v∈πc (τ )
wobei πc (τ ) die c-te Partition und zc (τ ) das Zentrum der Partition in Iteration π ist.
Wir wollen nun F maximieren. Es ist offensichtlich, dass F eine endliche obere Schranke besitzt,
wenn der Graph endlich ist. Daher genügt es zeigen, dass die Operationen AssignPartition
und ComputeCenters den Wert von F bezüglich der Eingabe maximieren. Für die Operation
AssignPartition ist dies leicht einzusehen, da die Knoten jeweils der Partition zugeteilt werden,
die die meiste Last sendet. Für ComputeCenters ist dies hingegen nicht offensichtlich, sodass wir
zunächst folgendes Resultat beweisen werden:
Lemma 5.18. Sei G = (V, E) ein Graph und u, v ∈ V zwei beliebige Knoten. Dann gilt:
[w]uv = [w]vu .
Beweis. Wir betrachten die FOS/C-Prozedur mit Quelle u. Dann ist der Flussvektor d definiert
als d = (−δ, . . . , −δ, δ(n−1), −δ, . . . , −δ)T , wobei δ(n−1) der Eintrag in Zeile u ist. Die Iteration
von FOS/C zum Zeitpunkt t + 1 für den Knoten v und Quelle u kann folgendermaßen dargestellt
werden:
[w(t+1) ]uv = [Mt+1 w(0) ]uv + [(I + M1 + . . . + Mt )d]uv
Xt
= [Mt+1 w(0) ]uv + nδ
Mlv,u − (t + 1)δ.
l=0
Wir haben in Abschnitt 5.2.1 gelernt, dass Mt+1 w(0) gegen w = (1, . . . , 1)T , die balancierte
Lastverteilung, konvergiert. Dies gilt sogar, wenn die Kanten des Graphen gewichtet sind. Somit
erhalten wir:
X t
[w]vu − [w]uv = nδ
Mlu,v − Mlv,u .
l=0
Da M und somit auch alle Potenzen von M symmetrisch sind, verschwinden alle Summanden
auf der rechten Seite und wir erhalten die Aussage des Lemmas.
Obiges Resultat ist in seiner Allgemeinheit überraschend, da man keine Lastsymmetrie in
einem beliebigen Graphen ohne Symmetrie vermuten würde. Es ist daher beim gestörten Diffusionsschema FOS/C von besonderem Interesse. In unserem Fall hilft es uns dabei, das nächste
wichtige Lemma zu beweisen.
5.3. Balancierung abhängiger Lasten mittels Graphpartitionierung
73
Lemma 5.19. Die Operation ComputeCenters maximiert den Wert der Potentialfunktion F für
eine gegebene k-Partitionierung Π.
Beweis. Sei Π die aktuelle Partitionierung. ComputeCenters berechnet für jede Partition πc , c ∈
{1, . . . , k}, eine FOS/C-Prozedur mit mehreren Quellen, wobei die gesamte Partition als Quellmenge fungiert. Betrachte die Partition πc und die dazugehörige Multi-Quellen-FOS/C-Prozedur,
die w durch Lw = d berechnet. Dabei ist d der zugehörige Flussvektor. Wir wollen
P nun diese
Prozedur in Teilprozeduren aufteilen, die jeweils Lwi = di , i ∈ πc , berechnen mit i∈πc di = d.
Solch eine Aufteilung L(w1 + w2 + · · · + w|πc | ) = d1 + d2 + · · · + d|πc | existiert. Beachten Sie dazu,
dass jede Teilprozedur Lwi = di einer FOS/C-Prozedur mit einzelner Quelle entspricht, bei dem
der Abflussvektor mit |π1c | skaliert wurde:
[di ]v =
(
δn
δ
|πc | − |πc | ,
− |πδc | ,
v ∈ πc , v Quelle in Teilverfahren i
sonst
P
Es ist einfach zu zeigen, dass i∈πc di = d und di ⊥ (1, . . . , 1)T gilt, P
sodass jede Teilprozedur
eine Lösung besitzt. Zusammen mit der Linearität von L erhalten wir i∈πc wi = w. Das neue
Zentrum von Partition πc ist nun der Knoten mit der größten Last im System der Multi-QuellenFOS/C-Prozedur.
Mit den obigen Überlegungen folgt, dass dies
P
P der Knoten
Pu sein muss, für den
[w]u = i∈πc [w]iu maximal ist. Nach Lemma 5.18 gilt dann i∈πc [w]iu = i∈πc [w]ui , sodass das
neue Zentrum zc derjenige Knoten u ist, für den die meiste Last in
Peiner FOS/C-Prozedur mit
einer Quelle in der Partition πc verbleibt. Folglich wird der Beitrag v∈πc [w]zvc für jede Partition
πc in F maximiert.
Theorem 5.20. Sei w der Lastvektor im stationären Zustand von FOS/C. Dann gehört die
größte Last in w zur Quellmenge S. Nachdem k paarweise disjunkte Zentren initial gewählt
wurden, existieren stets k verschiedene Zentren und genau k Partitionen während der Ausführung
von Bubble-FOS/C.
Beweis. Der stationäre Zustand in FOS/C ist äquivalent zu einem `2 -minimalem Fluss-Problem,
bei dem die Quellen Last an die verbliebenen Knoten senden und somit eine höhere Last besitzen.
Somit ist die erste Aussage klar. Für die zweite Aussage ist die Beziehung "≤" offensichtlich,
sodass wir noch zeigen müssen, dass mindestens k verschiedene Zentren und Partitionen in jedem
Iterationsschritt existieren.
Beim initialen Festlegen der Zentren können wir einfach gewährleisten, dass k verschiedene
Knoten ausgewählt werden. In jedem Fall gehören die Zentren, die von ComputeCenters ausgewählt werden, zu einer eigenen Partition und müssen somit verschieden sein. Weiterhin belässt
AssignPartition jedes Zentrum in seiner aktuellen Position. Seien nun zi and zj zwei beliebiz
ge, aber verschiedene Zentren. Nach Lemma 5.18 wissen wir bereits, dass [w]zji = [w]zzij gilt. Da
z
[w]zzii > [w]zzij gilt, erhalten wir [w]zzii > [w]zji und damit die gewünschte Aussage.
Mit obigen Resultaten folgt nun direkt das Haupttheorem und damit die Konvergenz des
Algorithmus.
Theorem 5.21. Der Algorithmus Bubble-FOS/C konvergiert und berechnet eine k-Partitionierung.
Diese Partitionierung ist lokal optimal bezüglich der Potentialfunktion F .
Theorem 5.22. Bubble-FOS/C berechnet relaxierten Kantenschnitt.
Der vollständige Beweis zu Theorem 5.22 findet sich im Artikel Beyond Good Partition Shapes:
An Analysis of Diffusive Graph Partitioning von Meyerhenke und Sauerwald [MS12].
74
5. Lastbalancierung paralleler Berechnungen
5.3.5. DibaP
Folgt.
5.4. Weiterführende Literatur
Folgt.
[MMS09b]
[MMS09a]
75
6. Ausdünnung von Graphen und
Laplace-Löser
Eine ganze Reihe von Graphenalgorithmen erwarten als Eingabegraphen einen dünnen1 Graphen. Dies liegt oft daran, dass für dünne Graphen gute Lösungen einfacher zu finden sind. Aus
praktischer Sicht sind Software-Werkzeuge meist auf Anwendungsfälle mit dünnen Graphen optimiert, weil diese die üblichen Eingaben aus der Praxis darstellen. Doch was passiert, wenn der
Eingabegraph dicht ist? Neben dem Speicherverbrauch steigt normalerweise die Rechenzeit stark
an. Noch problematischer ist es allerdings, wenn die eingesetzten Algorithmen und Werkzeuge
keine guten Lösungen mehr berechnen, weil sie für dünne Graphen optimiert sind. Wir möchten dann den Graphen geeignet ausdünnen, ohne dass dabei die wesentlichen Informationen des
ursprünglichen Graphen verloren gehen. Schematisch ist dies in Abbildung 6.0.1 dargestellt.
Abbildung 6.0.1.: Schematische Darstellung zur Ausdünnung eines Graphen.
6.1. Schnitterhaltende Ausdünnung von Graphen
Eine Ausdünnung wird nicht in jedem Fall jede Eigenschaft eines Graphen erhalten können. In der
Folge beschäftigen wir uns zunächst mit einem Ausdünnungs-Verfahren, das die Gewichte aller
Schnitte eines Graphen approximativ erhält – zumindest mit einer gewissen Wahrscheinlichkeit.
6.1.1. Definitionen
Die Bestimmung von minimalen Schnitten in einem Graphen besitzt vielfältige Anwendungsszenarien, wie wir bereits bei einigen vorher behandelten Themen angemerkt haben. Zu nennen
sind z.B. Clusteranalyse, wissenschaftliches Rechnen oder Bioinformatik. Wir formalisieren die
Problemstellung wie folgt:
Definition 6.1. Sei G = (V, E, ω) ein ungerichteter Graph mit positiver Kantengewichtsfunktion
u : E → R+ . Für S ⊆ V sei
δG (S) = e = {u, v} ∈ E | u ∈ S, v ∈ S̄
1
Die Definition von dünn ist sehr problemabhängig. Häufig versteht man darunter, dass m = O(n) gilt. In diesem
Kapitel bezeichnen wir aber auch Graphen mit m = O(n · polylog(n)) als dünn.
76
6. Ausdünnung von Graphen und Laplace-Löser
e
Abbildung 6.1.1.: Beispiel für einen ungewichteten Graphen, bei dem Random Sampling kein
geeignetes Ausdünnungsverfahren ist.
der durch S induzierte Schnitt und
w(δG (S)) =
X
w(e)
e∈δG (S)
das Gewicht des durch S induzierten Schnitts in G.
Definition 6.2. Sei G = (V, E, wG ) ein Graph mit positiver Kantengewichtsfunktion wG : E →
R+ . Als Ausdünnung von G mit approximativer Schnitterhaltung bezeichnen wir einen Graphen
H = (V, F, wH ) mit F ⊂ E und |F | |E| sowie Gewichtsfunktion wH : F → R+ , falls
wH (δH (S)) = (1 ± ) ωG (δG (S))
für alle S ⊆ V gilt.
Also bleibt nach dieser Art der Ausdünnung der Wert eines Schnitts δ(S) in G auch in H
approximativ erhalten. Einen ausgedünnten Graphen H = (V, F, wH ) können wir alternativ auch
durch eine nicht-negative Gewichtsfunktion wH : E → R≥0 beschreiben, indem genau die Kanten
entfernt werden, für die das Gewicht 0 ist. Den Graphen H, der durch Ausdünnung eines Graphen
G entstanden ist, werden wir nachfolgend auch als H = S(G) schreiben. Ist ein (exakter) Algorithmus A auf G zu langsam, der Ausdünnungsalgorithmus S aber deutlich schneller, so bietet es
sich an, den Algorithmus A auf den ausgedünnten Graphen S(G) anzuwenden. Wir erhalten somit einen Approximationsalgorithmus A(S(G)). (Die Approximationseigenschaft setzt natürlich
voraus, dass A keine wesentlichen Informationen außer den Schnittgewichten verwendet.) Wir
erarbeiten nun, wie sich die Ausdünnung S(G) berechnen lässt.
6.1.2. Der Sampling-Prozess
Ein erster Ansatz wäre es, jeder Kante e ∈ E mit der gleichen Wahrscheinlichkeit (random
sampling) zu entfernen und dies so lange zu betreiben, bis die Anzahl der verbliebenen Kanten
klein genug ist. Dies führt jedoch schnell dazu, dass die wesentliche Struktur eines Graphen
verloren geht, wie Abbildung 6.1.1 zeigt. Entfernen wir hier die Kante e, so zerfällt der Graph
in zwei Komponenten. Wir müssen somit die Wichtigkeit einer Kante bezüglich Schnittbildung
definieren und dürfen wichtige Kanten nicht einfach entfernen.
Definition 6.3. Sei G = (V, E, w) ein Graph. Die Konnektivität ke einer Kante e ∈ E ist das
minimale Gewichts eines Schnitts S ⊂ V, der e enthält, d. h. es gilt
ke =
min
S⊂V,e∈δG (S)
w(δG (S)).
Mit dem Max-Flow-Min-Cut-Theorem folgt direkt, dass ke der Wert eines maximalen Flusses
in einem geeigneten Flussproblem ist. Für e = {u, v} wählen wir hierfür als Quelle s = u,
6.1. Schnitterhaltende Ausdünnung von Graphen
77
als Senke t = v und ersetzen die ungerichteten Kanten durch jeweils zwei gerichtete Kanten
mit Kapazität we . Somit kann ke für jede Kante e effizient berechnet werden. Kanten mit großer
Konnektivität kommen in Schnitten mit vielen anderen Kanten vor, so dass diese weniger wichtig
sind. In unserem Beispiel hat die Kante e eine Konnektivität von 1 und ist somit wichtiger als
die restlichen Kanten. Nachfolgend betrachten wir zur einfacheren Darstellung den Fall, dass alle
Kanten e ∈ E Gewicht 1 besitzen, d. h. es gilt w(F ) = |F | für F ⊆ E. Der allgemeine Fall lässt
sich durch analoge Überlegungen nachvollziehen.
Aufbauend auf der Definition der Kantenkonnektivität, erhalten wir den folgenden Algorithmus:
Algorithmus 26 : Iteratives randomisiertes Sampling
Input : Ungewichteter Graph G = (V, E), Anzahl der Runden ρ
Output : Ausgedünnter Graph H = (V, F, w)
1 w ←0
2 foreach e ∈ E do
3
Berechne ke
4
5
6
for i = 1 to ρ do
foreach e ∈ E do
Mit Wahrscheinlichkeit 1/ke , erhöhe we um ke /ρ
Ein Vorteil des vorgestellten Sampling-Prozesses ist, dass die Kantengewichte im Erwartungswert erhalten bleiben:
Lemma 6.4. Für jede Kanten e ∈ E gilt: E [we ] = 1.
Beweis. Der erwartete Zuwachs für we in Iteration i beträgt (1/ke ) · (ke /ρ) = 1/ρ. Da der
Erwartungswert linear ist und insgesamt ρ Iterationen durchgeführt werden, gilt somit:
E(we ) = ρ ·
1
= 1.
ρ
Algorithmus 26 ist somit erwartungstreu hinsichtlich der Kantengewichte. Durch die Linearität
des Erwartungswerts ergibt sich somit auch direkt das nachfolgende Resultat:
Lemma 6.5. Sei F ⊆ E. Dann gilt: E [w(F )] = |F |.
Das Gewicht eines Schnittes bleibt somit ebenfalls im Erwartungswert erhalten. Allerdings
ist dieses Resultat noch zu schwach für unsere Zwecke. Wir möchten vielmehr, dass mit hoher
Wahrscheinlichkeit das Gewicht eines Schnittes erhalten bleibt, d. h. dass w(F ) mit hoher Wahrscheinlichkeit nahe bei |F | = E [w(F )] liegt. Anders ausgedrückt, muss eine Konzentration von
w(F ) um seinen Erwartungswert vorliegen.
6.1.3. Konzentration um den Erwartungswert
Zunächst erinnern wir an die Chernov-Schranken aus der Wahrscheinlichkeitstheorie:
Theorem 6.6. (Chernov-Schranken) Seien X1 , . . . , Xn Zufallsvariablen von n unabhängigen
Bernoulli-Experimenten mit Erfolgswahrscheinlichkeit p, d. h. Xi ∼ Bin(1, p). Dann gilt:
P
• E [Anzahl der Erfolge] = E [ ni=1 Xi ] = pn
78
6. Ausdünnung von Graphen und Laplace-Löser
• Für jedes δ > 0 gilt:
Pr
"
n
X
i=1
• Für δ ∈ [0, 1] gilt:
Pr

#
Xi ≥ (1 + δ) · pn ≤ exp −
"
n
X
i=1
#
n 2o
min δ, δ
3
δ2
Xi ≤ (1 − δ) · pn ≤ exp − pn
2

pn
Betrachten wir einen beliebigen Schnitt δ(S) in G. Sei Xi,e die Bernoulli-Zufallsvariable, die
angibt, ob Kante e in Iteration i ausgewählt wurde, i = 1, . . . , ρ und e ∈ δ(S). Dann ist das
Gewicht w(δ(S)) des Schnitts δ(S) im Ausgabegraphen H gegeben durch die Zufallsvariable X
mit
ρ
X
X ke
· Xi,e .
X=
ρ
i=1 e∈δ(S)
Da die Zufallsvariablen Xi,e unabhängig sind, können wir die Chernov-Schranken anwenden,
um eine Konzentration von X um den Erwartungswert E [X] zu beweisen. Allerdings müssen für
eine beidseitige Abschätzung die Zufallsvariablen (ke /ρ)·Xi,e in [0, 1] liegen. Da die Koeffizienten
ke sehr groß und, was entscheidend ist, sehr unterschiedlich werden können, ist eine direkte
Anwendung nicht möglich. Betrachten wir dazu das nachfolgende Beispiel:
P
Beispiel 6.7. Sei X = ni=1 n·Xi gegeben, wobei die Xi unabhängige Bernoulli-Zufallsvariablen
sind. Obwohl der Koeffizient n groß ist, können
P beiden Chernov-Schranken
P wir dennoch die
anwenden. Die Zufallsvariable X ist gerade n · ni=1 Xi und für ni=1 Xi sind die Koeffizienten
jeweils 1.
P
Betrachten wir hingegen die Zufallsvariable Y = n·Y0 + ni=1 Yi und Y0 , . . . , Yn seien BernoulliZufallsvariablen mit Trefferwahrscheinlichkeit p = n1 . Dann ist E(Y ) = 2 und P r(Y ≥ n) ≥ n1 .
Die Chernov-Schranken können folglich nicht angewendet werden.
Um eine Konzentration dennoch zeigen zu können, werden
einteilen,
wir die Kanten in Gruppen
deren Konnektivität ungefähr gleich ist. Sei dazu Ei = e ∈ E | 2i−1 ≤ ke < 2i , wodurch wir
eine Partition E = E1 ∪ E2 ∪ . . . ∪ Elog(n) der Kantenmenge erhalten. Anstatt eine Konzentration
von w(δ(S)) um E [w(δ(S))] direkt zu bestimmen, werden wir die Chernov-Schranken jeweils auf
w(δ(S) ∩ Ei ) anwenden. Für e ∈ δ(S) ∩ Ei sind nach Konstruktion die Koeffizienten kρe ungefähr
gleich.
Eine Kantenmenge F der Form F = δ(S) ∩ Ei nennen wir nachfolgend eine schnittinduzierte
Menge. Es könnte allerdings eine Knotenmenge S 0 ⊂ V geben mit F = δ(S) ∩ Ei = δ(S 0 ) ∩ Ei .
Wir betrachten daher jeweils den Schnitt mit kleinster Kardinalität, da der Stichprobenfehler
w(F ) klein gegenüber |δ(S)| sein soll und dies am schwierigsten ist, wenn |δ(S)| kleinstmöglich
gewählt wird. Wir definieren weiterhin: q(F ) = min {|δ(S)| | S ⊂ V, δ(S) ∩ Ei = F }. Mit Hilfe
der Chernov-Schranken erhalten wir dann das nachfolgende Lemma für die Menge F :
Lemma 6.8. Sei F ⊆ Ei eine schnittinduzierte Menge. Dann gilt für > 0:
· q(F )
2 ρ · q(F )
P r |w(F ) − E [w(F )] | >
≤ 2 exp −
.
log n
3 · 2i log2 n
Der Beweis dieses Lemmas bleibt dem Leser als Selbstübung durch Anwendung der ChernovSchranke überlassen.
6.1. Schnitterhaltende Ausdünnung von Graphen
79
6.1.4. Das Hauptresultat
Wir möchten nun das Haupttheorem dieses Abschnitts beweisen, nämlich dass Algorithmus 26
tatsächlich eine approximativ schnitterhaltende Ausdünnung des Eingabegraphen berechnet:
Theorem 6.9. Sei G = (V, E) ein ungerichteter Graph mit n Knoten. Dann produziert Algorithmus 26 mit Wahrscheinlichkeit ≥ 21 eine Gewichtsfunktion w : E → R≥0 , die den Wert
aller Schnitte in G approximativ, d. h. bis auf den Faktor 1 ± , erhält und nur O(n log3 (n) /2 )
Nichtnulleinträge erzeugt.
Durch eine weitergehende, kompliziertere Analyse lässt sich der Faktor log3 (n) auf log2 (n)
reduzieren bzw. durch eine andere Herangehensweise sogar ganz eliminieren. Nachfolgend beschränken wir uns jedoch auf das oben genannte Resultat.
Anzahl der Nichtnulleinträge. Die Anzahl der Nichtnulleinträge von w ist leicht zu analysieren.
Wir setzen zunächst ρ = 100 log3 (n/2 ). Sei Xi,e erneut die Indikator-Zufallsvariable, die angibt,
ob die Kante e in Iteration i ausgewählt
Pρ Pwurde. Dann ist E [Xi,e ] = 1/ke . Die Anzahl der
Nichtnulleinträge in w ist höchstens i=1 e∈E Xi,e und somit gilt
E [Anzahl Nichtnulleinträge] = ρ
X 1
= O(n log3 (n)/2 ),
ke
e∈E
P
da
e∈E 1/ke ≤ n − 1 für jeden Graphen mit |V | = n gilt. Wir erinnern an die MarkovUngleichung aus der Wahrscheinlichkeitstheorie:
Lemma 6.10. Sei X eine Zufallsvariable mit Werten in [0, ∞]. Dann gilt für beliebiges r > 0
die Abschätzung:
1
P r (X ≥ r · E [X]) ≤ .
r
Mit der Markov-Ungleichung folgt für r = 4 direkt, dass die Anzahl Nichtnulleinträge mit
Wahrscheinlichkeit ≥ 3/4 kleiner als 4 O(n log3 (n)/2 ) ist.
Konzentration um den Erwartungswert. Für den Beweis der Konzentration um den Erwartungswert, werden wir zeigen, dass für jede schnittinduzierte Menge F mit hoher Wahrscheinlichkeit
q(F )
|w(F ) − |F || ≤
(6.1.1)
log(n)
gilt. Dann erhalten wir für jeden Schnitt C = δ(S) die folgenden Beziehungen:
|w(C) − |C|| ≤
≤
≤
log
Xn
i=1
log
Xn
i=1
log
Xn
i=1
|w(C ∩ Ei ) − |C ∩ Ei ||
q(C ∩ Ei )
log n
|C|
= |C|.
log n
Dabei gilt die erste Ungleichung nach der Dreieckunsgleichung, die zweite folgt aus Formel 6.1.1
und die dritte Ungleichung aus der Tatsache, dass q(C∩Ei ) das Gewicht des kleinsten Schnitts ist,
der C ∩ Ei induziert. Es gilt daher die gewünschte Eigenschaft, dass das Gewicht eines Schnittes
80
6. Ausdünnung von Graphen und Laplace-Löser
durch die Ausdünnung approximativ erhalten bleibt. Es bleibt somit zu zeigen, dass Formel 6.1.1
tatsächlich gilt.
Sei nachfolgend i ∈ {1, . . . , log n} fest. Seien ferner F 1 , F 2 , . . . die durch Ei schnittinduzierten
Mengen. Ordne diese derart, dass q(F 1 ) ≤ q(F 2 ) ≤ . . . gilt. Ferner definieren wir pj durch
2 ρ · q(F j )
q(F j )
j
j
≤ 2 exp −
,
pj := P r |w(F ) − E w(F ) | >
log n
3 · 2i log2 (n)
(6.1.2)
wobei die Ungleichung nach Lemma 6.8 gilt.
S
P
Mit der Bonferroni-Ungleichung (engl. „union bound”) P r ( i Ai ) ≤ i P r(Ai ) für Ereignisse
Ai und der Definition der pj erhalten wir
X
P r(schnittinduzierte Teilmenge F ⊂ Ei erfüllt nicht 6.1.1) ≤
pj .
j
Wir können nun jedoch nicht direkt Lemma 6.8 anwenden, da es exponentiell viele Mengen F j
geben kann.
2
Betrachten wir zunächst nur die ersten n2 schnittinduzierten Mengen F 1 , . . . , F n . Da jede
Kante e ∈ F j auch zu Ei gehört, gilt folglich ke ≥ 2i−1 . Somit hat jeder Schnitt, der die Kante e
enthält, mindestens Größe 2i−1 und damit q(F j ) ≥ 2i−1 . Setzen wir dies nun in Ungleichung 6.1.2
ein, so ergibt sich für unser gewähltes ρ = 100 log3 (n)/2 :
2
(100 log3 (n)/2 ) 2i−1
pj ≤ 2 exp −
≤ 2 exp (−16 log n) ≤ 2n−16 .
3 · 2i log2 (n)
Es gilt also:
Hilfslemma:
Pn2
j=1 pj
≤ 2n−14 . Für die restlichen F j mit j > n2 benötigen wir das nachfolgende
Lemma 6.11. Sei G = (V, E) ein Graph. Sei fener B ⊂ E und K ≤ min {ke | e ∈ B}. Dann
gilt für jede reelle Zahl α > 1:
| {δ(S) ∩ B : S ⊆ V ∧ |δ(S)| ≤ α · K} | < n2α .
Anders ausgedrückt ist die Anzahl der Schnittmengen eines Schnitts δ(S), dessen Größe durch
α·K beschränkt ist, mit einer beliebigen Kantenteilmenge B kleiner als n2α . Setzen wir in diesem
Lemma B = Ei und K = 2i−1 , dann gilt für jedes α ≥ 1:
| schnittiniduzierte Menge F ⊆ Ei mit q(F ) ≤ α · 2i−1 | < n2α .
Also ist für α ≥ 1 die Anzahl der F j mit q(F j ) ≤ α · 2i−1 kleiner als n2α . Setzen wir nun
α = ln j/(2 ln n) in Ungleichung 6.1.2 ein, so ergibt sich:
2
(100 log3 (n)/2 ) ln(j) 2i−1
pj ≤ 2 exp −
< j −8 .
6 · 2i log2 (n) ln(n)
Durch Summation über j > n2 erhalten wir nun
−7 ∞
ˆ ∞
X
X
j
−8
−8
pj <
j ≤
j dj = −
< n−14 .
7
2
2
n
j=n
2
2
j>n
j>n
6.2. Spektrale Approximation
81
Insgesamt ergibt sich also:
X
2
pj =
j
n
X
j=1
pj +
X
pj < 2n−14 + n−14 < n−2 .
j>n2
Wenn wir jetzt die Bonferroni-Ungleichung auf alle E1 , . . . , Elog n anwenden, dann erhalten wir
P r(schnittinduzierte Teilmenge F erfüllt nicht 6.1.1)
≤
≤
<
log
Xn
P r(schnittinduzierte Teilmenge F ⊂ Ei erfüllt nicht 6.1.1)
i=1
log
Xn X
i=1
log
Xn
i=1
pj
j
n−2 <
1
.
n
Die Ungleichung 6.1.1 gilt somit mit Wahrscheinlichkeit ≥ 1 − 1/n und damit ist auch unser
Haupttheorem bewiesen.
6.2. Spektrale Approximation
6.2.1. Definitionen
In diesem Abschnitt möchten wir ein Ausdünnungsverfahren kennenlernen, bei dem der ausgedünnte Graph H eine spektrale Approximation des Eingabegraphen G darstellt. Formalisieren
lässt sich dies wie folgt:
Definition 6.12. Sei G = (V, E, wG ) ein Graph mit positiver Kantengewichtsfunktion w : E →
R+ und Laplace-Matrix LG . Als (1 + )-spektrale Ausdünnung von G bezeichnen wir einen Graphen H = (V, F, wH ) mit F ⊂ E, |F | |E| und Laplace-Matrix LH und Gewichtsfunktion
wH : F → R+ , falls
1 T
x LG x ≤ xT LH x ≤ (1 + )xT LG x
1+
für alle x ∈ Rn gilt.
Beachten Sie, dass eine spektrale Ausdünnung automatisch auch eine Ausdünnung mit approximativer Schnitterhaltung ist. Die Umkehrung gilt im allgemeinen Fall nicht. Beide Aussagen
werden dem Leser als einfache Übungsaufgabe empfohlen. Spektrale Approximation findet in
verschiedenen Approximationsalgorithmen für Graphenprobleme Verwendung, z. B. zur Partitionierung oder zur Berechnung maximaler Flüsse. Es ist möglich, eine spektrale Ausdünnung
H mit O(n/) Kanten in Laufzeit O(m) zu berechnen. In diesem Abschnitt begnügen wir uns
jedoch mit einem etwas schwächeren Resultat, das das Haupttheorem dieses Abschnitts bildet.
Theorem 6.13. Sei G = (V, E) ein Graph mit |V | = n und |E| = m. Ferner sei > 0. Dann
existiert ein randomisierter Algorithmus, der mit Wahrscheinlichkeit ≥ 1 − 1/n eine spektrale
Approximation von G mit O(n log(n)/2 ) Nichtnulleinträgen berechnet.
Bevor wir einen Algorithmus angeben können, der das obige Theorem erfüllt, benötigen wir
noch einige Einsichten, wie Graphen und elektrische Netzwerke zusammenhängen.
82
6. Ausdünnung von Graphen und Laplace-Löser
Abbildung 6.2.1.: Beispiel für ein elektrisches Netzwerk.
6.2.2. Graphen und elektrische Netzwerke
Sei G = (V, E) ein gerichteter Graph mit Gewichtsfunktion w. Wir können G wie folgt als
elektrisches Netzwerk auffassen:
• Jeder Kante e ∈ E ordnen wir einen Widerstand re = 1/we zu.
• Jeder Knoten i ist eine Stromquelle, die dem System di Ampere Strom zuführt.
• Einer der Knoten ist geerdet und über ihn verlässt Strom das System (für diesen Knoten
ist di somit negativ).
• Jeder Knoten besitzt ein Potential zi , mit dem der Stromfluss auf der Kante e = (i, j)
genau (zi − zj )wij beträgt.
Beispielhaft ist ein solches elektrisches Netzwerk in Abbildung 6.2.1 dargestellt. Der Potentialvektor z lässt sich durch Lösen des linearen Gleichungssystem Lz = d berechnen, wobei L die
Laplace-Matrix von G und d = (d1 , . . . , dn ) der Vektor ist, der die Stromzu- und abflüsse (ins
bzw. aus dem System) darstellt.
Nach dem Kirchhoffschen Potentialgesetz ist für jeden Zyklus im Graphen G die Summe der
Stromflüsse auf den Kanten des Zyklus gerade 0. Ferner heben sich die Zu- und Abflüsse auf
einem Knoten nach dem Kirchhoffschen Flussgesetz auf, wenn man den Zu- und Abfluss aus dem
Stromnetzwerk mit berücksichtigt. Dies ist ein Analogon zur Lastbalancierung mit Diffusion, die
wir im letzten Kapitel erarbeitet hatten. Hier gibt ein Knoten, der zu viel Last hat, diesen Zufluss
komplett ins Netzwerk ab. Der Abfluss aus dem Netzwerk am Knoten kommt in einen Knoten
vom restlichen Netzwerk, der zu wenig Last hat.
Für das weitere Kapitel ist die Größe des effektiven Widerstands einer Kante eine zentrale
Größe, die wir effizient berechnen möchten. Diese werden wir für den randomisierten Algorithmus
zur spektralen Approximation benötigen.
Definition 6.14. Sei G = (V, E) ein gerichteter Graph und e = (u, v) ∈ E eine Kante. Sei z der
Potentialvektor des Gleichungsysteme Lz = d, wobei der Stromflussvekor d gegeben ist durch:


falls x = u
1,
dx = −1, falls x = v


0
sonst
Dann ist der effektive Widerstand Re der Kante e = (u, v) definiert durch R(u,v) = (zu −zv )w(u,v) .
6.2. Spektrale Approximation
83
Das Stromflussproblem in obiger Definition entspricht der Lösung von zwei FOS/C-Prozeduren,
wobei u das Zentrum der ersten Prozedur und v das Zentrum der zweiten Prozedur ist. Seien d1
der Vektor, der an der Stelle u den Wert 1 hat und sonst nur aus 0 besteht, und d2 der Vektor,
der an der Stelle v den Wert 1 hat und ansonsten nur 0. Dann entspricht die erste Prozedur
dem Gleichungssystem Lz1 = d1 und die zweite dem Gleichungssystem Lz2 = d2 . Es gilt somit
d = d1 − d2 und der in obiger Definition gesuchte Potentialvektor ergibt sich durch z = z1 − z2 .
Der effektive Widerstand Re entspricht folglich einer Potentialdifferenz in z, so dass eine hohe
Potentialdifferenz für einen „Flaschenhals” im System spricht.
Wir möchten nun erarbeiten, wie wir den effektiven Widerstand alternativ berechnen können.
Sei hierfür B ∈ {−1, 0, 1}m×n die Knoten-Kanten-Inzidenzmatrix 2 , d. h. es gilt


falls v Endknoten von e
1,
Be,v = −1, falls v Startknoten von e


0,
sonst
Für e = (u, v) kann der effektive Widerstand Re berechnet werden durch
Re = (eu − ev )T L† (eu − ev ),
wobei L† die Pseudo-Inverse der Laplace-Matrix und ei der i-te Einheitsvektor ist. Setzen wir
nun Π := BL† B T , dann gilt somit Re = Πe,e , da (eu − ev )T gerade die Zeile von Π ist, die zur
Kante e = (u, v) gehört. Die Matrix Π hat dabei einige interessante Eigenschaften, die wir (ohne
Beweis) im nächsten Lemma zusammenstellen:
Lemma 6.15. Sei Π = BL† B T . Dann gilt:
1. Π ist symmetrisch.
2. Π2 = Π
3. Die Eigenwerte von Π sind 0 oder 1.
4. P r (e ist Kante in zufälligem Spannbaum) = Re .
6.2.3. Algorithmus und Beweis des Haupttheorems
Mit den erarbeiteten Definition des effektiven Widerstands Re einer Kante e können wir nun einen
iterativen Algorithmus zur Berechnung der spektralen Approximation angeben (Algorithmus 27).
Beachten Sie dabei, dass die Summe über alle Re genau n − 1 ist.
Der Algorithmus erinnert vom Aufbau an den Algorithmus aus dem letzten Abschnitt über
schnitterhaltende Ausdünnung. Da wir die effektiven Widerstände Re über die Matrix Π berechnen möchten, benötigen wir für den Beweis des Haupttheorems noch eine „Chernov-Schranke für
Matrizen”:
Theorem 6.16. Sei > 0 hinreichend klein und M ∈ Rm×m eine zufällige, symmetrische, positiv
semidefinite Matrix mit E [M ] = Im . Seien ferner ρ := supM ||M || und M1 , . . . , MS stochastisch
unabhänige Kopien von M . Dann gilt:
"
#
S
1X
S2
P r ||
Mi − Im || > ≤ 2m · exp −
S
2ρ
i=1
2
Beachten Sie, dass wir auf den Folien zu Kapitel 3 die Matrix B als B T (und umgekehrt) definiert hatten. Die
Definition im Skript ist allerdings konsistent.
84
6. Ausdünnung von Graphen und Laplace-Löser
Algorithmus 27 : Iteratives randomisiertes Sampling
Input : Graph G = (V, E), Anzahl der Runden ρ
Output : (1 + )-spektrale Approximation von G
1 w ←0
2 foreach e ∈ E do
3
Berechne Re
4
5
6
for i = 1 to ρ do
foreach e ∈ E do
Mit Wahrscheinlichkeit Re /(n − 1), erhöhe we um Re /ρ
Mit den getätigten Vorarbeiten können wir nun Theorem 6.13 beweisen:
Beweis. (Prüfungsrelevant ist die Beweisstruktur, die konkreten Inhalte der Formeln sind es
nicht. Sie sollten aber das grundsätzliche Vorgehen und die dabei beteiligen Matrizen sowie
deren Zweck und Aufbau kennen.)
Sei G = (V, E) der Graph, für den eine spektrale Approximation berechnet werden soll. Wir
wählen eine Orientierung für jede Kante e ∈ E und B sei die dazugehörige Knoten-KantenInzidenzmatrix. Weiter sei Π = BL† B T wie im vorherigen Abschnitt und Πe die Spalte von Π,
die zur Kante e gehört.
Sei Y eine Zufallsvariable mit P r (Y = e) = pe , wobei pe = Re /(n − 1) die Wahrscheinlichkeit
√
aus Algorithmus 27 ist. Setze ve = Πe / pe und sei vY der durch Y induzierte Zufallsvektor, d. h.
P r (vY = ve ) = pe . Wir definieren weiter eine Zufallsmatrix M = vY vYT ; ferner seien Mi = vYi vYTi
stochastisch unabhänige Kopien von M , für i = 1, . . . , S. Dann gilt für die Matrix M :
E[M ] = E[ve veT ] =
X
Πe ΠTe = Π
e∈E
Nach Lemma 6.15, Eigenschaften 1 P
bis 3, ist die Matrix Π eine Projektionsmatrix und somit
äquivalent zu einer Diagonalmatrix dj=1 ej eTj für ein d ≤ m, hierbei ist d die Vielfachheit des
P
Eigenwerts 1. Die „Chernov-Schranken für Matrizen” gelten ebenfalls, wenn E [M ] = dj=1 ej eTj
für
zu einer Diagonalmatrix der Form
Pd ein d T≤ m gilt und sogar auch, wenn E [M ] äquivalent
2
j=1 ej ej mit d ≤ m ist. Da außerdem Re = ||Πe || gilt, folgt direkt
||ve ||2 =
||Πe ||2
Re
=
=n−1
pe
pe
und somit ||Mi || ≤ n − 1 für alle i. Wir können daher die Chernov-Schranke für Matrizen aus
Theorem 6.16 anwenden. Wir erhalten die Abschätzung
S2
,
(6.2.1)
P r(||Π̃ − Π|| > ) ≤ 2(n − 1) · exp −
2(n − 1)
P
P
wobei die Matrix Π̃ durch Π̃ = S1 Si=1 Mi = S1 Si=1 vYi vYTi gegeben ist. Setzen wir S als
Ω(n logn/2 ), so erhalten wir eine Fehlerwahrscheinlichkeit von n−Ω(1) .
Wir möchten dieses nun auf die Laplace-Matrix LH des ausgedünnten Graphen H anwenden.
Aus Π = BL†G B T folgt für eine Kante e ∈ E
BL† be
Πe
ve = √ = √ G = BL†G ue ,
pe
pe
6.2. Spektrale Approximation
85
√
wobei be die Zeile von B ist, die zur Kante e gehört, und ue = be / pe ist. Damit ergeben sich
zusammen mit der Definition der Laplace-Matrix von H
LH =
S
S
1X
1 X bYi bTYi
=
uYi uTYi
S
p Yi
S
i=1
i=1
die Zusammhänge
Π̃ =
=
Π =
S
S
1X
1X
vYi vYTi =
BL†G uYi uTYi L†G B T
S
S
i=1
BL†G LH L†G B T
BL†G B T
BL†G LG L†G B T
i=1
Es gilt damit
||Π̃ − Π|| = sup |
x6=0
xT BL†G (LH − LG )L†G B T x
xT (Π̃ − Π)x
|
=
sup
|
|.
xT x
xT x
x6=0
Ist z ein Vektor mit Bz = 0, so muss z parallel zum Vektor 1 = (1, . . . , 1)T sein, da der Graph G
zusammenhängend ist. Somit gilt für z 6= 0, dass aus hz, 1i = 0 direkt Bz 6= 0 folgt. Wir können
somit in der obigen Gleichung den Vektor y durch Bz substituieren. Da für solch einen Vektor z
die Eigenschaft LG L†G z = z gilt, erhalten wir:
||Π̃ − Π|| ≥
sup
z6=0,hz,1i=0
|
z T B T BL†G (LH − LG )L†G B T Bz
|
z T B T Bz
z T LG L†G (LH − LG )L†G LG z
=
sup
|
|
z T LG z
z6=0,hz,1i=0
=
sup
z6=0,hz,1i=0
|
z T (LH − LG )z
|
z T LG z
Zusammen mit dem Resultat aus Formel 6.2.1 erhalten wir die gewünschte Eigenschaft
!
z T (LH − LG )z
sup
|
|
>
≤
P
r
Pr
||
Π̃
−
Π||
>
= n−Ω(1) .
z T LG z
z6=0,hz,1i=0
Dies entspricht genau der Definition der (1+)-spektralen Approximation und unser Algorithmus
berechnet eine solche mit Wahrscheinlichkeit ≥ 1 − 1/n.
Der vorgestellte Algorithmus zur spektralen Approximation hat bei effizienter Implementierung eine Laufzeit von O(m log(1/)). Um die effektiven Widerstände Re für die Kanten effizient
mittels der Matrix Π = BL† B T berechnen zu können, benötigen wir somit eine effiziente Berechnung der Matrix L† , der Pseudoinversen der Laplace-Matrix. Diese ist jedoch im Allgemeinen
eine dichte Matrix! Die Zeitkomplexität entspricht somit einer Inversion einer Matrix und die
Raumkomplexität ist O(n2 ). Alternativ zur Inversion kann es daher sinnvoll sein, die Re zu berechnen, indem wir Gleichungssysteme der Form Lz = d lösen. Einen schnellen Löser für solche
Gleichungssysteme stellen wir im nächsten Abschnitt vor.
86
6. Ausdünnung von Graphen und Laplace-Löser
Eine alternative Herangehensweise besteht darin, die Re durch einen Algorithmus mit konstanter relativer Güte approximieren zu lassen. Dieser soll eine Laufzeit von O(m log r) besitzen
mit r = wmax /wmin . Hierbei gilt folgendes Resultat, das wir ohne Beweis benutzen.
Theorem 6.17. Sei G = (V, E, w) ein gewichteter Graph und > 0. Dann gibt es einen Algorithmus mit Laufzeit O(m log r/2), der eine Matrix Z der Dimension (24 log(n/2)) × n derart
berechnet, dass für jedes Knotenpaar (u, v) mit Wahrscheinlichkeit ≥ 1 − 1/n gilt:
(1 − )R(u,v) ≤ ||Z̃(eu − ev )||2 ≤ (1 + )R(u,v) .
6.3. Kombinatorische Löser für Laplace-Systeme
6.3.1. Grundidee
In diesem Abschnitt wollen wir erarbeiten, wie man ein Gleichungssystem der Form Lv = d
effizient lösen kann, wobei L eine symmetrische, positiv semidefinite Matrix und d ein Vektor ist,
dessen Einträge in der Summe 0 ergeben. Dazu stellen wir den kombinatorischen Löser KOSZ
von Kelner, Orecchia, Sidford und Zhu vor, der nahezu lineare Laufzeit besitzt.
Wir beschränken uns dabei sogar auf Systeme der Form Lv = es − et , wobei ei ein Vektor ist,
der an der Stelle i eine 1 enthält und sonst nur aus Nullen besteht. Andere rechte Seiten lassen
sich stets darauf reduzieren. Im Abschnitt zu Graphen und elektrischen Netzen haben wir bereits
erarbeitet, dass die Lösung des obigen Gleichungssystem einem Potentialvektor in einem elektrischen Netzwerk entspricht. Potentialdifferenzen induzieren dabei einen balancierenden Fluss, der
in unserem Fall gesucht ist. Denn der balancierende Fluss ist dual zum Potentialvektor v, der
Lösunge des linearen Gleichungssystems. Wir werden daher einen Approximaionsalgorithmus
entwickeln, der diesen Fluss berechnet und so auch das entsprechende Gleichungssystem löst.
Nach dem Kirchhoffschen Potentialgesetz ist die Summe der Flüsse auf einem Zyklus gerade 0.
Wir können daher den folgenden Ansatz wählen:
• Starte mit einem zulässigen Fluss f zwischen den Knoten s und t.
• Bestimme einen Zyklus C zufällig bezüglich einer gegebenen Wahrscheinlichkeitsverteilung.
• Falls erforderlich, passe f auf C so an, dass die Summe des Flusses auf C gleich 0 ist.
• Führe weitere Iterationen durch, bis eine Fehlerschranke erreicht ist.
Wir werden nun das KOSZ-Verfahren erarbeiten, das diesen Ansatz verfolgt.
6.3.2. Flüsse, Energie und Baumzyklen
Sei G = (V, E, w) ein gerichteter Graph mit |V | = n und |E| = m. Ferner setzen wir den
Widerstand re = 1/we für jede Kante e ∈ E. Beachten Sie den Unterschied zwischen Widerstand
(Kehrwert des Kantengewichts) und dem effektiven Widerstand (Stromfluss auf der Kante).
Einen Fluss f auf den Kanten interpretieren wir als Vektor aus Rm . Es gilt dabei für alle e =
(a, b) ∈ E, dass die Flussrichtung sich aus dem Vorzeichen ergibt und somit f (a, b) = −f (b, a).
Sei B die Kanten-Knoten-Inzidenzmatrix, L die Laplace-Matrix von G und R = (rij ) ∈ Rm×m
eine Diagonalmatrix definiert durch
(
re , falls i = j = e
rij =
0, sonst
Dann gelten die folgenden Zusammenhänge:
6.3. Kombinatorische Löser für Laplace-Systeme
87
Lemma 6.18. Sei f ein Fluss, x ∈ Rn , a ∈ V und (a, b) ∈ E. Dann gilt:
1. [B T f ]a =
P
(b,a)∈E
f (b, a) −
2. L = B T R−1 B
P
(a,b)∈E
f (a, b)
3. [Bx](a,b) = xa − xb
4. xT Lx =
P
(a,b)∈E
(xa −xb )2
r(a,b)
Falls ein Graph ungewichtet ist, folgt somit aus Unterpunkt 2 die vereinfachte Gleichung L =
B T B.
Wir benötigen zunächst noch weitere Definitionen für spezielle Flüsse:
Definition 6.19. Sei G = (V, E, w) wie oben und B die Kanten-Knoten-Inzidenzmatrix.
• Ein Fluss f heißt Zirkulation, falls B T f = 0.
• Die Energie Er (f ) eines Flusses f ist definiert als
X
Er (f ) =
re · f (e)2 = f T Rf = ||f ||2R
e∈E
• Der Fluss fopt heißt elektrischer oder optimaler Fluss bezüglich des Bedarfsvektors d, falls
gilt:
fopt = argminB T f =d Er (f )
• Ein Fluss f heißt -approximativer elektrischer Fluss bezüglich des Bedarfvektors d, falls
B T f = d und Er (f ) ≤ (1 + )Er (fopt ).
Für einen Stromfluss f gilt nach dem Abschnitt über elektrische Netzwerke die Beziehung
f (i, j) = (vi − vj )wij . Also gilt f (i, j)/wij = vi − vj und folglich fopt = R−1 Bvopt . Mit dem
Kirchhoffschen Potentialgesetz können wir somit folgern:
Lemma 6.20. Ein Fluss f ist genau dann optimal, wenn f T Rc = 0 für alle Zirkulationen c gilt.
Lemma 6.20 werden wir nachfolgend noch vereinfachen und anhand von bestimmten Zyklen
formulieren. Sei dazu T ein Spannbaum von G. Wir definieren darauf aufbauend Baumpfade und
Baumzyklen:
Definition 6.21. Seien a, b ∈ V . Der Baumpfad P(a,b) ist der eindeutige Pfad von a nach b, der
nur Kanten von T benutzt. Der dazugehörige Fluss p(a,b) ist derjenige Fluss, der eine Flusseinheit
von a nach b sendet und nur auf Kanten aus T von Null verschieden ist (also nur Kanten von T
benutzt).
Definition 6.22. Sei (a, b) eine Kante, die nicht in T vorkommt. Dann ist der Baumzyklus
C(a,b) = (a, b) ∪ P(b,a) der eindeutige Kreis, der aus der Kante (a, b) und dem Baumpfad P(b,a)
besteht. Die dazugehörige Zirkulation c(b,a) ist diejenige Zirkulation, die eine Flusseinheit auf
C(a,b) sendet.
Die Menge aller Zirkulationen c ∈ Rm | B T c = 0 nennen wir Zyklenraum. Eine Basis des Zyklenraums bilden dabei die Zirkulationen {ce | e ∈ E\T }, die durch einen Baumzyklus induziert
werden. Wir erhalten somit folgende Charakterisierung.
88
6. Ausdünnung von Graphen und Laplace-Löser
Abbildung 6.3.1.: Graph aus Beispiel 6.25. Die Kanten des Spannbaums sind rot gefärbt.
Korollar 6.23. Ein Fluss f ist genau dann optimal, wenn f T Rce = 0 für alle von Baumzyklen
induzierten Zirkulationen ce gilt.
Korollar 6.23 ist zentral für den zu entwickelnden Algorithmus. Wie bereits oben skizziert,
werden wir iterativ überprüfen, ob auf gewählten Baumzyklen von G die Summe der Flüsse Null
ergibt. Jeden Baumzyklus Ce können wir ferner als „langen Widerstand” ansehen, der aus in
Serie geschalteten Einzelwiderständen besteht. Für diesen definieren wir:
Definition 6.24. Sei Ce ein Baumzyklus. Der Widerstand Re von Ce ist gegeben durch
X
Re =
re0 = cTe Rce .
e0 ∈Ce
Das durch einen Fluss f auf Ce induzierte Potential ∆ce (f ) ist definiert als
X
f (e0 )re0 = f T Rce .
∆ce (f ) =
e0 ∈Ce
Mit obiger Definition lässt sich die Charaktiersierung eines optimalen Flusses umformulieren
zu: Ein Fluss f ist genau dann optimal, wenn ∆ce (f ) = 0 für alle von Baumzyklen induzierten
Zirkulationen ce gilt.
Beispiel 6.25. Sei G = (V, E) gegeben wie in Abbildung 6.3.1 und die roten Kanten seien die
Kanten eines Spannbaums T . Der Fluss f verschickt eine Einheit vom Knoten 1 an den Knoten
4. Es gilt somit f (1, 2) = 1, f (2, 4) = 1 und f (e) = 0 für alle anderen Kanten. Der Einfachhheit
halber seien alle Kantengewichte 1, es gilt also re = 1 für alle Kanten e ∈ E.
Die Kante (1, 5) ist eine Nichtbaumkanten und es gilt
X
R(1,5) =
re0 = r(1,5) + r(5,4) + r(4,2) + r(2,1) = 4.
e0 ∈C(1,5)
Analog folgt R(1,6) = 4 und R(3,4) = 3. Berechnen wir nun die induzierten Flusspotentiale: Hier
gilt
X
∆c(1,5) (f ) =
f (e0 )re0 = f (1, 2) · r(1,2) + f (2, 4) · r(2,4) = 2
e0 ∈C(1,5)
und durch analoge Rechnung ∆c(1,6) (f ) = 1, sowie ∆c(3,4) (f ) = 1. Der Fluss f ist daher keinesfalls
optimal.
Im weiteren Verlauf möchten wir nur bestimmte Spannbäume von G betrachten, die niedrige
Steckung gemäß der folgenden Definition besitzen.
6.3. Kombinatorische Löser für Laplace-Systeme
89
Definition 6.26. Sei
P T ein Spannbaum vom Graphen G. Die Baum-Konditionszahl t(T ) ist
definiert als t(T ) = e∈E\T (Re /re ).
Die Streckung st(e) einer Kante e ∈ E ist gegeben durch
P
re0
0
st(e) = e ∈Pe
re
P
und die Streckung st(T ) eines Spannbaums T durch st(T ) = e∈E st(e).
Bevor wir nun die algorithmische Idee hinter dem KOSZ-Verfahren weiter untersuchen, benötigen wir eine letzte Definition.
Definition 6.27. Sei T ein Spannbaum von G und f ein Fluss in G. Sei s ∈ V beliebig, aber
fest. Dann ist die bauminduzierte Spannung v ∈ R|V | für a ∈ V definiert als
X
v(a) =
f (e) · re .
e∈P(a,s)
Beispiel 6.28. Sei die Situation wie in Beispiel 6.25. Für die Baumkonditionszahl von T gilt
mit den bereits berechneten Werten aus Beispiel 6.25:
X
X
t(T ) =
(Re /re ) =
Re we = 4 + 4 + 3 = 11.
e∈E\T
e∈E\T
Wir berechnen nun die Streckung st(e) einer Kante e ∈ E. Für e = (1, 5) gilt
st(1, 5) = (1/r(1,5) )
X
re0 = r(1,2) + r(2,4) + r(4,5) = 3.
e0 ∈P(1,5)
Die anderen Werte können ebenso
berechnet werden. Für die Streckung st(T ) des Spannbaums
P
T ergibt sich dann st(T ) = e∈E st(e) = 13.
Sei nun s = 1. Dann gilt für die bauminduzierte Spannung
X
v(5) =
f (e) · re = f(4,2) + f(2,1) = −f(2,4) − f(1,2) = −2.
e∈P(5,1)
Insgesamt ergibt sich der Vektor v = (0, −1, −1, −2, −2, −1)T . Setzen wir hingegen s = 3, dann
gilt v(5) = f(4,2) = −1 und wir erhalten den Vektor v = (1, 0, 0, −1, −1, 0)T .
6.3.3. Der Algorithmus SimpleSolver
Unser Ziel wird es nun sein, einen zu dem Gleichungssystem Lv = d gehörenden, (1 + )approximativen elektrischen Fluss zu berechnen. Wir gehen dazu wie folgt vor:
1. Berechne zunächst einen Spannbaum mit niedriger Streckung.
2. Berechne damit einen initialen zulässigen Fluss.
3. Iterative Zyklenaktualisierung: Berechne einen neuen zulässigen Fluss, der die Energie
senkt.
• Wähle eine Nichtbaumkante e mit Wahrscheinlichkeit Re /re aus.
• Überprüfe, ob für den Baumzyklus Ce die Eigenschaft f T Rce = 0 gilt. Falls nein,
ändere f entsprechend ab.
90
6. Ausdünnung von Graphen und Laplace-Löser
4. Gebe den Fluss f und die Bauminduzierte Spannung v zurück.
Dieser Algorithmus heißt SimpleSolver. Sein Pseudocode ist in Algorithmus 28 dargestellt. Der
Name rührt daher, dass die Autoren in ihrer Arbeit einen weiteren Löser mit noch etwas besseren
Eigenschaften angeben. Auf dessen Präsentation wird hier allerdings verzichtet.
Algorithmus 28 : SimpleSolver
Input : Graph G = (V, E, r), Bedarfsvektor d, Toleranz Output : -approx. elektr. Fluss f , zugeh. Potentialvektor v
1 T ← Spannbaum von G mit niedriger Streckung
2 f0 ← eindeutiger Fluss auf T mit B T f0 = d
R
1
3 pe ← t(T ) · r e für alle Nichtbaumkanten e
e st(T )·t(T )
4 K ← dt(T ) log
e
5
6
for i = 1 to K do
Wähle zufällige Nichtbaumkante ei mit Wahrscheinlichkeit pei
7
8
fi ← fi−1 −
∆cei (fi−1 )
cei
Rei
return fK und zugeh. Potentialvektor vK
Das Haupttheorem dieses Abschnitts besagt, dass SimpleSolver tatsächlich einen (1 + )approximativen elektrischen Fluss berechnet.
Theorem 6.29. Die Ausgabe von SimpleSolver erfüllt
E [Er (f )] ≤ (1 + )Ef (fopt )
und
E[kv − L† dkL ] ≤
√
kL† dkL .
Der Algorithmus kann so implementiert werden, dass seine Laufzeit
O(m log2 (n) log log n log(−1 n))
ist.
Um dieses Theorem zu beweisen, werden wir als ersten Schritt die Kovergenzgeschwindigkeit
analysieren.
6.3.4. Konvergenz des Algorithmus
In diesem Abschnitt werden wir zeigen, dass der Algorithmus SimpleSolver konvergiert und die
Konvergenzgeschwindigkeit 1 − 1/t(T ) beträgt. Wir möchten daher folgendes Theorem beweisen:
Theorem 6.30. Jede Iteration von SimpleSolver berechnet einen zulässigen Fluss fi derart, dass
E [Er (fi )] − Er (fopt ) ≤ (1 −
1 i
) (Er (f0 ) − Er (fopt )).
t(T )
Jede Iteration von SimpleSolver verringert also die Energie des aktuellen Flusses im Erwartungswert um (1 − 1/t) von der Energiedistanz zum optimalen Wert. Für einen zulässigen Fluss
f können wir den durch Er (f ) gemachten Fehler senken, indem wir ein Vielfaches einer Zirkulation c zu f addieren. Das nachfolgende Lemma zeigt, wie wir die Energie bestmöglich erhöhen
können.
6.3. Kombinatorische Löser für Laplace-Systeme
91
Abbildung 6.3.2.: Initialer Fluss f0 (links) und der daraus durch eine Iteration entstehende Fluss
f1 (rechts) in Beispiel 6.33.
T
Rc
Lemma 6.31. Für einen Fluss f , eine Zirkulation c und α∗ = − fcT Rc
∈ R gilt:
argminα∈R Er (f + αc) = α∗
und
Er (f + α∗ c) − Er (f ) = −
(f T Rc)2
cT Rc
Beweis. Nach Definition der Energie gilt Er (f ) = f T Rf . Für α ∈ R folgt somit
Er (f + αc) = (f + αc)T R(f + αc)
= f T Rf + 2αf T Rc + α2 cT Rc
Wir bilden nun die partiellen Ableitungen bezüglich α und setzen diesen Ausdruck gleich 0. So
erhalten wir
2f T Rc + 2α∗ cT Rc = 0.
Dann erfüllt α = α∗ diese Gleichheit und minimiert folglich den Ausdruck Er (f + αc).
Im Spezialfall eines Baumzyklus als Zirkulation, also c = ce für ein e ∈ E\T, entspricht
obiges α∗ gerade der Zyklusaktualisierung unseres Algorithmus, da in diesem Fall cTe Rce = Re
und f T Rce = ∆ce (f ) gilt. Wir können somit direkt folgendes Lemma zur Zyklusaktualisierung
folgern:
Lemma 6.32. Für einen zulässigen Fluss f und e ∈ E\T gilt:
Er (f −
∆ce (f )
∆c (f )2
ce ) − Er (f ) = − e
Re
Re
Beispiel 6.33. Wir führen Beispiel 6.25 weiter: Sei f0 der initiale Fluss mit f0 (1, 2) = 1,
f0 (2, 4) = 1 und f0 (e) = 0 für die anderen Kanten. Für alle Kanten e ∈ E gelte erneut re = 1.
Nach einer Iteration im SimpleSolver-Algorithmus entstehe der Fluss f1 wie in Abbildung 6.3.2
dargestellt. Für die Energie der beiden Flüsse gilt dann:
X
Er (f0 ) =
re · f0 (e)2 = f0 (1, 2)2 + f0 (2, 4)2
e∈E
= 1+1=2
X
Er (f1 ) =
re · f1 (e)2 = f1 (1, 2)2 + f1 (2, 4)2 + f1 (1, 5)2 + f1 (5, 4)2
e∈E
=
1 1 1 1
+ + + =1
4 4 4 4
Die Energiedifferenz der beiden Flüssen beträgt daher Er (f0 ) − Er (f1 ) = 2 − 1 = 1.
92
6. Ausdünnung von Graphen und Laplace-Löser
Definition 6.34. Die Lagrange-duale Lösung des optimalen Flusses fopt ist gegeben durch:
max(2v T d − v T Lv).
v∈Rn
Für ein v ∈ Rn setzen wir ζr (v) = 2v T d − v T Lv und definieren die Dualitätslücke gap(f, v)
durch gap(f, v) = Er (f ) − ζr (v).
Lemma 6.35. Für einen zulässigen Fluss f und bauminduzierte Spannungen v gilt:
gap(f, v) =
X ∆c (f )2
e
re
e∈E\T
Diesen Ausdruck der Zykluspotentiale werden wir benutzen, um den Abstand der Lösung des
Algorithmus zur optimalen Lösung nach oben zu beschränken.
Lemma 6.36. Für Iteration i des Algorithmus SimpleSolver gilt:
E [Er (fi ) − Er (fi−1 ) | gap(fi−1 , vi−1 )] = −
gap(fi−1 , vi−1 )
t(T )
Beweis. In jeder Iteration wählt der Algorithmus eine zufällige Kante ei ∈ E\T mit Wahrscheinlichkeit pei und addiert ein Vielfaches von cei auf fi−1 . Nach Lemma 6.32 verringert sich die
Energie um ∆ce (fi−1 )2 /Re . Somit gilt:


2
X
−∆
(f
)
ce i−1
E [Er (fi ) − Er (fi−1 ) | gap(fi−1 , vi−1 )] = E 
pe ·
| gap(fi−1 , vi−1 )
Re
e∈E\T


2
X
∆c (fi−1 )
Re
· − e
| gap(fi−1 , vi−1 )
= E
t(T ) · re
Re
e∈E\T
1
= E
· (−gap(fi−1 , vi−1 )) | gap(fi−1 , vi−1 )
t(T )
gap(fi−1 , vi−1 )
= −
,
t(T )
wobei der erste Schritt nach Lemma 6.32, der zweite Schritt durch die Beziehung pe = (1/t(T )) ·
(Re /re ) und der dritte Schritt schließlich mit Lemma 6.35 folgt.
Mit Lemma 6.36 können wir nun das folgende Lemma beweisen, das den letzten Schritt zum
Beweis von Theorem 6.30 darstellt.
Lemma 6.37. Für alle i ≥ 0 sei die Zufallsvariable Di definiert durch Di = Er (fi ) − Er (fopt ).
Dann gilt für alle Iterationen i ≥ 1:
1
E [Di ] ≤ (1 − )E [Di−1 ]
t
Beweis. Da Di eine diskrete Zufallsvariable ist, können wir das Gestz der totalen Wahrscheinlichkeit ausnutzen:
X
E [Di ] =
E [Di | Di−1 = c] · P r (Di−1 = c) .
c
6.3. Kombinatorische Löser für Laplace-Systeme
93
Wegen der Dualität wissen wir, dass Di ≤ gap(fi−1 , vi−1 ) gilt. Somit folgt nach Lemma 6.36:
E [Di | Di−1 = c] ≤ c − t(Tc ) . Insgesamt gilt also nach der Definition des Erwartungswerts
E[Di ] ≤
X
c
= (1 −
1
(1 −
)c · P r(Di−1 = c)
t(T )
1
)E[Di−1 ]
t(T )
Wenden wir nun das vorherige Lemma induktiv an, so erhalten wir nach Definition der Di
schließlich die Aussage von Theorem 6.30.
6.3.5. Beweis des Haupttheorems
Bevor wir den Beweis des Haupttheorems angehen werden, benötigen wir noch zwei Hilfslemmas.
Lemma 6.38. Es gilt: Er (f0 ) ≤ st(T ) · Er (fopt ).
Lemma 6.39. Sei f ein (primal) zulässiger Fluss mit Er (f ) ≤ (1 + )Er (fopt ) für ein > 0 und
sei v der Vektor der bauminduzierten Spannungen. Dann gilt:
p
||v − L+ d||L ≤ · t(T )||L+ d||L
Beweis. Nach Lemma 6.36 und der Optimalität von fopt gilt
Er (f ) −
gap(f, v)
≥ Er (fopt ).
t(T )
Nach Voraussetzung gilt dann gap(fopt , v) ≤ · t(T ) · Er (fopt ), denn:
gap(fopt , v) = Er (fopt ) − ζr (v)
≤ gap(f, v)
(wegen Optimalität)
≤ t(T ) · (Er (f ) − Er (fopt ))
(nach oben)
≤ t(T ) · ((1 + )Er (fopt ) − Er (fopt ))
(nach Voraussetzung)
= · t(T ) · Er (fopt )
Mit den Beziehungen
gap(fopt , v) = ||v − L+ d||2L = (v − L+ d)T L(v − L+ d)
und
Er (fopt ) = ||L+ d||2L = (L+ d)T L(L+ d)
94
6. Ausdünnung von Graphen und Laplace-Löser
folgt schließlich
||v − L+ d||L =
≤
q
q
gap(fopt )
· t(T ) · Er (fopt )
(nach oben)
p
=
· t(T ) · ||L+ d||L
Nun haben wir alle Vorarbeiten geleistet, um unser Haupttheorem beweisen zu können.
Beweis. Wir zeigen zuerst, dass der Algorithmus die gewünschte Güte besitzt.
Wir müssen nun noch die Laufzeit des Algorithmus beweisen. Dazu analysieren wir die Laufzeit
der einzelnen Berechnungsschritte:
• Verwende einen Spannbaum T mit st(T ) = O(m log n log log n), der in Zeit O(m log n log log n)
berechnet werden kann. Dann gilt ebenfalls t(T ) = O(m log n log log n).
• Der initiale Fluss f0 wird in Zeit O(n) berechnet.
• Re kann für alle Kanten mit Tarjans LCA-Algorithmus in O(m) oder durch eine eigene
Datenstruktur in O(m log n) berechnet werden.
• Die Initialisierung der Datenstruktur benötigt O(n log n).
• Pro Iteration ist die Laufzeit einer Zyklusaktualisierung O(log n) und die Anzahl der Iterationen ist O(m log n log(n−1 ) log log n).
Insgesamt ergibt sich daher die Laufzeit als O(m log2 (n) log log n log(n−1 )).
6.4. Weiterführende Literatur
Folgt.
95
Literaturverzeichnis
[BM72]
Bayer, Rudolf ; Mccreight, EM: Organization and Maintenance of Large Ordered
Indexes. In: Acta Informatica 1 (1972), S. 173–189
[Bos09]
Bosch, Siegfried: Algebra. Springer, 2009 (Springer-Lehrbuch)
[GMS92]
Gilbert, John R. ; Moler, Cleve ; Schreiber, Robert: Sparse matrices in MATLAB: design and implementation. In: SIAM Journal on Matrix Analysis and Applications 13 (1992), Nr. 1, S. 333–356
[Gra09]
Gramlich, G.: Lineare Algebra: Eine Einführung. Fachbuchverl. Leipzig im Carl
Hanser Verlag, 2009 (Mathematik-Studienhilfen)
[Gus72]
Gustavson, Fred G.: Some basic techniques for solving sparse systems of linear
equations. In: Sparse matrices and their applications. Springer, 1972, S. 41–52
[KG11]
Kepner, Jeremy (Hrsg.) ; Gilbert, John (Hrsg.): Graph Algorithms in the Language
of Linear Algebra. Society for Industrial and Applied Mathematics, 2011
[Koz91]
Kozen, Dexter C.: The Design and Analysis of Algorithms. Springer New York, 1991
(Texts and Monographs in Computer Science)
[LG14]
Le Gall, François: Powers of Tensors and Fast Matrix Multiplication. In: CoRR
abs/1401.7714 (2014)
[MMS09a] Meyerhenke, Henning ; Monien, Burkhard ; Sauerwald, Thomas: A New
Diffusion-based Multilevel Algorithm for Computing Graph Partitions. In: Journal
of Parallel and Distributed Computing 69 (2009), Nr. 9, S. 750–761
[MMS09b] Meyerhenke, Henning ; Monien, Burkhard ; Schamberger, Stefan: Graph Partitioning and Disturbed Diffusion. In: Parallel Computing 35 (2009), Nr. 10–11, S.
544–569
[MS12]
Meyerhenke, Henning ; Sauerwald, Thomas: Beyond Good Partition Shapes:
An Analysis of Diffusive Graph Partitioning. In: Algorithmica 64 (2012), Nr. 3, S.
329–361
[NS12]
Naumann, Uwe (Hrsg.) ; Schenk, Olaf (Hrsg.): Combinatorial Scientific Computing.
Chapman & Hall/CRC, 2012 (Computational Science Series)
[SM00]
Shi, Jianbo ; Malik, Jitendra: Normalized cuts and image segmentation. In: Pattern
Analysis and Machine Intelligence, IEEE Transactions on 22 (2000), Nr. 8, S. 888–
905
97
A. Anhang
A.1. Grundlagen der linearen Algebra
Dieser Abschnitt wiederholt einige Grundlagen aus der linearen Algebra, die typischerweise in
Anfängervorlesungen wie Mathematik für Informatiker eingeführt werden. Eine vollständige Einführung von Notation und Grundlagen ist hier nicht vorgesehen. Für eine grundlegende und
tiefergehende Wiederholung wird dem Leser die Lektüre gängiger Einstiegslehrbücher empfohlen. Das Buch von Bosch [Bos09] beispielsweise ist als Begleitung von universitären Vorlesungen
gedacht. Sehr praktisch angelegt ist dagegen das Buch von Gramlich [Gra09].
Definition A.1. Seien im folgenden n ∈ N, x, y ∈ Rn und A = (aij ) ∈ Rn×n .
1. Das Skalarprodukt zweier Vektoren x und y ist definiert durch hx, yi =
2. Zwei Vektoren x und y heißen orthogonal, wenn gilt: hx, yi = 0.
3. Als Norm eines Vektors x verwenden
wir die Summennorm ||x||1 =
p
die euklidische Norm ||x||2 = hx, xi.
P
Pn
i=1 xi
i |xi |
· yi .
bzw. meistens
4. Die Matrix AT = (aji ) ∈ Rn×n heißt transponierte Matrix von A.
5. Eine Matrix A heißt symmetrisch, wenn A = AT gilt.
6. Seien k1 , k2 ≥ 0, dann besitzt A eine Bandbreite von k1 + k2 + 1, wenn aij = 0 für j < i − k1
und j > i + k2 .
P
7. Das Matrix-Vektorprodukt y = Ax ist definiert durch yi = nj=1 aij · xj = hAi• , xi.
8. Die Norm einer Matrix A ist durch ||A|| = supx6=0
||Ax||
||x||
definiert.
9. λ heißt Eigenwert der Matrix A, wenn Au = λ · u für ein u ∈ Rn , u 6= 0, gilt. Alle Vektoren
u mit Au = λ · u heißen dann Eigenvektoren zum Eigenwert λ von A.
10. Die Eigenvektoren einer symmetrischen Matrix A bilden eine orthonormale Basis. A besitzt
n Eigenwerte {λ1 , . . . , λn }, wobei diese mehrfach vorkommen dürfen, d.h. λ1 ≤ λ2 ≤ · · · ≤
λn .
11. Das charakteristische Polynom der Matrix A ist definiert durch fA (λ) = det(A − λEn ).
Ohne Beweis geben wir die folgenden drei Theoreme an:
Theorem A.2. Seien A, B ∈ Rn×n und x ∈ Rn . Dann gilt:
1. ||A · B|| ≤ ||A|| · ||B||
2. ||Ax|| ≤ ||A|| · ||x||
Theorem A.3. Sei A ∈ Rn×n . λ ist genau dann ein Eigenwert von A, wenn λ eine Nullstelle
des charakteristischen Polynoms fA ist.
98
A. Anhang
Theorem A.4. Sei A ∈ Rn×n symmetrisch. Dann besitzt A nur reelle Eigenwerte und die
Eigenvektoren zu verschiedenen Eigenwerten bilden eine Orthogonal-Basis des Rn .
Theorem A.5. Sei A ∈ Rn×n symmetrisch und λ1 ≤ λ2 ≤ . . . ≤ λn die Eigenwerte von A.
Dann gilt:
hAx, xi
hAx, xi
λ1 = min
und λn = max
x6=0 hx, xi
x6=0 hx, xi
Beweis. Sei u1 , . . . , un eine Orthogonal-Basis aus Eigenvektoren von A zu den Eigenwerten
λ1 , . . . , λn . Jedes x ∈ Rn lässt sich als Linearkombination der ui schreiben:
x=
n
X
αi ∈ R
αi ui ,
i=1
n
X
=⇒ Ax =
αi Aui =
i=1
n
X
αi λi ui
i=1
=⇒ hAx, xi = h
n
X
i=1
αi λi ui ,
n
X
j=1
αj uj i =
n X
n
X
i=1 j=1
αi λi αj hui , uj i
Da die Eigenvektoren paarweise senkrecht aufeinander stehen, gilt hui , uj i = 0 für i 6= j:
hAx, xi =
=⇒
n
X
i=1
hAx, xi
≤ λn
hx, xi
λi αi2 hui , ui i ≤ λn
n
X
i=1
hαi ui , αi ui i = λn hx, xi
∀x 6= 0
Für x = un gilt ferner hAx,xi
hx,xi = λn . Die Aussage für λ1 zeigt man entsprechend, indem man
hAx, xi mit λ1 nach unten abschätzt.
Korollar A.6. Sei A ∈ Rn×n und λn der größte Eigenwert der Matrix AT A. Dann gilt:
p
||A|| = λn
Beweis. AT A ist symmetrisch und aus dem Beweis zu Satz A.5 folgt für beliebige x ∈ Rn :
||Ax||2 = hAx, Axi = hAT Ax, xi ≤ λn hx, xi = λn ||x||2
p
=⇒ ||A|| = λn ,
da für x = un die Gleichung ||Ax||2 = λn ||x||2 erfüllt ist.
Definition A.7. Sei G = (V, E) ein beliebiger Graph mit n = |V | Knoten, V = {v1 , . . . , vn }.
Die Laplace-Matrix LG = (lij ) ∈ Zn×n ist definiert durch:

 grad(vi ) , falls i = j
−1 , falls (vi , vj ) ∈ E
lij =

0 , sonst
A.1. Grundlagen der linearen Algebra
99
Die Zeilensumme einer Laplace-Matrix LG ist nach Konstruktion immer 0. Es gilt also:
   
 
1
1
0
 ..   .. 
 .. 
LG  .  =  .  = 0 ·  . 
1
0
1
Somit ist 0 ein Eigenwert jeder Laplace-Matrix und (1 . . . 1) ein zugehöriger Eigenvektor. Offensichtlich ist die Laplace-Matrix von ungerichteten Graphen symmetrisch. Nach Satz A.4 sind
daher alle Eigenwerte der Matrix reell und die zugehörigen Eigenvektoren bilden eine OrthogonalBasis. Man kann ferner zeigen, dass alle Eigenwerte größer gleich Null sind, 0 ist also der kleinste
Eigenwert einer Laplace-Matrix. Ferner gilt, dass ein ungerichteter Graph genau dann zusammenhängend ist, wenn alle anderen Eigenwerte echt größer als Null sind.
A.1.1. Spektrale Zerlegung einer symmetrischen Matrix
Sei A eine symmetrische Matrix mit den Eigenwerten λ1 , . . . , λn und den zugehörigen Eigenvektoren v1 , . . . , vn . Dann gilt also Avi = λi vi ∀i.
Sei weiterhin V die Matrix, die als i-te Spalte den i-ten Eigenvektor vi besitzt und Λ sei die
Diagonalmatrix mit Λii = λi .
Dann gilt:
AV = V Λ.
Durch die Multiplikation von V T von rechts ergibt sich aufgrund der Orthonormalität die
spektrale Eigenzerlegung von A:
X
A = AV V T = V ΛV T =
λi vi viT .
i
Herunterladen