A*算法求解迷宫寻路问题(启发式算法)

A*算法求解迷宫寻路问题

  • 求点赞关注
  • 实验内容
  • 设置相关数据
    • 设置两种地图
    • 设置两种启发式函数
  • 性能分析
    • 分析不同起点终点
    • 分析不同启发式函数
    • 分析不同地图
  • 总结
  • 附录代码

A*算法求解迷宫寻路问题资源链接如右:A*算法求解迷宫寻路问题

求点赞关注

如果觉得这篇文章对你有帮助请点赞收藏加关注啊,真的很谢谢大家!大家可以进入我的CSDN主页查看其它文章,都是我在进行课后题目与课程设计时遇到的一些问题,如果你正在学习人工智能,一定会有所收获,并且可以在我的GitHub仓库主页下载相关代码,如无法进入GitHub仓库主页也可以进入Gitee进行查看,后续我也会根据需求不断完善。

lazyn的CSDN_blog_code(GitHub)
lazyn的CSDN_blog_code(Gitee)

同时如果想要系统化的学习人工智能,可以进入下面的网站进行学习

通俗易懂,风趣幽默的人工智能学习网站-床长人工智能教程

作为人工智能专业的学生,我认为该网站的课程设置足够专业与完整,由浅入深,基本涵盖了当前人工智能的热门领域并且在不断完善,目录简洁明了,大家可以对照目录进行查漏补缺,作为读者,我发现课程内容通俗易懂,风趣幽默,可以激发大家的学习兴趣。

实验内容

在一个n×m的迷宫里,入口坐标和出口坐标分别为(startx,starty)和(endx,eny),每一个坐标点有两种可能:0或1,其中0表示该位置允许通过,1表示该位置不允许通过。以寻路问题为例实现A*算法的求解程序,设计两种不同的估价函数。

设置相关数据

设置两种地图

根据题意,用矩阵设置两个地图。
地图1:设置5行5列的迷宫,代码如下:

a = np.mat([[0, 0, 0, 0, 0], 
            [1, 0, 1, 0, 1], 
            [0, 0, 1, 1, 1], 
            [0, 1, 0, 0, 0], 
            [0, 0, 0, 1, 0]])

地图2:设置20行20列的迷宫,代码如下

a = np.mat([[0, 1, 0, 1, 0, 1, 1, 0, 1, 1, 0, 0, 1, 1, 1, 0, 1, 1, 1, 1], 
            [0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 1, 0, 1, 0, 1, 0, 0, 0, 1, 1], 
            [0, 1, 0, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 0, 1, 1],
            [0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 1, 0, 1, 0, 0, 0, 1, 0, 1, 1],
            [1, 1, 1, 1, 0, 1, 0, 0, 1, 1, 1, 0, 0, 1, 1, 1, 0, 0, 1, 1],
            [0, 0, 1, 0, 0, 0, 0, 0, 1, 0, 1, 1, 1, 1, 0, 1, 1, 0, 0, 1],
            [0, 1, 0, 1, 0, 0, 0, 0, 1, 0, 1, 0, 0, 1, 0, 0, 1, 0, 1, 1],
            [1, 0, 0, 0, 0, 1, 0, 0, 0, 1, 1, 0, 0, 1, 1, 1, 1, 0, 0, 1],
            [0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 1, 1, 1, 0, 1],
            [0, 1, 0, 0, 1, 1, 1, 1, 1, 1, 0, 0, 0, 1, 0, 1, 1, 0, 1, 0],
            [0, 0, 1, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 0, 0, 0, 1],
            [0, 1, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 1, 1],
            [0, 1, 1, 1, 0, 1, 0, 1, 0, 0, 1, 1, 1, 0, 0, 1, 0, 0, 0, 0],
            [0, 0, 0, 0, 0, 1, 0, 1, 1, 1, 0, 1, 1, 1, 1, 1, 0, 0, 0, 1],
            [1, 1, 0, 1, 1, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1],
            [0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1],
            [0, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0],
            [0, 1, 0, 0, 1, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
            [1, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 1, 1, 0],
            [0, 0, 1, 1, 1, 1, 0, 0, 1, 1, 1, 1, 1, 0, 0, 1, 1, 0, 1, 0]])

设置两种启发式函数

定义估价函数
f ( n ) = g ( n ) + h ( n ) f(n)=g(n)+h(n) f(n)=g(n)+h(n)
式中, g ( n ) g(n) g(n)为起点到 n n n状态的最短路径代价的估计值, h ( n ) h(n) h(n) n n n状态到目的状态的最短路径代价的估计值。
g ( n ) g(n) g(n)为起点到 n n n状态的曼哈顿距离,代码如下:

def gs(i, j):
    return abs(i - startx) + abs(j - starty)

定义两种启发式函数。
启发式函数 h 1 ( n ) h_1 (n) h1(n) h 1 ( n ) = 10 × ( ∣ n x − e n d x ∣ + ∣ n y − e n d y ∣ ) h_1 (n)=10×(|n_x-endx|+|n_y-endy|) h1(n)=10×(nxendx+nyendy),代码如下:

def h1(i, j):
    return 10*(abs(i - endx) + abs(j - endy))

启发式函数 h 2 ( n ) h_2 (n) h2(n) h 2 ( n ) = ( n x − e n d x ) 2 + ( n y − e n d y ) 2 h_2 (n)=(n_x-endx)^2+(n_y-endy)^2 h2(n)=(nxendx)2+(nyendy)2,代码如下:

def h2(i, j):
    return pow(i - endx, 2) + pow(j - endy, 2)

性能分析

分析不同起点终点

采用地图2,具体如下图1,启发式函数 h 1 h_1 h1进行分析,分别设置起点为(0,0)和(9,5),终点为(20,20)、(18,20)。
A*算法求解迷宫寻路问题(启发式算法)_第1张图片

(0,0)→(20,20)的路径如图2,(9,5)→(18,20)的路径如图3。
A*算法求解迷宫寻路问题(启发式算法)_第2张图片
A*算法求解迷宫寻路问题(启发式算法)_第3张图片
两次寻路过程的性能分析如下表1。

路径 (0,0)→(20,20) (9,5)→(18,20)
扩展节点数 107 80
生成节点数 79 59
运行时间 0.001601705298526 0.000871252588694
由上述图表可知路径延长后运行时间会相对变长,扩展节点及生成节点也会相应增多,且两次寻找的路程有重合的部分,所以寻找到的路径为较优路径。

分析不同启发式函数

采用地图2,启发式函数 h 1 , h 2 h_1,h_2 h1h2进行分析,设置起点为(0,0),终点为(20,20),两次寻路过程的路径,扩展节点数、生成节点数和运行时间分别如下图4,图5。
A*算法求解迷宫寻路问题(启发式算法)_第4张图片
A*算法求解迷宫寻路问题(启发式算法)_第5张图片

由图表可知,两种启发式函数所用时间相近,但 h 2 h_2 h2相比 h 1 h_1 h1所扩展的节点数和生成的节点数会减少,仔细分析可以发现启发式函数 h 2 h_2 h2陷入的凹路径会少一些,更接近最优路径,但在远离目标点的路径行进时还是会陷进凹路径。

分析不同地图

上述过程一直采用地图2进行实验,为验证程序的普适性,现采用地图1进行实验。经过分析,选择上述较优的启发式函数 h 2 h_2 h2进行分析。寻路问题初始节点为(0,0),目标节点为(5,5),寻路路径如图5。
A*算法求解迷宫寻路问题(启发式算法)_第6张图片
应用启发式函数 h 2 h_2 h2对地图2的寻路路径彩绘图如下(因显示问题,第一行略去)。
A*算法求解迷宫寻路问题(启发式算法)_第7张图片

汇总上述性能报告如下表2。

地图 启发式函数 扩展节点数 生成节点数 运行时间
地图1 h 2 h_2 h2 14 13 0.0001113599
地图2 h 1 h_1 h1 107 79 0.0008827725
地图2 h 2 h_2 h2 103 71 0.0007970126

总结

A*算法在地图寻路问题中具有很好的优势,相比宽度优先搜索,效率更高,所耗时间更少,相比深度优先搜索,可以解决其不能找到最优解的不足,具有较高的应用价值。该算法的重点及难点就是启发式函数的选择,通过上述实验,可以发现启发式函数 h 2 h_2 h2相比 h 1 h_1 h1效果更好,但仍存在一些问题,需要继续找寻更优的启发式函数。

附录代码

主程序代码如下,其中用到的方法和地图在上述代码中已定义,故不再给出。设置不同的起点与终点需相应的更改startx,starty和endx,endy的值。

b = a
startx, starty = 1, 1
i = startx - 1
j = starty - 1
endx, endy = 20, 20
Open, Close = [[i + 1, j + 1]], [[i + 1, j + 1]]
Opens = [[i + 1, j + 1]]
road = 100
start = time.clock()
while(Open != []):  
    if(Open[-1] != [endx, endy]):
        Open = []
        minf = 10000
        if(i + 1 < len(a) and a[i + 1, j] == 0):
            f = gs((i + 1), j) + h2((i + 1), j)
            if([i + 2, j + 1] not in Close):
                Open.append([i + 2, j + 1])
            if(f < minf):
                minf = f
                i1 = i + 1
                j1 = j
        if(i - 1 >= 0 and a[i - 1, j] == 0):
            f = gs((i - 1), j) + h2((i - 1), j)
            if([i, j + 1] not in Close):
                Open.append([i, j + 1])
            if(f < minf):
                minf = f
                i1 = i - 1
                j1 = j
        if(j + 1 < len(a) and a[i, j + 1] == 0):
            f = gs(i, (j + 1)) + h2(i, (j + 1))
            if([i + 1, j + 2] not in Close):
                Open.append([i + 1, j + 2])
            if(f < minf):
                minf = f
                i1 = i
                j1 = j + 1
        if(j - 1 >= 0 and a[i, j - 1] == 0):
            f = gs(i, (j - 1)) + h2(i, (j - 1))
            if([i + 1, j] not in Close):
                Open.append([i + 1, j])
            if(f < minf):
                minf = f
                i1 = i
                j1 = j - 1
        b[i, j] = road
        road = road + 1
        i = i1
        j = j1
        Close.append([i + 1, j + 1])
        Opens.extend(Open)
    else:
        end = time.clock()
        b[endx - 1, endy - 1] = road + 1
        print("最短路径寻找成功,路径为:")
        for l in range(len(b)):
            for m in range(b[0].size):
                #0表示format中第一个元素,>表示右对齐输出,3表示占三个字符
                print("{0: >4}".format(b[l, m]), end = '')
            print('')
        print("扩展节点数为:", len(Opens))
        print("生成节点数为:", len(Close))
        print('用时为:', end - start)

        print('Close表为:', Close)
        print("点的移动轨迹为:")
        for k in range(len(Close)):
            if(k < len(Close) - 1):
                print(Close[k], "-->", end = '')
            else:
                print(Close[k])

        break
if(Open == []):
    print("最短路径寻找失败,失败位置为:", Close[-1], "路径为:", Close)

你可能感兴趣的:(机器学习,人工智能原理,1024程序员节,机器学习,ai,启发式算法)