Liebe Programmierkollegen,
Wir entwickeln eine Software, die den Fahrzeugverkehr simuliert. Ein Teil des als "Zuweisung" bezeichneten Prozesses befasst sich mit der Zuweisung von Fahrzeugen zu ihren Routen und muss eine Art Algorithmus zum Auffinden kürzester Wege verwenden.
Traditionell tun dies Menschen mit Dijkstra, und bestimmte wissenschaftliche Literatur scheint darauf hinzudeuten, dass A * und andere Alternativen keine signifikante Verbesserung ergeben, möglicherweise aufgrund der Art des Diagramms.
Daher verwenden wir auch Dijkstra. Ein kleines Problem bestand darin, dass Sie, wenn Sie Verkehrsverbindungen (Straßenspannen zwischen Kreuzungen) als Kanten und Kreuzungen als Knoten behandeln, kein klassisches unidirektionales Diagramm erhalten können: Wenn Sie sich einer Kreuzung nähern, von der Sie häufig abbiegen können, hängt dies davon ab woher Sie kommen, während Sie in einem herkömmlichen Diagramm eine beliebige Kante von einem Knoten nehmen können.
Wir haben dieses Problem ganz einfach gelöst, indem wir ein Verbindungs-Schnittpunkt-Paar (nennen wir es "Latte") als Knoten dargestellt haben. Da Sie einen Link durchlaufen müssen, um zu einer nachfolgenden "Leiste" oder einem Punkt Ihrer Wahl zu gelangen, wird eine Kante als diese Durchquerung definiert, und Sie erhalten ein typisches Diagramm.
Die Ergebnisse werden dann in einer einfachen Tabelle N x N gespeichert, wobei N die Anzahl der "Latten" ist.
Hier ist der (unvermeidliche?) Nachteil. Wenn ein typisches Netzwerk für unsere Simulation beispielsweise 2000 Kreuzungen haben kann, hat es ungefähr 6000 Verbindungen, dh N = 3V. Wenn wir in Bezug auf die Schnittpunkte (V) gezählt werden, sind wir jetzt bis zu O (log (3V) * (3V + E)).
Sie könnten argumentieren, dass 3 (oder 9) ein konstanter Faktor ist, aber vom praktischen Standpunkt aus verlangsamt er die Dinge erheblich und erhöht den Speicherplatz auf 3 V x 3 V.
Hat jemand eine Idee, wie wir dies umstrukturieren können, um die Leistung zu verbessern? Nicht unbedingt ein alternativer Algorithmus, vielleicht die Datenstrukturen neu formen, um sie auf andere Weise an einen Graphen anzupassen?
quelle
Antworten:
Dijkstra findet den kürzesten Weg zwischen einem bestimmten Knoten und allen anderen Knoten, daher erwarte ich, dass er teurer als A * wäre. Es sieht jedoch so aus, als würden Sie versuchen, die Kosten und den Pfad von einem Knoten zu einem anderen vorab zu berechnen. Dann ist Dijkstra der richtige Weg.
Für eine einfachere Darstellung fallen einige Dinge ein:
An vielen Kreuzungen können Sie kommen und gehen, wie Sie wollen. Es ist nur eine Teilmenge, für die Sie Einschränkungen wie "keine Linkskurve" haben. Sie können die "Latten" also nur für Kreuzungen verwenden, an denen Sie sie tatsächlich benötigen. Das sollte die Größe genau dort stark reduzieren.
Sie können dies automatisch tun, indem Sie nach "äquivalenten Latten" suchen und diese kombinieren. Zwei Latten sind gleichwertig, wenn alle herauskommenden Links gleich sind. Wenn beispielsweise "Schnittpunkt X aus dem Westen" und "Schnittpunkt X aus dem Süden" beide zu demselben Satz anderer Knoten mit denselben Kosten führen, führen Sie diese einfach zu einem einzigen Knoten zusammen.
Sind Sie sicher, dass Sie den besten Pfad vorberechnen müssen / möchten, anstatt ihn online zu berechnen? Videospiele berechnen diese Dinge normalerweise online.
Wie repräsentieren Sie die Pfade? In Ihrer Matrix müssen Sie nur den ersten Link im Pfad darstellen. Um beispielsweise von Bobs Haus zu Bobs Arbeit zu gelangen, müssen Sie nur den ersten Link kennen. Wenn sie dort ankommen, können Sie jetzt in Ihrer Matrix nachsehen, wie Sie vom ersten Link zu Bobs Arbeit gelangen, die Sie erhalten der zweite Link usw.
quelle
Sie haben eine große Grafik und haben sie noch größer gemacht. Martinc C. Martin hat empfohlen, Drehmaschinen nur bei Bedarf zu verwenden, daher werde ich nicht darauf eingehen.
Eines der Dinge, die Ihnen helfen könnten, ist die Umwandlung Ihres Diagramms in kleinere Diagramme.
Die erste Vereinfachung, die mir sehr geholfen hat (ich habe mit Straßennetzen europäischer Staaten gearbeitet), war das rekursive "Entfernen" von Knoten mit Digree 1 und 2. Auf diese Weise haben Sie keine Sackgassen und T-Kreuzungen (ursprünglich Grad 3) werden zu Grad 2, und das ist nicht interessant, wenn Sie nicht zu diesem Knoten oder Knoten in dieser entfernten Sackgasse gehen.
Danach können Sie versuchen, Ihr Diagramm in Teile zu unterteilen, die eine große Anzahl interner Knoten und Kanten aufweisen, aber nur eine minimale Verbindung zu anderen Teilen haben. Um sie zu finden, habe ich einen minimalen Schnitt verwendet, bei dem Spüle und Quelle so weit voneinander entfernt waren (in Kanten) und Kanten in ihrer Nähe eine große Kapazität hatten und Kanten dazwischen klein waren.
quelle