人工智能导论——A*算法实验
一、实验目的:
熟悉和掌握启发式搜索的定义、估价函数和算法过程,并利用A*算法求解N数码难题,理解求解流程和搜索顺序。
二、实验原理:
A*算法是一种启发式图搜索算法,其特点在于对估价函数的定义上。对于一般的启发式图搜索,总是选择估价函数f值最小的节点作为扩展节点。因此,f是根据需要找到一条最小代价路径的观点来估算节点的,所以,可考虑每个节点n的估价函数值为两个分量:从起始节点到节点n的实际代价以及从节点n到达目标节点的估价代价。
A*算法中,若对所有的x存在h(x)≤h*(x),则称h(x)为的下限,表示某种偏于保守的估计。采用的下限h(x)为启发函数的A算法,称为A*算法,其中限制:h(x)≤h*(x)十分重要,它能保证A*算法找到最优解。在本问题中,g(x)相对容易得到,就是从初始节点到当前节点的路径代价,即当前节点在搜索树中的深度。关键在于启发函数h(x)的选择,A*算法的搜索效率很大程度上取决于估价函数h(x)。一般而言,满足h(x)≤h*(x)前提下,h(x)的值越大越好,说明其携带的启发性信息越多,A*算法搜索时扩展的节点就越少,搜索效率就越高。
传统的BFS是选取当前节点在搜索树中的深度作为g(x),但没有使用启发函数h(x),在找到目标状态之前盲目搜索,生成了过多的节点,因此搜索效率相对较低。
本实验分别使用不在位的元素个数和曼哈顿距离作为启发函数h(x)。每次从open表中选取时,优先选取估价函数最小的状态来扩展。
A*算法的估价函数可表示为:
f'(n) = g'(n) + h'(n)
这里,f'(n)是估价函数,g'(n)是起点到终点的最短路径值(也称为最小耗费或最小代价),h'(n)是n到目标的最短路经的启发值。由于这个f'(n)其实是无法预先知道的,所以实际上使用的是下面的估价函数:
f(n) = g(n) + h(n)
其中g(n)是从初始结点到节点n的实际代价,h(n)是从结点n到目标结点
的最佳路径的估计代价。在这里主要是h(n)体现了搜索的启发信息,因为g(n)是已知的。用f(n)作为f'(n)的近似,也就是用g(n)代替g'(n),h(n)代替h'(n)。这样必须满足两个条件:
(1)g(n)>=g'(n)(大多数情况下都是满足的,可以不用考虑),且f必须保持单调递增。
(2)h必须小于等于实际的从当前节点到达目标节点的最小耗费h(n)<=h'(n);第
二点特别的重要。可以证明应用这样的估价函数是可以找到最短路径的。
具体步骤:从初始状态S_0出发,分别采用不同的操作符作用于生成新的状态x并将其加入open表中(对应到状态空间图中便是根节点生成新的子节点n) ,接着从open表中按照某种限制或策略选择一个状态x使操作符作用于x又生成了新的状态并加入open表中(状态空间图中相应也产生了新的子节点),如此不断重复直到生成目标状态。
对于以上所述的“某种策略”,在图搜索过程中,若该策略是依据进行排序并选取最小的估价值,则称该过程为A算法。
三、实验内容:
1 参考A*算法核心代码(原程序输出如下图1),以8数码问题为例实现A*算法的求解程序,要求设计两种不同的估价函数。
两种启发函数h(x):
①不在位的元素个数
int calw(string s) //计算该状态的不在位数h(n)
{
int re=0;
for(int i=0;i<9;i++) if(s[i]!=t[i]) re++;
return re;
}
②曼哈顿距离
int distance(string s) {
int count=0,begin[3][3],end[3][3]; //count记录所有棋子移动到正确位置需要的步数
for(int i = 0; i < 8; i++){
begin[i/3][i%3]=s[i];
end[i/3][i%3]=t[i];
}
for(int i = 0; i < 3; i++) //检查当前图形的正确度
for(int j = 0; j < 3; j++)
{
if(begin[i][j] == 0)
continue;
else if(begin[i][j] != end[i][j])
{
for(int k=0; k<3; k++)
for(int w=0; w<3; w++)
if(begin[i][j] == end[k][w])
count = count + fabs(i-k*1.0) + fabs(j-w*1.0);
}
}
return count ;
}
图1 原程序输出
2 在求解8数码问题的A*算法程序中,增加初始状态和目标状态逆序对数奇偶性判断,然后设置相同的初始状态和目标状态(如下图2所示),针对不同的估价函数,求得问题的解,并比较它们对搜索算法性能的影响,包括扩展节点数、生成节点数等,参考输出如下图3所示。
计算逆序对:
int num(string s){
int a = 0;
for (int i = 0; i < 9; i++){
if (s[i] == '0')
continue;
for (int j = i+1; j < 9; j++)
{
if (s[j] == '0')continue;
if (s[i]>s[j]) a++;}
}
return a;
}
若逆序对的奇偶性不一样,则返回报错(写在solve函数中):
int k1=num(t);
int k2=num(p.s);
if(k1%2 != k2%2)
{cout<<"有错"<<endl;
return -1;
}
目标状态设定:
const string t="123456780";
初始状态:
“486703215”
初始状态 目标状态
图2
不同启发函数性能比较如表2
表2不同启发函数比较
启发函数h(n) |
|||
不在位数 |
曼哈顿距离 |
广度优先(0) |
|
初始状态 |
486703215 |
486703215 |
486703215 |
目标状态 |
123456780 |
123456780 |
123456780 |
最优解 |
|
|
|
扩展节点数 |
10374 |
2183 |
102659 |
生成节点数 |
15715 |
3506 |
123849 |
运行时间 |
0.297s |
0.159s |
1.742s |
3 对于8数码问题,设置与上述2相同的初始状态和目标状态,用宽度优先搜索算法(即令估计代价h(n)=0的A*算法)求得问题的解,以及搜索过程中的扩展节点数、生成节点数。
即:h(n)=0
程序设定:p.w=0;
用宽度优先进行搜索的结果如上表。
- 参考A*算法核心代码,试修改成能求解15数码问题的代码,15数码问题的初始状态(初始棋局)和目标状态(目标棋局)如下,要求给出问题的解,以及搜索过程中的扩展节点数、生成节点数。
因为两位数的数字输出不太方便,把[1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,0]改为[
A,B,C,D,E,F,G,H,I,J,K,L,M,N,O],输入依旧以数字输入。
例如:11 9 4 15 1 3 0 12 7 5 8 6 13 2 10 14
5 1 3 4 2 6 7 8 9 10 12 0 13 14 11 15
运行了很久,发现用不在位数做启发函数,运行不出来。
用曼哈顿距离做启发函数,还是比较快的。
试验结果如图4
图4 15数码搜索结果
可知:生成节点数为:244266
扩展节点数为:126723
搜索时间为: 2.388s
5数码修改的部分代码:
6提交实验报告和源程序。
四、实验结果:
1 在求解8数码问题的A*算法程序中,增加初始状态和目标状态逆序对数奇偶性判断是否有解,然后设置相同的初始状态和目标状态,针对不同的估价函数,求得问题的解,并比较它们对搜索算法性能的影响,包括扩展节点数、生成节点数等。
在相同输入和目标情况下,结果比较如表3(来源表2)
表3不同估价函数结果比较
估价函数 |
不在位数 |
曼哈顿距离 |
宽度优先 |
扩展节点数 |
10374 |
2183 |
102659 |
生成节点数 |
15715 |
3506 |
123849 |
运行时间 |
0.297s |
0.159s |
1.742s |
扩展节点为count1,生成节点为count2,实验结果和要求的节点数均在实验内容2中。
输入和目标相同时,可得曼哈顿距离做估价函数比不在位数做估价函数更好,曼哈顿距离做估价函数的生成节点和扩展节点只有两三千,不在位数做估价函数的生成节点和扩展节点都超过了一万,可知搜索空间也少很多,曼哈顿做估价函数的效率高很多。
2 根据宽度优先搜索算法和A*算法,分析启发式搜索的特点。
广度优先搜索法在有解的情形总能保证搜索到最短路经,也就是移动最少步数的路径。但广度优先搜索法的最大问题在于搜索的结点数量太多,因为在广度优先搜索法中,每一个可能扩展出的结点都是搜索的对象。随着结点在搜索树上的深度增大,搜索的结点数会很快增长,并以指数形式扩张,从而所需的存储空间和搜索花费的时间也会成倍增长。
我们可以发现采用A*算法求解八数码问题时间以及搜索的节点数目远远小于采用宽度优先搜索算法,这说明对于八数码问题,选用的启发性信息有利于搜索效率的提高。
3 对比15数码和8数码问题,试分析A*算法求解不同问题规模的性能。
当使用不在位数做估价函数改进8数码代码,程序运行很长时间也没有结果。所以若问题规模过大,使用A星算法时要设计好估价函数,设计的不合适就会使搜索空间太大了,一直没有结果。本实验中采用曼哈顿距离做估价函数,搜索还是很快的,有20多万的生成节点和10多万的扩展节点,使用曼哈顿做估价函数效率很高,时间也只有2s多。
五实验总结:
通过这次实验,使我对启发式搜索算法有了更进一步的理解,尤其是对估价函数的应用和设计上有了一定的体会,一个合适高效的估价函数对于启发式搜索算法来说是十分重要的。
人工智能导论——A*算法实验相关推荐
- 人工智能导论罗马尼亚问题实验一搜索算法C++实现详解
人工智能导论搜索算法实验 使用说明 题目要求 开始写代码之前的思考: 建立图 考虑深度优先搜索策略: 给出DFS的代码: 主函数 运行结果如下: 考虑宽度优先搜索策略 实现代码 输出结果: 考虑迭代加 ...
- 图像恢复重建(浙大人工智能导论作业四)
图像恢复重建(浙大人工智能导论作业四) 实验思路代码有很多不完善之处,仅供学习参考 如果同是NKU2021人工智能导论的同学,可以跳过这篇博客,因为会等到实验截止之后笔者才会将实验的具体代码补全. 实 ...
- (AI)人工智能导论实验【A* 算法】
人工智能导论实验 文章目录 人工智能导论实验 A-star algorithm A-star algorithm 传送:看懂A*的网站 源码 """ 实验内容:假设在一个 ...
- 【人工智能导论】吃豆人游戏(上):对抗搜索与Minimax算法
吃豆人实验(The Pac-Man Project)简介 The Pac-Man projects were developed for UC Berkeley's introductory arti ...
- 人工智能导论实验二 食人族传教士过河+黑白棋 prolog+Python
实验目的及要求: 本项目要求能够理解人工智能的基本原理,理解状态空间的概念.原理和方法,掌握用状态空间表示问题的步骤,掌握搜索方法的基本原理,并能够实际问题给出具体的实现. 实验内容: 状态.状态空间 ...
- 人工智能导论实验2——野人渡河黑白棋问题
人工智能导论实验2--野人渡河&黑白棋问题 实验目的及要求: 本项目要求能够理解人工智能的基本原理,理解状态空间的概念.原理和方法,掌握用状态空间表示问题的步骤,掌握搜索方法的基本原理,并能够 ...
- 【AI】人工智能导论 小白零基础入门学习
Q1:我为什么开始学习AI?------------------- A1:虽然我目前在做苹果物联网的项目,但面临GTP-4的面世,深感人工智能是未来的发展趋势,如果不学习就会被淘汰,所以先提前布局,了 ...
- lr分析器的设计与实现实验报告_《计算机导论》课程实验报告(一维数组)
<计算机导论>课程实验报告 专业班级: 姓名: 学号: 实验类型:设计型实验 时间: 实验题目:一维数组 实验目的: 1.掌握数组定义.初始化和元素引用的方法: 2.掌握数组的输入.输出方 ...
- [渝粤教育] 西安理工大学 人工智能导论 参考 资料
教育 -人工智能导论-章节资料考试资料-西安理工大学[] 第一讲 人工智能概述单元测试 1.[单选题]人工智能中通常把( )作为衡量机器智能的准则. A.图灵机 B.图灵测试 C.中文屋思想实验 D. ...
最新文章
- 终于找到了一篇文章!通俗地讲解面向对象的工作原理
- 小F的2013应届校招历程小结
- 1055 The World‘s Richest (25 分)【难度: 一般 / 知识点: 多关键字排序】
- abaqus的python安装文件在哪_在abaqus2016中安装xlwt和xlrd库教程
- kubernetes学习笔记之七:Ingress-nginx部署使用
- vb.net datagridview数据批量导入sql_导入:Java实现大批量数据导入导出(100W以上)
- 基于Apache POI 从xlsx读出数据
- 【转】10分钟精通SharePoint - VS开发模板
- 2021公益数字化研究报告
- 安全是什么意思_进衡水火车站要转着圈找门!这是什么意思……清扫车路边倒水 既浪费又不安全...
- php生成静态页的方法
- 御剑后台扫描工具下载
- 神武手游哪个服务器人最多,神武4端游什么老区人最多
- C语言绘画示例-进度条
- handsome主题添加服务器信息,全屏响应式精美typecho主题handsome
- windows下引导盘安装雪豹
- linux jpg图片转base64,html中的图片直接使用base64编码后的字符串代替
- 源码资本宣布完成人民币四期38亿新基金募集
- Oracle数据库中的级联查询、级联删除、级联更新操作教程
- 【已解决】CentOS 7 安装MySQL80报错:mysql-community-icu-data-files = 8.0.28-1.el7 is needed by mysql-community
热门文章
- 什么是荟萃分析?荟萃分析与Meta分析有什么区别?
- 最全ChatGPT技术汇总
- 在windows下烧写嵌入式linux镜像sdcard.img到sd卡
- Java类加载原理解析
- 计算机英语反义词,计算机英语的学习方法
- 用python庆祝生日_吃重庆小面 庆祖国华诞丨我们用重庆特色,为祖国母亲送上祝福...
- 《Android多媒体应用开发实战详解:图像、音频、视频、2D和3D》——2.1节简析Android安装文件...
- win10,Anaconda2,Python2.7.14下rar,unrar安装成功!“LookupError: Couldn‘t find path to unrar library”错误消失
- 零基础可以学的vue(2)
- bbc 王超_BBC Microbit入门