A* Nodes bestimmen bei Dynamischer Map
Übersicht BlitzMax, BlitzMax NG Beginners-Corner
PhillipKBetreff: A* Nodes bestimmen bei Dynamischer Map |
Di, Okt 11, 2011 11:01 Antworten mit Zitat |
|
---|---|---|
Heyho Community.
Dies ist mittlerweile version 3 des Posts, jeden Tag einen (den ich aber unabgeschickt verworfen hatte, weil mir beim schreiben immer eine weitere idee einfiel) Leider fruchtet garnichts -.- Mein Problem ist meine A* wegfindung. Sie funktioniert, sie tut so als würde sie was finden, alles super. Nachteil: Ich nutze direkt meinen "map" array (short[,]) als Nodes. Selbst bei 75x75 auflösung des Rasters und einer leicht komplexen map (beispielsweise 2 große bogen, ) ( so etwa, in der mitte der Map als wand) führt dazu, das meine TUnits nicht wirklich oft in bewegung sind. Der grund ist eventuell die Heuristik die ich verwende und sicher auf die Auflösung der Map. Ich arbeite immer eine Wegfindung nach der anderen ab. Ich habe meinem Programm 10ms gegeben, soviele Nodes abzuarbeiten, wie es nur geht, aufgeteilt in 100 durchläufe pro aufruf. Grund: Weniger variablen initialisierungen etc (bring das bei Blitzmax überhaupt was? naja egal) Ergebnis ist, das 100 einheiten Kurze pfade in einem Frame abarbeiten, allerdings wenn nur einer mit einem Längeren PFad dazwischen ist, können auch mal 5 sekunden vergehen, bevor sich überhaupt irgendwas wieder bewegt. Ich verzweifel Nun, beim stöbern bin ich auf dieser seite gelandet: KLICK - das klingt vielversprechend. Tatsächlich, eine geringere auflösung würde enorm weniger Vergleiche nach sich ziehen - damit könnte ich den weg recht schnell finden. Allerdings bin ich auch da nicht sicher - wie setze ich bei einer Block/Tilemap eine solche auflösung fest? Bereits bei einer auflösung von 4x4 Kacheln pro Node könnte es diverse probleme geben: Code: [AUSKLAPPEN] X O O X O X O O O X O O X O O X Angenommen, X ist nicht passierbar, O ist passierbar. Ausserdem ist die Dritte spalte auch die einzige möglichkeit, die Node darüber irgendwie zu erreichen. Ich hatte schon etliche ideen der Speicherung, welche alle enorm viele Variablen mit sich bringen würde. Ich erachte das einfach als nicht zulässig Aber es muss doch irgendwie eine möglichkeit geben, bestimmte wegpunkte in der map zu verteilen. Einfach auf gut glück nach einem raster ausrichten kann auch nicht funktionieren - die gefahr ist zu groß, das die Wegpunkte die einen Schmalen pass am nächsten sind plötzlich in einer Mauer liegen. So wäre der weg - von den Wegpunkten her - unbrauchbar und es bräuchte wieder eine Hochauflösende A* methode, um den weg zu finden. Die nächste idee die irgendwo auf der seite stand, war das unterteilen der map in "inseln". Das heißt, bestimmte bereiche die komplett umschlossen sind, makieren, und beim starten der A* Methode ersteinmal überprüfen, ob das Ziel innerhalb einer solchen 'Insel' liegt. Die idee wollte ich ausbauen, prüfen ob der Weg der gefunden wurde, irgendwelche besonderheiten aufweist (zb erstmal weit weg vom ziel -> deutet auf eine kante hin) und diese Besonderen Punkte dann in eine Globale Wegpunktliste aufnehmen. Egal was ich tue, ich komm einfach auf keinen Zweig. Ich fürchte, hier muss ich an die hand genommen werden. Vielleicht kennt jemand das Problem, vielleicht hat mal einer bei den ganzen aufkommenden Minecraftclones einen eigenen geschrieben und dort auch eine wegfindung eingebaut. Ansonsten wäre ich auch über richtige Stichworte für die Googlesuche erfreut, hauptsache irgendwelches material, das ich aus meinem Nachdenk-loch rauskomme Gruß, Phillipk :3 |
||
mpmxyz |
Di, Okt 11, 2011 15:19 Antworten mit Zitat |
|
---|---|---|
Eine Frage: Nutzt du inzwischen Prioritätswarteschlangen auf Baumbasis für die offene Liste?
Wenn der Algorithmus nämlich nicht optimal ist, ist es nicht verwunderlich, dass es Geschwindigkeitsprobleme gibt. Es sollte außerdem eine weitere große Optimierungsmöglichkeit geben: Wandle das Raster in eine günstigere Form um! Das, was A-Star in diesem Fall so langsam macht, ist die Tatsache, dass es viel zu viele gleichwertige Möglichkeiten für den Weg gibt. Du kannst das Problem vereinfachen, indem du nur folgende Knoten betrachtest: 1a. Randknoten zum begehbaren Bereich (Küste: Wasser<->Land, Klippen: Land<->Abgrund, Nachteil: viele Verbingungsdaten) 1b. Eckknoten am Rand des begehbaren Bereiches (Vorteil gegenüber 1a: Keine direkte Aneinanderreihung von Knoten und dadurch viel weniger Verbindungen) 2. Start- und Endknoten (nur während der Suche vorhanden) Im Gegenzug müssen einmal am Anfang die möglichen Direktverbindungen zwischen den einzelnen Knoten bestimmt werden. (Was "direkt" heißt, bestimmst du! Die entsprechende Bewegung kann sich auch an das Raster halten.) Dieser Ansatz verbraucht auch durch die extra gespeicherten Informationen mehr Speicherplatz - bei 100 Knoten maximal 5050 Verbindungen, bei 200 Knoten maximal 20100 Verbindungen, aber dafür wird er - ich habe es nicht getestet, aber die Anzahl an Knoten, die entfernt wird, spricht meiner Meinung nach für sich - viel schneller sein. mfG mpmxyz |
||
Moin Moin!
Projekte: DBPC CodeCruncher Mandelbrot-Renderer |
PhillipK |
Di, Okt 11, 2011 15:57 Antworten mit Zitat |
|
---|---|---|
Hey mpmxyz (wasn name )
Nein, ich nutze noch keine Prioritätswarteschlange. Ich habe HamZta's code eingebaut und getestet - das ergebnis war erschreckend. An und für sich ist das ein super code, solange nicht zuviele unterschiedliche prioritäten darin vorkommen. In seinem beispiel mit den 4 Prio's leuchtet mir das ganze noch wunderbar ein. Das finden des günstigsten hat sich als performance armer rausgestellt, das das ständige neu linken des Data array's beim einfügen. Sprich: Immernoch Tlist. Allerdings hatte ich ein anderes Konstrukt im sinn, das ähnlich funktioniert aber beim einfügen in den meisten fällen schneller sein sollte: BlitzMax: [AUSKLAPPEN] Type THeap Idee: _nodeAVGprio enthält die durchschnittliche priorität aller nodes und beim Adden wird geschaut, ob es mehr sinn machen würde, vorne oder hinten mit der suche anzufangen. Das ungetüm ist allerdings ungeschrieben, ich plane es nur eventuell, wenn ich eine genauere auswertung der geschwindigkeiten aller Parts meiner A* funktion durchgeführt habe und die TList tatsächlich der größte speedverlust ist. ------------- Zu 2: "gleichwertige Möglichkeiten" - meinst du damit, das es (in einem Komplexen fall) viele Knoten gibt, die relativ ähnliche F_costs aufweisen? Das ganze dick auszulagern und mit einer groben vorprüfung versehen ist grade das einzige, was mir noch einfällt. Ich verstehe zwar nicht genau, was du mir mit 1a) und 1b) vermitteln willst, allerdings klingt es recht ähnlich meinem vorhaben. Ah, nun hab ichs, ich weiß was du mir sagen willst 1a) Empfielt, jede Kachel die begehbar ist und an eine Wand endet, mit einer Node zu versehen. 1b) klingt nach formsuche: Jede begehbare Linie wird auch als solche aufgefasst und an deren enden wird ein Knoten gesetzt. Ich weiß zwar noch nicht, wie ich die direktverbindungen bestimmen soll, aber es ist auf jedenfall ein anfang. Leider ist die Map ziemlich unsauber (hier mal ein Png render meiner Map [WARNUNG: 3.072px × 2.816px groß! https://www.blitzforum.de/upload/file.php?id=10964 - diese wird im endeffekt mit dem A* system bestückt!) DH in beiden fällen werden auf jedenfall eine menge Datensätze anfallen. Gut, das lässt sich noch eingrenzen, indem ich zb nur besuchte bereiche *verknote* - aber über kurz oder lang kommt da eine menge zusammen. Dennoch, ich schreibs mir schonmal auf die Todo. Solang es erstmal funktioniert, will ich mich über das bisschen ram nicht beklagen *g* (hey das bringt mich drauf, ich könnte mal einen kleinen test machen - Wegpunkte sterben nach einer gewissen zeit aus, wenn sie nicht vom A* als "guter weg" erkannt werden - damit werden sich langsam aber sicher die wichtigsten punkte herauskristalisieren, oder? ) *grübel* Heute ist leider nixmehr mit ausprobieren, aber morgen früh, punkt 06:30 werd ich mich gleich dran machen und deine vorschläge in erste Tests umschreiben. (mir hat sich grade noch ein ungetüm der node platzieren ergeben. 1b) - dazu eine linienbildung von 2 oder 3 nodes, dann die bestimmung des normalvektors, vektor verlängern bis ich eine gedachte linie zwischen 2 weiteren Nodes schneide - länge halbieren, node platzieren. Damit dürfte ich die ungefähre mitte der flächen erhalten. Nun muss man nurnoch ein wenig basteln um die genauen ecken der flächen rauszufinden und die überschüssigen Knoten wieder entfernen - Das ganze im Kopf durchgespielt dürfte echt super platziere knoten geben - aber meine CPU würde mir einen husten, solch bescheuerte rechnungen machen zu müssen *g*) Ich danke dir schoneinmal recht herzlich, mpmxyz Nachtrag: Oh schreck! Ich habe grade versucht, meine idee der Priority heap sache umzusetzen, Basierend auf verlinkungen untereinander. Vorteil: Dynamischer, noch schnelleres auslesen der daten, höchste und niedrigste Priorität möglich. Nachteil: Langsamer als die Methode von HamZta und nun kommts: Mein Speedtest hat folgendes ergeben: Code: [AUSKLAPPEN] ------------------ Priority_new system durchgearbeitet --------------
Einfügen von 10000 objekten: 1674 Auslesen von 10000 objekten: (sortiert) 3 ------------------ TList durchgearbeitet -------------- Einfügen von 10000 objekten: 18 Auslesen von 10000 objekten: (sortiert) 23604 ------------------ TPriorityHeap (by HamZta :) ) durchgearbeitet -------------- Einfügen von 10000 objekten: 119 Auslesen von 10000 objekten: (sortiert) 67 Das oberste ist meine version, das unterste die von Hamzta. Die TList variante ist 1zu1 so, wie ich sie in meinem A* algo nutze. Ich geh kaputt, ich habe HamZta's Type ganz umsonst verdächtigt :O Der grund, warum es mit seinem Type langsamer war, ist definitv NICHT durch das Type selber, sondern ein - noch unidentifizierter fehler - meinerseits. Der Test oben ist übrigends im debug. Im release braucht mein krams 200ms zum eintragen, 1ms zum auslesen, seins aber nur 64ms + 9ms. Tja, das heißt alles neu schreiben und HamZta's Priority Heap verwenden :O *freu* |
||
Midimaster |
Mi, Okt 12, 2011 12:42 Antworten mit Zitat |
|
---|---|---|
sind deine Testergebnisse für das 75x75er Feld gewesen, oder für die große 3000x2800 Map?
Beschreib mal, was der Finde-Algo genau können muss. Vleiiecht hab ich das was für dich.... |
||
Gewinner des BCC #53 mit "Gitarrist vs Fussballer" http://www.midimaster.de/downl...ssball.exe |
PhillipK |
Mi, Okt 12, 2011 13:00 Antworten mit Zitat |
|
---|---|---|
Ich glaube, das von HamZta ist schon mit eines der oberen Optimums die ich dafür bekommen kann.
Sinn von AStern ist, das es mögliche nachbar felder der knoten auswertet und ihre ungefähren wegkosten bestimmt. Die niedrigsten Wegkosten kriegen gleichzeitig die höchste priorität zugeschrieben, das sie wahrscheinlicher zum Ziel führen. Das heißt, es muss eine Sortierte liste her, welche nach möglichkeit direktzugriff auf den 'Wichtigsten Knoten' bietet und auch beim einfügen nicht sehr lange braucht. Das scheint - nach den testergebnissen auf 100.000 durchläufe - mit HamZta's code der fall zu sein. Der Test bezog sich auf einen direkten vergleich mit identischen umständen. Hierzu habe ich einen Array der Länge 100.000 mit ebensovielen Random-integern gefüllt und diese in die Listen einsortiert. Die randomzahl der array einträge war gleichermaßen ein String mit den Zahlen als auch die Priorität. Identische bedingungen also |
||
Midimaster |
Mi, Okt 12, 2011 13:44 Antworten mit Zitat |
|
---|---|---|
ich wollte das eher ganz praktisch auf das Feld bezogen wissen...
Wie "schnell" findet der akt. Algo denn nun den Weg? Wie groß war das Array? 100.000 bedeutet 320x320? |
||
Gewinner des BCC #53 mit "Gitarrist vs Fussballer" http://www.midimaster.de/downl...ssball.exe |
PhillipK |
Mi, Okt 12, 2011 13:50 Antworten mit Zitat |
|
---|---|---|
Das kann ich grade garnicht so genau sagen.
Ich nehme grade einen kompletten Rewrite vor , da das letzte system beständig um ideen erweitert wurde. Hier haben sich wohl ein paar fehler eingeschlichen. Vorher war es unterschiedlich - je Komplexer die wegfindung, desto länger, logischerweise. Bei den alten tests habe ich pro frame etwa 1000 Knoten überprüfen können, bevor es unter 60fps gerutscht ist. Das ganze war so aufgebaut, das ich meiner funktion ein paar MS zeit gegeben habe, bestimmt durch den vorangegangenen Mainloop-code. In der Zeit konnte er etwa 10 durchläufe starten, mit je 100 knoten zu prüfen. Ich brauche noch zirka 20minuten, dann habe ich den Testcode soweit wieder Flott. Diesmal besser sortiert, vollends durchdacht von anfang an und mit HamZta's heapnode system. Danach werde ich auch explizite Zeitmessungen durchführen, um festzustellen, welche programmteile die meiste "zeit" benötigen. Zu den 100.000: Das ganze war ein Testcode, der nichts weiter tut, als die 3 sortiermöglichkeiten exakt gegeneinander zu testen. Das war keineswegs auf die Testmap bezogen, diese hatte ein 75x75 Raster (5600 knoten odersowas ). Die 100.00 ist möglichst hoch gewählt, allerdings so, das keine Kaffepause drin war *g* |
||
Midimaster |
Mi, Okt 12, 2011 15:22 Antworten mit Zitat |
|
---|---|---|
ich hab da mal was für dich:
#EDIT Version 1.03:# https://www.blitzforum.de/upload/file.php?id=11018 ist eine demo meines Wegfindungs-Algos. lege mit der linken Maus einen Punkt fest, von dem der Weg zum Ziel (ca. Bildmitte) gefunden werden soll. Du kannst es beliebig wiederholen. Lege mit der rechten Maus einen neuen Zielpunkt fest. Die Grün-Tönung verrät Dir schon viel über den Algo. Je heller ein Feld, desto näher ist es beim Ziel. mit "R" kannst du ein neues Random-Feld erzeugen. Danach muss man durch Eingabe von <1> bis <5> bestimmen, wieviele Mauern prozenztual zu sehen sein sollen. mit <M> kommst du ins Malen. Dann mit der Maus malen, dann mit <ESC> wieder zum Wegtesten zurück.. das Problem mit dem Aufhängen habe ich auch gelöst. Nun kann man auch hoffnungslose Positionen anklicken und das Programm merkt, dass es keine Verbindung gibt. Aber Vorsicht: das Test Programm ist ohne Fehlerabfragen: das bedeutet: halte dich von den Rändern fern. (wenn doch geklickt: beendest du es mit STRG-ALT-ENTF) |
||
Gewinner des BCC #53 mit "Gitarrist vs Fussballer" http://www.midimaster.de/downl...ssball.exe |
- Zuletzt bearbeitet von Midimaster am Mi, Okt 12, 2011 17:59, insgesamt 2-mal bearbeitet
PhillipK |
Mi, Okt 12, 2011 15:26 Antworten mit Zitat |
|
---|---|---|
Schaut super aus.
Soweit ich das sehen konnte, ist rot ne mauer. Wenn ich mit der Rechten maustaste klicke, sehe ich immer ein gewissen bereich, was so betrehtbar ist. Was ist das genau? Meine A* methode ist leider noch am scheitern, ich hab ne abfrage vermurxt, sodass er nur den startknoten überprüft :-/ |
||
Midimaster |
Mi, Okt 12, 2011 15:33 Antworten mit Zitat |
|
---|---|---|
Der Effekt zeigt beim ersten Start, von welche Feldern überhaupt nicht das Ziel erreicht werden kann.
Der Effekt zeigt nach einem RECHTE MAUS, dass nur ein Bereich des Feldes gescannt werden musste um die Verbindung zu finden. Betretbar ist nun aber auch der graue Bereich ( solange du in dieser Testversion keinen abgeschlossenen Raum anklickst). Witzig dabei sind die Zeiten, die fast immer unter 2msec liegen. Wen mal was längeres angezeigt wird, dann nur deshalb, weil das Zeichnen mitdazukam! |
||
Gewinner des BCC #53 mit "Gitarrist vs Fussballer" http://www.midimaster.de/downl...ssball.exe |
PhillipK |
Mi, Okt 12, 2011 15:47 Antworten mit Zitat |
|
---|---|---|
Kannst du eine kleine Wand-dazumalen funktion einbauen?
Mein größtes problem bei den wegfindungen waren bis jetzt immer mauerteile, die ähnlich einem C aussahen. Code: [AUSKLAPPEN] --------------------------------------------- | _________________ | | / | | / | | / | | ZIEL | START | | \ | | \ | | \__________________ | | | --------------------------------------------- (mal eine kleine asciiskizze dazu) In diesem Gebilde durchsucht ein A* fast immer den kompletten kasten, da dies der einfachste weg zu sein scheint (heuristik!). Dh man unmengen abfragen, obwohl der weg ganz einfach zu sein scheint. Genau wegen solchen (zwar ziemlich unmöglichen, aber dennoch auftretetenden gebilden) versuche ich grade, eine grobe Vorprüfung zu bauen. Beim Testen habe ich solche Mauern auch als "worst case" ausgemacht und versuche nun, eine solche Wegfindung zu beschleunigen, sodass mindestens 50 einheiten relativ schnell (dh weniger als 5sek standzeit pro Einheit) umher wandern kann. Meine testmap mit dem simplen AStern algo läuft nun wieder. Ich werde mich gleich mal ans einbauen von Debug-DrawText's machen, damit ich auch eine dauer-anzeige habe |
||
Midimaster |
Mi, Okt 12, 2011 16:12 Antworten mit Zitat |
|
---|---|---|
ich habe es geupdatet:
https://www.blitzforum.de/upload/file.php?id=11018 mit "R" kannst du ein neues Random-Feld erzeugen. mit <M> kommst du ins Malen. Dann mit der Maus malen, dann mit <ESC> wieder zum Wegtesten zurück das Problem mit dem Aufhängen habe ich auch gelöst. Nun kann man auch hoffnungslose Positionen anklicken und er merkt, dass es keine Verbindung gibt. |
||
Gewinner des BCC #53 mit "Gitarrist vs Fussballer" http://www.midimaster.de/downl...ssball.exe |
- Zuletzt bearbeitet von Midimaster am Mi, Okt 12, 2011 17:59, insgesamt 2-mal bearbeitet
PhillipK |
Mi, Okt 12, 2011 16:18 Antworten mit Zitat |
|
---|---|---|
schnüff^^
Ich habe meine Funktion auch mit einer Dauer-ausgabe versehen. Nun habe ich in beiden programmein ein ähnliches feld gebastelt - e voila - deins braucht 4ms, meins läuft immernoch. Bei Komplexen wegen gibts bei mir grade derbe Performance einbrüche, ich denke da habe ich irgendwo eine abfrage falsch. Das ganze muss ich nocheinmal genauer durchschauen, denn es kann weder die Knoten-findung sein, noch die Abfragen oO Zur sicherheit poste ich hier mal den Code: BlitzMax: [AUSKLAPPEN]
Das ganze nutzt folgende Funktion (von hamZta!): BlitzMax: [AUSKLAPPEN] Const BLOCK_SIZE:Int = 16 Und hier das Testprogramm dazu: BlitzMax: [AUSKLAPPEN] SuperStrict Sollte eigentlich alles mit dem Identisch sein, was ich in den ersten versionen auch habe. Tatsächlich kommt es mir so vor, als würde mit jedem Compilen meine funktion Länger brauchen o.o Ps: In AStern ist eine Abfrage für Schrägbewegungen an einer mauer entlang enthalten. Diese ist zu missachten. Ist noch verdreht :> |
||
Midimaster |
Mi, Okt 12, 2011 16:24 Antworten mit Zitat |
|
---|---|---|
ich mach das gar nicht mit a* sondern mit was eigenem | ||
Gewinner des BCC #53 mit "Gitarrist vs Fussballer" http://www.midimaster.de/downl...ssball.exe |
PhillipK |
Mi, Okt 12, 2011 16:29 Antworten mit Zitat |
|
---|---|---|
Gut, raus mit der Sprache ^^
Ausser es ist geheim :3 Ich wollte die tage mit einem Wegpunktesystem anfangen, worauf mich eine bekannte gebracht hat. Idee : Alle X felder die eine einheit zurückgelegt hat, wird geprüft ob ein neuer, globaler Wegpunkt geschaffen wird, welcher seine nachbarn kennt. Das könnte zum erschaffen ein wenig Berechnung brauchen, hat aber den sinn, das 2 Wegpunkte dann miteinander verbunden sind, wenn sie weniger als 50 Knoten berechnung als A* brauchen. Das ist im allgemeinen Ziemlich schnell, da meist auch eine direkt (oder indirekte) sichtverbindung herscht - man kann die einheiten bequehm von punkt zu punkt tingeln lassen und die wege sogar noch wärend des Laufens in ihrerer vollen form berechnen lassen. Zu meinem code: Kannst du grade - rein zufällig - erkennen, ob ich irgendwo einen Leak in die Astern-update methode eingebaut habe? Je weiter die Suchtiefe vorran schreitet, desto länger brauchen die einzelnen update aufrufe. Hab das grade nachgeprüft, indem ich bei unit.astern.update() (hauptprogramm) eine ms-differenz bestimmt habe und diese ausgegeben habe. Die ausgabe war eindeutig: Gute 20-30% länger als der vorherige aufruf, ab und an eine zurücksetzung |
||
Midimaster |
Mi, Okt 12, 2011 17:02 Antworten mit Zitat |
|
---|---|---|
also hier:
der Code ist eher symbolisch zu verstehen. Ich hab ihn gleich mal umfangreich kommentiert. Die Vorgehensweise ist folgende: Angefangen wird beim Ziel. Zuerst scanne ich alle Nachbarfelder des Ziels. Von hier aus wäre 1 Kosten nötig, um zum Ziel zu kommen. Felder, die Mauern sind, werden gleich erst gar nicht aufgenommen. Diese bis zu 4 Nachbarfelder kommen nun in die Liste. Die Liste wird von vorne bearbeitet und von allen wieder die Nachbarn gescannt. Wieder verwerfe ich alle Mauern, aber auch gleich alle Nachbarn, die bereits früher besser (mit weniger Kosten) gescannt waren. Um frische Felder von bereits gescannten zu unterscheiden haben alle "frischen" Felder beim Start eine 999 als Kosten bekommen. Langsam entstehen sowas wie ISO-Kreise um das Ziel. Und irgendwann ist plötzlich das Startfeld dabei. Der eigentliche Weg wird nun rückwärts (also von Start zum Ziel) gefunden. Ich muss nur noch den Kosten in den Nachbarfelder Checked[x,y] so folgen, dass ich immer dem kleinsten Wert folge, bis ich am Ziel bin. BlitzMax: [AUSKLAPPEN]
|
||
Gewinner des BCC #53 mit "Gitarrist vs Fussballer" http://www.midimaster.de/downl...ssball.exe |
PhillipK |
Mi, Okt 12, 2011 19:32 Antworten mit Zitat |
|
---|---|---|
An sich liest sich das wie eine allgemeinere Suchroutine. Das kreisförmige ausbreiten habe ich die tage schonmal in einem Java applet gesehen.
In den meisten fällen ist A* leider schneller :< Ich werde dennoch deine idee einmal in meine Wegfinderoutine aufnehmen um einen direktvergleich zu haben. Ziemlich stark auffallen tut schonmal, das deine Funktion komplett ohne eine extra Klasse (zb TKnoten ) auskommt, das dürfte einiges an Speed sparen. In anbetracht der tatsache, das meine TKnoten klasse eine kleinere Berechnung durchführt und wiederholt einige wichtige felder abgefragt werden. Deine Version kommt mit einem Simplen integer und einem Map gleichdimensionierten Array aus -intressant Am ende tuts vielleicht gar eine Mischung aus beiden. Selbst wenn ich das ganze nicht in dieser Form nutzen sollte, schwebt mir dennoch schonmal eine anwendung dafür vor: In der nähebefindliche Wegpunkte finden! Diese sollen auf direktem wege verbunden sein, allerdings ohne große Mauern dazwischen - mit einer gewissen Suchtiefe (dh kreisförmiges durchgehen) kann ich so ziemlich schnell ausfindig machen, ob um einen Punkt herum eine Wegmakierung ist. Hmpf, soviele ideen und doch so wenig zeit ^^ Ich danke dir für diese vorführung und erklärung, ich melde mich, sobald ich das ganze einmal durchprobiert habe |
||
Midimaster |
Do, Okt 13, 2011 10:45 Antworten mit Zitat |
|
---|---|---|
Genau, aber das ist ja A* auch (Quelle: Wikipedia:
Zitat: Der A*-Algorithmus... gehört zur Klasse der informierten Suchalgorithmen.
Und so sehr weit ist mein Algo von dem A* nicht weg. Wenn Du Dir die Definition von A* mit den Eigenschaften meines Codes vergleichst, so hält sich mein Algo an alle dort vorgegebenen Schritte. Vergleiche mal den Text auf Wikipedia! Einzig die "Vorahnung" einer Richtung habe ich ersetzt durch "in alle Richtungen suchen". Was sich in vielen Fällen als nutzvoll heraussstellt. Es ist halt im Spiel doch ganz oft so, dass die Luftlinie nicht zum Ziel führt. So gesehen ist mein Algo eher ein Dijkstra-Algorithmus Heuristik fällt auch weg bei meinem Algo, denn das Ziel wird ja so unglaublich schnell gefunden, also warum schätzen? Solange die Findezeiten unter 1 msec liegen, muss man nicht über weitere Maßnahmen nachdenken. "Entscheidend ist, was hinten rauskommt" Es wäre erst noch zu beweisen, dass der A* hier mehr leisten kann. Wenn der Aufbau eines Spielfeldes (Anz. Dimensionen, Array() ja/nein, Bewegungsmuster) bekannt ist, dann ist ein auf diesen Situation angepasster Algo im Vorteil. Und genau das macht mein Algo. Er kennt die Struktur des Spielfeldes und ahmt sie in seinem Checked[] nach. Dadurch spar er viel Zeit, sich über die Knoten zu informieren. So kommt er "billig" an die Nachbarknoten. Die Knoten werden nicht alle in einer Liste gehalten, sondern immer nur die neuesten. Fertig untersuche Informationen kommen in das Array. Das "Zeiger-Modell" der Knoten ersetze ich durch die späte Rückwärtssuche im Array. Das Array zeigt ebenso den Weg zum Ausgangspunkt, wie es die Zeiger tun würden. Denn je näher ich dem Startpunkt komme, desto niedriger sind die auf den Array-Feldern errechneten Kosten. Das Array ist auch gleichzeitig die Closed-List. Der Algo erfährt hier eindeutig, ob ein Knoten bereits zuende untersucht wurde und nimmt ihn nicht wieder in die OpenList auf. Das bringt den entscheidenden Vorteil des A*. Hier würde ich auch in Deinem Algo den Fehler vermuten. Eine Lösung ist immer eine schrittweise Darstellung. Stoppe nach jedem Knoten. Lass dir die Koordinaten ausgeben, die als neue Knoten aufgenommen werden und vergleiche ob sie nicht manchmal zweimal in der Liste stehen. Ein typischer Fehler ist nämlich, dass die Liste aus mehr Knoten besteht als Felder im Spielfeld betroffen sind. Ich habe übrigens die Visualisierung der Vorgehensweise in meinem Code überarbeitet. Den Download fiindest Du an der alten Stelle. |
||
Gewinner des BCC #53 mit "Gitarrist vs Fussballer" http://www.midimaster.de/downl...ssball.exe |
BladeRunnerModerator |
Do, Okt 13, 2011 12:39 Antworten mit Zitat |
|
---|---|---|
Zitat: Einzig die "Vorahnung" einer Richtung habe ich ersetzt durch "in alle Richtungen suchen". Was sich in vielen Fällen als nutzvoll heraussstellt. Es ist halt im Spiel doch ganz oft so, dass die Luftlinie nicht zum Ziel führt. So gesehen ist mein Algo eher ein Dijkstra-Algorithmus
das stimmt, und dieser ist eben nicht der optimale Weg, zumindest nicht Wenn Start- und Zielpunkt bekannt sind. Zitat: Es wäre erst noch zu beweisen, dass der A* hier mehr leisten kann. Wenn der Aufbau eines Spielfeldes (Anz. Dimensionen, Array() ja/nein, Bewegungsmuster) bekannt ist, dann ist ein auf diesen Situation angepasster Algo im Vorteil.
Hier darf ich auf den von dir angeführten Wikipedia-Artikel von Dir verweisen, in dem auch der mathematische Beweis dafür ausgeführt ist dass der A-Star die optimale Lösung findet, insofern muss ich also sagen dass Du dich mit deiner Behauptung recht weit aus dem Fenster lehnst. Der Dijkstra ist ja mathematisch betrachtet nur eine Sonderform des Astar, allerdings nicht die automatisch Günstigste. Auch hier verweise ich auf den von Dir angeführten Wikipedia-Artikel. Natürlich kann man mit solch einer Breitensuche viel erreichen, aber der optimale Weg ist es idR. nicht. |
||
Zu Diensten, Bürger.
Intel T2300, 2.5GB DDR 533, Mobility Radeon X1600 Win XP Home SP3 Intel T8400, 4GB DDR3, Nvidia GF9700M GTS Win 7/64 B3D BMax MaxGUI Stolzer Gewinner des BAC#48, #52 & #92 |
Midimaster |
Do, Okt 13, 2011 13:53 Antworten mit Zitat |
|
---|---|---|
@BladeRunner
..naja... der A* wird ja oft mit dem Beispiel "Straßennetz" erklärt. Hierzu passt er auch optimal. Der Unterschied zum Labyrith" besteht ja darin, dass man oft davon ausgehen kann, das ein Straße die wenigstens schon mal in die Himmelrichtung zum Ziel zeigt auch wirklich dort hinführt. Straßen haben auch den Vorteil, dass es "irgendwie immer" weitergeht. Im freien Feld mit plötzlich auftretenden Total-Hindernissen sieht die Sache schon anders aus. Oder im Labyrith, wo durch die Himmelsrichtung leider gar nichts gewonnen ist. Auch hierzu findet sich Kritik im Wikipedia-Beitrag. In solchen Fällen muss der A* viel zu oft und immer wieder bereits betrachtete Knoten neu aufnehmen und kann sich so gut wie nie sicher sein, dass er jetzt für diesen Knoten das Optimum gefunden hat. Und irgendeinen Grund muss es ja haben, dass so viele andere Algos nebenher existieren Wir werden sehen, was bei PhillipK am Ende rauskommt. Ich hatte sein Bild von dem Test-Labyrith (früherer Thread) vor Augen und wußte, das A* hier nicht die Lösung sein wird. Und letzemdlich ist es ja Unsinn einen "noch besseren" Algo zu suchen, wenn für das akt. Problem eine Lösung von unter 1msec gefunden ist. PhillipK könnte ja mal eine typische zu erwartenden Testumgebung erstellen, wo man dann den Algo drauf loslässt. Nur so ins Blaue einen Algo zu basten, ohne zu wissen was er genau lösen soll, ist wie "Koffer packen für einen unbekannte Urlaubsregion". |
||
Gewinner des BCC #53 mit "Gitarrist vs Fussballer" http://www.midimaster.de/downl...ssball.exe |
Übersicht BlitzMax, BlitzMax NG Beginners-Corner
Powered by phpBB © 2001 - 2006, phpBB Group