【发布时间】:2018-02-27 07:10:18
【问题描述】:
我编写了一个用于解决滑动块/n 谜题的 a-star 算法。它在小谜题上运行良好,但随着复杂性的增加而陷入困境。
我已经实现了几种提高效率的方法(heapq 等),但我的想法已经走到了尽头。你能想到我还能做些什么来改进它吗?
我的代码在这里: https://repl.it/@Jaspirian/SimilarWoodenMemoryallocator
一些重要的部分:
启发式:
def heuristic_estimate_manhattan(self, other):
"""
Finds the heuristic estimation of the cost to reach another state from this one.
This heuristic is based on "manhattan distance."
"""
estimate = 0
for index in range(len(self.blocks)):
estimate += abs(other.blocks[index][0] - self.blocks[index][0]) + abs(other.blocks[index][1] - self.blocks[index][1])
return estimate
邻域函数:
def get_neighbors(self, previous):
"""
Gets all adjacent neighbors of the state, minus the previous.
This function gives 7 neighbors: 4 orthogonal, 4 diagonal, with the previous state trimmed.
"""
neighbors = []
moves = ((-1,0),(1,0),(0,-1),(0,1))
zeroLoc = self.blocks[0]
for move in moves:
# swap 0 and whatever
newBlocks = copy.deepcopy(self.blocks)
newZeroLoc = (zeroLoc[0] + move[0], zeroLoc[1] + move[1])
# skip this state if we've moved off the board
if newZeroLoc[0] < 0 or newZeroLoc[1] < 0 or newZeroLoc[0] > self.width-1 or newZeroLoc[1] > self.height-1:
# print("we've moved off the board.")
continue
# skip this state if it's the same as the previous
if previous and previous.blocks[0] == newZeroLoc:
# print("this is just the same!")
continue
# move the 0
newBlocks[0] = newZeroLoc
# move whatever's in that location...
# to the previous one
for face, location in newBlocks.items():
if face != 0 and location == newZeroLoc:
newBlocks[face] = zeroLoc
neighbor = Block_Puzzle(newBlocks)
neighbors.append(neighbor)
return neighbors
a-star 算法:
def aStar(start, goal):
"""
A star search algorithm. Takes a start state and an end state.
While there are available moves, loops through them and exits if the end is found.
Returns the list of states that are the "quickest" way to the end.
"""
...
openHeap = [start]
heapq.heapify(openHeap)
...
# While there are yet nodes to inspect,
while(len(openHeap) > 0):
# Pop the lowest f-score state off.
current = heapq.heappop(openHeap)
# print(len(openHeap))
# If we've reached the goal:
if current == goal:
# return the list of states it took to get there.
...
return path
# make sure we won't visit this state again.
closedDict[current] = True
# For each possible neighbor of our current state,
for neighbor in current.get_neighbors(cameFrom.get(current)):
# Skip it if it's already been evaluated
if neighbor in closedDict:
continue
# Add it to our open heap
heapq.heappush(openHeap, neighbor)
tentative_gScore = gScore[current] + 1
# If it takes more to get here than another path to this state, skip it.
if tentative_gScore >= gScore[neighbor]:
continue
# If we got to this point, add it!
cameFrom[neighbor] = current
gScore[neighbor] = tentative_gScore
fScore[neighbor] = gScore[neighbor] + neighbor.heuristic_estimate_manhattan(goal)
return None
【问题讨论】:
-
IDA* 在这个问题上比 A* 快。借助强大的启发式算法,您可以使用 IDA* 获得非常好的性能。
-
为此我将自己限制在 A*,但我同意 IDA* 更胜一筹。
标签: python performance a-star