我目前正在编写一种算法,该算法通过使用Python的A *搜索算法来解决8谜题游戏。但是,当我计时代码时,发现get_manhattan_distance
花费的时间非常长。
我使用cProfile
为Python运行了我的代码,结果低于该程序输出的结果。 Here is a gist解决我的问题。
通过使用Numpy数组而不是Python的列表进行复制,我已经使我的程序更加高效。我不太清楚如何使这一步骤更有效率。我当前的get_manhattan_distance
代码是
def get_manhattan(self):
"""Returns the Manhattan heuristic for this board
Will attempt to use the cached Manhattan value for speed, but if it hasn't
already been calculated, then it will need to calculate it (which is
extremely costly!).
"""
if self.cached_manhattan != -1:
return self.cached_manhattan
# Set the value to zero, so we can add elements based off them being out of
# place.
self.cached_manhattan = 0
for r in range(self.get_dimension()):
for c in range(self.get_dimension()):
if self.board[r][c] != 0:
num = self.board[r][c]
# Solves for what row and column this number should be in.
correct_row, correct_col = np.divmod(num - 1, self.get_dimension())
# Adds the Manhattan distance from its current position to its correct
# position.
manhattan_dist = abs(correct_col - c) + abs(correct_row - r)
self.cached_manhattan += manhattan_dist
return self.cached_manhattan
其背后的想法是,3x3网格的目标难题如下:
1 2 3
4 5 6
7 8
在有空白图块的地方(该空白图块在int数组中由0表示)。所以,如果我们有一个难题:
3 2 1
4 6 5
7 8
它的曼哈顿距离应该为6。这是因为3离它应该在的位置两个地方。 1离应有的地方两个。 5是应该离开的地方,而6是应该离开的地方。因此,2 + 2 +1 + 1 = 6。
不幸的是,此计算需要很长时间,因为有成千上万的不同电路板。有什么方法可以加快计算速度吗?
答案 0 :(得分:1)
在我看来,您只需要为整个木板计算一次完整的曼哈顿距离总和-对于第一个木板。之后,您将通过交换两个相邻的数字,从现有的实体中创建新的Board
实体。新板上的曼哈顿总距离将仅因这两个数字的曼哈顿距离变化之和而不同。
如果其中一个数字是空白(0
),则总距离将变化一到一个或一个,这取决于非空白数字是更靠近其适当位置还是离其更远。如果两个数字都是非空白的(例如,当您制作“双胞胎”时),则总距离将变化为负两个,零个或两个。
这就是我要做的:在manhattan_distance = None
上添加一个Board.__init__
自变量。如果没有给出,计算板子的曼哈顿总距离;否则,只需存储给定的距离即可。创建不带此参数的第一块板。从现有的木板创建新木板时,请计算总距离的变化并将结果传递给新木板。 (cached_manhattan
无关紧要。)
这应该使与距离有关的计算总数减少很多-我希望它可以使速度提高几倍,更大的板子尺寸也可以。