python迷宫寻路_迷宫寻路问题——A*算法

迷宫寻路问题——A*算法

迷宫寻路问题是人工智能中的有趣问题,如何表示状态空间和搜索路径是寻路问题的重点,本文的主要内容是A*搜索算法的理解和应用,首先对基本知识和算法思想进行了解,再通过其对迷宫问题求解应用,编写 Python 程序进行深入学习。

1. 搜索区域

我们假设某个人要从 Start 点到达 End 点,存在墙壁把这两个点层层隔开,如下图所示,绿色部分代表起点 Start 和终点 End,红色部分代表它们之间的墙:

我们把这一块搜索区域分成了一个一个的方格,使搜索区域简单化,这正是寻找路径的第一步。这种方法将我们的搜索区域简化成了一个普通的二维数组。数组中的每一个元素表示对应的一个方格,该方格的状态被标记为可通过的和不可通过的。通过找出从 Start 点到 End 点所经过的方格,就能得到 Start->End 的路径。

2. Open 和 Closed 表

创建了一个简单的搜索区域后,A*算法有两个重要的数据列表:一个记录下所有被考虑来寻找最短路径的方格(称为 open列表)和一个记录下不会再被考虑的方格(称为 closed列表)。

首先在 closed 列表中添加起点位置,然后把所有与它当前位置相邻的可通行小方格添加到 open 列表中。在A*算法中,我们从起点开始,依次检查它的相邻方格,选取相邻方格然后继续向外扩展直到找到目的地。但是该选哪一个方格呢?我们需要一个评价值。

3. 路径评价

设置路径上的每个方格对应一个 评价值 F = G + H:

G 是从起点沿着已生成的路径到一个给定方格的移动开销,从起点开始到相邻方格的移动量为1,该值会随着离始点越来越远而增大。

H 是从当前方格到终点的移动估算值,被称为视探,因为我们并不能确定剩余移动开销是多少,它仅仅是一个估算值。移动量估算值离真实值越接近,最终的路径会更加精确。如果估计值停止作用,很可能生成的路径不会是最优的。

4. 算法流程

重复以下步骤,直到遍历到终点 End,找到最短路径:

选取当前 open 列表中评价值 F 最小的节点,将这个节点称为 S;

将 S 从 open 列表移除,然后添加 S 到 closed 列表中;

对于与 S 相邻的每一块可通行的方格节点 T:如果 T 在 closed 列表中,忽略;如果 T 不在 open 列表中,添加它然后计算出它的评价值 F;如果 T 已经在 open 列表中,当我们从 S 到达 T 时,检查是否能得到 更小的 F 值,如果是,更新它的 F 值和它的前继(parent = S)。

在此迷宫问题中,将使用 “曼哈顿距离”(也叫 “曼哈顿长” 或者 “城市街区距离” )作为 H 值,计算出距离终点水平和垂直方向上的方格数量和,忽略障碍物。这里 H 作为一种搜索的启发信息,搜索过程为广度优先搜索+贪心策略。当 End 被加入到 open 列表作为待检验节点时,表示路径被找到,此时应终止循环;或者当 open 列表为空,表明已无可以添加的新节点,而已检验过的节点中没有终点节点,则意味着无路径可达终点,此时也终止循环。从终点开始沿父节点回溯到起点,记录整个遍历中得到的节点坐标,便得到了最优路径。

5. 算法实现

输入地图:

基本的搜索流程:

# 查找路径的入口函数

def find_path(self):

# 构建开始节点

p = Node_Elem(None, self.s_x, self.s_y, 0.0)

while True:

# 扩展节点

self.extend_round(p)

# 如果open表为空,则不存在路径,返回

if not self.open:

return

# 取F值最小的节点

idx, p = self.get_best()

# 到达终点,生成路径,返回

if self.is_target(p):

self.make_path(p)

return

# 把此节点加入close表,并从open表里删除

self.close.append(p)

del self.open[idx]

选取 F 值最小的节点作为扩展节点,其中 G 是实际移动量,H 是估计剩余移动量,我们取用曼哈顿距离:

# 求距离

def get_dist(self, i):

# F = G + H

return i.dist + math.sqrt((self.e_x-i.x)*(self.e_x-i.x))+ math.sqrt((self.e_y-i.y)*(self.e_y-i.y))

当我们遍历到终点节点的时候,对路径进行回溯,就能得到最优路径:

# 生成路径

def make_path(self, p):

# 从终点回溯到起点,起点的parent为None

while p:

self.path.append((p.x, p.y))

p = p.parent

运行结果:

6. 总结

在本文的实例中,我们采用A*算法得到了最终路径,搜索过程为启发式广度优先搜索,节点选择上实质上为贪心算法。

你可能感兴趣的:(python迷宫寻路)