631306050107侯甚男 启发式搜索 状态空间搜索课件.docx
- 文档编号:25202188
- 上传时间:2023-06-06
- 格式:DOCX
- 页数:31
- 大小:40.87KB
631306050107侯甚男 启发式搜索 状态空间搜索课件.docx
《631306050107侯甚男 启发式搜索 状态空间搜索课件.docx》由会员分享,可在线阅读,更多相关《631306050107侯甚男 启发式搜索 状态空间搜索课件.docx(31页珍藏版)》请在冰豆网上搜索。
631306050107侯甚男启发式搜索状态空间搜索课件
重庆交通大学计算机与信息学院
验证性实验报告
班级:
计软专业13级1班
学号:
631306050107
姓名:
侯甚男
实验项目名称:
启发式搜索A*算法
实验项目性质:
验证性实验
实验所属课程:
人工智能
实验室(中心):
软件中心实验室(语音楼8楼)
指导教师:
朱振国
实验完成时间:
2016年6月9日
一、实验目的
1、理解和掌握A*算法
2、掌握人工智能系统中问题的求解过程
二、实验内容及要求
1、实验内容:
在一个3*3的九宫中有1-8个数码及一个空格随即的摆放在其中的格子里,现在要求实验这个问题:
将该九宫格调整为某种有序的形式。
调整的规则是,每次只能将与空格(上、下、左、右)相邻的一个数字平移到空格中。
在8数码问题中,利用策略函数判断搜索,并使用A*算法减少搜索目标。
2、实验要求:
用选定的编程语言编写程序,利用策略函数判断搜索和A*算法实现状态空间搜索策略。
三、实验设备及软件
笔记本,MicrosoftVisualStudio2010
四、设计方案
(一)题目
在 3×3方格盘上,放有八个数码,剩下第九个为空,每一空格其上下左右的数码可移至空格。
要求解决的问题是:
给出一个初始状态和一个目标状态,找出一种从初始转变成目标状态的移动棋子步数最少的移动步骤。
所谓问题的一个状态就是棋子在棋盘上的一种摆法。
棋子移动后,状态就会发生改变。
解八数码问题实际上就是找出从初始状态到达目标状态所经过的一系列中间过渡状态。
解八数码的问题如果按正常的思维,采用盲目搜索的话,如上面实验的宽度优先搜索和深度优先搜索,不仅搜索的次数多,而且往往容易陷入死循环中,所以面对此问题需要一种策略——启发式搜索。
(二)启发式搜索策略
1、A*算法
A*(A-Star)算法是一种静态路网中求解最短路最有效的方法。
公式表示为:
f(x)=d(x)+w(x),
其中f(x)是节点x从初始点到目标点的估价函数,
d(x)是在状态空间中从初始节点到n节点的实际代价,
w(x是从x到目标节点最佳路径的估计代价。
保证找到最短路径(最优解的)条件,关键在于估价函数h(n)的选取:
估价值w(x)<=x到目标节点的距离实际值,这种情况下,搜索的点数多,搜索范围大,效率低。
但能得到最优解。
如果估价值>实际值,搜索的点数少,搜索范围小,效率高,但不能保证得到最优解。
估价值与实际值越接近,估价函数取得就越好。
例如对于几何路网来说,可以取两节点间欧几理德距离(直线距离)做为估价值,即f=g(n)+sqrt((dx-nx)*(dx-nx)+(dy-ny)*(dy-ny));这样估价函数f在g值一定的情况下,会或多或少的受估价值h的制约,节点距目标点近,h值小,f值相对就小,能保证最短路的搜索向终点的方向进行。
明显优于Dijstra算法的毫无无方向的向四周搜索。
其中
是当前被考察和扩展的结点
在搜索图中的节点深度,
是节点
与目标状态结点
相比较,错位的数字个数。
一般来说,某结点的
越大,说明它离目标节点越远。
2、主要代码的设计
定义goal数组为目标状态——{1,2,3,8,0,4,7,6,5}。
结构体Chessboard记录棋盘信息,其中变量pos数组坐标记录每个数码a的位置,其值为数码a。
d表示该棋盘的深度,f为启发函数值,move为父节点移动到该节点的方式,以便在输出时告诉用户该如何移动棋子知道目标状态。
2)structLNode:
定义节点LNode结构体,存放该节点状态时的棋盘信息board,和指向父节点、下一节点的指针(*parent,*next),以及标记量flag——值为true时表示该节点是最佳路径上的节点。
3)int*Findzero(LNode*&Node):
为方便找到空格,我设计了找到该函数Findzero(*&Node),以便找到当前节点空格所在位置以利于接下来的程序执行。
返回值为空格所在的行和列。
4)intWrong(LNode*Node)和intpick(LNode*Node):
分别为函数和。
5)LNode*extend(LNode*Node,intdepth,intzero[2],intmoveflag,intChoose)
树形方式扩展节点。
Node为要扩展的当前节点,depth为当前深度,zero存放该节点空格位置信息,moveflag即扩展节点的移动方式,Choose为选择函数还是。
6)voidInitList(LNode*&Open,LNode*&Close)和intListInsert(List&L,LNode*NewNode)
分别为表OPEN、CLOSE的创建和表的插入操作。
7)LNode*Getminf(List&L)
主要是实现从OPEN表中选择一个值最小的节点。
如果有几个节点值相同,当其中
有一个为目标节点时,则选择此目标节点;否则就选择其中任一个节点作为节点。
5、主要代码
#include
#include
#include
#defineOverflow1
#defineN3
intgoal[N][N]={1,2,3,8,0,4,7,6,5};
intzero[2],NodeQTY=0;
int*z=zero;//记录0的位置,zero[0]:
r行;zero[1]:
c列
typedefintPiece;
structChessboard{//棋盘信息
Piecepos[N][N];//记录每个数码a的位置r行c列
intd,f,move;//d:
深度;f:
启发函数值;move:
父节点移动到该节点的方式
};
structLNode{
Chessboardboard;
LNode*parent,*next;
boolflag;
};
typedefLNode*List;
int*Findzero(LNode*&Node)
{
inti,j,zr[2];
int*z=zr;
for(i=0;i for(j=0;j if(Node->board.pos[i][j]==0){ zr[0]=i+1; zr[1]=j+1; break; } } } returnz; } intWrong(LNode*Node) { intw=0,i,j; for(i=0;i for(j=0;j if(Node->board.pos[i][j]! =goal[i][j]&&Node->board.pos[i][j]! =0) w++; } } returnw; } intpick(LNode*Node) { intw=0,i,j,ii,jj; for(i=0;i for(j=0;j if(Node->board.pos[i][j]! =goal[i][j]&&Node->board.pos[i][j]! =0){ for(ii=0;ii for(jj=0;jj if(Node->board.pos[i][j]==goal[ii][jj]){ w=w+abs(ii-i)+abs(jj-j); break; } } } } returnw; } LNode*extend(LNode*Node,intdepth,intzero[2],intmoveflag,intChoose) { LNode*NewNode=newLNode; for(inti=0;i for(intj=0;j NewNode->board.pos[i][j]=Node->board.pos[i][j]; } } switch(moveflag) { case1: //向左移,不能出界: zero[1]>=2 New-Node->board.pos[zero[0]-1][zero[1]-1]=NewNode->board.pos[zero[0]-1][zero[1]-2]; NewNode->board.pos[zero[0]-1][zero[1]-2]=0; break; case2: //向右移,不能出界: zero[1]<=2 New-Node->board.pos[zero[0]-1][zero[1]-1]=NewNode->board.pos[zero[0]-1][zero[1]]; NewNode->board.pos[zero[0]-1][zero[1]]=0; break; case3: //向上移,不能出界: zero[0]>=2 New-Node->board.pos[zero[0]-1][zero[1]-1]=NewNode->board.pos[zero[0]-2][zero[1]-1]; NewNode->board.pos[zero[0]-2][zero[1]-1]=0; break; case4: //向下移,不能出界: zero[0]<=2 New-Node->board.pos[zero[0]-1][zero[1]-1]=NewNode->board.pos[zero[0]][zero[1]-1]; NewNode->board.pos[zero[0]][zero[1]-1]=0; break; } NewNode->board.d=depth+1; switch(Choose){ case1: NewNode->board.f=NewNode->board.d+Wrong(NewNode);break; case2: NewNode->board.f=NewNode->board.d+pick(NewNode);break; } NewNode->board.move=moveflag; NewNode->parent=Node; NodeQTY++; returnNewNode; } voidInitList(LNode*&Open,LNode*&Close) { Open=(List)malloc(sizeof(LNode)); Close=(List)malloc(sizeof(LNode)); if(! Open&&! Close) exit(Overflow); Open->next=NULL; Close->next=NULL; } intListInsert(List&L,LNode*NewNode) { Listp=L; while(p->next){ p=p->next; } NewNode->next=p->next; p->next=NewNode; returntrue; } LNode*Getminf(List&L) { Listp=L,q=L->next,r=L,min; min=q;//p,q寻找f最小值的指针,r指向表L中min前一个元素 if(! q) returnNULL; while(q) { if(min->board.f>q->board.f){ r=p; min=q; } p=q; q=q->next; } r->next=min->next; min->next=NULL; returnmin; } intmain() { inti,j,choose; ListOpen,Close; LNode*Best,*current; LNode*Start=newLNode; printf("\t\t\t八数码问题求解\n"); printf("\n请输入初始状态: "); for(i=0;i for(j=0;j scanf("%d",&(Start->board.pos[i][j])); } } printf("(注: Theflagofmovement--1: 左移;2: 右移;3: 上移;4: 下移)\n"); printf("初始棋盘状态: \n"); for(i=0;i for(j=0;j printf("|%d",Start->board.pos[i][j]); } printf("|\n"); } InitList(Open,Close); printf("请选择(1: A算法;2: A*算法): "); scanf("%d",&choose); Start->board.d=0; switch(choose){ case1: Start->board.f=Start->board.d+Wrong(Start);break; case2: Start->board.f=Start->board.d+pick(Start);break; }//Start->board.f=0+Wrong(Start); Start->board.move=0; Start->parent=NULL; Start->next=NULL; Start->flag=1; ListInsert(Open,Start);//将S加入到Open表中 while(Open->next){ Best=Getminf(Open); ListInsert(Close,Best); if(! (Best->board.f-Best->board.d)){ printf("$$$******有解! ******$$$\n"); break; } z=Findzero(Best); zero[0]=*(z+0);zero[1]=*(z+1); if(zero[1]>=N-1&&Best->board.move! =2) ListInsert(Open,extend(Best,Best->board.d,zero,1,choose)); if(zero[1]<=N-1&&Best->board.move! =1) ListInsert(Open,extend(Best,Best->board.d,zero,2,choose)); if(zero[0]>=N-1&&Best->board.move! =4) ListInsert(Open,extend(Best,Best->board.d,zero,3,choose)); if(zero[0]<=N-1&&Best->board.move! =3) ListInsert(Open,extend(Best,Best->board.d,zero,4,choose)); } printf("本算法搜索图中总共扩展的节点数为: %d\n",NodeQTY); printf("\t最佳路径如下所示: \n"); if(Open->next) { while(Best->parent){ Best->flag=1; Best=Best->parent; } Listp=Close->next,q=Close->next; if(p==Start)q=p->next; elseexit (1); intStep=0; while(p&&q)//在Close表中依标记找到路径 { if(q->flag==1&&q->parent==p){ printf("Step%d: 0moveas the%d-flagofmovement.\n",++Step,q->board.move); for(i=0;i for(j=0;j printf("|%d",q->board.pos[i][j]); } printf("|\n"); } p=q;//记住父节点 } q=q->next; } printf("到达目标状态! \n"); } elseprintf("该问题无法求解! \n"); } 六、实验体会 通过本次验证性实验,了解学习了A*算法,获益匪浅。 重庆交通大学计算机与信息学院 验证性实验报告 班级: 计软专业13级1班 学号: 631306050107 姓名: 侯甚男 实验项目名称: 状态空间搜索(8数码问题) 实验项目性质: 验证性实验 实验所属课程: 人工智能 实验室(中心): 软件中心实验室(语音楼8楼) 指导教师: 朱振国 实验完成时间: 2016年6月8日 一、实验目的 1、理解和掌握状态空间搜索的策略 二、实验内容及要求 1、实验内容: 在一个3*3的九宫中有1-8个数码及一个空格随即的摆放在其中的格子里,现在要求实验这个问题: 将该九宫格调整为某种有序的形式。 调整的规则是,每次只能将与空格(上、下、左、右)相邻的一个数字平移到空格中。 2、实验要求: 用选定的编程语言编写程序,利用不同的搜索策略进行状态空间搜索(如宽度优先搜索、深度优先搜索、有界深度优先搜索等)。 三、实验设备及软件 电脑,Eclipse 四、设计方案 1、宽度优先算法 1、把根节点放到队列的末尾。 2、每次从队列的头部取出一个元素,查看这个元素所有的下一级元素,把它们放到队列的末尾。 并把这个元素记为它下一级元素的前驱。 3、找到所要找的元素时结束程序。 4、如果遍历整个树还没有找到,结束程序。 2、深度优先算法 1、把根节点压入栈中。 2、每次从栈中弹出一个元素,搜索所有在它下一级的元素,把这些元素压入栈中。 并把这个元素记为它下一级元素的前驱。 3、找到所要找的元素时结束程序。 4、如果遍历整个树还没有找到,结束程序。 五、主要代码 #include"stdafx.h" #include"iostream" #include #include #include #include staticinttarget[9]={1,2,3,8,0,4,7,6,5}; //classdefinition classeight_num { private: intnum[9]; intnot_in_position_num; intdeapth; inteva_function; public: eight_num*parent; eight_num*leaf_next; eight_num*leaf_pre; eight_num(intinit_num[9]); eight_num(intnum1,intnum2,intnum3,intnum4,intnum5,intnum6,intnum7,intnum8,intnum9) { num[0]=num1; num[1]=num2; num[2]=num3; num[3]=num4; num[4]=num5; num[5]=num6; num[6]=num7; num[7]=num8; num[8]=num9; } eight_num(void) { for(inti=0;i<9;i++) num[i]=i; } voidcul_para(void); voidget_numbers_to(intother_num[9]); intget_nipn(void) { returnnot_in_position_num; } intget_deapth(void) { returndeapth; } intget_evafun(void) { returneva_function; } voidset_num(intother_num[9]); voidshow(void); eight_num&operator=(eight_num&); eight_num&operator=(intother_num[9]); intoperator==(eight_num&); intoperator==(intother_num[9]); }; //计算启发函数g(n)的值 voideight_num: : cul_para(void) { inti; inttemp_nipn=0; for(i=0;i<9;i++) if(num[i]! =target[i]) temp_nipn++; not_in_position_num=temp_nipn; if(this->parent==NULL) deapth=0; else deapth=this->parent->deapth+1; eva_function=not_in_position_num+deapth; } //构造函数1 eight_num: : eight_num(intinit_num[9]) { for(inti=0;i<9;i++) num[i]=init_num[i]; } //显示当前节点的状态 voideight_num: : show() { usingstd: : cout; cout< cout<<""; cout< cout<<""; cout< cout<<"\n"; cout< cout<<""; cout< c
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- 631306050107侯甚男 启发式搜索 状态空间搜索课件 631306050107 侯甚男 启发式 搜索 状态 空间 课件