Algorithmus, um die effizientesten Bewegungen zu finden, um zu einem bestimmten Punkt zu gelangen

8

(Dies ist nicht genau das Problem, das ich habe, aber es ist isomorph, und ich denke, dass diese Erklärung für andere am einfachsten zu verstehen sein wird.)

Angenommen, ich habe eine Menge von Punkten in einem n -dimensionalen Raum. Verwenden Sie zum Beispiel 3 Dimensionen:

%Vor%

Ich habe auch eine Reihe von Vektoren, die mögliche Bewegungen in diesem Raum beschreiben:

%Vor%

Nun, da ich einen Punkt dest habe, muss ich einen Anfangspunkt finden p und eine Reihe von Vektoren bewegt , die mich dazu bringen werden dest auf die effizienteste Weise. Effizienz ist definiert als "möglichst wenige Züge", nicht unbedingt "kleinste lineare Entfernung": Es ist zulässig, ein p zu wählen, das weiter von dest entfernt ist als andere Kandidaten, wenn der Zug gesetzt wurde ist so, dass du mit weniger Zügen dahin kommen kannst. Die Vektoren in moves müssen eine strikte Teilmenge der verfügbaren Vektoren sein; Sie können den gleichen Vektor nicht mehr als einmal verwenden, es sei denn, er erscheint mehr als einmal im Eingabe-Set.

Meine Eingabe enthält ~ 100 Startpunkte und vielleicht ~ 10 Vektoren, und meine Anzahl an Dimensionen ist ~ 20. Die Startpunkte und verfügbaren Vektoren werden für die Lebensdauer der App festgelegt, aber ich werde Pfade für viele, viele verschiedene dest Punkte finden. Ich möchte auf Geschwindigkeit und nicht auf Speicher optimieren. Es ist akzeptabel, dass der Algorithmus fehlschlägt (um keine möglichen Pfade zu dest zu finden).

Aktualisierung mit akzeptierter Lösung

Ich habe eine Lösung angenommen, die der nachstehend als "akzeptiert" sehr ähnlich ist. Ich iteriere über alle Punkte und Vektoren und erstelle eine Liste aller erreichbaren Punkte mit den Routen, um sie zu erreichen. Ich konvertiere diese Liste in einen Hash von & lt; em> Ziel , p + Vektoren & gt; und wähle den kürzesten Satz von Vektoren für jeden Zielpunkt aus. (Es gibt auch ein wenig Optimierung für die Hash-Größe, die hier nicht relevant ist.) Nachfolgende dest Abfragen finden in konstanter Zeit statt.

    
JSBձոգչ 21.01.2010, 18:46
quelle

6 Antworten

6

Wenn man bedenkt, dass Sie ungefähr 10 Vektoren haben, können Sie für einen gegebenen Ziel Punkt nur die 1024 "Ziele" aus der Teilmenge von Vektoren berechnen - zB jeder erreichbare Raum, mit der Information darüber, was für eine Bewegung erreicht wird. Das kann je nach Kontext "langsam" oder "schnell" sein (es ist absurd schnell, wenn es auf einem parallelen Computergerät wie der GPU implementiert wird).

Mit allen Sets, die dorthin kommen, können Sie die Pfade viel schneller berechnen, dann können Sie den Punkt auswählen, von dem Sie zu dest in den wenigsten Zügen gelangen, indem Sie aus der Teilmenge der Einsen wählen das sind entweder Ihre Anfrage oder weiter.

(Danke an Strilanc)

    
Kornel Kisielewicz 21.01.2010, 19:05
quelle
5

Ich glaube, dass Sie in der Lage sein werden, den Pfadsuchalgorithmus A * (alias A star) zu verallgemeinern. Es gibt keinen Grund, warum es nicht im N-ten Raum gemacht werden kann. Es garantiert den optimalen Weg, wenn Sie die Kosten jeder Bewegung beschreiben können.

Ссылка

    
Matt 21.01.2010 19:03
quelle
5

Sie möchten also eine Teilmenge Ihrer Vektoren so finden, dass die Teilmenge zu einem bestimmten Wert addiert wird. In 1 Dimension wird dies als Subset-Summenproblem bezeichnet und ist NP-Complete.

Zum Glück haben Sie nur ~ 10 Vektoren, also ist Ihre Problemgröße eigentlich ziemlich klein und handlich. Beginnen Sie damit, alle 2 ^ 10 Zugkombinationen für jeden Startpunkt auszuprobieren und den besten auszuwählen. Dann arbeite von dort nach einfachen Optimierungen.

Einige einfache Optimierungen, die funktionieren könnten:

  • Priorisieren Sie Suchsubsets einschließlich Vektoren, die in die richtige Richtung zeigen.
  • Treffen in der Mitte. Verwende eine Hash-Tabelle, um alle Punkte zu speichern, die du mit Teilmengen der ersten Hälfte deines Zugsets erreichen kannst, und sieh nach, ob du mit der zweiten Hälfte deines Zugsatzes vom Ende an einen Treffer erzielen kannst.
  • Geh rückwärts. Sie haben nur einen Endpunkt, also überprüfen Sie alle erreichbaren Startpunkte von dort aus und überprüfen Sie dann alle möglichen Startpunkte.
  • Parallelität
Craig Gidney 21.01.2010 19:07
quelle
2

Wenn Sie die Startpunkte und einen festen Vektorsatz haben, können Sie die Liste aller erreichbaren Ziele berechnen und dann einfach nach einem bestimmten Ziel suchen?

    
Chris Hulan 21.01.2010 19:00
quelle
1

Wie Kornel sagt, haben Sie höchstens 2 ^ 10 = 1024 erreichbare Ziele. Sie können also alle erreichbaren Ziele in 2 ^ N Zeit (wobei N die Anzahl der Vektoren ist) durch eine einfache rekursive Generierung erzeugen. Das wird natürlich schnell genug sein. Nehmen wir an, Sie wollten es dehnen.

Sie könnten es auf 0 (2 ^ (N / 2 + 1)) Zeit optimieren, indem Sie eine Meet-in-the-Middle-Lösung verwenden. Sie teilen den Vektorsatz in zwei Teilmengen auf und generieren unabhängig voneinander alle erreichbaren Ziele für jede Teilmenge. Sie durchlaufen dann einen Satz erreichbarer Ziele und finden für jeden Ort den Unterschied zwischen dem Ziel und dem Ziel. Wenn sich dieser Differenzvektor in der anderen Gruppe erreichbarer Ziele befindet, haben Sie eine Lösung: Kombinieren Sie die beiden und Sie sind fertig. Die Schwierigkeit hierbei besteht darin, effizient abzufragen, ob Sie den erforderlichen Vektor in der anderen Menge haben: Dies kann in O (1) -Zeit unter Verwendung einer Hash-Tabelle erfolgen.

Das ist O (2 ^ (N / 2)) Zeit pro Teilmenge, mal geben zwei Teilmengen O (2 ^ (N / 2 + 1)). Um die beiden zu verbinden, ist es O (2 ^ (N / 2)) Zeit. Das gibt uns insgesamt O (2 ^ (N / 2 + 1)) Zeit.

    
marcog 21.01.2010 20:37
quelle
0
  1. Beginnen Sie am Anfang.
  2. Machen Sie eine Weile
  3. Erhalte die Entfernung zum Ziel
  4. Teste alle möglichen Züge und wähle diejenige aus, die dich in einem Zug dem Ziel am nächsten bringt.
  5. Ende tun

Dies kann um das Ziel oszillieren, aber es bringt Sie in die Nähe.

    
xpda 21.01.2010 19:05
quelle