人工智能与及应用.docx

上传人:b****3 文档编号:26428867 上传时间:2023-06-19 格式:DOCX 页数:9 大小:27.54KB
下载 相关 举报
人工智能与及应用.docx_第1页
第1页 / 共9页
人工智能与及应用.docx_第2页
第2页 / 共9页
人工智能与及应用.docx_第3页
第3页 / 共9页
人工智能与及应用.docx_第4页
第4页 / 共9页
人工智能与及应用.docx_第5页
第5页 / 共9页
点击查看更多>>
下载资源
资源描述

人工智能与及应用.docx

《人工智能与及应用.docx》由会员分享,可在线阅读,更多相关《人工智能与及应用.docx(9页珍藏版)》请在冰豆网上搜索。

人工智能与及应用.docx

人工智能与及应用

 

实验报告

|

|

 

实验名称图搜索问题求解

课程名称人工智能及应用

一、实验目的及要求

熟悉PROLOG语言的特点和某种PROLOG编程环境;掌握编写与调试简单的PROLOG程序的方法。

通过设计、编写和调试了解PROLOG编译器;掌握PROLOG语言中常量、变量的表示方法和PROLOG进行事实库、规则库的编写方法。

加深对逻辑程序运行机理的理解,掌握PROLOG语言的特点,熟悉其编程环境。

针对实际应用问题,分析题目背景,利用编程实现图搜索技术的问题求解方法,以牢固掌握图搜索技术的基本原理和常用算法,加深对图搜索技术的理解。

实验要求采用PROLOG编程求解8*8骑士周游问题以及农夫、狼、羊、菜问题。

采用熟悉的高级语言编程实现“过河问题”、“九宫格”等问题的求解。

二、所用仪器、设备

计算机、TRINC-PROLOG及高级语言程序设计环境。

三、实验原理

1.8*8骑士周游问题求解,以squre(x,y)表示骑士的位置,然后寻找一条是否存在的路径判断是否存在此路径的周游方法。

通过x与y的值的范围,判断是否可以向左右方向移动,达到求解周游的问题。

2.农夫、狼、羊、菜问题求解,采用宽度优先搜索算法,寻找一条安全的路径,农夫把三物品从河的一岸送到对岸,设计状态state(x,y,z,w)表示当前四物所处在的状态,按照算法寻找出最后的路径。

3.四皇后问题解决,封装Queen类,包括皇后个数,以及皇后位置是否正确而的判断方法,然后再主方法中调用方法即可。

4.极大极小方法求解井字棋问题,对状态空间采用最大最小值搜索,计算机在生成的子节点中选择评估函数值最大的节点,而计算机在选择着数时使人选择评估函数值最小的节点,也就是对计算机一方最不利的节点。

四、实验方法与步骤

1.8*8骑士周游问题,通过当前点的坐标范围判断是否可以向“加一”,“加二”方向移动,而实现8*8周游问题的解决。

通过对横纵坐标的范围,确定是否可以对其进行移动而得到判断,只需要写好对应的坐标变化,然后与当前要移动的坐标是否合一,而确定是否存在这样的路径。

Path()则是对于在两坐标判断是否存在其中的路径然后对其蕴含式的解析。

当path(x,y)的x与y参数相同是则退出。

实现算法:

move(squre(Row,Column),squre(New_Row,New_Column)):

-

Row=<6,New_RowisRow+2,Column=<7,New_ColumnisColumn+1.

move(squre(Row,Column),squre(New_Row,New_Column)):

-

Row=<6,New_RowisRow+2,Column>=2,New_ColumnisColumn-1.

move(squre(Row,Column),squre(New_Row,New_Column)):

-

Row>=3,New_RowisRow-2,Column=<7,New_ColumnisColumn+1.

move(squre(Row,Column),squre(New_Row,New_Column)):

-

Row>=3,New_RowisRow-2,Column>=2,New_ColumnisColumn-1.

move(squre(Row,Column),squre(New_Row,New_Column)):

-

Row=<7,New_RowisRow+1,Column=<6,New_ColumnisColumn+2.

move(squre(Row,Column),squre(New_Row,New_Column)):

-

Row=<7,New_RowisRow+1,Column>=3,New_ColumnisColumn-2.

move(squre(Row,Column),squre(New_Row,New_Column)):

-

Row>=2,New_RowisRow-1,Column=<6,New_ColumnisColumn+2.

move(squre(Row,Column),squre(New_Row,New_Column)):

-

Row>=2,New_RowisRow-1,Column>=3,New_ColumnisColumn-2.

been(squre(0,0)).

path(X,X).

path(X,Y):

-move(X,Z),not(been(Z)),dynamic(knight_tour,been/1),asserta(knight_tour,been(Z)),path(Z,Y).

2.农夫、狼、羊、菜过河问题,定义状态state(x,y,z,w)表示四个物体当前所在的位置(河东还是河西用e跟w表示),move(state(x,y,z,w),state(u,v,w,g))表示从和的一岸向另一岸移动,当然移动必须满足要求,移动之后的状态必须处在一个安全的状态,用unsafe(state())来检测所处位置是否安全,并且是农夫与移动的物体一起移动,采用go(start,goal)表示从现在开始的状态以及要达到的目标态而进行路径搜索,path(Open_queue,Closed_set,Goal)表示移动路径所需要满足的条件之一,即就是本宽度算法中的open,closed表,当然在本算法中涉及到队列的各种方法,拼接,判空等操作都需要在算法中给予具体的实现。

具体实现的算法为:

move(state(X,X,G,C),state(Y,Y,G,C)):

-opp(X,Y).

move(state(X,W,X,C),state(Y,W,Y,C)):

-opp(X,Y).

move(state(X,W,G,X),state(Y,W,G,Y)):

-opp(X,Y).

move(state(X,W,G,C),state(Y,W,G,C)):

-opp(X,Y).

unsafe(state(X,Y,Y,C)):

-opp(X,Y).

unsafe(state(X,W,Y,Y)):

-opp(X,Y).

opp(e,w).

opp(w,e).

go(Start,Goal):

-empty_queue(Empty_open_queue),

enqueue([Start,nil],Empty_open_queue,Open_queue),

empty_set(Closed_set),

path(Open_queue,Closed_set,Goal).

path(Open_queue,_,_):

-empty_queue(Open_queue),

write("Nosolutionfoundwiththeserules").

path(Open_queue,Closed_set,Goal):

-

dequeue([State,Parent],Open_queue,_),State=Goal,

write("Asolutionisfound:

"),nl,

printsolution([State,Parent],Closed_set).

%printsolution1(Closed_set).

path(Open_queue,Closed_set,Goal):

-

dequeue([State,Parent],Open_queue,Rest_open_queue),

get_children(State,Rest_open_queue,Closed_set,Children),

add_list_to_queue(Children,Rest_open_queue,New_open_queue),

union([[State,Parent]],Closed_set,New_closed_set),

path(New_open_queue,New_closed_set,Goal).

get_children(State,Rest_open_queue,Closed_set,Children):

-

bagof(Child,moves(State,Rest_open_queue,Closed_set,Child),Children).

moves(State,Rest_open_queue,Closed_set,[Next,State]):

-

move(State,Next),not(unsafe(Next)),

not(member_queue([Next,_],Rest_open_queue)),

not(member_set([Next,_],Closed_set)).

%printsolution1(L):

-empty_set(L).

%printsolution1([H|T]):

-printsolution1(T),write(H),nl.

 

printsolution([State,nil],_):

-write(State),nl.

printsolution([State,Parent],Closed_set):

-

member_set([Parent,Grandparent],Closed_set),

printsolution([Parent,Grandparent],Closed_set),

write(State),nl.

 

empty_set([]).

member_set([State,Parent],[[State,Parent]|_]).

member_set(X,[_|T]):

-member_set(X,T).

empty_queue([]).

enqueue(E,[],[E]).

enqueue(E,[H|T],[H|Tnew]):

-enqueue(E,T,Tnew).

dequeue([State,Parent],[[State,Parent]|T],T).

add_list_to_queue(List,Queue,New_queue):

-append(Queue,List,New_queue).

append(X,Y,Z):

-X=[],Z=Y.

append(X,Y,Z):

-X=[A|B],Z=[A|W],append(B,Y,W).

 

member(X,[X|T]).

member(X,[_|T]):

-member(X,T).

member_queue(Element,Queue):

-member(Element,Queue).

 

union([],Set,Set).

union([H|T],S,Snew):

-union(T,S,S2),add_if_not_in_set(H,S2,Snew).

add_if_not_in_set(X,S,S):

-member(X,S),!

.

add_if_not_in_set(X,S,[X|S]).

3.四皇后问题,在类中封装方法,boolbCanPlace(intk),oidBackTrack(intk),voidPrintX(void),实现实现对皇后位置的检测,最后打印出结果为每行皇后的位置的列即就是为一个有效的序列。

主要方法:

classQueen{

friendintnQueen(int);

private:

boolbCanPlace(intk);

voidBackTrack(intk);

voidPrintX(void);

intn,*x,sum;

};

boolQueen:

:

bCanPlace(intk)//判断是否合法

{

boolbOk=true;

for(inti=1;i

{

if((abs(k-i)==abs(x[k]-x[i]))||(x[k]==x[i]))

{

bOk=false;

break;

}

}

returnbOk;

}

4.极大极小值求井字棋问题,voidInit()棋盘初始化函数,voidPrintQP()打印棋盘函数voidUserInput()用户输入落子位置函数,这三份方法程序中当前的棋局进行读写操作;ntIsWin(States)判断当前棋局是否有一方获胜,并判断哪一方获胜的函数,inte_fun(States)评估函数值计算函数,当前的棋局进行判断;intAutoDone()极大极小值算法主函数,计算机决定在哪个位置落子所采用的核心算法,并且可以判断计算机落子前后棋局的状态,如果在搜索树的深度范围内能判断哪一方必胜,则可提前打印输赢信息,并结束本棋。

主要方法:

intIsWin(States)//有人赢了吗?

返回0表示没有人赢,返回-1表示人赢了,返回1表示计算机赢了

{

for(inti=0;i<3;i++)

{

if(s.QP[i][0]==1&&s.QP[i][1]==1&&s.QP[i][2]==1)return1;

if(s.QP[i][0]==-1&&s.QP[i][1]==-1&&s.QP[i][2]==-1)return-1;

}

for(i=0;i<3;i++)

{

if(s.QP[0][i]==1&&s.QP[1][i]==1&&s.QP[2][i]==1)return1;

if(s.QP[0][i]==-1&&s.QP[1][i]==-1&&s.QP[2][i]==-1)return-1;

}

if((s.QP[0][0]==1&&s.QP[1][1]==1&&s.QP[2][2]==1)||(s.QP[2][0]==1&&s.QP[1][1]==1&&s.QP[0][2]==1))return1;

if((s.QP[0][0]==-1&&s.QP[1][1]==-1&&s.QP[2][2]==-1)||(s.QP[2][0]==-1&&s.QP[1][1]==-1&&s.QP[0][2]==-1))return-1;

return0;

}

inte_fun(States)//评估函数

{

boolflag=true;

for(inti=0;i<3;i++)

for(intj=0;j<3;j++)

if(s.QP[i][j]==0)flag=false;

if(flag)returnNO_BLANK;

if(IsWin(s)==-1)return-MAX_NUM;//如果计算机输了,返回最小值

if(IsWin(s)==1)returnMAX_NUM;//如果计算机赢了,返回最大值

intcount=0;//该变量用来表示评估函数的值

//将棋盘中的空格填满自己的棋子,既将棋盘数组中的0变为1

for(i=0;i<3;i++)

for(intj=0;j<3;j++)

if(s.QP[i][j]==0)tmpQP[i][j]=1;

elsetmpQP[i][j]=s.QP[i][j];

//电脑一方

//计算每一行中有多少行的棋子连成3个的

for(i=0;i<3;i++)

count+=(tmpQP[i][0]+tmpQP[i][1]+tmpQP[i][2])/3;

//计算每一列中有多少列的棋子连成3个的

for(i=0;i<3;i++)

count+=(tmpQP[0][i]+tmpQP[1][i]+tmpQP[2][i])/3;

//斜行有没有连成3个的?

count+=(tmpQP[0][0]+tmpQP[1][1]+tmpQP[2][2])/3;

count+=(tmpQP[2][0]+tmpQP[1][1]+tmpQP[0][2])/3;

//将棋盘中的空格填满对方的棋子,既将棋盘数组中的0变为-1

for(i=0;i<3;i++)

for(intj=0;j<3;j++)

if(s.QP[i][j]==0)tmpQP[i][j]=-1;

elsetmpQP[i][j]=s.QP[i][j];

//对方

//计算每一行中有多少行的棋子连成3个的

for(i=0;i<3;i++)

count+=(tmpQP[i][0]+tmpQP[i][1]+tmpQP[i][2])/3;

//计算每一列中有多少列的棋子连成3个的

for(i=0;i<3;i++)

count+=(tmpQP[0][i]+tmpQP[1][i]+tmpQP[2][i])/3;

//斜行有没有连成3个的?

count+=(tmpQP[0][0]+tmpQP[1][1]+tmpQP[2][2])/3;

count+=(tmpQP[2][0]+tmpQP[1][1]+tmpQP[0][2])/3;

returncount;

}

五、实验结果

图一八骑士周游结果一

图二八骑士周游结果二

图三农夫、狼、羊、菜问题结果

图四四皇后的一个解

 

图五下棋过程截图

六、讨论与结论

通过本次实验,对在人工智能课上学习的内容有了更加深刻的理解,真正的学习必须得自己在实践中寻找问题发现问题,最终解决问题,我们要的不是一个答案,而是发现答案的过程,在不断的出错中不断的进步才是学习的进步。

通过在实验中对课上学习的内容的实践,真正的体会算法的作用图搜索算法的作用,在一般的计算方式下,计算模式是多么不科学,时间耗费,是否最优的达到时间以及空间的复杂度,解决实际的问题,首先的抽象出问题的数学模型,转化为数学计算,最后运用程序设计语言设计数据模型,将问题抽象解决。

当然在这个过程中,需要付出时间与精力,在本实验的过程中,由于对prolog语言不太熟悉,所以在真正的写算法的过程中遇到了很多的问题,并且在编写的过程中也是出现了很多的错误,最后通过向老师请教,一步一步的改进与进步,最终实现了部分功能。

高级语言设计部分,因为比较的了解,相对来说比较的容易一些。

 

展开阅读全文
相关资源
猜你喜欢
相关搜索

当前位置:首页 > 教学研究 > 教学案例设计

copyright@ 2008-2022 冰豆网网站版权所有

经营许可证编号:鄂ICP备2022015515号-1