何昭霞 状态空间搜索 启发式搜索Word文档格式.docx
- 文档编号:19958052
- 上传时间:2023-01-12
- 格式:DOCX
- 页数:18
- 大小:250.10KB
何昭霞 状态空间搜索 启发式搜索Word文档格式.docx
《何昭霞 状态空间搜索 启发式搜索Word文档格式.docx》由会员分享,可在线阅读,更多相关《何昭霞 状态空间搜索 启发式搜索Word文档格式.docx(18页珍藏版)》请在冰豆网上搜索。
三、实验设备及软件
PC机一台、VisualStudio2012编程软件
四、设计方案
㈠题目
状态空间搜索8数码问题
㈡设计的主要思路
考虑广度优先算法:
(1)状态空间盲目搜索——宽度优先搜索
其基本思想是,从初始节点开始,向下逐层对节点进形依次扩展,并考察它是否为目标节点,再对下层节点进行扩展(或搜索)之前,必须完成对当层的所有节点的扩展。
再搜索过程中,未扩展节点表OPEN中的节点排序准则是:
先进入的节点排在前面,后进入的节点排在后面。
(2)宽度优先算法如下
首先把初始结点S0放入OPEN表中,然后若OPEN表为空,则搜索失败,问题无解,接着取OPEN表中最前面的结点N放在CLOSE表中,并冠以顺序编号n,若目标结点Sg=N,则搜索成功,问题有解。
若N无子结点,则重复取OPEN表中最前面的结点N放在CLOSE表中。
扩展结点N,将其所有子结点配上指向N的放回指针,依次放入OPEN表的尾部,然后重复取OPEN表中最前面的结点N放在CLOSE表中。
根据算法的中心思想进行程序设计,其流程图如下图所示。
㈢主要功能
使用C语言相关知识,将3*3的九宫格调整为某种有序的形式。
五、主要代码
#include<
stdlib.h>
memory.h>
structnode
{
intx,y;
intcntdif;
intstep;
intf[9];
intxy[3][3];
}
queue[10000];
intmap[3][3];
intdir[4][2]={{-1,0},{1,0},{0,1},{0,-1}};
intopen[10000];
intzz[9];
intf1,f2;
structnodesour,dest;
queue[tail].f[i*3+j]=queue[tail].xy[i][j]=ff[i*3+j];
queue[tail].step=HH.step+1;
queue[tail].x=sx;
queue[tail].y=sy;
queue[tail].cntdif=count(queue[tail].f,zz);
open[tail]=visit(queue[tail].f);
print(queue[tail].xy);
if(match(queue[tail]))
{
printf("
step(s):
%d!
\n"
queue[tail].step);
return;
}
qsort(queue+head,tail-head+1,sizeof(queue[0]),comp);
//排序,每次选择cntdif数目最小的扩展
intmain()
inti,j,a[9],b[9];
Pleaseinputthenitialstatus,input0tothevacantposition:
);
for(i=0;
i<
3;
i++)
for(j=0;
j<
j++)
scanf("
%d"
&
map[i][j]);
sour.xy[i][j]=map[i][j];
sour.f[i*3+j]=map[i][j];
a[i*3+j]=map[i][j];
if(map[i][j]==0)
sour.x=i;
sour.y=j;
sour.step=0;
tdif=0;
Pleaseinputthefinalstatus:
dest.xy[i][j]=map[i][j];
dest.f[i*3+j]=map[i][j];
b[i*3+j]=map[i][j];
zz[i*3+j]=map[i][j];
if((judge(a)+judge(b))&
1)
Thefinalstatuscannotbereached."
return0;
Thesearchingprocessis:
bfs();
六、测试结果及说明
七、实验体会
人工智能搜索可分为盲目搜索和启发式搜索。
盲目搜索算法有宽度优先算法、深度优先算法(有界深度优先算法),启发式搜索算法有A算法、A*算法。
我在本实验中,采用的是宽度优先(广度优先)算法,这种算法是按预定的控制策略进行,在搜素的过程中所获得的信息不用来改进控制策略。
由于搜索总是按预定的路线进行,没有考虑问题本身的特性,这种缺乏问题求解的针对性,需要进行全方位的搜索,而没有选择最优的搜索路径。
通过这次实验更加熟悉状态空间的宽度优先搜索、深度优先搜索和启发式搜索算法及计算机语言对常用数据结构如链表、队列等的描述应用。
因此,我对人工智能搜索有了更深的认识。
启发式搜索
理解和掌握A*算法。
在8数码问题中,利用策略函数判断搜索,并使用A*算法减少搜索目标。
启发式搜索A*算法
根据任务要求,该实验我采用A*搜索算法。
对于八数码问题的解决,首先要考虑是否有答案。
每一个状态可认为是一个1×
9的矩阵,问题即通过矩阵的变换,是否可以变换为目标状态对应的矩阵.由数学知识可知,可计算这两个有序数列的逆序值,如果两者都是偶数或奇数,则可通过变换到达,否则,这两个状态不可达。
这样,就可以在具体解决问题之前判断出问题是否可解,从而可以避免不必要的搜索。
如果初始状态可以到达目标状态,常用的状态空间搜索有深度优先和广度优先。
广度优先是从初始状态一层一层向下找,直到找到目标为止。
深度优先是按照一定的顺序前查找完一个分支,再查找另一个分支,以至找到目标为止。
在这里就要用到启发式搜索
启发中的估价是用估价函数表示的,如:
f(n)=g(n)+h(n)
其中f(n)是节点n的估价函数,g(n)是在状态空间中从初始节点到n节点的实际代价,h(n)是从n到目标节点最佳路径的估计代价。
在此八数码问题中,显然g(n)就是从初始状态变换到当前状态所移动的步数,估计函数f(n)我们就可采用当前状态各个数字牌不在目标状态未知的个数,即错位数。
1.状态的表示
在A*算法中,需要用到open表和closed表,特别是在open表中,待扩展节点间有很严格的扩展顺序。
因此在表示当前状态的变量中,与数据结构中的链表相似,必须要有能指向下一个扩展节点的指针,以完成对open表中元素的索引。
这里表示问题的结构体包括表示当前节点状态的DATA和指向open表中下一个待扩展节点的指针NEXT。
其中DATA中包括的内容采用一个的二维数组s[3][3]表示当前状态的具体信息。
而为了保证在搜索到目标状态后能够顺利复现寻优路径,当前状态的DATA中还应该包括一个指向其父节点的指针father,这样,才能在达到目标状态后,通过指针father逐层回溯到初始状态,即复现寻优路径。
2.启发函数的设计
根据A*算法的定义,启发函数应满足:
h(n)<
=h*(n)其中h*(n)表示从当前节点n到目标节点s_g的最优路径的实际代价。
3.规则库设计
0在某一位置时,能选择向左、向右、向上、向下移动中的哪几种策略进行移动,主要是由当前0所处位置(更具体地说是当前位置的行列号)和其祖父节点(为提高搜索效率,新扩展的节点应当至少不为其祖父节点)所决定的。
当然,按照A*算法的思想,每扩展出一个新节点,都要判断其是否为有效子节点,不为有效子节点的不能加入到open表中。
使用C++语言的相关知识,利用策略函数判断搜索,并使用A*算法减少搜索目标。
#include"
iostream"
stdlib.h"
conio.h"
#definesize3
usingnamespacestd;
//定义二维数组来存储数据表示某一个特定状态
typedefintstatus[size][size];
structSpringLink;
//定义状态图中的结点数据结构
typedefstructNode
statusdata;
//结点所存储的状态
structNode*parent;
//指向结点的父亲结点
structSpringLink*child;
//指向结点的后继结点
structNode*next;
//指向open或者closed表中的后一个结点
intfvalue;
//结点的总的路径
intgvalue;
//结点的实际路径
inthvalue;
//结点的到达目标的苦难程度
}NNode,*PNode;
//定义存储指向结点后继结点的指针的地址
typedefstructSpringLink
structNode*pointData;
//指向结点的指针
structSpringLink*next;
//指向兄第结点
}SPLink,*PSPLink;
PNodeopen;
PNodeclosed;
//开始状态与目标状态
statusstartt={0,1,2,3,4,5,6,7,8};
statustarget={1,4,2,3,5,8,6,7,0};
//初始化一个空链表
voidinitLink(PNode&
Head)
{Head=(PNode)malloc(sizeof(NNode));
Head->
next=NULL;
}//判断链表是否为空
boolisEmpty(PNodeHead)
{if(Head->
next==NULL)
returntrue;
else
returnfalse;
}//从链表中拿出一个数据
voidpopNode(PNode&
Head,PNode&
FNode)
if(isEmpty(Head))
{FNode=NULL;
}
FNode=Head->
next;
next=Head->
next->
FNode->
}//向结点的最终后继结点链表中添加新的子结点
voidaddSpringNode(PNode&
Head,PNodenewData)
PSPLinknewNode=(PSPLink)malloc(sizeof(SPLink));
newNode->
pointData=newData;
newNode->
child;
child=newNode;
}//释放状态图中存放结点后继结点地址的空间
voidfreeSpringLink(PSPLink&
Head)
{PSPLinktmm;
while(Head!
=NULL)
{tmm=Head;
Head=Head->
free(tmm);
}//释放open表与closed中的资源
voidfreeLink(PNode&
PNodetmn;
tmn=Head;
free(tmn);
{//首先释放存放结点后继结点地址的空间
freeSpringLink(Head->
child);
computeAllV
alue(udNewNode,theNode);
//将本结点加入后继结点链表
addNode(spring,udNewNode);
}//空的格子下边的格子向上移动
if(row!
=2)
PNodeduNewNode=(PNode)malloc(sizeof(NNode));
statusAEB(duNewNode,theNode);
changeAB(duNewNode->
data[row][col],duNewNode->
data[row+1][col]);
if(hasAnceSameStatus(duNewNode,theNode->
parent))
free(duNewNode);
//与父辈相同,丢弃本结点
duNewNode->
parent=theNode;
child=NULL;
alue(duNewNode,theNode);
addNode(spring,duNewNode);
//输出给定结点的状态
voidoutputStatus(PNodestat)
for(inti=0i<
3i++)
for(intj=0j<
3j++)
cout<
<
stat->
data[i][j]<
"
;
endl;
}//输出最佳的路径
voidoutputBestRoad(PNodegoal)
intdeepnum=goal->
gvalue;
if(goal->
parent!
outputBestRoad(goal->
parent);
第"
<
deepnum--<
层的状态:
"
outputStatus(goal);
voidAStar()
PNodetmpNode;
//指向从open表中拿出并放到closed表中的结点的指针PNodespring;
//tmpNode的后继结点链
PNodetmpLNode;
//tmpNode的某一个后继结点
PNodetmpChartNode;
PNodethePreNode;
//指向将要从closed表中移到open表中的结点的前一个结点指针
boolgetGoal=false;
//标识是否达到目标状态
longnumcount=1;
//记录从open表中拿出结点的序号
initial();
//对函数进行初始化
initLink(spring);
//对后继链表的初始化
tmpChartNode=NULL;
从open表中拿出的结点的状态及相应的值"
while(!
isEmpty(open))
{//从open表中拿出f值最小的元素,并将拿出的元素放入closed表中
popNode(open,tmpNode);
addNode(closed,tmpNode);
numcount++<
个状态是:
outputStatus(tmpNode);
其f值为:
tmpNode->
fvalue<
其g值为:
gvalue<
其h值为:
hvalue<
//如果拿出的元素是目标状则跳出循环
if(computeHValue(tmpNode)==0)
getGoal=true;
break;
//产生当前检测结点的后继(与祖先不同)结点列表,产生的后继结点的parent属性指向当前检测的结点
SpringLink(tmpNode,spring);
//遍历检测结点的后继结点链表
isEmpty(spring))
popNode(spring,tmpLNode);
//状态在open表中已经存在,thePreNode参数在这里并不起作用
if(inLink(tmpLNode,open,tmpChartNode,thePreNode))
addSpringNode(tmpNode,tmpChartNode);
if(tmpLNode->
tmpChartNode->
gvalue)
tmpChartNode->
parent=tmpLNode->
parent;
gvalue=tmpLNode->
fvalue=tmpLNode->
fvalue;
free(tmpLNode);
//状态在closed表中已经存在
elseif(inLink(tmpLNode,closed,tmpChartNode,thePreNode))
PNodecommu;
freeSpringLink(tmpChartNode->
popNode(thePreNode,commu);
addAscNode(open,commu);
}//新的状态即此状态既不在open表中也不在closed表中
addSpringNode(tmpNode,tmpLNode);
addAscNode(open,tmpLNode);
}//目标可达的话,输出最佳的路径
if(getGoal)
最佳路径长度为:
最佳路径为:
endl;
outputBestRoad(tmpNode);
//释放结点所占的内存
freeLink(open);
freeLink(closed);
getch();
AStar();
6、测试结果及说明
广度和深度优先搜索有一个很大的缺陷就是他们都是在一个给定的状态空间中穷举。
这在状态空间不大的情况下是很合适的算法,可是当状态空间十分大,且不预测的情况下就不可取了。
他的效率实在太低,甚至不可完成。
由于八数码问题状态空间共有9!
个状态,对于八数码问题如果选定了初始状态和目标状态,有9!
/2个状态要搜索,而采用A*算法则克服了这个缺陷。
它对每一个搜索的位置进行评估,得到最好的位置,再从这个位置进行搜索直到目标。
这样可以省略大量无畏的搜索路径,提到了效率。
在启发式搜索中,对位置的估价是十分重要的。
采用了不同的估价可以有不同的效果。
总之,这次实验让我对启发式搜索有了更深一步的认识,也对它的优势有了更深的体会。
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- 何昭霞 状态空间搜索 启发式搜索 状态 空间 搜索 启发式