- Fachgebiet Datenbanken und Informationssysteme

Werbung
Leibniz Universität Hannover
Fakultät für Elektrotechnik und Informatik
Fachgebiet Datenbanken und Informationssysteme
Studienarbeit
im Studiengang Mathematik mit Studienrichtung Informatik
Entwicklung und Optimierung eines Datenbankmoduls
für Graphenalgorithmen
28. August 2006
Yvon Regis Tounkap Nkwate
Matr.-Nr. 2143512
Prüfer: Prof. Dr. Udo Lipeck
Betreuer: Prof. Dr. Udo Lipeck
Inhaltsverzeichnis
1 Einleitung
1.1 Aufgabenstellung . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
1.2 Gliederung dieser Arbeit . . . . . . . . . . . . . . . . . . . . . . . . .
4
4
4
2 Graphentheorie
2.1 Begriffe der Graphentheorie . . . . . . . . . . . . . . . . . . . . .
2.1.1 Definitionen und Beispiele . . . . . . . . . . . . . . . . . .
2.2 Transitive Hülle . . . . . . . . . . . . . . . . . . . . . . . . . . . .
2.2.1 Definition und Beispiel . . . . . . . . . . . . . . . . . . . .
2.2.2 Effiziente Berechnung der transitiven Hülle eines Graphen
2.3 Alle kürzesten Wege (“all sources shortest paths problem”) . . . .
5
5
5
7
7
7
8
.
.
.
.
.
.
.
.
.
.
.
.
3 Darstellung der Graphen als Relationen und Implementierung der
Algorithmen
10
3.1 Darstellung der Graphen als Relationen . . . . . . . . . . . . . . . . . 10
3.1.1 Darstellung eines Graphen als Relation für die Berechnung der
transitiven Hülle . . . . . . . . . . . . . . . . . . . . . . . . . 11
3.1.2 Graphendarstellung zur Berechnung der kürzesten Wege . . . 12
3.2 Algorithmus zur Berechnung der transitiven Hülle bei einer vollständigen
Speicherung eines Graphen als Relation . . . . . . . . . . . . . . . . . 13
3.3 Algorithmen zur Berechnung der transitiven Hülle bei einer unvollständigen Speicherung eines Graphen als Relation . . . . . . . . . . . 14
3.4 Algorithmen zur Berechnung aller kürzesten Wege von vollständig
gespeicherten Graphen . . . . . . . . . . . . . . . . . . . . . . . . . . 17
3.4.1 Erster Algorithmus . . . . . . . . . . . . . . . . . . . . . . . . 17
3.4.2 Zweiter Algorithmus . . . . . . . . . . . . . . . . . . . . . . . 19
3.5 Algorithmen zur Berechnung aller kürzesten Wege von unvollständig
gespeicherten Graphen . . . . . . . . . . . . . . . . . . . . . . . . . . 20
3.5.1 Erster Algorithmus . . . . . . . . . . . . . . . . . . . . . . . . 21
3.5.2 Zweiter Algorithmus . . . . . . . . . . . . . . . . . . . . . . . 22
3.5.3 Beispiel . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 24
3.5.4 Methoden für die Rekonstruktion der Wege . . . . . . . . . . 25
4 Tests der Algorithmen
26
4.1 Test der Algorithmen allshortestspathsA und AllshortestpathsB . . . 26
4.1.1 Bereitstellung der Testdaten . . . . . . . . . . . . . . . . . . . 26
2
Yvon Regis Tounkap Nkwate
4.2
4.1.2
Tests
phen
4.2.1
4.2.2
4.2.3
4.2.4
4.2.5
4.2.6
5 Ausblick
Kapitel 0
Studienarbeit
Vergleich der Laufzeiten beider Algorithmen . . . . . . . . .
der Algorithmen basierend auf unvollständig gespeicherte Gra. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Bereitstellung der Testdaten für die Berechnung der transitiven Hülle . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Vergleich der Laufzeiten der Algorithmen
Floyd Warschall1/2/3 . . . . . . . . . . . . . . . . . . . . .
Ausführungspläne der Hauptanfragen der Algorithmen . . .
Bereitstellung der Testdaten für die Berechnung
aller kürzesten Wege . . . . . . . . . . . . . . . . . . . . . .
Vergleich der Laufzeit der Algorithmen
Allshortestpaths1A/1B/2 . . . . . . . . . . . . . . . . . . . .
Programmierung . . . . . . . . . . . . . . . . . . . . . . . .
. 28
. 28
. 29
. 29
. 30
. 34
. 34
. 35
36
3
Kapitel 1
Einleitung
1.1
Aufgabenstellung
Matrizen und Graphen sind als klassische Datenstrukturen mit dazu gehörenden Rechenoperationen und Algorithmen nicht mehr wegzudenken. Für bestimmte Anwendungsbereiche sind auch schon Matrixkonzepte in relationalen Datenbanksystemen
umgesetzt worden.
Ziel dieser Arbeit ist es für große Graphen, die in Datenbanken abgelegt sind, zu
untersuchen, ob sich Algorithmen zur Berechnung der transitiven Hülle und zur
Berechnung aller kürzester Wege (all sources shortest paths problem), die auf
Adjazenzmatrizen basieren, effizient implementieren lassen.
1.2
Gliederung dieser Arbeit
Die nachfolgenden Kapitel sind folgendermaßen gegliedert.
Kapitel 2 erläutert grundlegende Begriffe der Graphentheorie. In diesem Kapitel wird die transitive Hülle eines gerichteten Graphen definiert und der Algorithmus
von Floyd Warshall beschrieben. Dieser Algorithmus liefert eine effiziente Berechnung der transitiven Hülle eines gerichteten Graphen. Dann wird der Algorithmus
zur Berechnung aller kürzester Wege und die Methoden zur Rekonstruktion dieser
Wege vorgestellt.
Kapitel 3 beschreibt zunächst die Darstellung der Graphen als Relationen. Dabei kann ein Graph vollständig oder unvollständig in einer Relation gespeichert werden. Für jede Speicherungsart werden verschiedene Algorithmen vorgestellt, die in
PL/SQL die transitve Hülle und alle kürzeste Wege berechnen.
In Kapitel 4 werden die aus dem vorherigen Kapitel vorgestellten Algorithmen
getestet. Ihre Laufzeit werden verglichen um den besten Algorithmus zu bestimmen.
Bei der Berechnung der transitiven Hülle von unvollständig gespeicherten Graphen
werden Ausführungspläne der Hauptanfragen der Algorithmen kommentiert.
Kapitel 5 gibt einen Ausblick über eine kritische Situation, die sich ergeben
kann, und beschreibt eine mögliche Lösung, die noch untersucht werden soll.
Kapitel 2
Graphentheorie
In diesem Kapitel werden grundlegende Begriffe der Graphentheorie erläutert. Dann
wird die transitive Hülle eines gerichteten Graphen definiert. Ihre effiziente Berechnung wird mit dem Algorithmus von Floyd-Warshall, basierend auf Adjazenzmatrizen, beschrieben. Zum Schluss wird der Algorithmus zur Berechnung aller kürzester
Wege zusammen mit zwei Methoden zur Rekonstruktion dieser Wege vorgestellt.
Für dieses Kapitel wurden Materialien aus [Li05-06] und [CT] entnommen.
2.1
2.1.1
Begriffe der Graphentheorie
Definitionen und Beispiele
Definition:
Ein Graph ist in der Graphentheorie ein Gebilde aus Knoten (auch Ecken oder
Punkte) genannt, die durch Kanten verbunden sein können. Somit ist ein Graph ein
geordnetes Paar G = (V,E ) zweier Mengen V und E. Dabei bezeichnet V die Menge
der im Graph enthaltenen Knoten. Knoten werden üblicherweise durch Zahlen oder
Buchstaben bezeichnet. E bezeichnet die Menge der Kanten des Graphen. Eine
Kante wird durch ein Paar, bestehend aus zwei verschiedenen Knoten, identifiziert.
Die Bezeichnungen der Knotenmenge V und der Kantenmenge E stammen aus dem
Englischen: V für vertices (engl. für Knoten) und E für edges (engl. für Kanten).
Man unterscheidet in der Graphentheorie vor allem zwischen ungerichteten
und gerichteten Graphen.
Beispiel 1
a
e
b
c
d
f
Abbildung 2.1: ungerichteter Graph
V = {a,b,c,d,e,f} ; E = {(a,b),(a,f),(b,c),(b,d),(e,d),(b,f)}.
Yvon Regis Tounkap Nkwate
Studienarbeit
Beispiel 2
b
a
d
c
Abbildung 2.2: gerichteter Graph
V = {a,b,c,d} ; E = {(a,b),(b,a),(b,c),(a,d)}.
In einem gerichteten Graphen haben wir geordnete Paare, d.h. wir unterscheiden
(a,b) und (b,a). Die Kanten eines Graphen können mit einer Marke (Gewicht, engl.
weight) versehen werden, und man spricht dann von einem gewichteten Graph.
Gewichte können zum Beispiel Abstände, Zeiten oder Kosten darstellen.
Beispiel 3
4
1
6
2
3
Abbildung 2.3: gewichteter und gerichteter Graph
Ein gerichteter Graph g (er kann auch gewichtet sein) kann als Adjazenzmatrix
dargestellt werden. Eine Adjazenzmatrix von g ist eine Matrix M (mit n Zeilen und
n Spalten falls |V | = n) , die zu jedem Paar von Knoten (i,j ) genau einen booleanEintrag hat:
• M [i,j ]= T (oder 1) bedeutet, dass der Graph eine Kante (i,j ) hat.
• M [i,j ]= F (oder 0) bedeutet, dass der Graph keine Kante (i,j ) hat.
Falls der Graph gerichtet ist gilt:
• M [i,j ]= Gewicht von (i,j ), falls (i,j ) ∈ E
• M [i,j ]= +∞ falls es keine Kante (i,j ) ∈ E gibt.
Beispiel:
Der Graph in Abbildung 2.3 entspricht folgender Adjazenzmatrix:
Kapitel 2
6
Yvon Regis Tounkap Nkwate
Studienarbeit
1
2
1 +∞ +∞
2
4
+∞
3 +∞ +∞
3
6
+∞
+∞
Tabelle 2.1: Darstellung des Graphen als Adjazenzmatrix
Die folgenden Algorithmen setzen voraus, dass der Graph gerichtet (Berechnung
der transitiven Hülle) und gewichtet ist (all sources shortest paths problem).
2.2
Transitive Hülle
2.2.1
Definition und Beispiel
Definition
Die transitive Hülle eines gerichteten Graphen G =(V,E ) ist der gerichtete Graph
G + = (V,E + ) mit E + = {(u,v ) mit u,v ∈ V, u 6= v und es gibt einen gerichteten
Pfad von u nach v }.
Beispiel
A
B
A
C
E
D
B
C
D
E
Abbildung 2.4: Die transitive Hülle G + (rechts) von G(links)
2.2.2
Effiziente Berechnung der transitiven Hülle eines Graphen
Sei G ein Graph mit der Knotenmenge {1,...,n} als Adjazenzmatrix dargestellt.
Falls also eine Kante (i, j ) in G existiert gilt G[i,j ] = 1, ansonsten G[i,j ] = 0. Die
transitive Hülle von G, wird im Graph H, als Adjazenzmatrix dargestellt gespeichert.
Ansatz: Die Kanten im schrittweise enstehenden Ergebnisgraphen (H ) sollen
nach dem k -ten Durchlauf genau denjenigen Pfaden in G entsprechen, die nur Zwischenknoten aus der Menge {1,...,k } enthalten! Zum Schluss (k = n) sind alle Pfade
erfasst.
Kapitel 2
7
Yvon Regis Tounkap Nkwate
1
2
3
4
5
6
7
8
9
10
11
Studienarbeit
algorithm Floyd-Warshall(G):Graph:
Eingabe: gerichter Graph G mit Knoten 1,...,n als Adjazenzmatrix
Ausgabe: transitive Hülle H = G + von G als Adjazenzmatrix
H ← G; //kopiere G, so dass der Graph nicht verändert wird
for k ← 1,2,...,n do
for i, j ← 1,2,...,n do
if (i 6= j and i 6= k and j 6= k then)
if (H [i,j ] 6= 1 and H [i,k ] = 1 and H [k,j ] = 1)
then H [i,j ] ← 1;
return H ;
Zum Kernschritt des Algorithmus: Ein Pfad vom Knoten i nach j nur über
Zwischenknoten aus {1,...,k } kann sein:
• entweder ein Pfad von i nach j nur über Zwischenknoten aus {1,...,k -1}
• oder ein Pfad von i nach k nur über Zwischenknoten aus {1,...,k -1} gefolgt
von einem Pfad von k nach j nur über Zwischenknoten aus {1,...,k -1}.
j
i
k
Abbildung 2.5: Zwischenknoten k
In Abbildung 2.5 stellen die gestrichelten Linien die Pfade nur über Zwischenknoten
aus {1,...,k -1} dar.
Sofern es also in H für (i,j ) nicht schon eine Kante aus dem (k -1)-ten Durchlauf
gibt (H [i,j ] 6= 1) , wird in H eine Kante im k -ten Durchlauf neu eingetragen
(H [i,j ] ← 1), wenn es in H Kanten (i,k ) (and H [i,k ] = 1) und (k,j ) (and H [k,j ] = 1)
aus früheren Schleifendurchläufen gibt. Beachte: der Algorithmus arbeitet in-place
bzgl. H.
Laufzeit: das Einfügen und das Feststellen der Existenz einer Kante benötigen
bei einer Adjazenzmatrix O(1). Also hat Floyd-Warshall offensichtlich eine Laufzeit
von O(n 3 ).
2.3
Alle kürzesten Wege (“all sources shortest paths
problem”)
Die Gewichte der kürzesten Wege (die Entfernungen) zwischen allen Knoten
eines gerichteten gewichteten Graphen G kann man mit einer geschickten Variante
des Floyd-Warshall-Algorithmus auf die Adjazenzmatrix von G berechnen, wiederum in O(n 3 ). Zudem sollen während des Algorithmus Informationen festgehalten
werden, um die Wege rekonstruieren zu können.
Kapitel 2
8
Yvon Regis Tounkap Nkwate
Studienarbeit
Sei G der Originalgraph mit n Knoten (Nummern) 1,...,n. H sei eine n×nAdjazenzmatrix zur Berechnung der Entfernungen zwischen allen Knoten; P sei eine
n×n-Matrix, welche die maximalen Nummern von Zwischenknoten abspeichern soll.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
algorithm AllshortestPaths(G):
Eingabe: gerichter gewichteter Graph G mit Knoten 1,...,n als
Adjazenzmatrix
Ausgabe: Graph H als Adjacentmatrix, in der die Länge der kürzesten
Wege zwischen den Knoten von G gespeichert sind. Zusätzlich wird
die Matrix P zur Rekonstruktion der kürzesten Wege ausgegeben.
H ← G; //kopiere G, so dass der Graph nicht verändert wird
for k ← 1,...,n do //analog Floyd-Warshall
for i ← 1,...,n do
for j ← 1,...,n do
if (i 6= j and i 6= k and j 6= k ) then
if (H [i,j ] + H [k,j ]) ≤ H [i,j ] then
H [i,j ] ← H [i,k ] + H [k,j ]; // Erklärung (*) s.u.
P [i,j ] ← k ;
return H ;
return P ;
(*) Anstatt also eine neue Kante hinzuzufügen, wird geprüft, ob der Weg über
einen Zwischenknoten k kürzer ist als der direkte Weg, und es wird der jeweils
kürzere Weg eingetragen. Dabei können i und j auch adjazent sein.
Die Matrix P enthält im Eintrag P [i,j ] den Knoten mit der maximalen Nummer
auf dem kürzesten Weg von i nach j. Die Rekonstruktion dieses Weges funktioniert
mit den rekursiven Methoden path und between:
method path(i,j )
if H [i,j ] 6= ∞ then
write(“von Knoten ”i );
between(i,j );
write( “nach Knoten ”j );
else write( “kein Weg ”)
Hilfsmethode between:
method between(i,j ):
Knoten k ← P [i,j ];
if k 6= 0 then
between(i,k );
write(“über Knoten ”k );
between(k,j ).
.
Kapitel 2
9
Kapitel 3
Darstellung der Graphen als
Relationen und Implementierung
der Algorithmen
In diesem Kapitel wird zunächst beschrieben, wie gerichtete Graphen, deren transitive Hülle berechnet werden soll, in einer relationalen Datenbank gespeichert werden
können. Ebenso wird für gerichtete gewichtete Graphen für die alle kürzesten Wege
zwischen den Knoten ermittelt und rekonstruiert werden sollen, eine mögliche Darstellung als Relation vorgestellt. Dabei kann der Graph sowohl bei der Berechnung
der transitiven Hülle als auch bei der Berechnung aller kürzesten Wege vollständig
oder unvollständig (wie bei dünnbesetzten Matrizen) gespeichert werden.
Im Falle einer vollständigen Speicherung wird für alle Knoten i, j aus der Knotenmenge eine Kante (i,j ) und die Information, ob sie existiert oder nicht, in der
Relation eingetragen. Im Falle einer unvollständigen Speicherung, werden nur existierende Kanten eines Graphen gespeichert.
Dann wird im Falle einer vollständigen Speicherung eines Graphen als Relation
für die Berechnung der transitiven Hülle ein PL/SQL-Algorithmus vorgestellt. Für
die Berechnung aller kürzesten Wege werden zwei Algorithmen vorgestellt.
Im Falle einer unvollständigen Speicherung werden für die Berechnung der transitiven Hülle drei PL/SQL-Algorithmen vorgestellt . Für die Berechnung aller kürzesten
Wege werden zwei Algorithmen vorgestellt, wobei einer davon in zwei Varianten geschrieben werden kann.
Alle diese Algorithmen basieren auf dem Floyd Warschall-Algorithmus. Anschließend werden für die Rekonstruktion der berechneten kürzesten Wege zwei PL/SQLMethoden vorgestellt.
3.1
Darstellung der Graphen als Relationen
In diesem Abschnitt soll festgelegt werden, wie gerichtete (und gewichtete) Graphen in Relationen gespeichert werden können. Möchte man nach der Berechnung
aller kürzesten Wege auch diese Wege rekonstruieren, so soll vorher dafür gesorgt
werden, daß Zwischenknoten auf einem kürzesten Pfad gespeichert werden. Diese
Zwischenknoten sind bei der Berechnung der transitiven Hülle irrelevant. Dies führt
Yvon Regis Tounkap Nkwate
Studienarbeit
uns zu einer unterschiedlichen Darstellung eines Graphen als Relation für die Berechnung der transitiven Hülle und die Berechnung aller kürzesten Wege.
3.1.1
Darstellung eines Graphen als Relation für die Berechnung der transitiven Hülle
Ein Graph, dessen transitive Hülle berechnet werden soll, wird in einer Relation als
Adjazenzmatrix gespeichert mit folgenden Spaltennamen und zugehörigen Datentypen.
Spaltenname
knoteni
knotenj
kanteij
Datentyp
number (eine natürliche Zahl größer als 0)
number (eine natürliche Zahl größer als 0)
number (Werte: 0 oder 1)
Tabelle 3.1: Darstellung eines Graphen als Relation 1
Beschreibung der Spalten:
• Die Spalte knoteni speichert die Nummer eines Knotens.
• Die Spalte knotenj speichert die Nummer eines Knotens.
• Die Spalte kanteij hat den Wert 1, falls es einen Weg von Knoten i nach
Knoten j gibt und den Wert 0 sonst.
Bemerkung:
1. Im Falle einer unvöllständigen Speicherung kann die Spalte kanteij nie den
Wert 0 annehmen, da nur existierende Kante gespeichert werden.
2. Nach der Berechnung der transitiven Hülle wird für alle Knoten i, j mit j
6= i in der Relation eingetragen, ob es einen Weg von i nach j gibt. Da die
transitive Hülle keine Information über mögliche Schleifen enthält muss gelten
j 6= i !
Beispiel 1:
Der Graph G = (V,E ) mit der Knotenmenge V={(1,2,3)} und Kantenmenge
E ={(1,2),(1,3),(2,1)}
1
2
3
Abbildung 3.1: Beispiel 1
entspricht der Relation (vollständige Speicherung)
Kapitel 3
11
Yvon Regis Tounkap Nkwate
knoteni
1
1
1
2
2
2
3
3
3
Studienarbeit
knotenj
1
2
3
1
2
3
1
2
3
kanteij
0
1
1
1
0
0
0
0
0
Tabelle 3.2: Graph als Relation 1
Bei unvollständiger Speicherung sind die Datensätze, in denen die Spalte kanteij
den Wert 0 hat, nicht vorhanden.
3.1.2
Graphendarstellung zur Berechnung der kürzesten Wege
Die gerichteten gewichteten Graphen, für die alle kürzesten Wege berechnet werden
sollen, werden in Tabellen mit folgenden Spaltennamen und zugehörigen Datentypen
gespeichert.
Spaltenname
knoteni
knotenj
kanteij
zwischenknoten
Datentyp
number (eine natürliche Zahl größer als 0)
number (eine natürliche Zahl größer als 0)
number (eine positive reelle Zahl oder null)
number (eine natürliche Zahl)
Tabelle 3.3: Darstellung eines Graphen als Relation 2
Beschreibung der Spalten:
• Die Spalten knoteni und knotenj speichern jeweils Knotennummern.
• Die Spalte kanteij speichert das Gewicht der Kante, die von i nach j führt,
falls sie existiert, sonst hat sie den Wert null.
• Die Spalte zwischenknoten speichert die maximale Knotennummer auf dem
kürzesten Weg von i nach j. Falls für ein Paar (i,j ) die Spalte den Wert 0 hat,
bedeutet dies, dass es keinen Zwischenknoten k mit k 6= i, und k 6=j gibt auf
dem kürzesten Weg von i nach j.
Bemerkung: Bei einer unvollständigen Speicherung eines Graphen als Relation,
kann die Spalte kanteij nie den Wert null annehmen.
Kapitel 3
12
Yvon Regis Tounkap Nkwate
Studienarbeit
Beispiel 2:
Der Graph G = (V,E ) mit der Knotenmenge V={(1,2,3)}
und Kantenmenge E ={(2,1),(1,3)}
4
2
1
6
3
Abbildung 3.2: Beispiel 2
entspricht der Relation
knoteni
1
1
1
2
2
2
3
3
3
knotenj
1
2
3
1
2
3
1
2
3
kanteij
null
null
6
4
null
null
null
null
null
zwischenknoten
0
0
0
0
0
0
0
0
0
Tabelle 3.4: Graph als Relation 2
Bei einer unvollständigen Darstellung sind die Tupeln, deren Feld kanteij den
Wert null hat nicht gespeichert.
3.2
Algorithmus zur Berechnung der transitiven
Hülle bei einer vollständigen Speicherung eines Graphen als Relation
Der folgende PL/SQL-Algorithmus basiert zwar auf dem Floyd-Warshall-Algorithmus, unterscheidet sich aber vom Algorithmus aus Kapitel 2 Abschnitt 2.2.2 (Seite
9). Der wesentliche Unterschied besteht darin, dass die (i,j)-Schleifen (von Seite 9)
durch mengenorientierte Anweisungen ersetzt werden. Durch eine einzige SELECTAnfrage wird entschieden, ob sich zwei Knoten i und j (i 6= j ) durch einen Zwischenknoten k mit i 6= k und j 6= k verbinden lassen.
Es gibt eine einzige for-Schleife, in der die Knotenmenge durchlaufen wird und
alle Knoten als mögliche Zwischenknoten bearbeiten werden. Im k -ten Schleifendurchlauf werden durch eine SELECT-Anfrage die Knotenpaare (i,j ) mit i 6= k und
Kapitel 3
13
Yvon Regis Tounkap Nkwate
Studienarbeit
j 6= k, die sich durch Zwischenknoten k verbinden lassen bestimmt. Die Spalte Kanteij wird dann durch eine UPDATE-Anweisung für diese Knotenpaare auf 1 gesetzt.
Pseudocode zum Algorithmus.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
algorithm Floyd-WarshallA(G)
Eingabe: gerichteter Graph G mit Knoten 1,...,n als Relation gemäß
Darstellung im Abschnitt 3.1.1.
Ausgabe: transitive Hülle H = G + von G als Relation gemäß
Darstellung im Abschnitt 3.1.1.
H ← G;
for k ← 1,2,...,n do
UPDATE H SET kanteij = 1
WHERE (knoteni,knotenj) IN
(SELECT a.knoteni knoteni,b.knotenj knotenj
FROM H a
JOIN H b
ON (a.knotenj = b.knoteni)
WHERE a.knotenj = k
AND b.knoteni = k
AND a.kanteij = 1
AND b.kanteij = 1
AND a.knoteni <> b.knotenj);
return H ;
Kommentare zum Algorithmus
• Von Zeile 8 bis Zeile 18:
Im k -ten Schleifendurchlauf werden die Start (knoteni ) und Endknoten (knotenj ) von den Pfaden, die man mit Zwischenknoten aus der Menge 1,..k erhält
bestimmt. In der Relation H wird im Datenfeld mit den betroffenen Start und
Endknoten das Feld kanteij auf 1 gesetzt.
• Die Bedingungen in Zeile 14 und 15 sorgen dafür, daß alle mögliche Pfade mit
k als höchste Nummer eines Zwischenknoten bestimmt werden.
• Die Bedingungen in Zeile 16 und 17 sorgen dafür, daß nur die existierenden
Pfade mit k als höchste Nummer eines Zwischenknotens bestimmt werden.
• Die Bedingung in Zeile 18 sorgt dafür, daß Start und Endknoten eines Pfades
nicht übereinstimmen. (keine Schleife in der Ergebnisrelation!).
3.3
Algorithmen zur Berechnung der transitiven
Hülle bei einer unvollständigen Speicherung
eines Graphen als Relation
Wir haben in diesem Abschnitt mit Graphen, die unvollständig gespeichert werden,
zu tun. Da nur existierende Kanten dargestellt werden und somit die KnotennumKapitel 3
14
Yvon Regis Tounkap Nkwate
Studienarbeit
merierung nicht mehr fortlaufend ist, muss der vorige Algorithmus angepaßt werden.
Wir benötigen wie vorher nur eine Schleife, um alle Knoten als mögliche Zwischenknoten zu bearbeiten.
Im Gegensatz zum Algorithmus bei einer vollständigen Speicherung müssen nur
Startknoten existierender Kanten als Zwischenknoten bearbeitet werden. Somit stimmt
die Anzahl der Schleifendurchläufe mit der maximalen Nummer eines Startknotens
einer existierenden Kante überein.
Im k -ten Schleifendurchlauf (falls k Startknoten einer Kante ist) wird zunächst
(durch eine SELECT-Anfrage) für jedes Paar (i,j ) mit i 6= k und j 6= k bestimmt,
ob sich i und j durch k verbinden lassen. Ist dies der Fall, wird dann mit einer
Insert-Anweisung das Tripel (i,j,1) in der Relation eingetragen. Aber es werden nur
Tripel eingetragen, die es noch nicht in der Relation gibt. Durch geeignete Operationen (MINUS oder LEFT-OUTER-JOIN oder ANTI-SEMI-JOIN) werden dann die
zulässigen Tripel gefiltert. Es ergeben sich somit drei mögliche Algorithmen.
Erster Algorithmus (MINUS-Variante):
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
algorithm Floyd-Warshall1(G)
Eingabe: gerichteter Graph G unvollständig als Relation gespeichert gemäß
Darstellung im Abschnitt 3.1.1.
Ausgabe: transitive Hülle H = G + von G als Relation gemäß Darstellung
im Abschnitt 3.1.1.
H ← G;
number n ← SELECT MAX(knoteni) FROM H ;
number k ← SELECT MIN(knoteni) FROM H ;
for k <= n do
INSERT INTO H
(SELECT a.knoteni knoteni,a.knotenj knotenj,a.kanteij kanteij
FROM H a
JOIN H b
ON (a.knotenj = b.knoteni)
WHERE a.knotenj = k AND b.knoteni = k
AND a.knoteni <> b.knotenj)
MINUS
SELECT knoteni,knotenj,kanteij
FROM H x
WHERE knoteni = x.knoteni AND knotenj = x.knotenj;
k ← SELECT MIN(knoteni) FROM H WHERE knoteni > k ;
return H ;
Kommentare zum Algorithmus
• Zeile 7 und Zeile 9: da die Knotennummerierung nicht mehr fortlaufend ist,
ist nicht gewährleistet, dass für einen Graphen mit n Knoten, jeder Knoten
Startpunkt einer ausgehenden Kante ist. Die Knoten, die als Zwischenknoten in
Frage kommen, stehen in der Spalte knoteni und ihre Nummerierung ist nicht
stetig. In Zeile 7 wird die maximale Nummer eines Knotens einer ausgehenden Kante bestimmt und in n gespeichert. Die Anzahl der Schleifendurchläufe
Kapitel 3
15
Yvon Regis Tounkap Nkwate
Studienarbeit
muss n nicht überschreiten. In Zeile 8 wird der erte in Frage kommende Zwichenknoten (es muss nicht 1 sein!) bestimmt, zum ersten Schleifendurchlauf.
• Von Zeile 11 bis Zeile 16: Es werden Startknoten und Endknoten von Pfaden
mit k als Zwischenknoten bestimmt.
• Von Zeile 17 bis Zeile 20: Von den berechneten Verbindungen werden diejenigen, die schon in der Tabelle vorhanden sind aussortiert (MINUS) und nicht
mehr eingefügt.
• In Zeile 21 wird die nächste Zwischenknotennummer für den nächsten Schleifendurchlauf bestimmt.
Zweiter Algorithmus (ANTI-SEMI-JOIN-Variante):
Der wesentliche Unterschied zwischen diesem Algorithmus und dem Vorigen besteht
darin, dass statt der Benutzung eines MINUS-Operators, um schon in der Relation
existierende Verbindungen nicht ein zweites Mal einzufügen, man einen ANTI-SEMIJOIN (in SQL mit NOT EXISTS umgesetzt) benutzt.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
algorithm Floyd-Warshall2(G)
//Gleiche Anweisungen wie beim ersten Algorithmus
...
INSERT INTO H
(SELECT a.knoteni knoteni, a.knotenj knotenj, a.kanteij kanteij
FROM H a
JOIN H b
ON (a.knotenj = b.knoteni)
WHERE a.knotenj = k AND b.knoteni = k
AND a.knoteni <> b.knotenj
AND NOT EXISTS
(SELECT knoteni, knotenj, kanteij
FROM H x
WHERE a.knoteni = x.knoteni AND b.knotenj = x.knotenj));
...
//Gleiche Anweisungen wie beim ersten Algorithmus.
Dritter Algorithmus (LEFT-OUTER-JOIN-Variante):
Dieser Algorithmus unterscheidet sich von den anderen dadurch, dass mit Hilfe eines
LEFT OUTER JOIN mit geeigneter JOIN-Bedingung nur die Pfade, die noch nicht
existieren, in die Relation eingefügt werden. Die restlichen Anweisungen sind zu den
vorigen Algorithmen äquivalent.
Kapitel 3
16
Yvon Regis Tounkap Nkwate
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
Studienarbeit
algorithm Floyd-Warshall3(G)
//Gleiche Anweisungen wie beim ersten Algorithmus
...
INSERT INTO H
(SELECT a.knoteni knoteni, a.knotenj knotenj, a.kanteij kanteij
FROM H a
JOIN H b
ON (a.knotenj = b.knoteni)
LEFT OUTER JOIN H c
ON (a.knoteni = c.knoteni AND b.knotenj = c.knotenj)
WHERE a.knotenj = k AND b.knoteni = k
AND a.knoteni <> b.knotenj
AND c.kanteij IS NULL)
...
//Gleiche Anweisungen wie beim ersten Algorithmus.
Bemerkung: Welcher Algorithmus der beste ist, wird sich im vierten Kapitel
zeigen. Die Algorithmen werden mit einer großen Datenmenge getestet und wir werden ihre Laufzeiten vergleichen.
3.4
Algorithmen zur Berechnung aller kürzesten
Wege von vollständig gespeicherten Graphen
Die folgenden Algorithmen basieren wieder auf dem Floyd-Warshall Algorithmus.
Diese Algorithmen verfolgen denselben Ansatz. Es wird im ersten Schritt für alle
Knoten i,j, k mit i 6= j 6= k 6= i aus der Knotenmenge bestimmt, ob i und j sich
durch k verbinden lassen. Im gleichen Schritt wird die Länge des Weges von i nach
j über k berechnet und mit der alten Länge eines Weges zwischen diesen beiden
Knoten verglichen. Kann vom Startknoten i über Zwischenknoten k, der Endknoten
j mit einem kürzeren Weg erreicht werden, so muss das Tupel (i,j,Länge des Weges,k )
in der Relation stehen.
Im zweiten Schritt wollen wir dafür sorgen, dass das vorher ermittelte Tupel
(i,j,Länge des Weges,k ) richtig in der Relation eingetragen wird. Es ergeben sich
zwei Möglichkeiten: Die erste benutzt nur mengenorientierte Operationen und die
zweite arbeitet tupelweise.
3.4.1
Erster Algorithmus
Dieser erste Algorithmus berechnet für einen Graph G, der vollständig in einer Relation gespeichert ist, alle kürzeste Wege. Diese Wege werden dann in einer Relation
H gespeichert. Zunächst werden für alle Knoten k die Startknoten(i ), Endknoten(j )
und Länge der Wege (aij ), die man mit Zwischenknoten k erreichen kann, berechnet. Dies geschieht mit einer SELECT-Anfrage. Dann werden die Tupeln (i,j,aij,k )
durch eine INSERT-Anweisung in die Tabelle eingefügt. Da es nach dem Einfügen
eines solchen Tupels ein anderes Tupel (x,y,axy,w ) mit i = x , j = y, aber axy
Kapitel 3
17
Yvon Regis Tounkap Nkwate
Studienarbeit
> aij geben kann, wird das Tupel (x,y,axy,w ) aus der Tabelle gelöscht (mit einer
DELETE-Anweisung)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
.
15
16
17
18
19
20
21
22
23
24
25
26
27
28
algorithm AllshortestpathsA(G)
Eingabe: gerichteter gewichteter Graph G mit Knoten 1,...,n als Relation
gemäß Darstellung im Abschnitt 3.1.2.
Ausgabe: Graph H als Relation gemäß Darstellung im Abschnitt
3.1.2., in der die Länge der kürzesten Wege zwischen den Knoten von G
gespeichert sind und diese Wege auch rekonstruiert werden können.
H ← G;
for k ← 1,2,...,n do
INSERT INTO H
SELECT a.knoteni knoteni, b.knotenj knotenj
(a.kanteij + b.kanteij)kanteij, a.knotenj zwischenknoten
FROM H a
JOIN H b ON (a.knotenj = b.knoteni)
JOIN H c ON (a.knoteni = c.knoteni AND b.knotenj = c.knotenj)
WHERE (a.knotenj = k AND b.knoteni = k
AND a.kanteij IS NOT NULL AND b.kanteij IS NOT NULL)
AND ((a.kanteij + b.kanteij)< c.kanteij OR c.kanteij IS NULL)
AND a.knoteni <> b.knotenj;
DELETE FROM H
WHERE (knoteni, knotenj, zwischenknoten) IN(
SELECT b.knoteni, b.knotenj, b.zwischenknoten
FROM H a, JOIN H b
ON (a.knoteni = b.knoteni AND a.knotenj = b.knotenj)
WHERE (a.kanteij < b.kanteij OR b.kanteij IS NULL
AND a.kanteij IS NOT NULL
AND a.zwischenknoten = k );
return H ;
Kommentare zum Algorithmus
• Von Zeile 9 bis Zeile 18:
Es werden im k -ten Schleifendurchlauf Startknoten (i ), Endknoten (j ) und
Länge der kürzesten Pfade (aij ), die man mit Zwischenknoten aus der Menge
{1,..,k } erhält, bestimmt. Dann werden diese neuen Pfade (identiziert durch
(i,j,k,aij ) und im folgenden k -Pfade genannt...) in die Tabelle H eingefügt, mit
k als Wert für die Spalte zwischenknoten.
• Von Zeile 20 bis 27:
Da es nach dem Einfügen von k -Pfaden in H zwei Datenfelder geben kann mit
gleichem Startknoten (Spalte knoteni ) und gleichem Endknoten (Spalte knotenj ), die sich aber in den Spalten kanteij und zwischenknoten unterscheiden,
wird das Datenfeld mit größtem Wert in der Spalte kanteij (also der längste
Pfad) oder mit null als Wert der Spalte kanteij (nicht vorhandene Verbindung)
gelöscht.
Kapitel 3
18
Yvon Regis Tounkap Nkwate
Studienarbeit
• die Bedingungen der WHERE-Klausel (Zeile 25-27) sorgen dafür, daß die existierenden Pfade mit ähnlichem Start- und Enknoten wie die k -Pfade, die aber
länger sind, gelöscht werden. Falls die k -Pfade neue gefundene Wege zwischen
zwei Knoten sind, wird die Information (das entsprechende Tupel), dass die
betroffenen Knoten nicht verbunden waren, aus der Tabelle gelöscht.
3.4.2
Zweiter Algorithmus
Der zweite Algorithmus bekommt wieder als Eingabe einen Graph G, der vollständig
in einer Relation gespeichert ist und liefert die Tabelle H zurück, in der alle kürzesten
Wege gespeichert sind. Diese Wege können auch anschließend rekonstruiert werden.
G wird zunächst in H kopiert. Die Bestimmung der k -Pfade im k -ten Schleifendurchlauf geschieht mit der gleichen SELECT-Anfrage wie beim ersten Algorithmus. Im
Gegensatz zum ersten Algorithmus werden diese Pfade nicht mit einer INSERTAnweisung eingefügt. Die DELETE-Anweisung, um nicht mehr gültige Verbindungen zu löschen, entfällt auch. Statt dessen werden zunächst in einem Cursor K die
k -Pfade gespeichert. Für jeden k -Pfad (i,j,aij,k ) in dem Cursor K wird mit einer
UPDATE-Anweisung in der Tabelle H das Tupel mit dem Feld knoteni = i und
dem Feld knotenj = j in den Feldern kanteij und zwischenknoten mit den Werten i
und aij aktualisiert.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
algorithm AllshortestpathsB(G)
Eingabe: gerichteter gewichter Graph G mit Knoten 1,...,n als Relation
gemäß Darstellung im Abschnitt 3.1.2.
Ausgabe: Graph H als Relation gemäß Darstellung im Abschnitt 3.1.2.,
in der die Länge der kürzesten Wege zwischen den Knoten von G
gespeichert sind und diese Wege auch rekonstruiert werden können.
H ← G;
Cursor K ;
for k ← 1,2,...,n do
K ←SELECT a.knoteni knoteni, b.knotenj knotenj
(a.kanteij + b.kanteij)kanteij, a.knotenj zwischenknoten
FR0OM H a
JOIN H b ON (a.knotenj = b.knoteni)
JOIN H c ON (a.knoteni = c.knoteni
AND b.knotenj = c.knotenj)
WHERE (a.knotenj = k AND b.knoteni = k
AND a.kanteij IS NOT NULL AND b.kanteij IS NOT NULL)
AND ((a.kanteij + b.kanteij)< c.kanteij OR c.kanteij IS NULL)
AND a.knoteni <> b.knotenj;
for r in K do
UPDATE H
SET kanteij = r.kanteij, zwischenknoten =r.zwischenknoten
WHERE knoteni = r.knoteni and knotenj = r.knotenj
return H ;
Kommentare zum Algorithmus
Kapitel 3
19
Yvon Regis Tounkap Nkwate
Studienarbeit
• Zeile 8: Der Cursor K wird definiert. Jede Zeile von K hat diegleiche Struktur
wie eine Zeile der Tabelle H.
• Von Zeile 10 bis Zeile 19: solange noch nicht alle Knoten bearbeitet wurden,
werden im k -ten Schleifendurchlauf in dem Cursor K die k -Pfade gespeichert.
• Die Bedingung in Zeile 16 sorgt dafür, daß alle mögliche Pfade mit k als höchste
Nummer eines Zwischenknoten bestimmt werden.
• Die Bedingung in Zeile 17 sorgt dafür, daß nur die existierenden Pfade mit
k als höchste Nummer eines Zwischenknoten bestimmt werden.
• die Bedingung in Zeile 18 sorgt dafür, daß von den existierenden Pfaden mit k
als höchste Nummer eines Zwischenknoten, nur die kürzesten bestimmt werden. Es wird ein Vergleich zwischen der Länge der bisjehrigen Pfade (falls
sie existieren) und der Länge der k -Pfade gemacht. Falls die k -Pfade kleiner
sind, so werden sie in dem Cursor K eingefügt. Falls zwei Knoten nicht vorher
verbunden waren, aber durch k verbunden werden, wird die neue Verbindung
auch in K gespeichert.
• Die Bedingung in Zeile 19 sorgt dafür, daß Start und Endknoten eines k -Pfades
nicht übereinstimmen.
• Von Zeile 20 bis 23: Mit Hilfe des Startknoten und des Endknoten eines berechneten kürzesten Weges, wird durch eine UPDATE-Anweisung in der Tabelle H
an der richtigen Stelle die Länge des Weges und die zugehörige Zwischenknotennummer (k, im k -ten Schleifendurchlauf) eingetragen. Der Kursor K wird
dabei geöffnet und Zeile für Zeile geleert (also keine Mengenoperation).
Bemerkung:
Welcher Algorithmus zu bevorzugen ist, wird sich im vierten Kapitel zeigen. Da werden beide Algorithmen mit großen Graphen getestet und ihre Laufzeiten verglichen.
3.5
Algorithmen zur Berechnung aller kürzesten
Wege von unvollständig gespeicherten Graphen
In diesem Abschnitt arbeiten wir mit gerichteten gewichteten Graphen, die unvollständig in Relationen gespeichert werden. Die Bestimmung aller kürzesten Wege
geschieht anders, als bei vollständig gespeicherten Graphen. Zu beachten ist wieder, dass die Knotennummerierung nicht fortlaufend ist. Also nicht alle Knoten aus
{1,...,n} sind Startknoten einer Kante. Startknoten von Kanten sind in der Spalte knoteni gespeichert. Wir benötigen wieder eine Schleife, um alle Starknoten von
Kanten als Zwischenknoten zu bearbeiten und somit die k -Pfade zu bestimmen.
Der wesentliche Unterschied mit den Algorithmen bei einer vollständigen Speicherung liegt in der SELECT-Anfrage zur Bestimmung der k -Pfade. Die k -Pfade
Kapitel 3
20
Yvon Regis Tounkap Nkwate
Studienarbeit
sind entstanden, in dem wir im k -ten Schleifendurchlauf, für zwei Knoten i und j,
aik (Gewicht der Kante von i nach k ) + akj (Gewicht der Kante von k nach j )
mit aij (Gewicht der Kante von i nach j ) verglichen haben. Dieser Vergleich wurde durch den letzen JOIN (mit passenden Bedingungen) zwischen den Relationen
ermöglicht.Bei vollständig gespeicherten Graphen werden wir einen LEFT-OUTERJOIN benutzen um den Vergleich zu machen. Somit können auch gerade berechnete
Verbindungen, die aber noch nicht im Graph existieren, nicht verloren gehen. Statt
eines LEFT OUTER JOIN kann man auch einen ANTI-SEMI-JOIN benutzen. Unterschiede zwischen den folgenden Algorithmen werden sich, wie im Abschnitt dadurch 3.4 ergeben , daß der erste Algorithmus wieder mit INSERT und DELETE
arbeitet, während der zweite Algorithmus wieder einen Cursor K benutzt. Der Kursor K behält wie im Abschnitt 3. 4 die gleiche Funktionalität.
3.5.1
Erster Algorithmus
LEFT OUTER JOIN-Variante
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
algorithm Allshortestpaths1A(G)
Eingabe: gerichteter gewichteter Graph G unvollständig in einer Relation
gespeichert gemäß Darstellung im Abschnitt 3.1.2.
Ausgabe: Graph H als Relation gemäß Darstellung im Abschnitt 3.1.2.,
in der die Länge der kürzesten Wege zwischen den Knoten von G
gespeichert sind und diese Wege auch rekonstruiert werden können.
H ← G;
number n ← SELECT MAX(knoteni) FROM H ;
number k ← SELECT MIN(knoteni) FROM H ;
for k <= n do
INSERT INTO H
SELECT a.knoteni knoteni, b.knotenj knotenj
(a.kanteij + b.kanteij)kanteij, a.knotenj zwischenknoten
FROM H a
JOIN H b ON (a.knotenj = b.knoteni)
LEFT OUTER JOIN H c
ON (a.knoteni = c.knoteni AND b.knotenj = c.knotenj)
WHERE (a.knotenj = k AND b.knoteni = k
AND ((a.kanteij + b.kanteij)< c.kanteij OR c.kanteij IS NULL)
AND a.knoteni <> b.knotenj;
Kapitel 3
DELETE FROM H
WHERE (knoteni, knotenj, kanteij, zwischenknoten) IN(
SELECT b.knoteni, b.knotenj, b.kanteij, b.zwischenknoten
FROM H a,JOIN H b
ON (a.knoteni = b.knoteni AND a.knotenj = b.knotenj)
WHERE (a.kanteij < b.kanteij
AND a.zwischenknoten = k );
21
Yvon Regis Tounkap Nkwate
29
30
Studienarbeit
k ← SELECT MIN(knoteni) FROM H WHERE knoteni > k ;
return H ;
Kommentare:
• Von Zeile 11 bis Zeile 21: die k -Pfade werden berechnet und in der Tabelle H
eingefügt. Dabei wird ein LEFT-OUTER-JOIN benutzt, um in der SELECTAnfrage aik + akj mit aij zu vergleichen, falls aij existiert, ansonsten wird
der neue Pfad (i,j,(aik + akj ),k ) eingefügt.
• Von Zeile 23 bis Zeile 29: Zwischen zwei Knoten der Tabelle wird ermittelt, ob
es mehr als nur einen Pfad gibt (SELECT-Anfrage der DELETE-Anweisung).
Falls ja, wird der längere Weg gelöscht (DELETE-Anweisung).
ANTI-SEMI-JOIN-Variante
Hier wird statt eines LEFT-OUTER-JOIN in der SELECT-Anfrage zur Bestimmung
der k -Pfade, ein ANTI-SEMI-JOIN (also ..NOT EXISTS..) benutzt. Ansonsten gibt
es keine weitere Änderung .
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
algorithm Allshortestpaths1B(G)
// Anweisungen ähnlich wie bei der LEFT-OUTER-JOIN-Variante
...
INSERT INTO H
SELECT a.knoteni knoteni, b.knotenj knotenj
(a.kanteij + b.kanteij)kanteij, a.knotenj zwischenknoten
FROM H a
JOIN H b ON (a.knotenj = b.knoteni)
WHERE (a.knotenj = k AND b.knoteni = k
AND a.knoteni <> b.knotenj;
AND NOT EXISTS
(SELECT c.knoteni, c.knotenj, c.kanteij, c.zwischenknoten
FROM H c
WHERE c.knoteni = a.knoteni AND c.knotenj = b.knotenj
AND c.kanteij <= a.kanteij + b.kanteij)
// Anweisungen ähnlich wie bei der LEFT-OUTER-JOIN-Variante
...
3.5.2
Zweiter Algorithmus
Der zweite Algorithmus benutzt einen Cursor K, in dem wieder die k -Pfade gespeichert werden. Dafür benutzt der Algorithmus fast genau dieselbe SELECTAnfrage wie im ersten Algorithmus. Nur es wird zusätzlich das Gewicht aij des
“alten Weges”von Knoten i nach Knoten j selektiert. Falls aij existiert, wird eine
UPDATE-Anweisung ansonsten eine INSERT-Anweisung benutzt, um die k -Pfade
in der Tabelle H einzufügen.
Kapitel 3
22
Yvon Regis Tounkap Nkwate
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
Studienarbeit
algorithm Allshortestpaths2(G)
Eingabe: gerichteter gewichteter Graph G unvollständig in einer Relation
gespeichert gemäß Darstellung im Abschnitt 3.1.2.
Ausgabe: Graph H als Relation gemäß Darstellung im Abschnitt 3.1.2.,
in der die Länge der kürzesten Wege zwischen den Knoten von G
gespeichert sind und diese Wege auch rekonstruiert werden können.
H ← G;
number n ← SELECT MAX(knoteni) FROM H ;
number k ← SELECT MIN(knoteni) FROM H ;
Cursor K ;
for k <= n do
K ←SELECT a.knoteni knoteni, b.knotenj knotenj
(a.kanteij + b.kanteij)kanteij,
a.knotenj zwischenknoten, c.kanteij ckanteij
FROM H a
JOIN H b ON (a.knotenj = b.knoteni)
LEFT OUTER JOIN H c
ON (a.knoteni = c.knoteni AND b.knotenj = c.knotenj)
WHERE (a.knotenj = k AND b.knoteni = k
AND ((a.kanteij + b.kanteij)< c.kanteij
OR c.kanteij IS NULL)
AND a.knoteni <> b.knotenj;
for r in K do
if r.ckanteij is null then
INSERT INTO H VALUES
(r.knoteni,r.knotenj,r.kanteij,r.zwischenknoten);
else
UPDATE H SET kanteij = r.kanteij,
zwischenknoten = r.zwischenknoten
WHERE knoteni = r.knoteni AND knotenj = r.knotenj;
k ← SELECT MIN(knoteni) FROM H WHERE knoteni > k ;
return H ;
Kommentare zum Algorithmus
• Von Zeile 12 bis Zeile 22: die k -Pfade zusammen mit dem Gewicht aij werden
bestimmt und in K gespeichert. Eine Zeile von K hat dann die Struktur:
(i, j, (aik + akj ), (aij oder null))
• Von Zeile 23 bis Zeile 30: jeder Record r in K wird gelesen und K geleert.
Dabei werden die k -Pfade in H eingefügt.
Falls aij nicht existiert (also Knoten i und Knoten j sind nicht durch einen Weg
verbunden) , hat das Record-Feld ckanteij den Wert null. Mit einer INSERTAnweisung wird die neue Verbindung in H eingetragen. Falls aij schon vorhanden war (ckanteij is not null ) wird mit einer UPDATE-Anweisung die
betroffene Zeile in H in den Feldern kanteij und zwischenknoten aktualisiert.
Kapitel 3
23
Yvon Regis Tounkap Nkwate
3.5.3
Studienarbeit
Beispiel
Wir simulieren zwei Schritte (k = 1, 2) der Algorithmen Allshortestpaths1A und
Allshortestpaths2.
Dazu, sei G der folgende Graph:
1
2
4
1
3
3 3
1
1
4
Abbildung 3.3: Graph G
Dieser Graph wird unvollständig gespeichert, und entspricht der Relation:
knoteni
1
2
2
4
4
4
knotenj
2
3
4
1
2
3
kanteij
1
4
3
1
3
1
zwischenknoten
0
0
0
0
0
0
Schritt k = 1:
• Allshortestpaths1A
Die SELECT-Anfrage zur Bestimmung der 1 -Pfade (k = 1) liefert die Sicht:
knoteni
4
knotenj
2
kanteij
2
zwischenknoten
1
Dieses Tupel wir mit der INSERT-Anweisung in die Tabelle eingefügt und das
Tupel (4,3,2,0) wird mit der DELETE-Anweisung gelöscht.
• Im Fall Allshortestpaths2 erhalten wir:
K =
knoteni
4
knotenj
2
kanteij
2
zwischenknoten
1
ckanteij
3
Da c.kanteij für dieses Tupel nicht den null-Wert hat, wird mit der UPDATEAnweisung das Datenfeld (4,3,2,0) zum Datenfeld (4,2,2,1) aktualisiert.
Kapitel 3
24
Yvon Regis Tounkap Nkwate
Studienarbeit
Schritt k = 2:
• Allshortestpaths1A
Die SELECT-Anfrage zur Bestimmung der 2 -Pfade (k = 2) liefert die Sicht:
knoteni
1
1
knotenj
3
4
kanteij
5
4
zwischenknoten
2
2
Diese zwei Tupel werden dann in die Tabelle eingefügt.
• Im Fall Allshortestpaths2 erhalten wir:
knoteni
1
K =
1
knotenj
3
4
kanteij
5
4
zwischenknoten
2
2
ckanteij
null
null
Da ckanteij den Wert null für die beiden Tupel hat, werden diese beiden
Tupeln mit der INSERT-Anweisung in die Tabelle eingefügt.
3.5.4
Methoden für die Rekonstruktion der Wege
Die Rekonstruktion des kürzesten Weges zwischen zwei Knoten i und j des Graphen
H geschieht mit Hilfe der Methoden weg und zwischen.
1
2
3
4
5
6
7
8
9
10
11
method weg(i,j,H )
var1 NUMBER;
var1 = SELECT kanteij
FROM H
WHERE knoteni = i AND knotenj = j ;
if var1 IS NOT NULL then
DBMS OUTPUT.PUT LINE(’Von Knoten ’ki );
zwischen(i,j,H );
DBMS OUTPUT.PUT LINE(’Nach Knoten ’kj );
else
DBMS OUTPUT.PUT LINE(’Kein Weg !’);
1
2
3
4
5
6
7
8
9
method zwischen (i,j,H )
var1 NUMBER;
var1 = SELECT zwischenknoten
FROM H
WHERE knoteni = i AND knotenj = j ;
if var1 <> 0 then
zwischen(i,var1,H );
DBMS OUTPUT.PUT LINE(’über Knoten ’kvar1 );
zwischen(var1,j,H );
Kapitel 3
25
Kapitel 4
Tests der Algorithmen
In diesem Kapitel werden die Algorithmen zur Berechnung der transitiven Hülle und
die Algorithmen zur Bestimmung aller kürzesten Wege getestet und ihre Laufzeiten
verglichen. Dazu werden passende Testsdaten aufbereitet und zur Beschleunigung
des Zugriffs auf die Daten passende Indexe auf gewisse Spalten der Testtabellen
angelegt.
Zunächst stellen wir einen Algorithmus vor, der gerichtete und gewichtete Graphen vollständig in einer Relation speichert. Mit diesen Testgraphen werden die Algorithmen zur Berechnung aller kürzesten Wege von vollständig gespeicherten Graphen (AllshortestpathsA und AllshortestpathsB) getestet. Ihre Laufzeit bei wechselbarer Tabellengröße wird notiert, um den besten Algorithmus zu bestimmen.
Dann werden die Algorithmen, die auf unvollständig gespeicherten Graphen
basieren, getestet. Dazu werden wieder Testdaten aufbereitet und passende Indexe auf die Testtabellen angelegt. Die Laufzeiten der Algorithmen werden ebenfalls verglichen. Für die Berechnung der transitiven Hülle werden zusätzlich die
Ausführungspläne der Haupt-SELECT-Anfragen der Algorithmen ausgegeben und
kommentiert.
4.1
4.1.1
Test der Algorithmen allshortestspathsA und
AllshortestpathsB
Bereitstellung der Testdaten
Die Testtabellen werden mit dem folgenden Algorithmus erzeugt. Dieser Algorithmus bekommt als Eingabeparameter die Anzahl der Knoten der Testtabelle: n und
die Wahrscheinlichkeit (eine natürliche Zahl), mit der eine Kante zwischen zwei unterschiedlichen Knoten eingetragen wird: prob. Es gilt 0 6 prob 6 100.
Die Funktion VALUE aus dem Package DBMS RANDOM liefert eine reelle Zahl
aus dem Intervall [0,1). Diese reelle Zahl wird mit 100 multipliziert und wir erhalten
eine Zahl x aus dem Intervall [0,100). Falls 1 6 x 6 prob, wird eine Kante zwischen
zwei Knoten des Graphen eingetragen. Dabei ist das Gewicht der eingetragene Kante
gleich x. Falls x > n wird keine Kante eingetragen (Spalte kanteij hat den wert null).
Yvon Regis Tounkap Nkwate
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
Studienarbeit
algorithm creategraph(n, prob)
number i ← 1;
number j ← 1;
number x ;
number aij ;
tabelle Y ← CREATE TABLE Y (knoteni number, knotenj number,
kanteij number, zwischenknoten number)
while i 6 n do
while j 6 n do
x ← (100*DBMS RANDOM.VALUE);
if i = j then
INSERT INTO Y (knoteni, knotenj, zwischenknoten)
VALUES(i,j,0);
if x 6 prob and 1 6 x and i < j then
INSERT INTO Y VALUES (i, j, x, 0);
if x 6 prob and 1 6 x and i > j then
aij ← SELECT kanteij FROM Y
WHERE knoteni = i and knotenj = j ;
if aij is not null then
INSERT INTO Y VALUES(i, j, aij, 0);
else //In PL/SQL wird eine NO DATA FOUND-Ausnahme
//ausgelöst und abgefangen
INSERT INTO Y VALUES(i, j, x, 0);
else
INSERT INTO Y (knoteni, knotenj, zwischenknoten)
VALUES(i,j,0);
return Y
Kommentare zum Algorithmus:
• Solange noch nicht alle Zeilennummer (i ) und Spaltennummer (j ) bearbeitet
sind, wird (in Zeile 10) eine zufällige Zahl aus [0, 1) mit Hilfe der Funktion
VALUE aus dem Package DBSM RANDOM generiert. Diese Zahl wird mit 100
multipliziert, um eine natürliche Zahl aus [0,100) zu erhalten, und anschließend
in der Variable x gespeichert.
• Von Zeile 11 bis Zeile 13: die Kante (i, j ) mit dem Gewicht null wird in
Y eingetragen, falls i = j . Die Spalte zwischenknoten hat selbsverständlich
immer den Wert 0.
• Von Zeile 14 bis Zeile 15: die Kante (i, j ) mit i < j wird eingefügt, falls 1 6
x 6 prob. Dabei hat das Gewicht der Kante (i, j ) den Wert x. (je näher die
gelieferte Zahl an der Wahrscheinlichkeit ist, desto höher ist das Gewicht).
• Zeile 16 bis 23: falls eine Kante (i,j ) mit i > j eingefügt werden soll, wird
zunächst überprüft, ob die Kante (j,i ) schon vorhanden ist (Zeile 17-18). Existiert schon die Kante (j,i ), so wird einfach eine Rückkante mit gleichem Gewicht eingetragen (Zeile 20). Ist die Kante (j,i ) nicht vorhanden, so wird die
neue Kante (i,j ) mit dem Gewicht x eingetragen.
Kapitel 4
27
Yvon Regis Tounkap Nkwate
Studienarbeit
• falls i 6= j und x > prob ist, so wird eine Kante mit Gewicht null eingefügt
(Zeile 25-26).
4.1.2
Vergleich der Laufzeiten beider Algorithmen
Die PL/SQL-Prozeduren, die beide Algorithmen implementieren, befinden sich unter
den gleichen Namen, wie die Algorithmen in der elektronischen Abgabe dieser Arbeit.
Dort befindet sich auch eine Implementierung des Algorithmus creategraph.
Wir rufen die Prozedur creategraph mit unterschiedlichen Eingabeparametern
auf, und auf die erzeugten vollständig gespeicherten Graphen, lassen wir die beiden
Algorithmen AllshortestpathsA und AllshortestpathsB laufen. Folgende Laufzeiten
wurden notiert:
CREATEGRAPH(n,prob) allshotestspathsB allshotestspathsA
CREATEGRAPH(100,20)
9 s 60
10 s 83
CREATEGRAPH(100,50)
9 s 37
13 s 65
CREATEGRAPH(100,90)
9 s 79
17 s 01
CREATEGRAPH(150,20)
33 s 05
50 s 07
CREATEGRAPH(150,50)
29 s 29
57 s 15
CREATEGRAPH(150,90)
29 s 73
01 min 08 s
CREATEGRAPH(200,20)
01 min 19 s
02 min 18 s
CREATEGRAPH(200,50)
01 min 07 s
02 min 36 s
CREATEGRAPH(200,90)
01 min 04 s
03 min 13 s
CREATEGRAPH(250,20)
02 min 48 s
05 min 56 s
CREATEGRAPH(250,50)
02 min 18 s
06 min 07 s
CREATEGRAPH(350,20)
03min 59 s
18 min 44 s
Wie wir festellen können, ist der Algorithmus allshotestspathsB die bessere
Umsetzung des Algorithmus zur Berechnung aller kürzesten Wege in PL/SQL(bei
vollständig gespeicherten Graphen). Dies läßt sich dadurch erklären, dass wir im
Algorithmus AllshortestpathsB die k -Pfade berechnen und direkt mit INSERT, oder
UPDATE in der Tabelle einfügen. Das Durchlaufen der Datensätze eines Cursors ist
auch wohl eine Operation, die weniger Zeit in Anspruch nimmt als erwartet. Im
Algorithmus allshortestpathA berechnen wir die k -Pfade, fügen sie in die Tabelle
ein, und mit der DELETE-Anweisung greifen wir noch einmal auf diese k -Pfade zu.
Dies kann als Doppelarbeit von AllshortestpathsB angesehen werden.
4.2
Tests der Algorithmen basierend auf unvollständig gespeicherte Graphen
In diesem Abschnitt möchten wir mit unvollständig gespeicherten (großen) Graphen,
die Algorithmen zur Berechnung der transitiven Hülle und zur Bestimmung aller
kürzesten Wege testen, und ihre Laufzeit vergleichen. Zunächst werden die Testdaten
aufbereitet mit Hilfe zweier Prozeduren aufbereitet.
Kapitel 4
28
Yvon Regis Tounkap Nkwate
4.2.1
Studienarbeit
Bereitstellung der Testdaten für die Berechnung der
transitiven Hülle
Die Aufbereitung der Testdaten für die Berechnung der transitiven Hülle geschieht
mit Hilfe der Tabelle HANBKG250 EDGE$, mit dem Besitzer TIEDGE(owner =
’tiedge’). Diese Tabelle stellt das Straßennetz der Region Hannover als Graph im
Maßstab 1:250.000 dar. Die geometrischen Daten liegen allerdings in einem topologischen Datenmodell, das in der Arbeit [Tie03] entwickelt wurde.
Die Daten in dieser Tabelle weisen eine besondere Struktur auf, nämlich der
dargestelle Graph ist zwar gewichtet, aber nicht gerichtet und enthält Schleifen. So
gibt es Kanten, deren Startknoten und Endknoten übereinstimmen. Zudem kann es
mehr als nur eine Kante zwischen zwei Knoten geben.
Die Testdaten werden in der Tabelle HANBKG250 EDGE$FloydW gespeichert.
Diese neue Tabelle hat genau dieselbe Knotenmenge wie HANBKG250 EDGE$.
Falls in der Tabelle HANBKG250 EDGE$ eine ungerichtete Kante von Knoten
i nach Knoten j existiert, wird in der Tabelle HANBKG250 EDGE$FloydW eine Kante von i nach j und eine Kante von j nach i eingetragen. Schleifen, die
in HANBKG250 EDGE$ vorhanden sind, werden in HANBKG250 EDGE$FloydW
entfernt. Sind zwei Knoten durch mehr als nur eine Kante direkt verbunden , wird
nur eine Kante (in beide Richtungen) zwischen beiden Knoten eingetragen . Zur Beschleunigung der Zugriffe auf die Testtabelle, werden Indexe auf die Spalten knoteni
und knotenj angelegt. Statistiken der Tabelle werden ebenfalls erzeugt und im Data
Dictionary gespeichert.
Die Prozedur createGraph forFloydW, die sich in der elektronischen Abgabe
befindet, erzeugt die Testtabelle HANBKG250 EDGE$FloydW.
4.2.2
Vergleich der Laufzeiten der Algorithmen
Floyd Warschall1/2/3
Die Prozeduren, die konkret die Algorithmen Floyd Warschall1/2/3 implementieren
sind in der elektronischen Abgabe auch zu finden. Zu der Testtabelle HANBKG250EDGE$FloydW gelten vorm Start der Algorithmen folgende Statistiken:
• # Knoten: 1228
• # Kanten (Tabellengröße): 3198.
Laufzeit der Prozeduren:
Prozedur
Laufzeit
FLOYD WARSHALL1
41 Min 11 Sek
FLOYD WARSHALL2 mehr als 10 Stunden
FLOYD WARSHALL3
11 Min 20 Sek
Die Testtabelle HANBKG250 EDGE$FloydW enthält 1465330 Kanten im Endzustand. Feststellen kann man, daß der Algorithmus floyd warshall3 (also LEFTOUTER-JOIN-Variante), wohl die bessere PL/SQL-Implementierung der transitiven
Kapitel 4
29
Yvon Regis Tounkap Nkwate
Studienarbeit
Hülle für unvollständig gespeicherte Graphen ist. Der Allgorithmus floyd warshall2
ist am ineffizientsten.
4.2.3
Ausführungspläne der Hauptanfragen der Algorithmen
Sei der Graph (die Tabelle HANBKG250 EDGE$FloydW) im Endzustand. Er besitzt insgesamt 1465330 Kanten. Wir möchten uns die Ausführungspläne der SELECTAnfrage der Algorithmen zur Bestimmung neuer Verbindungen anschauen und kommentieren.
Dazu bestimmen wir einen Knoten, der die maximale Anzahl an ausgehenden
Kanten (1210) besitzt. (zum Beispiel Knoten 531 ist Startknoten von 1210 Kanten).
Wir simulieren also einen Schleifendurchlauf der Algorithmen mit dem Zwischenknotennummer 531 und erhalten folgende Ausführungspläne:
SELECT-Anfrage des Algorithmus floyd warshall1
SELECT a.knoteni knoteni ,b.knotenj knotenj,a.kanteij kanteij
FROM HANBKG250_EDGE$FLOYDW a
JOIN HANBKG250_EDGE$FLOYDW b ON(a.knotenj = b.knoteni)
WHERE a.knotenj= 531 AND b.knoteni = 531 AND a.knoteni<>b.knotenj
MINUS
(SELECT knoteni,knotenj,kanteij
FROM HANBKG250_EDGE$FLOYDW x
WHERE knoteni = x.knoteni AND knotenj = x.knotenj);
Elapsed: 00:00:00.14
Execution Plan
---------------------------------------------------------0
SELECT STATEMENT Optimizer=ALL_ROWS (Cost=877 Card=89793 Byt
es=2226334)
1
2
3
4
0
1
2
3
MINUS
SORT (UNIQUE) (Cost=588 Card=89793 Bytes=1616274)
HASH JOIN (Cost=72 Card=89793 Bytes=1616274)
TABLE ACCESS (BY INDEX ROWID) OF ’HANBKG250_EDGE$FLO
YDW’ (TABLE) (Cost=29 Card=229 Bytes=2290)
5
4
INDEX (RANGE SCAN) OF ’IDX2_HANBKG250_EDGE$FLOYDW’
(INDEX) (Cost=1 Card=229)
Kapitel 4
30
Yvon Regis Tounkap Nkwate
Studienarbeit
6
3
TABLE ACCESS (FULL) OF ’HANBKG250_EDGE$FLOYDW’ (TABL
E) (Cost=42 Card=237 Bytes=1896)
7
8
1
7
SORT (UNIQUE) (Cost=289 Card=61006 Bytes=610060)
TABLE ACCESS (FULL) OF ’HANBKG250_EDGE$FLOYDW’ (TABLE)
(Cost=42 Card=61006 Bytes=610060)
Statistics
---------------------------------------------------------190 recursive calls
0 db block gets
443 consistent gets
0 physical reads
320 redo size
336 bytes sent via SQL*Net to client
332 bytes received via SQL*Net from client
1 SQL*Net roundtrips to/from client
7 sorts (memory)
0 sorts (disk)
0 rows processed
Kommentar zum Ausführungsplan:
Zunächst wird auf die Tabelle HANBKG250 EDGE$FLOYDW zugegriffen. Dieser Zugrifff geschieht über die vom Index IDX2 HANBKG250 EDGE$FLOYDW
(auf die Spalte knotenj angelegt) gelieferten Rowids. Ist für eine Zeile der Tabelle
HANBKG250 EDGE$FLOYDW der Wert des Feldes knotenj gleich 531, so liefert
der Index die zugehörige Zeilennummer. Die Tupel der Tabelle mit den entsprechenden Zeilennummern bilden die Kopie a. Dann wird auf die Tabelle HANBKG250 EDGE$FLOYDW ein Relationenscan durchgeführt, und die Kopie b erzeugt. Kopie a
und Kopie b werden durch einen HASH-JOIN (mit JOIN-Bedingung: a.knotenj =
b.knoteni ) verbunden. Von HANBKG250 EDGE$FLOYDW wird eine neue Kopie x
(durch erneutes Relationenscan) erzeugt. Kopie ab und Kopie x werden sortiert, und
die Operation Kopie ab MINUS Kopie x bildet das Endergebnis. Anschließend wird
die Projektion der Endergebnismenge auf die gewünschten Spalten zurückgeliefert.
SELECT-Anfrage des Algorithmus floyd warshall2
SELECT a.knoteni knoteni ,b.knotenj knotenj,a.kanteij kanteij
FROM HANBKG250_EDGE$FLOYDW a
JOIN HANBKG250_EDGE$FLOYDW b ON(a.knotenj = b.knoteni)
WHERE a.knotenj= 531 AND b.knoteni = 531 AND a.knoteni<>b.knotenj
AND NOT EXISTS
(SELECT x.knoteni,x.knotenj,x.kanteij
FROM HANBKG250_EDGE$FLOYDW x
WHERE a.knoteni = x.knoteni AND b.knotenj = x.knotenj);
no rows selected
Elapsed: 00:00:00.04
Kapitel 4
31
Yvon Regis Tounkap Nkwate
Studienarbeit
Execution Plan
---------------------------------------------------------0
SELECT STATEMENT Optimizer=ALL_ROWS (Cost=115 Card=1 Bytes=2
6)
1
2
0
1
HASH JOIN (RIGHT ANTI) (Cost=115 Card=1 Bytes=26)
TABLE ACCESS (FULL) OF ’HANBKG250_EDGE$FLOYDW’ (TABLE) (
Cost=42 Card=61006 Bytes=488048)
3
4
1
3
HASH JOIN (Cost=72 Card=89793 Bytes=1616274)
TABLE ACCESS (BY INDEX ROWID) OF ’HANBKG250_EDGE$FLOYD
W’ (TABLE) (Cost=29 Card=229 Bytes=2290)
5
4
INDEX (RANGE SCAN) OF ’IDX2_HANBKG250_EDGE$FLOYDW’ (
INDEX) (Cost=1 Card=229)
6
3
TABLE ACCESS (FULL) OF ’HANBKG250_EDGE$FLOYDW’ (TABLE)
(Cost=42 Card=237 Bytes=1896)
Statistics
---------------------------------------------------------1 recursive calls
0 db block gets
372 consistent gets
0 physical reads
0 redo size
336 bytes sent via SQL*Net to client
332 bytes received via SQL*Net from client
1 SQL*Net roundtrips to/from client
0 sorts (memory)
0 sorts (disk)
0 rows processed
Kommentar zum Ausführungsplan:
Zunächst wird auf die Tupel der Tabelle HANBKG250 EDGE$FLOYDW über
Rowids (vom Index IDX2 HANBKG250 EDGE$FLOYDW zurückgeliefert) zugegriffen. Dabei werden die Tupel, mit 531 als Wert des Feldes knotenj zurückgeliefert.
Die entstandene Menge nennen wir a. Dann wird durch ein Relationenscan die Kopie b von HANBKG250 EDGE$FLOYDW erzeugt, und mit a durch einen HASHJOIN (mit JOIN-Bedingung: a.knotenj = b.knoteni ) verbunden. Die Ergebnismenge
ab wird mit der Kopie x von HANBKG250 EDGE$FLOYDW durch einen HASHJOIN (ANTI-SEMI-JOIN mit Bedingung: a.knoteni = x.knoteni and b.knotenj =
x.knotenj ) verbunden. Die entstandene Menge abx wird auf die Spalten für die Ausgabe projiziert und zurückgeliefert.
SELECT-Anfrage des Algorithmus floyd warshall3
Kapitel 4
32
Yvon Regis Tounkap Nkwate
Studienarbeit
SELECT a.knoteni knoteni ,b.knotenj knotenj,a.kanteij kanteij
FROM HANBKG250_EDGE$FLOYDW a
JOIN HANBKG250_EDGE$FLOYDW b on(a.knotenj = b.knoteni )
LEFT OUTER JOIN HANBKG250_EDGE$FLOYDW c
ON (a.knoteni = c.knoteni and b.knotenj = c.knotenj)
WHERE a.knotenj= 531 AND b.knoteni = 531
AND a.knoteni<>b.knotenj AND c.kanteij is null;
Elapsed: 00:00:00.09
Execution Plan
---------------------------------------------------------0
SELECT STATEMENT Optimizer=ALL_ROWS (Cost=127 Card=290 Bytes
=22910)
1
2
3
4
5
0
1
2
3
4
FILTER
HASH JOIN (OUTER) (Cost=127 Card=290 Bytes=22910)
VIEW (Cost=84 Card=290 Bytes=20010)
HASH JOIN (Cost=84 Card=290 Bytes=5220)
TABLE ACCESS (FULL) OF ’HANBKG250_EDGE$FLOYDW’ (TA
BLE) (Cost=42 Card=237 Bytes=1896)
6
4
TABLE ACCESS (FULL) OF ’HANBKG250_EDGE$FLOYDW’ (TA
BLE) (Cost=42 Card=480 Bytes=4800)
7
2
TABLE ACCESS (FULL) OF ’HANBKG250_EDGE$FLOYDW’ (TABLE)
(Cost=42 Card=61006 Bytes=610060)
Statistics
---------------------------------------------------------0 recursive calls
0 db block gets
552 consistent gets
0 physical reads
0 redo size
336 bytes sent via SQL*Net to client
332 bytes received via SQL*Net from client
1 SQL*Net roundtrips to/from client
0 sorts (memory)
0 sorts (disk)
0 rows processed
Kommentar zum Ausführungsplan:
Zunächst wird ein Relationenscan auf die Tabelle HANBKG250 EDGE$
FLOYDW durchgeführt, und die Kopie a erzeugt. Genauso wird die Kopie b erzeugt.
Dann werden a und b durch einen HASH-JOIN (Bedingung: a.knotenj = b.knoteni )
verbunden. Das Ergebnis ist die Kopie ab. Dann wird durch ein Full-Table Scan eine
dritte Kopie c der Tabelle HANBKG250 EDGE$FLOYDW erzeugt. ab und c werden
danach durch HASH-JOIN (LINKER-OUTER-JOIN mit Bedingung a.knoteni =
c.knoteni and b.knotenj = c.knotenj ) verbunden und die Ergebnismenge abc erzeugt.
Anschließend geschieht eine Projektion auf die Spalten der Ausgabe.
Kapitel 4
33
Yvon Regis Tounkap Nkwate
Studienarbeit
Bemerkung:
Die SELECT-Anfrage der Algorithmen verhalten sich (im Endzustand des Graphen) ähnlich, da es nicht viele Unterschiede zwischen den Kosten in den Ausführüngsplänen gibt. Es wurde allerdings festgestellt, daß sich die Ausführungspläne während
der Ausführung der Algorithmen nach einer bestimmten Zeit ändern und somit die
Stichprobe (k = 531) nicht aussagekräftig über die gesamten Laufzeiten ist.
4.2.4
Bereitstellung der Testdaten für die Berechnung
aller kürzesten Wege
Ähnlich wie bei der Erstellung der Tabelle für die Berechnung der transitiven Hülle,
werden die Testdaten für die Berechnung aller kürzesten Wege aus der Tabelle
HANBKG250 EDGE$ entnommen. Die neue Tabelle heißt HANBKG250 EDGE$ALL S PATH. Die Anzahl der Knoten bleibt dieselbe wie bei HANBKG250 EDGE$.
Da es zwischen zwei verschiedenen Knoten zwei (oder mehr) ungerichtete Kanten
mit unterschiedlichen Gewichten geben kann, wird für die Berechnung der kürzesten
Wege selbstverständlich die Kante mit dem kleinsten Gewicht gewählt und natürlich
in beide Richtungen eingetragen.
Da die geometrischen Daten der Tabelle HANBKG250 EDGE$ in einem topologischen Datenmodell liegen, wird für die Berechnung des Gewichts einer Kante die
Funktion: SDO LENGTH(geom IN SDO GEOMETRY, dim IN SDO DIM ARRAY
[, unit IN VARCHAR2]) RETURN NUMBER benötigt. Mit Hilfe dieser Funktion
werden die Gewichte der Kanten bestimmt. Diese Funktion befindet sich im Package
SDO GEOM der Erweiterung Oracle Spatial des DBMS Oracle 10g. Diese Erweitung von Oracle 10g stellt Packages bereit, die Funktionen und Prozeduren enthalten, mit deren Hilfe geometrische Objekte in der Datenbank gespeichert und
angefragt werden können. Das Buch [MC] liefert mehr Informationen über Oracle
Spatial.
Die Prozedur createGraph forALL S PATH, die aus der Tabelle HANBKG250 EDGE$ die Testtabelle HANBKG250 EDGE$ALL S PATH erzeugt, befindet
sich in der elektronischen Abgabe.
4.2.5
Vergleich der Laufzeit der Algorithmen
Allshortestpaths1A/1B/2
Die Prozeduren, die konkret die Algorithmen Allshortestpaths1A/1B/2 implementieren sind auch in der elektronischen Abgabe zu finden. Zu der Testtabelle HANBKG250 EDGE$ALL S PATH gelten vorm Start der Algorithmen folgende statistiken:
• Anzahl unterschiedlicher Knoten: 1228
• Tabellengröße(# Kanten): 3198.
Laufzeit der Prozeduren:
Kapitel 4
34
Yvon Regis Tounkap Nkwate
Studienarbeit
Prozedur
Laufzeit
Allshortestpaths1A 3 Stunden Min 03 Sek
Allshortestpaths1B mehr als 10 Stunden
Allshortestpaths2
1 Stunde 30 Min Sek
Die Testtabelle HANBKG250 EDGE$ALL S PATH enthält im Endzustand
1465330 Kanten. Feststellen kann man, daß der Algorithmus Allshortestpaths2 (LEFT
OUTER JOIN + KURSOR-Variante) wohl die bessere PL/SQL-Implementierung
des “all sources shortest paths problem ”für unvollständig gespeicherte Graphen ist.
Der Allgorithmus Allshortestpaths1B ist am ineffizientesten.
4.2.6
Programmierung
Die PL/SQL-Prozeduren, die die vorgestellten Pseudocode-Algorithmen implementieren, sind in der elektronischen Abgabe zu finden. Viele Operationen wurden
mit Dynamic-SQL-Techniken realisiert.
.
Kapitel 4
35
Kapitel 5
Ausblick
In diesem Kapitel wird eine kritische Situation, die sich ergeben kann beschrieben,
und eine mögliche Lösung geschildert.
Eine Frage, die man sich stellen kann, ist: Würde ein Knoten nach der Berechnung der transitiven Hülle bzw. aller kürzesten Wege ausfallen, müßte man dann
eine komplete neue Berechnung durchführen, um Verbindungen zwischen den Knoten wieder herzustellen? Die Algorithmen jedesmal in solch einer Situation neu zu
starten würde sich für Echtzeitanwendungen (zum Beispiel Navigationssysteme von
Fahrzeugen) als ungeeignete Lösung ergeben.
Eine schnellere Lösung würde etwa so aussehen:
Man könnte die Algorithmen umprogrammieren, sodaß alle mögliche Wege, die es
überhaupt zwischen zwei verschiedenen Knoten geben kann, gespeichert werden.
Man kann diese Idee umsetzen, in dem anstatt neue gefundene k -Pfade mit alten
Verbindungen zu vergleichen, man sie sofort in der Tabelle einfügt. Besser gesagt,
lassen sich zwei Knoten i und j durch einen Weg mit k als Zwischenknoten verbinden, so wird dieser Weg (von i nach j über k ) direkt in der Tabelle (INSERT)
eingefügt, unabhängig davon, ob es einen kürzeren Weg gibt. Diese Methode würde
viel Speicherplatz erfordern (also im schlechtesten Fall: ∀ i, j, k ∈ V i 6= j 6= k
6= i, gilt i kann mit j über k verbunden werden.): O(n3 ) (n.(n-1).(n-2)). Aber die
Laufzeit würde sich kaum ändern, da anstatt UPDATE, INSERT benutzt wird.
Die Methode zur Rekonstruktion der Wege müßte dann umgeschrieben werden.
Also falls etwa Knoten i ausfällt, müssen in der Endtabelle zunächst alle Tupel, die
i als Wert der Spalte knoteni oder knotenj haben, gelöscht werden. Für die Rekonstrüktion des (neuen) kürzesten Weges zwischen k und l, muss in den Methoden
zur Rekonstruktion der Wege, in der Haupt-SELECT-Anfrage zusätzlich die Aggregierungsfunktion MIN(kanteij) eingefügt und eine Gruppierung nach k in jedem
rekursiven Aufruf vorgenommen werden.
Tabellenverzeichnis
2.1
Darstellung des Graphen als Adjazenzmatrix . . . . . . . . . . . . . .
3.1
3.2
3.3
3.4
Darstellung eines Graphen als Relation 1
Graph als Relation 1 . . . . . . . . . . .
Darstellung eines Graphen als Relation 2
Graph als Relation 2 . . . . . . . . . . .
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
7
11
12
12
13
Abbildungsverzeichnis
2.1
2.2
2.3
2.4
2.5
ungerichteter Graph . . . . . . . . . . . . .
gerichteter Graph . . . . . . . . . . . . . . .
gewichteter und gerichteter Graph . . . . . .
Die transitive Hülle G + (rechts) von G(links)
Zwischenknoten k . . . . . . . . . . . . . . .
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
5
6
6
7
8
3.1
3.2
3.3
Beispiel 1 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 11
Beispiel 2 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 13
Graph G . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 24
Literaturverzeichnis
[Tie03] M.Tiedge: Entwicklung und Implematierung einer topologischen Erweiterung für objektbasierte räumliche Datenbanken.
[Li05-06] Udo Lipeck: Vorlesung Datenstrukturen und Algorithmen (WS 2005/06)
http://www.dbs.uni-hannover.de/dsalg0506.html
[MC] Michele Cyran,Paul Lane, JP Polk Oracle Database Concepts, 10g Release 2
(10.2)
c 1993, 2005, Oracle. All rights reserved.
Copyright [CT] Cormen, Thomas H. / Leiserson, Charles E. / Rivest, Ronald L. Algorithmen
– Eine Einführung, Oldenbourg-Verlag, München 2004
Herunterladen