人工智能实验报告2解读.docx
《人工智能实验报告2解读.docx》由会员分享,可在线阅读,更多相关《人工智能实验报告2解读.docx(23页珍藏版)》请在冰豆网上搜索。
人工智能实验报告2解读
昆明理工大学信息工程与自动化学院学生实验报告
(2012—2013学年第1学期)
课程名称:
人工智能开课实验室:
信自楼4452012年11月8日
年级、专业、班
学号
姓名
成绩
实验项目名称
八数码问题
指导教师
王剑
教师评语
该同学是否了解实验原理:
A.了解□B.基本了解□C.不了解□
该同学的实验能力:
A.强□B.中等□C.差□
该同学的实验是否达到要求:
A.达到□B.基本达到□C.未达到□
实验报告是否规范:
A.规范□B.基本规范□C.不规范□
实验过程是否详细记录:
A.详细□B.一般□C.没有□
教师签名:
年月日
一、上机目的及内容
1.上机内容:
用深度优先、广度优先、或者是其它方法实现八数码问题
2.上机目的
(1)掌握图搜索遍历过程
(2)掌握广度优先的算法和实现过程
(3)掌握深度优先的算法和实现过程
二、实验原理及基本技术路线图(方框原理图或程序流程图)
(1)建立一个只含有起始节点S的搜索图G,把S放到一个叫做OPEN的未扩展节点的表中;
(2)建立一个叫做CLOSED的已扩展节点表,其初始为空表;
(3)LOOP:
若OPEN表是空表,则失败退出;
(4)选择OPEN表上的第一个节点,把它从OPEN表移除并放进CLOSED表中,称此节点为节点n
(5)若n为一目标节点,则有解并成功退出,此解是追踪图G中沿着指针从n到S这条路径而得到的
(6)扩展节点n,同时生成不是n的祖先的那些后继节点的集合M。
把M的这些成员作为n的后继节点舔到图中;
(7)对那些未曾在G中出现过的M成员设置一个通向n的指针。
把M的这些成员加进OPEN表。
对已经在OPEN表或CLOSED表上的成员,确定是否需要更改通到n的指针方向;
(8)按某一任意方式或按某个探视值,重排OPEN表
宽度优先算法实现过程
(1)把起始节点放到OPEN表中;
(2)如果OPEN是个空表,则没有解,失败退出;否则继续;
(3)把第一个节点从OPEN表中移除,并把它放入CLOSED的扩展节点表中;
(4)扩展节点n。
如果没有后继节点,则转向
(2)
(5)把n的所有后继结点放到OPEN表末端,并提供从这些后继结点回到n的指针;
(6)如果n的任意一个后继结点是目标节点,则找到一个解答,成功退出,否则转向
(2)。
深度优先实现过程
(1)把起始节点S放入未扩展节点OPEN表中。
如果此节点为一目标节点,则得到一个解;
(2)如果OPEN为一空表,则失败退出;
(3)把第一个节点从OPEN表移到CLOSED表;
(4)如果节点n的深度等于最大深度,则转向
(2);
(5)扩展节点n,产生其全部后裔,并把它们放入OPEN表的前头。
如果没有后裔,则转向
(2);
(6)如果后继结点中有任一个目标节点,则得到一个解,成功退出,否则转向
(2)。
三、所用仪器、材料(设备名称、型号、规格等或使用软件),
1台PC及VISUALC++6.0或MATLAB软件
四、实验方法、步骤(或:
程序代码或操作过程)
方法一:
用C语言实现
#include
#include
#include
typedeflongUINT64;
typedefstruct
{
charx;//位置x和位置y上的数字换位
chary;//其中x是0所在的位置
}EP_MOVE;
#defineSIZE3//8数码问题,理论上本程序也可解决15数码问题,
#defineNUMSIZE*SIZE//但move_gen需要做很多修改,输入初始和结束状态的部分和check_input也要修改
#defineMAX_NODE1000000
#defineMAX_DEP100
#defineXCHG(a,b){a=a+b;b=a-b;a=a-b;}
#defineTRANS(a,b)
/*{longiii;(b)=0;for(iii=0;iii#defineRTRANS(a,b)\
{\
longiii;\
UINT64ttt=(a);\
for(iii=NUM-1;iii>=0;iii--)\
{\
b[iii]=ttt&0xf;\
ttt>>=4;\
}\
}//将一个64位整数a转换为数组b
//
typedefstructEP_NODE_Tag
{UINT64v;//保存状态,每个数字占4个二进制位,可解决16数码问题
structEP_NODE_Tag*prev;//父节点
structEP_NODE_Tag*small,*big;
}EP_NODE;
EP_NODEm_ar[MAX_NODE];
EP_NODE*m_root;
longm_depth;//搜索深度
EP_NODEm_out[MAX_DEP];//输出路径
//
longmove_gen(EP_NODE*node,EP_MOVE*move)
{longpz;//0的位置
UINT64t=0xf;
for(pz=NUM-1;pz>=0;pz--)
{if((node->v&t)==0)
{break;//找到0的位置
}
t<<=4;
}
switch(pz)
{case0:
move[0].x=0;
move[0].y=1;
move[1].x=0;
move[1].y=3;
return2;
case1:
move[0].x=1;
move[0].y=0;
move[1].x=1;
move[1].y=2;
move[2].x=1;
move[2].y=4;
return3;
case2:
move[0].x=2;
move[0].y=1;
move[1].x=2;
move[1].y=5;
return2;
case3:
move[0].x=3;
move[0].y=0;
move[1].x=3;
move[1].y=6;
move[2].x=3;
move[2].y=4;
return3;
case4:
move[0].x=4;
move[0].y=1;
move[1].x=4;
move[1].y=3;
move[2].x=4;
move[2].y=5;
move[3].x=4;
move[3].y=7;
return4;
case5:
move[0].x=5;
move[0].y=2;
move[1].x=5;
move[1].y=4;
move[2].x=5;
move[2].y=8;
return3;
case6:
move[0].x=6;
move[0].y=3;
move[1].x=6;
move[1].y=7;
return2;
case7:
move[0].x=7;
move[0].y=6;
move[1].x=7;
move[1].y=4;
move[2].x=7;
move[2].y=8;
return3;
case8:
move[0].x=8;
move[0].y=5;
move[1].x=8;
move[1].y=7;
return2;
}
return0;
}
longmov(EP_NODE*n1,EP_MOVE*mv,EP_NODE*n2)
//走一步,返回走一步后的结果
{
charss[NUM];
RTRANS(n1->v,ss);
XCHG(ss[mv->x],ss[mv->y]);
TRANS(ss,n2->v);
return0;
}
longadd_node(EP_NODE*node,longr)
{
EP_NODE*p=m_root;
EP_NODE*q;
while(p)
{q=p;
if(p->v==node->v)return0;
elseif(node->v>p->v)p=p->big;
elseif(node->vv)p=p->small;
}
m_ar[r].v=node->v;
m_ar[r].prev=node->prev;
m_ar[r].small=NULL;
m_ar[r].big=NULL;
if(node->v>q->v)
{q->big=&m_ar[r];
}
elseif(node->vv)
{q->small=&m_ar[r];
}
return1;
}
/*得到节点所在深度*/
longget_node_depth(EP_NODE*node)
{longd=0;
while(node->prev)
{d++;
node=node->prev;
}
returnd;
}
/*返回值:
成功-返回搜索节点数,节点数不够-(-1),无解-(-2)*/
longbfs_search(char*begin,char*end)
{longh=0,r=1,c,i,j;
EP_NODEl_end,node,*pnode;
EP_MOVEmv[4];//每个局面最多4种走法
TRANS(begin,m_ar[0].v);
TRANS(end,l_end.v);
m_ar[0].prev=NULL;
m_root=m_ar;
m_root->small=NULL;
m_root->big=NULL;
while((h{c=move_gen(&m_ar[h],mv);
for(i=0;i{mov(&m_ar[h],&mv[i],&node);
node.prev=&m_ar[h];
if(node.v==l_end.v)
{pnode=&node;
j=0;
while(pnode->prev)
{m_out[j]=*pnode;
j++;
pnode=pnode->prev;
}
m_depth=j;
returnr;
}
if(add_node(&node,r))r++;//只能对历史节点中没有的新节点搜索,否则会出现环
}
h++;
printf("\rSearch...%9d/%d@%d",h,r,get_node_depth(&m_ar[h]));
}
if(h==r)
{return-2;}
else
{return-1;}
}
longcheck_input(char*s,chara,longr)
{longi;
for(i=0;i{if(s[i]==a-0x30)return0;}
return1;
}
longcheck_possible(char*begin,char*end)
{charfs;
longf1=0,f2=0;
longi,j;
for(i=0;i{fs=0;
for(j=0;j
{
if((begin[i]!
=0)&&(begin[j]!
=0)&&(begin[j]}
f1+=fs;
fs=0;
for(j=0;j
{if((end[i]!
=0)&&(end[j]!
=0)&&(end[j]}
f2+=fs;
}
if((f1&1)==(f2&1))return1;
else
return0;
}
voidoutput(void)
{longi,j,k;
charss[NUM];
for(i=m_depth-1;i>=0;i--)
{RTRANS(m_out[i].v,ss);
for(j=0;j{for(k=0;k{printf("%2d",ss[SIZE*j+k]);
}
printf("\n");
}
printf("\n");
}
}
intmain(void)
{chars1[NUM];
chars2[NUM];
longr;
chara;
printf("请输入开始状态:
");
r=0;
while(r{a=getchar();
if(a>=0x30&&a<0x39&&check_input(s1,a,r))
{s1[r++]=a-0x30;
printf("%c",a);
}
}
printf("\n请输入结束状态:
");
r=0;
while(r{a=getchar();
if(a>=0x30&&a<0x39&&check_input(s2,a,r))
{s2[r++]=a-0x30;
printf("%c",a);
}
}
printf("\n");
if(check_possible(s1,s2))
{r=bfs_search(s1,s2);
printf("\n");
if(r>=0)
{printf("查找深度=%d,所有的方式=%ld\n",m_depth,r);
output();
}
elseif(r==-1)
{printf("没有找到路径.\n");
}
elseif(r==-2)
{printf("这种状态变换没有路径到达.\n");
}
else
{printf("不确定的错误.\n");
}
}
else
{printf("不允许这样移动!
\n");
}
return0;
}
方法二:
用MATLAB实现
program8no_bfs;{八数码的宽度优先搜索算法}
Const
Dir:
array[1..4,1..2]ofinteger{四种移动方向,对应产生式规则}
=((1,0),(-1,0),(0,1),(0,-1));
n=10000;
Type
T8no=array[1..3,1..3]ofinteger;
TList=record
Father:
integer; {父指针}
dep:
byte; {深度}
X0,Y0:
byte;{0的位置}
State:
T8no; {棋盘状态}
end;
Var
Source,Target:
T8no;
List:
array[0..10000]ofTList;{综合数据库}
Closed,open,Best:
integer{Best表示最优移动次数}
Answer:
integer;{记录解}
Found:
Boolean;{解标志}
procedureGetInfo;{读入初始和目标节点}
vari,j:
integer;
begin
fori:
=1to3do
forj:
=1to3doread(Source[i,j]);
fori:
=1to3do
forj:
=1to3doread(Target[i,j]);
end;
procedureInitialize;{初始化}
varx,y:
integer;
begin
Found:
=false;
Closed:
=0;open:
=1;
withList[1]dobegin
State:
=Source;dep:
=0;Father:
=0;
Forx:
=1to3do
Fory:
=1to3do
ifState[x,y]=0thenBeginx0:
=x;y0:
=y;End;
end;
end;
FunctionSame(A,B:
T8no):
Boolean;{判断A,B状态是否相等}
Vari,j:
integer;
Begin
Same:
=false;
Fori:
=1to3doforj:
=1to3doifA[i,j]<>B[i,j]thenexit;
Same:
=true;
End;
Functionnot_Appear(new:
tList):
boolean;{判断new是否在List中出现}
vari:
integer;
begin
not_Appear:
=false;
fori:
=1toopendoifSame(new.State,List[i].State)thenexit;
not_Appear:
=true;
end;
procedureMove(n:
tList;d:
integer;varok:
boolean;varnew:
tList);
{将第d条规则作用于n得到new,OK是new是否可行的标志}
varx,y:
integer;
begin
X:
=n.x0+Dir[d,1];
Y:
=n.y0+Dir[d,2];
{判断new的可行性}
ifnot((X>0)and(X<4)and(Y>0)and(Y<4))thenbeginok:
=false;exitend;
OK:
=true;
new.State:
=n.State;{new=Expand(n,d)}
new.State[X,Y]:
=0;
new.State[n.x0,n.y0]:
=n.State[X,Y];
new.X0:
=X;new.Y0:
=Y;
end;
procedureAdd(new:
tList);{插入节点new}
begin
ifnot_Appear(new)thenBegin{如果new没有在List出现}
Inc(open);{new加入open表}
List[open]:
=new;
end;
end;
procedureExpand(Index:
integer;varn:
tList);{扩展n的子节点}
vari:
integer;
new:
tList;
OK:
boolean;
Begin
ifSame(n.State,Target)thenbegin{如果找到解}
Found:
=true;
Best:
=n.Dep;
Answer:
=Index;
Exit;
end;
Fori:
=1to4dobegin{依次使用4条规则}
Move(n,i,OK,new);
ifnotokthencontinue;
new.Father:
=Index;
new.Dep:
=n.dep+1;
Add(new);
end;
end;
procedureGetOutInfo;{输出}
procedureOutlook(Index:
integer);{递归输出每一个解}
vari,j:
integer;
begin
ifIndex=0thenexit;
Outlook(List[Index].Father);
withList[Index]do
fori:
=1to3dobegin
forj:
=1to3dowrite(State[i,j],'');
writeln;
end;
writeln;
end;
begin
Writeln('Total=',Best);
Outlook(Answer);
end;
procedureMain;{搜索主过程}
begin
Repeat
Inc(Closed);
Expand(Closed,List[Closed]);{扩展Closed}
Until(Closed>=open)orFound;
ifFoundthenGetOutInfo{存在解}
elseWriteln('noanswer');{无解}
end;
Begin
Assign(Input,'input.txt');ReSet(Input);
Assign(Output,'Output.txt');ReWrite(Output);
GetInfo;
Initialize;
Main;
Close(Input);Close(Output);
End.
五、实验结果
六、实验总结
通过实验问题的求解过程就是搜索的过程,采用适合的搜索算法是关键的,因为对求解过程的效率有很大的影响,包括各种规则、过程和算法等推理技术。
八数码问题中,将牌的移动来描述规则,是一种相对较简单的方法。
用广度优先算法实现八数码问题,其实是一种比较费劲的方式;然而深度优先将是一个很好的方法,利用深度优先不但减少了程序实现的时间,是一种不错的方式。
但最好的方式是启发式搜索方式实现,在很大程度上相对于前两种方式是一种非常好的实现方式,不但节省了时间,也节省了空间。
通过这次试验使我对搜索算法有了一定的了解,并对实现这个问题的执行过程有了更一步的认识。
也通过它解决了八数码问题,但在实际的过程中还存在很多问题,也看了一些辅助书籍,以后还要加强学习,加强理论与实际的练习。
总之,这次试验使我受益匪浅。
读书的好处
1、行万里路,读万卷书。
2、书山有路勤为径,学海无涯苦作舟。
3、读书破万卷,下笔如有神。
4、我所学到的任何有价值的知识都是由自学中得来的。
——达尔文
5、少壮不努力,老大徒悲伤。
6、黑发不知勤学早,白首方悔读书迟。
——颜真卿
7、宝剑锋从磨砺出,梅花香自苦寒来。
8、读书要三到:
心到、眼到、口到
9、玉不琢、不成器,人不学、不知义。
10、一日无书,百事荒废。
——陈寿
11、书是人类进步的阶梯。
12、一日不读口生,一日不写手生。
13、我扑在书上,就像饥饿的人扑在面包上。
——高尔基
14、书到用时方恨少、事非经过不知难。
——陆游
15、读一本好书,就如同和一个高尚