A*-Implementation
Verfasst: Sonntag 4. Juli 2010, 16:09
Hallo zusammen,
Ich bin gerade dabei eine Lib zu schreiben, die etliche Algorithmen und einige Tools implementieren soll: pyreia. Das ganze steckt noch sehr in den Kinderschuhen, soll heißen: Ich weiß selbst, dass da noch einiges recht schlecht ist.
Ich habe einige Basis-Node-Klassen, die die wichtigsten Eigenschaften eines Nodes implementieren. Node.children ist z. B. ein Dictionary bestehend aus Kindern (keys) und den Kosten ein Kind zu erreichen (values).
Daher hatte ich um den A*-Algorithmus zu implementieren gedacht, dass ich eine Klasse names ANode erstelle, die von Node erbt und dann entsprechende Attribute hat (f, g, h etc). Der Algorithmus lief auch wunderbar, allerdings ist mir aufgefallen, dass ich dann einen konzeptionellen Fehler habe. Was mache ich denn z.B. wenn ich einen weiteren Algorithmus implementiere? Diese erbt dann wieder von Node und alles funktioniert gut. Und wenn ich nun einen Baum habe, auf dem ich mehrere Algorithmen laufen lassen will?
Also dachte ich mir, dass ich A* eben funktional (FP) implementiere. Dazu hab ich heapq etwas angepasst um eine cmp_func übergeben zu können. Dann braucht man an sich keine Klassen mehr dafür.
Zur eigentlichen Frage: Meine derzeitige A*-Implementation ist nicht sonderlich schön. Sie funktioniert zwar, aber ich finde mind. zwei Dinge extrem hässlich:
1. Hier möchte ich den Wert eines Heap-Elements verringen. Weder heapq noch meine Implementation unterstützen aber "decreaseKey". Daher muss ich wohl _siftup manuell ausführen. Das stört mich an sich nicht, aber ich muss das entsprechende Element erst mittels "index" suchen, was recht viel Zeit kosten dürfte. Kann ich das Verringern des Wertes besser implementieren? Habe ich das Konzept der Heaps als Vorrangwarteschlange da irgendwie falsch verstanden?
2. So eine Map ist zwar nicht unbedingt langsam, aber dennoch hässlich. Zwei Dicts zu nutzen ist mehr als hässlich, das geht mit OOP natürlich viel einfacher, aber - wie oben gesagt - von Nodes zu erben ist auch keine gute Idee. Kann ich das da irgendwie schöner machen?
Hoffe ich habe meine Probleme ausführlich und klar genug beschrieben;
Grüße, Keba.
Ich bin gerade dabei eine Lib zu schreiben, die etliche Algorithmen und einige Tools implementieren soll: pyreia. Das ganze steckt noch sehr in den Kinderschuhen, soll heißen: Ich weiß selbst, dass da noch einiges recht schlecht ist.
Ich habe einige Basis-Node-Klassen, die die wichtigsten Eigenschaften eines Nodes implementieren. Node.children ist z. B. ein Dictionary bestehend aus Kindern (keys) und den Kosten ein Kind zu erreichen (values).
Daher hatte ich um den A*-Algorithmus zu implementieren gedacht, dass ich eine Klasse names ANode erstelle, die von Node erbt und dann entsprechende Attribute hat (f, g, h etc). Der Algorithmus lief auch wunderbar, allerdings ist mir aufgefallen, dass ich dann einen konzeptionellen Fehler habe. Was mache ich denn z.B. wenn ich einen weiteren Algorithmus implementiere? Diese erbt dann wieder von Node und alles funktioniert gut. Und wenn ich nun einen Baum habe, auf dem ich mehrere Algorithmen laufen lassen will?
Also dachte ich mir, dass ich A* eben funktional (FP) implementiere. Dazu hab ich heapq etwas angepasst um eine cmp_func übergeben zu können. Dann braucht man an sich keine Klassen mehr dafür.
Zur eigentlichen Frage: Meine derzeitige A*-Implementation ist nicht sonderlich schön. Sie funktioniert zwar, aber ich finde mind. zwei Dinge extrem hässlich:
1. Hier möchte ich den Wert eines Heap-Elements verringen. Weder heapq noch meine Implementation unterstützen aber "decreaseKey". Daher muss ich wohl _siftup manuell ausführen. Das stört mich an sich nicht, aber ich muss das entsprechende Element erst mittels "index" suchen, was recht viel Zeit kosten dürfte. Kann ich das Verringern des Wertes besser implementieren? Habe ich das Konzept der Heaps als Vorrangwarteschlange da irgendwie falsch verstanden?
2. So eine Map ist zwar nicht unbedingt langsam, aber dennoch hässlich. Zwei Dicts zu nutzen ist mehr als hässlich, das geht mit OOP natürlich viel einfacher, aber - wie oben gesagt - von Nodes zu erben ist auch keine gute Idee. Kann ich das da irgendwie schöner machen?
Hoffe ich habe meine Probleme ausführlich und klar genug beschrieben;
Grüße, Keba.