Worum geht es? Ziel Voraussetzungen: Vorgehensweise

Werbung
Seminararbeit über
„Near-optimal fully-dynamic graph connectivity“ (M. Thorup)
von David Iwanowitsch
Worum geht es?
Anfragen der Form connected(v,w) an den Graphen sollen beantworten, ob es einen Pfad zwischen
den Knoten v und w gibt.
Zwischen den Anfragen können im Graph Kanten gelöscht und hinzugefügt werden.
Ziel
Die bisherige Update-Zeit für Lösch- und Einfügeoperationen Olog n ² soll auf
O log nlog log n ³ erwartete amortisierte Zeit verbessert werden.
Verbindungsanfragen können dann in O log n/log log log n Zeit beantwortet werden.
Die erreichte Komplexität ist nur um einen doppelt logarithmischen Faktor größer, als die
allgemeine untere Schranke für Cell-Probe-Probleme log n /log log n .
Voraussetzungen:
Graph G mit fester Knotenmenge V, ∣V∣=n .
G kann verändert werden, durch das Einfügen und Entfernen von Kanten
Im Normalfall wird mit einer leeren Kantenmenge gestartet.
Zwischen den Änderungen kann es zu Verbindungsanfragen kommen:
connected(v,w) liefert ob die beiden Knoten über einen Pfad verbunden sind.
Vorgehensweise:
Das Problem wird reduziert auf das Problem einen Spannenden Wald über den Graphen zu legen
und zu warten..
Wird der Baum in Ot  nlog n erzeugt, ist es über diesen möglich, mit Hilfe dynamischer
Bäume Verbindungsanfragen in O log n/log t n zu beantworten.
Konkret wird t n=log log n ³ erreicht.
Startpunkt ist der Algorithmus von Holm, de Lichtenberg und Thorup, zu dem gezeigt wird, wie
man die Baumoperationen besser organisieren und verarbeiten kann.
Algorithmus nach Holm et al.
Über den Graph G wird ein Spannender Wald F gelegt, dessen Kanten wir „Baumkanten“ nennen.
Mit jeder Kante e wird ein Level l e ≤l max=log 2 n  verbunden.
Gi ist der Teilgraph, bestehend aus allen Kanten mit l≥i . Fi analog.
Es gelten folgende Invarianten:
1) F ist maximaler (in Bezug zu l), spannender Wald von G, Fi ist spannender Wald von Gi
2) Die maximale Anzahl von Knoten in Gi (Fi) ist abgerundet(n/2i). Daher ergibt sich lmax.
David Iwanowitsch
14.05.2008
Seite 1 von 4
Initial haben alle Kanten Level l=0. Die Amortisation geschieht über das Erhöhen der Level.
Ein Level wird nur bei der Löschung verkleinert.
Algorithmus
– Insert(e): l(e):=0, Wenn die Endpunkte in F0 noch nicht verbunden sind wird e zu F0 zugefügt.
(1)(2) bleiben erfüllt.
– Delete(e): Wenn e keine Baumkante ist, wird sie gelöscht, sonst wird Replace(e) aufgerufen
– Replace(e=(v,w)): Nach (1) muss eine Ersetzungskante mindestens Level l(e) haben
Seien Tv und Tw die beiden Bäume in die Fl(e) zerfällt. Wir suchen eine Kante, die beide
verbindet.
Sei Tv der kleinere Baum.
Für alle nicht-Baumkanten in Tv: Wenn beide Enden in Tv liegen: Level erhöhen als
„Bezahlung“.
Wenn nicht, ist die Kante die gesuchte und wird ersetzt. Fertig.
Wenn keine Level l(e) Kante gefunden wird: Rekursion mit um eins verkleinertem l(e), bis l=0,
dann Ende.
Algorithmus anpassen
1) Passende Ersetzungskante finden
G, F wie bei Holm
Es wird ein gewurzelter Wald C erstellt, dessen Blätter den Knoten in G entsprechen.
Level l entspricht der Tiefe eines Knotens. Jeder Knoten a in C erhält eine Größe n a  , die der
Anzahl von Nachfolgenden Blättern entspricht.
v i entspricht dem Vorgänger von v, der l max – i Schritte oberhalb im Baum liegt.
Zwei Knoten in C können Zusammengefasst werden, wenn sie entweder Geschwister oder beide
Wurzeln sind. Knoten a und b zusammenfassen bedeutet, die Kinder von b an a zu hängen.
1.1) C aktualisieren
Werden nicht-Baumkanten gelöscht/eingefügt, ändert C sich nicht.
Baumkanten einfügen führt zum Zusammenfassen der Wurzeln beider Teilbäume, die neue Größe
des Baumes entsteht dabei durch Addition.
Baumkanten löschen: Ersetzungskante mit gleichem Level i suchen, dabei werden die Level der
Kanten erhöht, Sei (x,y) ein solche Kante. Das bedeutet für C, das die Knoten x i1 und y i y
zusammengefasst werden.
Wenn eine Kante gefunden wurde: das Ersetzen betrifft C nicht.
Wenn keine Kante gefunden wurde: Bäume werden gesplittet und in höherer Ebene eingefügt.
2) Um Suchen nach (nicht-)Baumkanten durchzuführen wird C erweitert
Zwischen jeden Knoten a in C und seine Kinder wird ein balancierter Binärbaum L(a) eingefügt.
Der erhaltene Baum heißt CL, hat Tiefe O(log n).
 In O(log n) lässt sich von einem Blatt zur Wurzel traversieren.
 Eine Kante (v,w) kann als Baumkante identifiziert werden durch Prüfen von v0=w0 in
O log n . Analog kann man Ersetzungskanten auf ihre Eignung testen.
Für jeden Knoten a in CL werden zwei Bitmaps erzeugt: tree(a) und nontree(a), die für jeden Level i
enthalten, ob es ein nachfolgendes Blatt gibt, das eine angrenzende Baum- bzw. nicht-Baumkante
hat.
David Iwanowitsch
14.05.2008
Seite 2 von 4
 Für jeden Knoten in G haben wir jetzt die Informationen, ob angrenzende Kanten mit
bestimmtem Level existieren die Baum- bzw. nicht-Baumkante sind.
 Da es max. 2log n Bitmaps an den Blättern gibt, kann man diese über einen Suchbaum in
O log log n erreichen.
 Wir können in O log n Zeit zu einem beliebigen Knoten in CL herausfinden, ob es an den
Blättern angrenzende Baumkanten gibt oder nicht.
3) Maßgeschneiderte Datenstruktur
Jedem Knoten b wird ein rang b=log nb  zugeordnet
Greedy-Algorithmus für die Kinder eines Knotens b:
Start: Jedes Kind ist Wurzel
Solange zwei Knoten den gleichen Rang r haben: beide werden unter einer neuen Wurzel
zusammengefasst. Die neue Wurzel hat Rang r+1.
Die höchstens log n Wurzeln werden über einen Pfad P verknüpft: von b in absteigender RangReihenfolge.
3.1) Anpassung der Methoden
Merging: Wir schneiden beide Teilbäumen ab, so dass wir 2log n Wurzeln erhalten, diese werden
nach Rang-Größe gemerged und wieder über einen Pfad an den übergeordneten Knoten
gehangen.
Adding: Wie Merging, nur das der eine Teil nur aus dem neuen Knoten besteht.
Removing (a von b): Wir entfernen den Pfad P von b, und erhalten eine Liste von Teilbäumen mit
Rängen, suchen daraus den Teilbaum der a enthält, entfernen dort den Pfad von a zur Wurzel
und erhalten wieder eine Menge von Teilbäumen mit Rang. Diese beiden Mengen werden
gemerged.
Bitmaps updaten: Bei Änderungen an der Baumstruktur müssen die Bitmaps aktualisiert werden.
Bei den obigen Operation werden je O(log n) Knoten verändert. Die Aktualisierung erfolgt
von unten nach oben:
Jedes Update ist ein bitweises 'oder' zwischen beiden Kindern.
→ Jeder Implementierungsteil braucht O(log n) Zeit pro Leveländerung, von denen wir O(log n)
pro Kante haben (amortisiert).
→ Pro Kante brauchen wir Olog n2  Zeit (amortisiert).
4) Von log(n) nach log log n
4.1) Lokale Bäume aufbauen
L(a) ist der binäre Baum, mit dem C^L gebaut wurde.
Sei B die Menge von Kindern von einem Knoten a aus C. Die Kinder werden in Gruppen mit
maximaler Größe 2 log n aufgeteilt (α>2 konstant). Über jede Gruppe kann man per
Standardsuchbaum in O log log n Zeit suchen.
Analog zum vorherigen Abschnitt werden die Suchbäume nach Rang paarweise zusammengefasst
und formen so einen neuen Suchbaum, dessen Operationszeit immer noch O log log n ist.
→ aus den Abschnitten 3) und 4.1) ergibt sich eine Höhe von O log n log log n für CL.
David Iwanowitsch
14.05.2008
Seite 3 von 4
Für jeden so entstandenen Baum gibt es eine Bitmap, die die Ränge der darunter liegenden Bäume
enthält. Bei einem Merge können so gemeinsame Ränge schnell gefunden werden.
4.2) Angrenzende Kanten finden
Ziel: Schnelles finden einer angrenzenden Kante mit passendem Level, von einem Knoten in CL
aus.
Jeder Knoten enthält eine Power p≤2log log n .
– Innere Knoten der Suchbäume aus (4.1) erhalten p=0.
– Sonst, wenn der Rang eines Knotens >0 ist, ist p = Bit mit dem niedrigsten Stellenwert von i.
– Wenn Rang = 0 ist: p = log log n.
Sei a ein Vorgänger von b: alle Knoten von a bis b haben Power qmin pa  , p b , dann ist
(a,b) eine Abkürzung mit Power q.
Der maximale Pfad von a nach b liegt jetzt in O log log n , da inneren Suchbäumen
übersprungen werden können.
Da es maximal O(log n) Abkürzungen zu einer angrenzenden Kante gibt, kann man die passende
Abkürzung über einen Suchbaum in O log log n Zeit finden.
=>Wir können über die Abkürzungen in Olog log n2  Zeit zu einer gewünschten Kante
wandern.
4.2.1) Anpassung der Abkürzungen
Dazu werden die Abkürzungen von Level i in den i+1-Teilbaum gemerged.
Löschen/Einfügen: in CL werden durchgeführt, indem für den einzufügende/zu löschenden Knoten
gefordert wird, dass p=0 ist. Dazu wird die Power kleiner gepusht, indem darunter liegende
Abkürzungen neu aufgebaut werden.
Merging: Die zusammenzufassenden Knoten müssen p=0 haben, daher muss man nur die inneren
Abkürzungen beachten. Da Abkürzungen aber nicht über die Rang-Wurzeln hinaus gehen,
muss man nur aktualisieren, wenn eine neue Wurzel erstellt wird bzw. eine bestehende
gelöscht wird.
Da wir dann nur den Pfad entlang gehen müssen um Abkürzungen zu entfernen/erstellen ist das
auch in Olog log n2  Zeit möglich.
5) Abschluss
Zu guter Letzt müssen die Kanten von G beachtet werden, die nicht im Spannbaum liegen.
Dazu müssen die Abkürzungen um ein Gewicht erweitert werden, das die Anzahl der darunter
liegenden angrenzenden Baumkanten enthält.
Dieses wird entlang der Abkürzungen in Olog log n2  Schritten aktualisiert. Da es
O log log n Abkürzungen gibt, die berücksichtigt werden müssen, braucht die
Gewichtsaktualisierung Olog log n3 Zeit.
Pro Kantenleveländerung werden also Olog log n3 Kosten verursacht.
Daraus ergibt sich eine amortisierte Zeit pro Update von O log nlog log n3  .
David Iwanowitsch
14.05.2008
Seite 4 von 4
Herunterladen