Dijkstra's Algorithmus auf riesigen Graphen


15

Ich bin mit Dijkstra sehr vertraut und habe eine spezielle Frage zum Algorithmus. Wenn ich einen riesigen Graphen habe, zum Beispiel 3,5 Milliarden Knoten (alle OpenStreetMap-Daten), kann ich den Graphen nicht im Speicher haben, also wird der Graphen auf einer Festplatte in einer Datenbank gespeichert.

Es stehen Bibliotheken zur Verfügung, mit denen kürzeste Pfade für solche Diagramme berechnet werden können. Wie machen sie das? Wie laden sie den erforderlichen Teil des Diagramms, um den Dijkstra-Algorithmus auszuführen?

Das Abrufen der Adjazenzliste jedes besuchten Scheitelpunkts würde nach meinen statistischen Daten ungefähr 1.500 Datenbankabfragen pro 10.000 Knoten erfordern, so dass es eindeutig nicht so ist, wie sie es tun. Das wäre viel zu langsam.

Wie machen Sie das? Ich versuche es selbst umzusetzen.


2
Sind Sie sicher, dass sie Dijkstra verwenden? Es gibt viele andere Algorithmen für kürzeste Wege, die möglicherweise besser für die von Ihnen beschriebene Situation geeignet sind.
David Richerby

1
Hast du in den Code geschaut? Woher sollen wir das wissen? "Datenbankabfragen" - Ich hoffe, Sie verwenden kein DBMS zum Speichern von Grafiken?
Raphael

@ David Richby ja, ich bin sicher, schauen Sie sich diesen Link
dimitris93

2
"[I] t wäre ein extrem mühsamer Prozess, um in reinen C-Code zu schauen." Aber nur so kann man wissen, was der Code tut. Also bitten Sie uns nur, Ihre mühsame Aufgabe für Sie zu erledigen, was nicht die
beste

1
@Shiro Sie fragen ausdrücklich: "Wie machen sie das?" Wenn das nicht wirklich die Frage ist, die Sie stellen möchten, müssen Sie sie umformulieren.
Raphael

Antworten:


6

Es stehen Bibliotheken zur Verfügung, mit denen kürzeste Pfade für solche Diagramme berechnet werden können. Wie machen sie das? Wie laden sie den erforderlichen Teil des Diagramms, um den Dijkstra-Algorithmus auszuführen?

Sie können eine Datenbank, ein benutzerdefiniertes Dateiformat zum Lesen von Datenträgern und eine speicherinterne Einstellung verwenden.

Nach meiner Erfahrung ist die Verwendung einer Datenbank jedoch ungefähr 5- bis 10-mal langsamer und speicherintensiver als das Schreiben eines eigenen Dateiformats auf der Grundlage eines "einfachen" Formats für verknüpfte Listen.

Das Gute ist, dass es mehrere Open-Source-Software-Frameworks mit OSM gibt, so dass Sie direkt in den Code hineinschauen können (siehe hier) . In der Open-Source-Routing-Engine von GraphHopper ist es sehr einfach, von einer Einstellung für die Speicherzuordnung (auf Disc-Basis) auf die Einstellung für den internen Speicher umzuschalten - beide verwenden dasselbe Format. Die "mmap" -Einstellung ermöglicht sogar die Verwendung auf speicherbeschränkten Mobilgeräten. Letztere ist wesentlich schneller, wenn Sie über den erforderlichen Arbeitsspeicher verfügen, z. B. auf einem Server. ZB für einen weltweiten Graphen (> 100 Millionen Knoten) benötigen Sie dann ungefähr 8-10 GB RAM, plus viel mehr RAM, wenn Sie alles weiter beschleunigen möchten, z. B. mit Kontraktionshierarchien - ungefähr 5-8 GB mehr für jedes Fahrzeug, das Sie möchten.

Das Format ist sehr simpel und speichert im Grunde nur die Daten, die Sie mit ein paar Tricks benötigen, um es kompakt zu machen. Lesen Sie hier mehr darüber . Haftungsausschluss: Ich bin der Autor von GraphHopper.

Zu den anderen Antworten:

Der anwendbare Dijkstras-Algorithmus wird für dieses Problem als nicht optimal angesehen

Der "normale" Dijkstra kann eine sehr vernünftige Leistung erbringen (<1s für landesweite Abfragen wie Ihr 3-Millionen-Knoten-Beispiel) und ist im "theoretischen Sinne" optimal , benötigt jedoch eine gewisse Anpassung , um in Produktionsszenarien schnell zu werden. Und Techniken wie Kontraktionshierarchien verwenden eine bidirektionale Modifikation davon und arbeiten sehr gut.

Straßennetze sind hierarchisch und planar.

Straßennetze sind nur für Autos hierarchisch und nicht eben (Brücken, Tunnel, ...)


Ich habe noch eine Frage. Wie finden Sie NodeIDden nächstgelegenen Knoten von der latitude/longitude? Dies ist erforderlich, um den kürzesten Pfad A-> B zu berechnen. Und wir müssen auch berücksichtigen, dass A und B möglicherweise nicht als Knoten existieren, da nicht jeder Quadratmeter einen Knoten enthält. Also müssen wir die 2 nächsten NodeIDs von A und B finden
dimitris93 29.03.16

Dies geschieht im LocationIndexTree, einer Art Quadtree, in dem die NodeIDs in einer Zelle, die zB für GraphHopper einen Radius von ~ 500 m hat, effizient gespeichert werden. Wenn nichts gefunden wird, wird der Radius bis zu einem gewissen Grad erweitert. Dies klingt theoretisch einfach, ist aber sehr komplex, da Sie möglicherweise Kanten haben, die den Bereich kreuzen. Sie müssen effizient beim Erstellen und Abfragen und vieles mehr sein.
Karussell

Sind KD-Bäume nicht effizienter bei der Suche nach dem nächsten Nachbarn? Warum hast du QuadTrees gegenüber KD-Trees gewählt? Ich implementiere gerade KD-Trees für meine Routing-Engine. Ich habe angefangen, QuadTrees zu implementieren, aber ich habe aufgehört, weil ich dachte, dass KD-Trees dasselbe ist, aber einfacher zu codieren und schneller den nächsten Nachbarn abzufragen. Liege ich falsch ?
Dimitris93

Bei der Verwendung von Quadtrees muss die Bounding Box nicht explizit gespeichert werden, wodurch ein für meinen Verwendungszweck kritischerer Speichervorteil entsteht (auch Quadtrees sind für mich einfacher;)). Die Abfragegeschwindigkeit ist kein Problem. In der Tat studierte jemand solche Versuche und es übertraf alle anderen Implementierungen inkl. KD Bäume, aber ich nehme an, dass alles von der spezifischen Implementierung abhängt ...
Karussell

Wenn Sie sich Seite 9 dieses PDFs von Stanford ansehen , müssen Sie für die Suche nach dem nächsten Nachbarn in KD-Trees die Begrenzungsrahmen überhaupt nicht kennen. Und eine andere Sache ist, dass wir, weil wir alle Punkte vorher kennen, einen ausgeglichenen Baum mit Stammhöhe erzeugen können. Sind Sie sich immer noch sicher, dass Quadtrees einen Vorteil gegenüber KD-Bäumen haben?
dimitris93

2

Sie müssen nicht alle Kanten, die benachbart sind, in die Prioritätswarteschlange stellen. "Lüge" zu Dijkstras Algorithmus und gib ihm nur den kürzesten Scheitelpunkt, v, der auf den Scheitelpunkt fällt, sagen wir w, der vom Stapel gezogen wurde. Wenn dann v aus der Warteschlange gezogen wird, sagst du "oops", ich habe einen Fehler gemacht und hätte dir auch diesen Scheitelpunkt geben sollen, der dem Scheitelpunkt w am nächsten ist. Es ist leicht zu erkennen, dass Sie auf diese Weise eine korrekte Lösung erhalten und die Warteschlangengröße sich dramatisch auf nur einen der vielen Scheitelpunkte eines Vorfalls reduziert. Sie müssen jedoch die Vorfälle im Auge behalten, um bei Bedarf immer den nächstgelegenen Scheitelpunkt zu ermitteln. Einer der Kommentare behauptete, Straßennetze seien eben, was falsch ist. Tatsächlich hat eine Studie gezeigt, dass sie in hohem Maße nicht planar sind. Denken Sie an alle Autobahnen, die über Brücken durch eine Stadt führen und viele Unebenheiten verursachen.


0

Der anwendbare Dijkstras-Algorithmus wird für dieses Problem als nicht optimal angesehen, obwohl effizientere Varianten als "ähnlich" angesehen werden könnten. es gibt verschiedene Vereinfachungen. Straßennetze sind hierarchisch und planar . Hier sind die grundlegenden Ansätze. Das Gebiet wird allgemein als "Routenplanung in Straßennetzen" bezeichnet.

  • Aus den Daten der Adjazenzliste kann eine Graphenstruktur "kompiliert" werden. Dies ist der Ansatz in der Bibliothek, die Sie zitieren , SpatiaLite. Diese Diagrammstrukturen werden in einem komprimierten Binärformat gespeichert, in dem die Diagrammpositionen durch binär codierte Ganzzahlen usw. dargestellt werden. Die Darstellung und Bearbeitung des Diagramms nimmt also viel weniger Platz in Anspruch als das Speichern aller Straßennamen usw .; Es scheint, dass der SpatiaLite-Algorithmus nicht "online" ist und vollständig im Speicher ausgeführt wird.

  • Es gibt parallele / verteilte Algorithmen. siehe zB Scalable GPU Graph Traversal / Merrill, Garland, Grimshaw.

  • Die Frage verwendet Client-Server-Terminologie, dh "Abfragen". Die Algorithmen werden nicht ausgeführt, indem die Datenbank im Client-Server-Sinne "abgefragt" wird. Abfragesprachen höherer Ebenen wie SQL sind eine Schnittstelle zur Datenbank und können verwendet werden, um die Anforderung zur Berechnung der minimalen Routen zu übertragen, werden jedoch vom Algorithmus nicht intern verwendet. Im Allgemeinen läuft der Algorithmus "innerhalb der Datenbank", dh vollständig "serverseitig". Daher ist das Schreiben eines Algorithmus mit kürzestem Pfad in Datenbankabfragen für kleine Netzwerke, aber nicht für mittlere oder große Netzwerke möglich.

  • Es gibt einen anderen Ansatz, bei dem Schätzungen innerhalb kleiner Prozentsätze akzeptabel sein können. Die Grundidee besteht darin, einen Index der Abstände zwischen Knoten zu führen. siehe z. B. Schnelle und genaue Abschätzung der kürzesten Wege in großen Graphen / Gubichev, Bedathur, Seufert, Weikum

  • Diese (235p!) Doktorarbeit ist besonders anwendbar. Routenplanung in Straßennetzen / Schultes

  • Einige Algorithmen verwenden viele dieser Ideen, andere sind hochentwickelt und proprietär und stoßen auf wettbewerbsfähige Geschäftsgeheimnisse. zB Googles. Möglicherweise gibt es irreführende Medien zu diesem Thema. ZB Der einfache, elegante Algorithmus, der Google Maps ermöglicht, was besagt / impliziert, dass Google den Dijkstras-Algorithmus ohne Angabe von Gründen verwendet.


1
Google Maps hat sicherlich auf etwas Besseres als die Dijskstra aufgerüstet. Jeder halbwegs kompetente Entwickler würde A * für Straßenkarten verwenden, aber bei meiner vorherigen Arbeit stellten wir fest, dass Googles Engine 2500 km Routen über einen Wegpunkt in <100 ms neu planen konnte. Das ist zu schnell für A *, daher ist es wahrscheinlich, dass sie so etwas wie ArcFlags verwenden.
MSalters

Karussells Antwort hinterfragt diesen einleitenden Satz "Dijkstras Algorithmus gilt zwar als nicht optimal für dieses Problem", der nicht erwartet hätte, wäre umstritten. Die Behauptung in der (frühen) Schultes-These, die ebenfalls eine sehr umfassende / aktuelle Untersuchung des Gebiets darstellt und auch die "hierarchischen und planaren" "Annäherungen" erläutert, findet sehr starke Unterstützung. Leider scheint es in der offenen Literatur zur flüchtigen Suche keinen Hinweis auf die tatsächlichen Google-Algorithmen zu geben.
vzn

-2

Für extrem große Datenmengen wie diese ist es am besten, eine Union-Find-Datenstruktur mit Pfadkomprimierung zu verwenden, um so schnelle Ergebnisse zu erzielen. Wenn Sie jedoch nur den Djikstra-Algorithmus verwenden und diesen optimieren möchten, kommt es darauf an, welche Informationen jeder Knoten im Diagramm hat. Höchstwahrscheinlich müssen Sie nicht alle 1.500 Abfragen durchführen.

Betrachten Sie beispielsweise das folgende Beispiel. Nehmen wir an, ich versuche, den Grad der Trennung zwischen zwei beliebigen Akteuren (die Bacon-Nummer) zu finden, und ich möchte den Pfad mit der geringsten Gewichtung finden (Pfad unter Verwendung der neuesten Filme, die möglich sind). Angenommen, ich habe eine Funktion namens shortestPath(actor A, actor B);. Stellen Sie sich das folgende Szenario vor.

Wenn Schauspieler A seit 1970 und Schauspieler B seit 2000 tätig ist, wäre es angesichts dieser Informationen viel logischer, einen Pfad zu finden, der vom ersten Film von Schauspieler B aus beginnt und sich dann auf den Weg zu Schauspieler A macht im Gegensatz zu jedem Film, in dem Schauspieler A mitgespielt hat.

Der wichtigste Punkt ist also, dass die Optimierung des Djikstra-Algorithmus wirklich von Ihrem Datensatz abhängt. Sie müssen weitere Informationen darüber bereitstellen, was Ihr Datensatz für uns bedeutet, damit Sie Ihren Algorithmus optimieren können.

BEARBEITEN: Nehmen wir an, Sie versuchen, den kürzesten Weg zwischen zwei Städten im selben Land zu finden. Wenn dieses Land länger als breit ist, z. B. Argentinien, können Sie Ihre Abfragen anhand des Längen- und Breitengrads der Länder durchführen Grenzen. Dann können Sie beginnen, vertikal (unter Verwendung des Längengrads) und nicht horizontal zu verfahren. Natürlich müsste es eine Ausnahmebehandlung geben, aber Sie haben eine allgemeine Vorstellung davon.


1
Wie benutzt man Union-Find in Dijkstra?
Raphael

Die Daten sind räumliche Daten, Breiten- und Längengrade. Ich fand das klar.
Dimitris93
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.