オリエンテーリングにA *検索を適用して、最適なルートを取得しようとしています。入力は2つのファイルです。1つは地形を説明する画像ファイルで、もう1つは標高を定義するテキストファイルです。事前に設定された値に基づいて地形の難易度を計算し、地形を移動できる速度を定義します。また、傾斜に基づいて高度の難易度を定義しました(傾斜が下がると速度が速くなり、その逆も同様です)。
地形と標高のデータは、マトリックス(リストのリスト)に保存されます。したがって、入力はマップ上のポイントと同じインデックスです。2つの入力が提供されます-例:
start = [230,327]
end = [241,347]
問題は、私のコードが、訪問したキューにすでに存在するノードを再訪問し続けることです。ノードは次のように定義されます。
class Node:
def __init__(self,value,parent,start=[],goal=[]):
self.children = []
self.parent = parent
self.value = value
self.timeToGoal = 0.0000
self.timeTravelled = 0.0000
if parent:
timeToParent = self.parent.timeTravelled
[parentX, parentY] = parent.value
[currentX, currentY] = self.value
xDiff = abs(currentX - parentX)
yDiff = abs(currentX - parentX)
distance = 12.7627
if xDiff == 0 and yDiff != 0:
distance = 10.29
elif xDiff != 0 and yDiff == 0:
distance = 7.55
# distanceFromParent = math.sqrt(((currentX - parentX) ** 2) - (currentY - parentY) ** 2)
speedFromParent = 1.388 * calculateTerrainDifficulty( terrainMap[currentX][currentY]) * calculateElevationDifficulty(elevationMap[parentX][parentY], elevationMap[currentX][currentY], distance)
timeTravelledFromParent = 0
if speedFromParent != 0:
timeTravelledFromParent = distance / speedFromParent
else:
"Error: Speed from Parent Cannot Be Zero"
self.timeTravelled = timeToParent + timeTravelledFromParent
self.path = parent.path[:]
self.path.append(value)
self.start = parent.start
self.goal = parent.goal
else:
self.path = [value]
self.start = start
self.goal = goal
def GetTime(self):
pass
def CreateChildren(self):
pass
また、関数を定義するためにSubNodeクラスを使用しました。時間は、自己到達までの時間+ゴールまでのピタゴラス斜辺距離として定義されています。
class SubNode(Node):
def __init__(self, value, parent, start=[], goal=[]):
super(SubNode, self).__init__(value, parent, start, goal)
self.timeToGoal = self.GetTime()
def GetTime(self):
if self.value == self.goal:
return 0
[currentX, currentY] = self.value
[targetX, targetY] = self.goal
parentTime = 0
if self.parent:
parentTime = self.timeTravelled
heuristicTime = 99999.99
# Pythagorean Hypotenuse - Straight-line Distance
distance = math.sqrt(((int(currentX) - int(targetX)) ** 2) + (int(currentY)- int(targetY)) ** 2)
speed = 1.38 * calculateTerrainDifficulty(terrainMap[currentX][currentY])
if speed != 0:
heuristicTime = distance / speed
heuristicTime=heuristicTime+parentTime
return heuristicTime
def CreateChildren(self):
if not self.children:
dirs = [-1, 0, 1]
[xVal, yVal] = self.value
for xDir in dirs:
newXVal = xVal + xDir
if newXVal < 0 or newXVal > 394: continue
for yDir in dirs:
newYVal = yVal + yDir
if ((xVal == newXVal) and (yVal == newYVal)) or (newYVal < 0 or newYVal > 499) or (
calculateTerrainDifficulty(terrainMap[newXVal][newYVal]) == 0):
continue
child = SubNode([newXVal, newYVal], self)
self.children.append(child)
A *検索クラスは次のように定義されました。ノードが再訪されないように条件をそこに入れたことがわかります。そこに印刷を入れると、条件が複数回満たされていることがわかります。
class AStarSearch:
def __init__(self, start, goal):
self.path = []
self.visitedQueue = []
self.priorityQueue = PriorityQueue()
self.start = start
self.goal = goal
def Search(self):
startNode = SubNode(self.start, 0, self.start, self.goal)
count = 0
self.priorityQueue.put((0, count, startNode))
while (not self.path and self.priorityQueue.qsize()):
closestChild = self.priorityQueue.get()[2]e
closestChild.CreateChildren()
self.visitedQueue.append(closestChild.value)
for child in closestChild.children:
if child.value not in self.visitedQueue:
count += 1
if not child.timeToGoal:
self.path = child.path
break
self.priorityQueue.put((child.timeToGoal, child.value, child))
if not self.path:
print("Not possible to reach goal")
return self.path
何らかの理由で、私のプログラムはいくつかのノードを再訪問し続けます(訪問したキューを印刷したときに出力からわかるように。これを回避するにはどうすればよいですか?
[230、327]、[231、326]、[229、326]、[231、325]、[231、328]、[229、328]、[231、327]、[229、327]、[ 231、327]、[229、327]、[229、325]、[231、324]、[230、323]、[231、329]、[229、329]、[231、327]、[229、 327]、[229、324]、[231、330]、[231、323]、[229、330]、[229、331]]
私が直面している別の問題はこれです:
TypeError: unorderable types: SubNode() < SubNode()
Pythonの優先度付きキューの使用を変更せずにこれを克服する方法はありますか?
子の代わりにclosestChildにテストを追加する必要があります。
closestChild = self.priorityQueue.get()[2]e
if closesChild.value not in self.visitedQueue:
closestChild.CreateChildren()
self.visitedQueue.append(closestChild.value)
それ以外の場合n1
はn2
、両方ともノードにリンクしていると言うことができますn3
。n3
に2回追加されるためpriorityqueue
、2回ポップされてから、に2回追加されvisitedQueue
ます。
この条件if child.value not in self.visitedQueue:
は、(優先度キューを小さくすることで)処理を高速化するのに役立ちますが、必須ではありません(不要なオブジェクトは、priorityQueue
それらをアンパイルするときに破棄されるため)。
発生するエラーについて:PriorityQueue
優先度付きキューに必要なカスタム順序付けをサポートしていないため、カスタム順序付けを作成する必要があります。ここに例があります。明らかに、_get_priority
関数はtimeTravelled
代わりに戻る必要がありますitem[1]
編集3:私たち(tobias_kと私)は最初に、Pythonがそれらの2つが等しいことを認識するように__eq__
関数を実装する必要があると言いSubNode
ましたが、self.visitedQueueに値のみを格納しているため、実際にはそうではありません。
この記事はインターネットから収集されたものであり、転載の際にはソースを示してください。
侵害の場合は、連絡してください[email protected]
コメントを追加