Eine heuristische Verfeinerung zu Dijkstras Algorithmus für mehrere Ziele Christoph Gulden April 2002 Zusammenfassung Wir betrachten ein eine Quelle mehrere Ziele kürzeste Wege Problem (SSMTSP) auf gerichteten Graphen mit nicht-negativen Kantengewichten. Ein Quellknoten s und ein Menge T von Zielknoten sind vorgegeben und das Ziel ist es einen kürzesten Weg von s zu einem Knoten in T zu berechnen. Es wird ein heuristisches Abruchkriterium für den Algorithmus von Dijkstra angegeben, um die Laufzeit zu verbessern. Die gemessenen Einsparungen werden durch stochastische Argumente erläutert. Inhaltsverzeichnis 1 Das 1.1 1.2 1.3 1.4 1.5 SSMTSP-Problem Formalisierung des SSMTSP-Problems . . Unser Beispielgraph . . . . . . . . . . . . Der Algorithmus von Dijkstra . . . . . . . Der Algorithmus von Dijkstra für mehrere Darstellung der Laufzeit . . . . . . . . . . . . . . . . . . . Ziele . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2 Die Heuristik 1 1 1 3 3 3 5 3 Stochastische Analyse 3.1 Das B(n, p)-Modell . . . . . . . . . . . . . . . . . . . . . . . 3.2 Knoten, die aus dem Knotenspeicher entfernt werden . . . . 3.3 Erreichbare Knoten . . . . . . . . . . . . . . . . . . . . . . . 3.4 Knoten, die in den Knotenspeicher eingefügt werden . . . . 3.5 I N R S . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3.6 Einsparungsmöglichkeiten . . . . . . . . . . . . . . . . . . . 3.7 I N R R . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3.8 Abschätzung der eingesparten Knotenspeicher-Operationen . . . . . . . . . . . . . . . . . . . . . . . . 7 9 9 10 11 12 12 13 13 4 Anwendung 13 4.1 Bipartites Matching . . . . . . . . . . . . . . . . . . . . . . . . . 14 4.2 LEDAs Algorithmus . . . . . . . . . . . . . . . . . . . . . . . . . 14 1 1 Das SSMTSP-Problem Wir betrachten in diesem Text Algorithmen, die einen kürzesten Weg in einem Graphen suchen. Dabei ist der Startknoten fest vorgegeben, während der Zielknoten lediglich in einer Menge möglicher Zielknoten liegen muß. Der konkrete Zielknoten für den berechneten kürzesten Weg steht demnach zu Beginn des Algorithmus noch nicht fest. Gegeben: ~ • Ein gerichteter Graph G = (V, E) ~ → R+ • Eine nicht-negative Kostenfunktion cost : E 0 • Ein ausgezeichneter Startknoten s • Eine Knotenmarkierung, die angibt ob ein Knoten frei ist oder nicht (d.h. ob er als Zielknoten zugelassen ist oder nicht) Gesucht: • Ein kürzester Weg von s zu einem freien Knoten Wir betrachten also eine Verallgemeinerung des klassischen kürzeste Wege Problems, da durch die Angabe einer einelementigen Zielknotenmenge das klassische Problem entsteht. 1.1 Formalisierung des SSMTSP-Problems Sei d(v) die Länge eines kürzesten Weges von s nach v, und d0 := min{d(v) : v ist frei } 1 . Unser Ziel ist es folgende Werte zu berechnen: 1. Einen freien Knoten v0 mit d(v0 ) = d0 (oder einen Hinweis, dass kein solcher Knoten existiert) 2. Die Teilmenge V 0 der Knoten mit d(v) < d0 , genauer v ∈ V 0 falls d(v) < d0 und d(v) ≥ d0 falls v ∈ / V0 2 3. Den Wert d(v) für alle Knoten v ∈ {v0 } ∪ V 0 , d.h. eine partielle Abbildung ˜ = d(v) für jedes v ∈ {v0 } ∪ V 0 d˜ mit d(v) Wir bezeichnen das hier gestellte Problem als eine Quelle mehrere Ziele kürzeste Wege Problem (SSMTSP3 ). 1.2 Unser Beispielgraph In Abbildung 1 (Seite 2) sieht man den Beispielgraphen4 der uns durch den Text begleiten wird. Dabei sind der Startknoten mit s, die freien Knoten mit f und 1 Falls kein freier Knoten von s aus erreichbar ist, setze d0 = +∞ Knoten v mit d(v) = d0 können in V 0 sein oder nicht 3 Abkürzung für die englische Bezeichnung: single source many targets shortest path 4 Der Graph wurde speziell gewählt, um die Effekte schon bei einem kleinen Graphen visualisieren zu können 2 Beachte: 1 f 50 12 13 10 9 10 50 30 20 20 f 11 8 10 10 150 50 150 10 10 7 5 10 30 50 100 50 f 6 2 1 10 10 3 4 10 150 s 50 14 Abbildung 1: Beispielgraph mit n = |V | = 15, m = |E| = 22, f = 3. Werte im f ≈ 0.136, c = pn ≈ 1.47. B(n, p)-Modell: p = nm2 ≈ 0.098, q = m die Kanten mit gerichteten Gewichten markiert. An diesem Beispielgraphen werden auch die unterschiedlichen Effekte der betrachteten Algorithmen, sowohl auf das berechnete Ergebnis als auch die benötigte Laufzeit, veranschaulicht. Farbmarkierungen in Ergebnisgrafiken: • Die roten Knotenwerte sind gültige Distanzwerte ⇒ sind in V 0 • Die roten durchgezogenen Kanten bilden den “kürzeste Wege“-Baum • Die blauen Knotenwerte sind vorläufige Distanzwerte • Die blauen gestrichelten Kanten gehören zu vorläufig kürzesten Wegen Farbmarkierungen in Aufwandgrafiken: • Die roten durchgezogenen Kanten erzeugen Insert-Operation auf dem Knotenspeicher5 • Die blauen Knoten werden mit einer Delete Min-Operation aus dem Knotenspeicher entfernt • Die grünen gestrichelten Kanten erzeugen Update Priority-Operationen auf dem Knotenspeicher 5 Der angesprochene Knotenspeicher bezieht sich auf den Algorithmus von Dijkstra in der Formulierung mit einem Knotenspeicher (vgl. nächster Abschnitt) 2 1.3 Der Algorithmus von Dijkstra Das SSMTSP-Problem läßt sich mit dem Algorithmus von Dijkstra lösen, indem man den “kürzesten Wege“-Baum zum Startknoten s berechnet und einen freien Knoten mit minimalem Knotengewicht auswählt. Man sieht den Algorithmus von Dijkstra mit einem Knotenspeicher formuliert, wenn man die beiden blau markierten Zeilen in Abbildung 4 (Seite 5) ignoriert. Hinweise zur Implementierung: • Der Knotenspeicher kann als geeignete Datenstruktur (z.B. Priority Queue) implementiert werden • Der Knotenspeicher muß über entsprechende Operationen Insert, Update Priority und Delete Min verfügen • Der Wert +∞ kann als spezieller Wert (z. B. Wahrheitswert oder undef/nil) implementiert werden In Abbildung 2 (Seite 4) sieht man das Ergebnis bei der Anwendung des Algorithmus von Dijkstra und Abbildung 3 (Seite 4) zeigt die Anzahl der notwendigen Operationen auf dem Knotenspeicher. Beobachtung: Alle Knoten, außer Knoten 14, werden eingefügt und entfernt6 . 1.4 Der Algorithmus von Dijkstra für mehrere Ziele Eine bekannte Beschleunigung für das SSMTSP-Problem liegt nahe. Die Idee dabei ist es den Algorithmus abzubrechen, sobald der erste freie Knoten abgearbeitet wurde. Dieses Abbruchkriterium sieht man in Abbildung 4 (Seite 5) in den Algorithmus von Dijkstra blau eingefügt. Der Algorithmus ist korrekt, da die Knoten in nicht-absteigender Reihenfolge abgearbeitet werden und es wird nur noch eine partielle Distanzfunktion berechnet, die unseren Anforderungen genügt. Abbildung 5 (Seite 6) zeigt das berechnete Ergebnis des Algorithmus von Dijkstra für mehrere Ziele, während Abbildung 6 (Seite 6) wieder den Aufwand an Knotenspeicheroperationen veranschaulicht. Beobachtung: Einige Knoten werden nicht in den Knotenspeicher eingefügt und einige der eingefügten Knoten werden nicht mehr aus dem Knotenspeicher entfernt. 1.5 Darstellung der Laufzeit Sei T die Menge der Knoten, die aus dem Knotenspeicher entfernt werden. Es werden die Kanten, die aus T − 1 Knoten herauslaufen, abgearbeitet und die Laufzeit läßt sich folgendermaßen ausdrücken7 : 6 Knoten 14 wird durch die Suche nicht erreicht Diese Darstellung ist von der gewählten Datenstruktur für den Knotenspeicher 7 Beachte: unahhängig. 3 100 f 50 100 12 10 13 90 10 50 30 20 20 f 11 8 10 90 80 10 50 80 150 10 5 270 6 50 100 50 50 60 2 1 110 70 10 30 120 150 10 7 f 9 150 s 0 10 10 4 3 10 170 50 14 Abbildung 2: Ergebnis bei der Anwendung des Algorithmus von Dijkstra f 50 12 13 10 9 10 50 30 20 20 f 11 8 10 150 10 50 150 10 10 7 5 10 30 50 100 50 f 6 2 1 10 10 3 4 10 150 s 50 14 Abbildung 3: Aufwand für den Algorithmus von Dijkstra: 14 Insert, 3 Update Priority, 14 Delete Min 4 Algorithmus von Dijkstra für mehrere Ziele Für alle v ∈ V führe aus: Setze pred[v] = nil, dist[v] = +∞ Setze dist[s] = 0 Füge s mit Priorität 0 in S ein Solange S 6= ∅ führe aus: Entferne v mit minimaler Priorität aus S Falls v frei ist dann: Breche ab Für alle e = (v, w) ∈ E führe aus: Setze c = dist[v] + cost[e] Falls pred[w] == nil und w 6= s dann: Füge w mit Priorität c in S ein Setze dist[w] = c, pred[w] = v Ansonsten, falls c < dist[w] dann: Setze die Priorität von w auf c Setze dist[w] = c, pred[w] = v Abbildung 4: Algorithmus von Dijkstra für mehrere Ziele O(1 + X (1 + outdeg(u)) + Q) u∈T \{v0 } Dabei bezeichnet Q die Anzahl der notwendigen Operationen auf dem Knotenspeicher. Die Operationen auf dem Knotenspeicher setzen sich aus |I| Insert-, |T | Delete Min- und einigen Update Priority-Operationen zusammen. Die Laufzeit um die pred- und dist-Werte zu initialisieren ist O(n). 2 Die Heuristik Die Heuristik fügt nun nur noch solche Knoten in den Knotenspeicher ein, die einen kürzesten Weg zu einem freien Knoten liefern können. Dazu werden alle Knoten ignoriert, deren Distanz nicht kleiner sein kann als der vorläufig kürzeste Weg zu einem freien Knoten. In Abbildung 7 (Seite 7) sieht man den Algorithmus von Dijkstra für mehrere Ziele mit blau eingefügter Heuristik. Die vorläufig kürzeste Entfernung zur Menge der freien Knoten wird gespeichert und es werden alle Knoten ignoriert, die schon zu weit vom Startknoten entfernt sind. Falls ein freier Knoten bearbeitet wurde, wird dieser Wert neu gesetzt. Der verfeinerte Algorithmus ist korrekt, da die Knoten wieder in nicht-absteigender Reihenfolge abgearbeitet werden und alle Knoten betrachtet werden, die einen kürzesten Weg zu einem freien Knoten liefern können. In Abbildung 8 (Seite 8) sieht man das berechnete Ergebnis für den Algorithmus von Dijkstra für mehrere Ziele mit eingefügter Heuristik und Abbildung 9 (Seite 8) zeigt den Aufwand bei Anwendung dieser Verfeinerung. 5 f 50 100 12 100 9 20 30 20 80 f 11 8 10 150 10 80 10 7 5 70 6 10 30 50 50 60 2 1 110 120 150 10 50 f 90 10 50 90 10 13 150 s 0 10 100 50 10 4 3 10 50 14 Abbildung 5: Ergebnis bei der Anwendung des Algorithmus von Dijkstra für mehrere Ziele f 50 12 13 10 9 10 50 30 20 20 f 11 8 10 150 10 50 150 10 10 7 5 10 30 50 100 50 f 6 2 1 10 10 3 4 10 150 s 50 14 Abbildung 6: Aufwand für den Algorithmus von Dijkstra für mehrere Ziele: 12 Insert, 3 Update Priority, 8 Delete Min 6 Algorithmus von Dijkstra für mehrere Ziele mit eingefügter Heuristik Setze upper bound = +∞ Für alle v ∈ V führe aus: Setze pred[v] = nil, dist[v] = +∞ Setze dist[s] = 0 Füge s mit Priorität 0 in S ein Solange S 6= ∅ führe aus: Entferne v mit minimaler Priorität aus S Falls v frei ist dann: Breche ab Für alle e = (v, w) ∈ E führe aus: Setze c = dist[v] + cost[e] Falls c < upper bound dann: Falls pred[w] == nil und w 6= s dann: Füge w mit Priorität c in S ein Setze dist[w] = c, pred[w] = v Ansonsten, falls c < dist[w] dann: Setze die Priorität von w auf c Setze dist[w] = c, pred[w] = v Falls v frei ist dann: Setze upper bound = c Abbildung 7: Algorithmus von Dijkstra für mehrere Ziele mit eingefügter Heuristik Beobachtung: Es werden wiederum weniger Insert- und Delete Min-Operationen ausgeführt. 3 Stochastische Analyse Wir betrachten folgende Werte für zufällige Grafen: • Die Anzahl der Knoten die entfernt werden, wenn die Anzahl der erreichbaren Knoten bekannt ist • Die Anzahl der erreichbaren Knoten • Die Anzahl der Knoten, die im Standard-Schema8 eingefügt aber nicht entfernt werden (INRS9 ) • Die Anzahl der Knoten, die im verfeinerten Schema10 eingefügt aber nicht entfernt werden (INRR11 ) • Eine untere Schranke für die Anzahl der eingesparten (Knotenspeicher-)Operationen 8 Algorithmus 9 Abkürzung von Dijkstra für mehrere Ziele für die englische Bezeichnung: inserted but never removed in the standard scheme 10 Algorithmus von Dijkstra für mehrere Ziele mit eingefügter Heuristik 11 Abkürzung für die englische Bezeichnung: inserted but never removed in the refined scheme 7 f 100 50 12 13 10 90 10 50 30 20 20 f 11 90 9 80 8 10 150 10 50 150 10 10 7 5 70 6 80 10 30 50 50 f 1 2 60 10 4 3 10 150 120 10 100 50 s 0 50 14 Abbildung 8: Ergebnis bei der Anwendung des Algorithmus von Dijkstra für mehrere Ziele mit eingefügter Heuristik f 50 12 13 10 9 10 50 30 20 20 f 11 8 10 150 10 50 150 10 10 7 5 10 30 50 100 50 f 6 2 1 10 10 3 4 10 150 s 50 14 Abbildung 9: Aufwand für den Algorithmus von Dijkstra für mehrere Ziele mit eingefügter Heuristik: 10 Insert, 1 Update Priority, 7 Delete Min 8 Das B(n, p)-Modell 3.1 Definitionen:12 n = |V | : Anzahl der Knoten in G m = |E| : Anzahl der Kanten in G f m n2 m c = pn = n f q= n p= : Anzahl der freien Knoten in G : Wahrscheinlichkeit, dass eine mögliche Kante in G vorhanden ist : Erwarteter Knotengrad : Wahrscheinlichkeit, dass ein Knoten frei ist Wir sind an dem Fall interessiert, dass p = c/n für eine kleine Konstante c (z.B. 2 ≤ c ≤ 10) und q eine Konstante ist. Falls wir nur unendliche Graphen hätten und jeder Knoten von s aus erreichbar wäre, so wäre die erwartete Anzahl der entfernten Knoten 1/q. Unsere Graphen sind jedoch endlich (dies ist für großes n unerheblich) und nur eine Teilmenge der Knoten ist von s aus erreichbar. Bemerkung: Die Wahrscheinlichkeit, daß s keine ausgehenden Kanten hat, beträgt (1 − p)n ≈ e−c . 3.2 Knoten, die aus dem Knotenspeicher entfernt werden Das folgende Lemma enthält eine Aussage über die Anzahl der Knoten die aus dem Knotenspeicher entfernt werden, wenn die Anzahl der erreichbaren Knoten bekannt ist. Lemma 1 Sei R die Anzahl der Knoten, die von s aus in G erreichbar sind, und sei T die Anzahl der Iterationen, d.h. in Iteration T wird der erste freie Knoten aus der Queue entfernt. Falls kein freier Knoten von s aus erreichbar ist, T = R. Dann gilt: ½ (1 − q)t−1 q falls 1 ≤ t < r, Pr (T = t|R = r) = (1 − q)t−1 falls t = r. Darüberhinaus erhalten wir für die erwartete Anzahl der Iterationen: E[T |R = r] = 1 (1 − q)r − . q q Bemerkung: Die erwartete Anzahl von bearbeiteten Kanten ist ≈ ((1/q) − 1)(m/n), da ausser beim letzten Knoten alle c Kanten abgearbeitet werden. 12 Die Werte sind bei Abbildung 1 (Seite 2) für unseren Beispielgraphen angegeben 9 Beweis Da jeder Knoten mit der Wahrscheinlichkeiten q = f /n frei ist und da die Eigenschaft frei zu sein unabhängig von der Reihenfolge, in der die Knoten aus der Queue entfernt werden, ist, erhalten wir Pr(T = t|R = r) = (1 − q)t−1 q und Pr(T ≥ t|R = r) = (1 − q)t−1 , für 1 ≤ t < r. Falls t = r, Pr(T = t|R = r) = (1 − q)r−1 = Pr(T ≥ r|R = r). Die erwartete Anzahl der Iterationen ist: X E[T |R = r] = Pr(T ≥ t|R = r) t≥1 = X (1 − q)t−1 + (1 − q)r−1 1≤t<r = = 1 − (1 − q)r 1 − (1 − q) 1 (1 − q)r − . q q ¤ 3.3 Erreichbare Knoten Sei α > 0, so dass α = 1 − e−cα erfüllt ist, und R die Anzahl der von s aus erreichbaren Knoten. Dann gilt: Für jedes ² > 0 und δ > 0 gibt es ein t0 , so dass für alle genügend großen n gilt: 1 − α − 2² ≤ Pr(R ≤ t0 ) ≤ 1 − α + ² und α − 2² ≤ PR((1 − δ)αn < R < (1 + δ)αn) ≤ α + 3² Dann ist R mit der Wahrscheinlichkeit 1 − α durch eine Konstante beschränkt und mit Wahrscheinlichkeit α ungefähr nα. In Tabelle 1 (Seite 10) sieht man experimentelle Ergebnisse für Zufallsgraphen c α MS ML R F 2 0.7968 15 714 796.5 7958 5 0.993 2 981 993 9931 8 0.9997 1 996 999.7 9997 8 0.9997 1 1995 1999.3 9995 Tabelle 1: Experimentelle Ergebnisse für die Anzahl der erreichbaren Knoten bei 10.000 Zufallsgraphen mit 1.000 Knoten bei unterschiedlichen Ausgangswerten. Interpretation: Die Menge der Zufallsgraphen zerfällt also in zwei Klassen: 10 entweder sind viele (ML) oder wenige (MS) Knoten von einem gegebenem Startknoten aus erreichbar. Diese Eigenschaft von Zufallsgraphen wird in [2] detailliert behandelt. Wir interessieren uns im folgenden lediglich für den ersten Fall, d. h. R ≈ (1 − δ)αn. Die Wahrscheinlichkeit, dass alle erreichbaren Knoten aus dem Knotenspeicher gelöscht werden, ist ≈ (1 − q)αn = exp(αn ln(1 − q)) ≈ exp(−αnq) = exp(−αf ) Dies ist weniger als 1/n2 , falls c ≥ 2 und f ≥ 4 ln(n). Wir verwenden die Sprechweise “R und f sind groß“, um auf diese Annahme hinzuweisen. 3.4 Knoten, die in den Knotenspeicher eingefügt werden Das folgende Lemma enthält eine Aussage über die Anzahl der Knoten die im Algorithmus von Dijktra für mehrere Ziele in den Knotenspeicher eingefügt werden. Lemma 2 Sei IS die Anzahl der Einfügungen im Standard-Schema. Dann gilt: E[IS|T = t] = n − (n − 1)(1 − p)t−1 und E[IS|R und f sind groß ] = c(1 − q) (1 − q)c/n − + 1 + o(1) q + (1 − q)c/n q + (1 − q)c/n Bemerkungen: • E[IS|R und f sind groß ] ≈ c q − c + 1 + o(1), falls c n << q • Intuitive Erklärung: Es werden die Kanten aus 1/q−1 Knoten und entfernt und es werden durchschnittlich c Kanten pro Knoten betrachtet • Für großes n gibt es immer weniger Überschneidungen unter den Zielknoten dieser Kanten • Die Anzahl der Einfüge-Operationen ist ungefähr c q −c+1 Beweis Im Standard-Schema wird jeder Knoten, der durch die Suche erreicht wird, in die Queue eingefügt. Falls wir insgesamt t Elemente aus der Queue entfernen, werden die herauszeigenden Kanten von (t − 1) Elementen gescannt. Ein Knoten v, v 6= s, ist nicht-erreichbar, falls keiner dieser (t−1) Knoten eine Kante nach v hat. Die Wahrscheinlichkeit, dass dies eintritt, ist (1 − p)t−1 und damit ist die erwartete Anzahl E[IS|T = t] erreichbarer Knoten n − (n − 1)(1 − p)t−1 . Dies ist also die erwartete Anzahl von Einfügungen in die Queue im StandardSchema. Falls R und f groß sind, erhalten wir: 11 E[IS|R und f sind groß ] = = R P t=1 P E[IS|T = t und R und f sind groß ]Pr(T = t|R und f sind groß ) (n − (n − 1)(1 − p)t−1 )(1 − q)t−1 q t≥1 = = +(n − (n − 1)(1 − p)R−1 )(1 − q)R−1 P − (n − (n − 1)(1 − p)t−1 )(1 − q)t−1 q Pt≥R (n − (n − 1)(1 − p)t−1 )(1 − q)t−1 q + o(1) t≥1 P n − q(n − 1) (1 − q)t (1 − p)t + o(1) t≥0 1 = n − q(n − 1) 1−(1−p)(1−q) + o(1) q = n − 1 − (n − 1) p+q−pq + 1 + o(1) p−pq = (n − 1) p+q−pq + 1 + o(1) c(1−q) (1−q)c/n = q+(1−q)c/n − q+(1−q)c/n + 1 + o(1) ≈ c q − c + 1 + o(1). ¤ 3.5 INRS Indem man nun die Differenz der Ergebnisse aus den beiden vorhergehenden Lemmas bildet, erhält man eine Abschätzung für die Anzahl der Knoten die im Algorithmus von Dijkstra für mehrere Ziele in den Knotenspeicher eingefügt jedoch nicht entfernt werden. E[INRS|R und f sind groß] ≈ c q −c+1− 1 q ≈ c−1 q An dieser Stelle kann die Verfeinerung Laufzeit einsparen. 3.6 Einsparungsmöglichkeiten 1. Knoten, die aus der Queue entfernt werden, können weniger Queue-Operation nach sich ziehen, da sie später eingefügt werden oder weil einige Herabsetzung der Entfernung nicht zu einer Queue-Operation führen 2. Knoten die im Standard-Schema niemals aus der Queue entfernt werden, werde im verfeinerten Schema nicht eingefügt 3. Knoten die im Standard-Schema niemals aus der Queue entfernt werden, werde das verfeinerte Schema eingefügt, führen aber zu weniger Herabsetzungen der Entfernungsangaben und damit zu weniger Queue-Operationen Die Einsparung 2.) ist bemerkbar und wird weiter unten abgeschätzt. Die Einsparungen 1.) und 3.) werden hier nicht weiter betrachtet, da die Anzahl der Update Priority-Operationen gering ist13 . 13 Beachte, dass nur wenige einlaufende Kanten pro Knoten bearbeitet werden 12 3.7 INRR Sei El das Ereignis, dass im Algorithmus von Dijkstra mit mehreren Zielen genau l Knoten eingefügt, aber nicht entfernt, werden. Für die erwartete Anzahl der Knoten die die eingefügt aber nicht entfernt werden, ergibt sich - in Abhängigkeit von dem Ereignis El : E[IN RR|El ] ≤ 1q (1 + ln(lq)) 3.8 Abschätzung der eingesparten Knotenspeicher-Operationen Damit erhalten wir eine untere Schranke für die Anzahl der eingesparten Operationen auf dem Knotenspeicher: c−1 1 − (1 + ln(c − 1)) q q 2 + ln c c (1 − ). ≈ q c E[S|R und f sind groß ] ≥ c q IN RS IN RS ∗ IN RR IN RR∗ 2 0.02 40.41 40.16 11.00 39.05 5 0.06 56.99 56.90 12.00 37.13 8 0.18 30.85 30.57 5.00 15.03 Tabelle 2: Es wurden Durchschnittswerte für die Anzahl der Knotenspeicheroperationen bei 10.000 Zufallsgraphen mit 1.000 Knoten im Experiment (siehe [1]) ermittelt. In Tabelle 2 (Seite 13) sieht man Auszüge aus experimentellen Ergebnissen (IN RS, IN RR) im Vergleich mit den berechnet Werten (IN RS∗, IN RR∗) für verschiedene Ausgangswerte. Bemerkung: Falls nur wenige Werte erreichbar waren, wurden die Werte ignoriert (d.h. es wurden (1 − α)n Durchläufe ignoriert). 4 Anwendung In [1] wird beschrieben, daß die hier betrachtete Heuristik für den “bipartiten Matching“-Algorithmus der LEDA-Bibliothek implementiert und in die Version 4.3 aufgenommen wurde. 13 4.1 Bipartites Matching Gegeben: ˙ E) • Bipartiter Graph G = (A∪B, • Kantengewichtsfunktion w : E → R Gesucht: • Perfektes Matching mit maximalem Gewicht 4.2 LEDAs Algorithmus Der Algorithmus unterhält folgende Werte: • Ein Matching M , das zu Beginn leer ist • Eine Potentialfunktion π : V → R, mit – w(e) ≤ π(a) + π(b) für jede Kante e = (a, b) – w(e) = π(a) + π(b) für jede Kante e = (a, b) ∈ M – π(b) = 0 für jeden freien Knoten b ∈ B Zu Beginn gilt: π(a) = maxe∈E w(e) für jedes a ∈ A und π(b) = 0 für jedes b ∈ B. Der Algorithmus sucht erhöhende Wege mit minimalen Reduzierungskosten, von freien Knoten in A zu freien Knoten in B, deren Kanten abwechselnd in M und nicht in M sind. Jede Suche nach einem solchen Weg entspricht dem Lösen eines SSMTSP-Problems und vergrößert dadurch das Matching um eine Kante. Ein gewichtetes bipartites Matching für einen Graphen, mit n Knoten auf jeder Seite, reduziert sich damit auf n SSMTSP Probleme, wobei die Anzahl der Ziele absteigend Werte zwischen n und 1 annimmt. Mehlhorn und Schäfer berichten in [1] von einer Beschleunigung um bis zum Faktor zehn durch die Anwendung der hier beschriebenen Heuristik. Literatur [1] Kurt Mehlhorn und Guido Schäfer A Heuristic for Dijktra’s Algorithm with Many Targets and its Use in Weighted Matching Algorithms. In 9th Annual European Symposium on Algorithms. Springer, 2001. [2] Noga Alon und Joel Spencer The Probabilistic Method. Second Edition. John Wiley, 2000. [3] Norbert Henze Stochastik für Einsteiger. 3. Auflage. Vieweg Verlag, 2002. 14