传教士和野人问题
求解野人与传教士问题1
题目分析:
定义节点的结构:以取般的一个来回作为一步搜索,这样节点可由下面几个量进行描述:两岸的传教士人数和野人人数、本节点距离起始节点的距离,即由初始节点搜索几步后到达本节点。需要注意的是并不是所有节点都是可达的,题目中对可达节点作出了限制,只有两大 岸上的人数必须不能为负。
void goon(); //判断是否继续搜索
void main()
{
int flag; //标记扩展是否成功
for(;;)
{
initiate();
flag=search()
if(flag==1)
releasemem();
goon();
}
}
}
void initiate()
{
int x;
char choice;
uend=unopened=(struc SPQ*)malloc(sizeof(spq));
void releasemem(); //释放占用内存
void showresult(); //显示解
void addtoopened(struc SPQ *ntx); //将节点ntx从UNOPENED链表移至OPRNENED
//链表中
newnode -> sst = sst;
newnode -> spt = spt;
newnode -> ssr = 0
newnode -> spr = 0
试验七用Prolog求解传教士和野人问题
实验七用Prolog求解传教士和野人问题1、实验目的复习经典谓词演算中的归结原理,掌握人工智能程序设计语言Prolog,理解通过搜索求解问题实现人工智能的思想。
2、实验原理谓词演算中的消解法,3、实验内容设有3个传教士和3个野人同在河的左岸,他们都要到对岸去;河里只有一条船,他们都会划船,但每次渡船至多只能乘两人;如果在任何一边河岸上,野人的数量超过传教士,野人就要吃掉传教士,问怎样才能用船将3个传教士和3个野人从左岸都渡到右岸,又不会发生传教士被吃的事件呢?通过Prolog程序,给出乘船过河的动作序列。
4、实验步骤(1)设计该问题的状态。
例如:((左岸牧师数,左岸野人数),(右岸牧师数,右岸野人数),船的位置)。
(2)定义目标状态。
这里是:((0,0),(3,3),1)(3)描述可能的动作。
船上所能够载人的状态就是可能的操作。
用谓词move/2表示。
(4)判断合法状态(5)深度优先搜索三个传教士和三个野人的示例程序如下:move(1,0).move(0,1).move(0,2).move(2,0).move(1,1).legal((X,Y,_)):-legal1(X),legal1(Y).legal1((X,Y)):-X=:=0,Y>=0,!.legal1((X,Y)):-Y=:=0,X>=0,!.legal1((X,Y)):-X>=Y,X>=0,Y>=0.update((X,Y,0),Move,Statu1):-(A,B)=X,(C,D)=Y,(E,F)=Move,C1 is C+E,D1 is D+F,A1 is A-E,B1 is B-F,Statu1=((A1,B1),(C1,D1),1). update((X,Y,1),Move,Statu1):- (A,B)=X,(C,D)=Y,(E,F)=Move,C1 is C-E,D1 is D-F,A1 is A+E,B1 is B+F,Statu1=((A1,B1),(C1,D1),0). connect(Statu,Statu1):-move(X,Y),update(Statu,(X,Y),Statu1), legal(Statu1).findroad(X,X,L,L):-write(L). findroad(X,Y,L,L1):-connect(X,Z),not(member(Z,L)),findroad(Z,Y,[Z|L],L1).。
人工智能:野人与修道士问题
野人与修道士问题(Missionaries-and-Cannibals Problem )[修道士与野人问题]:三个野人与三个传教士来到河边,打算乘一只船从右岸渡到左岸去,该船的最大负载能力为两个人。
在任何时候,如果野人人数超过传教士人数,那么野人就会把传教士吃掉。
用状态空间法表示修道士与野人问题并设计编写计算机程序求问题的解。
问题分析:从上图可知,修道士、野人和船一共有六种可能,M L 、C L 、B L 、M R 、C R 、B R 。
可以表示为q =(M ,C ,B ),其中m 表示修道士的数目(0、1、2、3)、c 表示野人的数目(0、1、2、3)、b 表示船在左岸(1)或右岸(0)。
1、定义状态的描述形式:(m ,c ,b )2、表示所有可能的状态,并确定初始状态集和目标状态集:s0(3,3,1) s8(1,3,1) s16(3,3,0) s24(1,3,0)s1(3,2,1) s9(1,2,1) s17(3,2,0) s25(1,2,0)s2(3,1,1) s10(1,1,1) s18(3,1,0) s26(1,1,0)s3(3,0,1) s11(1,0,1) s19(3,0,0) s27(1,0,0)s4(2,3,1) s12(0,3,1) s20(2,3,0) s28(0,3,0)s5(2,2,1) s13(0,2,1) s21(2,2,0) s29(0,2,0)s6(2,1,1) s14(0,1,1) s22(2,1,0) s30(0,1,0)s7(2,0,1) s15(0,0,1) s23(2,0,0) s31(0,0,0)初始状态:(3,3,1)目标状态:(0,0,0)3、定义算符:L ij :把i 个修道士,j 个野人从河的左岸送到右岸R ij :把i 个修道士,j 个野人从河的右岸送到左岸整个问题就抽象成了怎样从初始状态经中间的一系列状态达到目标状态。
问修道士M野 人C 左L 右R题状态的改变是通过划船渡河来引发的,所以合理的渡河操作就成了通常所说的算符,根据题目要求,可以得出以下5个算符(按照渡船方向的不同,也可以理解为10个算符):渡1野人、渡1牧师、渡1野人1牧师、渡2野人、渡2牧师即:L01或R01,L10或R10,L11或R11,L02或R02,L20或R204、状态空间图:5、设计编写计算机程序求问题的解:算法:在应用状态空间表示和搜索方法时,用(M,C,B)来表示状态描述,其中M和C分别表示在左岸的传教士与野人数。
传教士(牧师)与野人问题-模拟人工智能实验_CSDN博客_传教士与野人问题
传教士(牧师)与野人问题-模拟人工智能实验_结缘缘的博客-CSDN博客_传教士与野人问题题目有n个牧师和n个野人准备渡河但只有一条能容纳c个人的小船为了防止野人侵犯牧师要求无论在何处牧师的人数不得少于野人的人数(除非牧师人数为0) 且假定野人与牧师都会划船试设计一个算法确定他们能否渡过河去若能则给出小船来回次数最少的最佳方案。
实验步骤输入牧师人数(即野人人数) n 小船一次最多载人量c。
输出若问题无解则显示Failed 否则显示Successed输出所有可行方案并标注哪一组是最佳方案。
用三元组(X1, X2, X3)表示渡河过程中的状态。
并用箭头连接相邻状态以表示迁移过程初始状态- 中间状态- 目标状态。
例当输入n 2 c 2时输出221- 200- 211- 010- 021- 000 其中X1表示起始岸上的牧师人数X2表示起始岸上的野人人数X3表示小船现在位置(1表示起始岸0表示目的岸)。
要求写出算法的设计思想和源程序并有用户界面实现人机交互控制台或者窗口都可以进行输入和输出结果如Please input n: 2 Please input c: 2 Optimal Procedure: 221- 200- 211- 010- 021- 000Successed or Failed?: Successed实现代码#include stdio.h #include iostream #include stdlib.h using namespace std;struct State { int Lsavage; int Lgodfather; int Rsavage; int Rgodfather; int boat; //boat at left 0 ; boat at right struct State *States new State[150];struct routesave { int savage; int godfather;struct routesave* routesaves new routesave[150];int godfather, savage, boatnum;void init(State m) { cout 请输入野人和牧师的人数n 以及船的最大载量c endl; int n, c; cin n c; m.Rgodfather n; m.Rsavage n; godfather n, savage n; boatnum c; m.Lgodfather m.Lsavage 0; m.boat 1;void boaloading(int i, int s, int g) { //s个野人和g个传教士if (States[i].boat 0) { routesaves[i].savage s*-1; //左边到右边是负数个野人routesaves[i].godfather g * -1; //左边到右边负数个传教士States[i 1].LsavageStates[i].Lsavage - s; States[i 1].Lgodfather States[i].Lgodfather - g; States[i 1].Rsavage States[i].Rsavage s; States[i 1].Rgodfather States[i].Rgodfather g; States[i 1].boat 1; else{ routesaves[i].savage s; //右边到左边是正数个野人routesaves[i].godfather g; //右边到左边正数个传教士States[i 1].Rsavage States[i].Rsavage-s; States[i 1].RgodfatherStates[i].Rgodfather - g; States[i 1].Lsavage States[i].Lsavage s; States[i 1].Lgodfather States[i].Lgodfather g; States[i 1].boat0;bool checkState(State m) { if (m.Rgodfather 0 m.Rgodfather m.Rsavage) return false; if (m.Lgodfather 0 m.Lgodfatherm.Lsavage) return false; else return true;void showSolution(int i) { cout 问题解决解决路径为endl; for (int c 0; c i; c ) { if (routesaves[c].savage 0) cout 第c 1 步routesaves[c].savage 个野人和routesaves[c].godfather 个传教士乘船去左边endl; else cout 第c 1 步routesaves[c].savage * -1 个野人和routesaves[c].godfather * -1 个传教士乘船去有右边endl; void nextstep(int i) { int c; if (i 150) cout 试探路径过大无法计算; exit(0); for (c 0; c i; c ) /*if the current state is same to previous,retrospect*/ if (States[c].Lsavage States[i].Lsavage States[c].Lgodfather States[i].Lgodfather States[c].Rsavage States[i].Rsavage States[c].Rgodfather States[i].Rgodfather States[c].boat States[i].boat) goto a; if (States[i].Rsavage 0 States[i].Rgodfather 0 States[i].boat 0) { showSolution(i); exit(0); if (States[i].boat 1) { //船在右边for (int s 1; s boatnum s States[i].Rsavage; s ) {//g 0 int g 0; boaloading(i, s, g); if (checkState(States[i 1])) { nextstep(i 1); for (int g 1; g boatnum g States[i].Rgodfather; g ) { //g! 0 for (int s 0; s boatnum - g s States[i].Rsavage s g; s ) { boaloading(i, s, g); if(checkState(States[i 1])) { nextstep(i 1); if (States[i].boat 0) { //船在左边for (int s 1; s boatnum s States[i].Lsavage; s ) {//g 0int g 0; boaloading(i, s, g); if (checkState(States[i 1])) { nextstep(i 1); for (int g 1; g boatnum g States[i].Lgodfather; g ) { //g! 0 for (int s 0; s boatnum - g s States[i].Lsavage s g; s ) { boaloading(i, s, g); if (checkState(States[i 1])) { nextstep(i 1);a:return;void main() { init(States[0]); nextstep(0);实验结果展示。
传教士和野人问题
传教士和野人问题传教士和野人问题(Missionaries and Cannibals)传教士和野人问题是一个经典的智力游戏问题。
在这个问题中,实际上隐含了这样一个条件:如果在河的某一岸只有野人,而没有传教士,也同样被认为是合法状态。
在具体书写某些条件时,为了简便,这一点有时并没有考虑,但我们默认这个条件是被考虑了的。
有N个传教士和N个野人来到河边准备渡河,河岸有一条船,每次至多可供k 人乘渡。
问传教士为了安全起见,应如何规划摆渡方案,使得任何时刻,在河的两岸以及船上的野人数目总是不超过传教士的数目。
即求解传教士和野人从左岸全部摆渡到右岸的过程中,任何时刻满足M(传教士数)?C(野人数)和M,C?k的摆渡方案。
设N,3,k,2,则给定的问题可用图1.2表示,图中L和R表示左岸和右岸,B,1或0分别表示有船或无船。
约束条件是:两岸上M?C,船上M,C?2。
图1.2 M,C问题实例由于传教士和野人数是一个常数,所以知道了一岸的情况,另一岸的情况也就知道了。
因此为了简便起见,在描述问题时,只描述一岸--如左岸--的情况就可以了。
另外,该问题我们最关心的是在摆渡过程中,两岸状态的变化情况,因此船上的情况并不需要直接表达出来。
在一次摆渡过程中,船上究竟有几个传教士和野人,可以通过两个相连的状态简单得到。
这样表达更简练,突出了问题的重点。
(1)综合数据库:用三元组表示左岸的情况,即(,,),其中0?,?3,?{0,1},其中表示在左岸的传教士人数,表示在左岸的野人数,,1表示船在左岸,,0表示船在右岸。
则此时问题描述可以简化为: (3,3,1)?(0,0,0)N,3的M,C问题,状态空间的总状态数为4×4×2,32,根据约束条件的要求,可以看出只有20个合法状态。
再进一步分析后,又发现有4个合法状态实际上是不可能达到的。
因此实际的问题空间仅由16个状态构成。
下表列出分析的结果:( ) ( ) ( 0 0 1)达不到( 0 0 0) (传教士均在右,船在( 0 1 0) 左) ( 0 2 0) ( 0 1 1) ( 0 3 0)达不到 ( 0 2 1) ( 1 0 0)不合法( 0 3 1) (右岸野人多) ( 1 0 1)不合法( 1 1 0) (右岸野人多) ( 1 2 0)不合法( 1 1 1) (左岸野人多) ( 1 2 1)不合法( 1 3 0)不合法(左岸野人多) (左岸野人多) ( 1 3 1)不合法( 2 0 0)不合法(左岸野人多) (右岸野人多) ( 2 0 1)不合法( 2 1 0)不合法(右岸野人多) (右岸野人多) ( 2 1 1)不合法( 2 3 0)不合法(右岸野人多) (右岸野人多) ( 2 2 1) ( 3 0 0) ( 2 3 1)不合法( 2 2 0) (左岸野人多) ( 3 1 0) ( 3 0 1)达不到 ( 3 2 0)( 3 1 1) ( 3 3 0)达不到 ( 3 2 1)( 3 3 1)规则集可以划分为两组:一组是从左岸到右岸,称为p操作,另一组是从右岸到左岸,称为q操作。
传教士野人问题参考答案
传教士野人问题参考答案传教士-野人问题有N个传教士和N个野人要过河,现在有一条船只能承载K个人(包括野人),K<N,在任何时刻,如果有野人和传教士在一起,必须要求传教士的人数多于或等于野人的人数。
设M为传教士的人数,C为野人的人数,用状态空间发求解此问题的过程如下:M、C = N,boat = k,要求M>=C且M+C <= K初始状态目标状态L R L RM 3 0 M 0 3C 3 0 C 0 3B 1 0 B 0 1(1)用三元组来表示(ML , CL , BL)其中0<=ML , CL <= 3 , BL ∈{ 0 , 1}(3 , 3 , 1) (0 , 0 , 0)(2)规则集合P10if ( ML ,CL , BL=1 ) then ( ML–1 , CL , BL –1 )P01if ( ML ,CL , BL=1 ) then ( ML , CL–1 , BL –1 )P11if ( ML ,CL , BL=1 ) then ( ML–1 , CL–1 , BL –1 )P20if ( ML ,CL , BL=1 ) then ( ML–2 , CL , BL –1 )P02if ( ML ,CL , BL=1 ) then ( ML , CL–2 , BL –1 )Q10if ( ML ,CL , BL=0 ) then ( ML+1 , CL , BL+1 )Q01if ( ML ,CL , BL=0 ) then ( ML , CL+1 , BL +1 )Q11if ( ML ,CL , BL=0 ) then ( ML+1 , CL +1, BL +1 )Q20 if ( ML ,CL , BL=0 ) then ( ML+2 , CL +2, BL +1 )Q02if ( ML ,CL , BL=0 ) then ( ML , CL +2, BL +1 )(3)寻找一个启发式函数引导规则的选用右岸总人数6 – ML – CL 两岸中传教士数目>=野人数目f =–∞其它f=3 f=2 f=1 f=1f=1 f=2 (3,3,(3,(2,(3,(3,2,(3,0,f=3 (3,1,f=2 (1,1,f=4 (2,2,f=2 (1,1,f=4 (2,2,f=2 (0,2,f=4 (0,3,f=3 (0,1,f=5(0,2,f=4 (0,0,f=3 (1,1,f=46.2.3 用状态空间法求解传教士和食人者问题例6-2 传教士和食人者问题(The Missionaries and Cannibals Problem)。
传教士野人问题
问题:野人过河问题属于人工智能学科中的一个经典问题,问题描述如下:有三个牧师(也有的翻译为传教士)和三个野人过河,只有一条能装下两个人的船,在河的任何一方或者船上,如果野人的人数大于牧师的人数,那么牧师就会有危险. 你能不能找出一种安全的渡河方法呢?解答一:一、算法分析先来看看问题的初始状态和目标状态,假设和分为甲岸和乙岸:初始状态:甲岸,3野人,3牧师;乙岸,0野人,0牧师;船停在甲岸,船上有0个人;目标状态:甲岸,0野人,0牧师;乙岸,3野人,3牧师;船停在乙岸,船上有0个人;整个问题就抽象成了怎样从初始状态经中间的一系列状态达到目标状态。
问题状态的改变是通过划船渡河来引发的,所以合理的渡河操作就成了通常所说的算符,根据题目要求,可以得出以下5个算符(按照渡船方向的不同,也可以理解为10个算符):渡1野人、渡1牧师、渡1野人1牧师、渡2野人、渡2牧师算符知道以后,剩下的核心问题就是搜索方法了,本文采用深度优先搜索,通过一个FindNext(…)函数找出下一步可以进行的渡河操作中的最优操作,如果没有找到则返回其父节点,看看是否有其它兄弟节点可以扩展,然后用Process(…)函数递规调用FindNext(…),一级一级的向后扩展。
搜索中采用的一些规则如下:1、渡船优先规则:甲岸一次运走的人越多越好(即甲岸运多人优先),同时野人优先运走;乙岸一次运走的人越少越好(即乙岸运少人优先),同时牧师优先运走;2、不能重复上次渡船操作(通过链表中前一操作比较),避免进入死循环;3、任何时候河两边的野人和牧师数均分别大于等于0且小于等于3;4、由于只是找出最优解,所以当找到某一算符(当前最优先的)满足操作条件后,不再搜索其兄弟节点,而是直接载入链表。
5、若扩展某节点a的时候,没有找到合适的子节点,则从链表中返回节点a的父节点b,从上次已经选择了的算符之后的算符中找最优先的算符继续扩展b。
二、基本数据结构仔细阅读问题,可以发现有些基本东西我们必须把握,例如:每时刻河两岸野人牧师各自的数目、船的状态、整个问题状态。
传教士与野人
实验题目:产生式设计——野人与传教士过河问题专业班级:计算机11-2 学生姓名. 吴璨No. 1137074实验目的:1.掌握人工智能的基础思想2.熟练应用程序实现人工智能3.强化实践能力产生式设计:1.实验语言环境:c语言2.数据结构:typedef struct{int m; //传教士在左岸的实际人数int c; //野人在左岸的实际人数int wz; //为1时船在左岸int sm; //船上传教士的实际人数int sc; //船上野人是实际人数}Baidu;3.算法设计(以一组较小数据为例,假设N=3,K=2)(1)设定状态变量及确定值域。
左岸的传教士数为m,则有m={0,1,2,3};对应右岸的传教士数为3—m;左岸的野人数为c,则有c={0,1,2,3};对应右岸野人数为3—c;左岸船数为b,故又有b={0,1};对应右岸的船数为1-b。
(2)确定状态组,分别列出初始状态集和目标状态集。
问题的状态可以用一个三元数组来描述,以左岸的状态来标记,即右岸的状态可以不必标出。
S k=(m, c, b)初始状态只有一个:S=(3,3,1),初始状态表示全部成员在河的的左岸;目标状态也只有一个:S=(0,0,0),表示全部成员从河的左岸全部渡河完毕。
(3)定义并确定操作集。
以河的左岸为基点来考虑,把船从左岸划向右岸定义为L(Sm,Sc)操作。
其中,第一下标Sm表示船载的传教士数,第二下标Sc表示船载的野人数;同理,从右岸将船划回左岸称之为R(Sm,Sc)操作,下标的定义同前。
(4)估计全部的状态空间数,并尽可能列出全部的状态空间。
在这个问题世界中,S={3,3,1}为初始状态,S=(0,0,0)为目标状态。
全部的可能状态共有32个,如表所示。
值得注意的是按照题目规定的条件,我们应该划去不合法的状态。
例如,首先可以划去岸边野人数目超过传教士的情况,即S4、S8、S9、S20、S24、S25等6种状态是不合法的;其次,应该划去右岸边野人数目超过野人的情况,即S6、S7、S11、S22、S23、S27等情况;余下20种合法状态中,又有4种是不可能出现的状态;S15和S16不可能出现,因为船不可能停靠在无人的岸边;S3不可能出现,因为传教士不可能在数量占优势的野人眼皮底下把船安全地划回来;还应该划去S28,因为传教士也不可能在数量占优势的野人眼皮底下把船安全地划向对岸。
传教士野蛮人过河问题--python
传教⼠野蛮⼈过河问题--python三名传教⼠和三个野蛮⼈同在⼀个⼩河渡⼝,渡⼝上只有⼀条可容两⼈的⼩船。
问题的⽬标是要⽤这条⼩船把这六个⼈全部渡到对岸去,条件是在渡河的过程中,河两岸随时都保持传教⼠⼈数不少于野蛮⼈的⼈数,否则野蛮⼈会把处于少数的传教⼠状态集合为(x,y,b)三元组,x表⽰左岸野⼈数,y表⽰左岸传教⼠数,x,y取值0~3。
b为0表⽰船在左边,b为1表⽰船在右边动作集合为⼀个传教⼠从左到右,两个传教⼠从左到右,⼀个野⼈从左到右,两个野⼈从左到右,⼀个野⼈⼀个传教⼠从左到右;从右到左类似也有5个动作,共10个动作,于是就可以画出⼀个状态转换图,下⾯的python代码可以帮助我们完成这个任state_legal判断给定状态是否合法,act_legal判断在当前状态执⾏给定动作是否合法,f(x,y,b)打印所有从(x,y,b)可以执⾏的动作和转移到的状态def state_legal(x, y, b):if x < 0 or y < 0 or x > 3 or y > 3:return Falseif y < x and y > 0:return Falseelif (3-y) < 3-x and 3-y > 0:return Falseelse:return Truedef act_legal(x, y, b, xx, yy, bb):if b != bb:return Falseif b == 0 and state_legal(x - xx, y - yy, 1 - b):return Trueelif b == 1 and state_legal(x + xx, y + yy, 1 - b):return Trueelse:return False#when calling f, (x,y,b) is ensured to be state_legaldef f(x,y,b):for act in actions:if act_legal(x, y, b, act[0], act[1], act[2]):if act[2] == 0:print(x,y,b,"---",act, '---', x - act[0], y - act[1], 1 - b)else:print(x,y,b,"---",act, '---', x + act[0], y + act[1], 1 - b)a = (0,1,2,3)actions = []for b in (0,1):for x in (0,1,2):for y in (0,1,2):if x + y >= 1 and x + y <= 2:actions.append((x,y,b))print(actions)for x in a:for y in a:for b in (0,1):if not(x == 0 and y == 0) and state_legal(x, y, b):f(x,y,b)#x is num of savages, y is num of missionaries。
传教士野人过河问题两种解法思路
第6次:右岸到左岸,传教士过去1人,野人过去1人
第7次:左岸到右岸,传教士过去2人,野人过去0人
第8次:右岸到左岸,传教士过去0人,野人过去1人
第9次:左岸到右岸,传教士过去0人,野人过去2人
第10次:右岸到左岸,传教士过去1人,野人过去0人
第11次:左岸到右岸,传教士过去1人,野人过去1人
F={P01,P10,P11,P02,P20,Q01,Q10,Q11,Q02,Q20}
P10ﻩif (ML,CL,BL=1)then(ML–1 , CL,BL–1)
P01ﻩif ( ML,CL , BL=1)then ( ML ,CL–1 , BL–1)
P11ﻩif (ML,CL,BL=1) then ( ML–1 , CL–1,BL–1)
二、解答步骤
(1)设置状态变量并确定值域
M为传教士人数,C为野人人数,B为船数,要求M>=C且M+C<=3,L表示左岸,R表示右岸。
初始状态ﻩﻩ目标状态
LﻩRﻩﻩﻩLR
Mﻩ30ﻩﻩﻩM03
Cﻩ30ﻩﻩﻩﻩﻩC03
B1ﻩ0ﻩﻩﻩﻩB0ﻩ1
(2)确定状态组,分别列出初始状态集和目标状态集
用三元组来表示 :(ML,CL,BL)(均为左岸状态)
图1状态空间图
箭头旁边所标的数字表示了P或Q操作的下标,即分别表示船载的传教士数和食人者数。
三、算法设计
方法一:树的遍历
根据规则由根(初始状态)扩展出整颗树,检测每个结点的“可扩展标记”,为“-1”的即目标结点。由目标结点上溯出路径。
见源程序1。
方法二:启发式搜索
构造启发式函数为:
选择较大值的结点先扩展。
野人传教士过河问题
一、对N=5、k≤3时,求解传教士和野人问题的产生式系统各组成部分进行描述(给出综合数据库、规则集合的形式化描述,给出初始状态和目标条件的描述),并画出状态空间图。
答:用M表示传教士,C表示野人,B表示船,L表示左岸,R表示右岸。
初始状态:目标状态:1,综合数据库定义三元组:(M,C,B)其中:0=<M l<=5,表示传教士在河左岸的人数。
0=<C l<=5,表示野人在河左岸的人数。
B l属于集合(0,1),B l=1,表示船在左岸,B l=0,表示船在右岸。
2,规则集规则集可以用两种方式表示,两种方法均可。
按每次渡河的人数分别写出每一个规则,共(3 0)、(0 3)、(2 1)、(1 1)、(1 0)、(0 1)、(2 0)、(0 2)八种渡河的可能(其中(x y)表示x个传教士和y个野人上船渡河),因此共有16个规则(从左岸到右岸、右岸到左岸各八个)。
注意:这里没有(1 2),因为该组合在船上的传教士人数少于野人人数。
规则集如下:IF (M l, C l, 1) THEN (M l -3, C l, 0) p30IF (M l, C l, 1) THEN (M l, C l -3, 0) p03IF (M l, C l, 1) THEN (M l -2, C l -1, 0) p21IF (M l, C l, 1) THEN (M l -1, C l -1, 0) p11IF (M l, C l, 1) THEN (M l -1, C l, 0) p10IF (M l, C l, 1) THEN (M l, C l -1, 0) p01IF (M l, C l, 1) THEN (M l -2, C l, 0) p20IF (M l, C l, 1) THEN (M l, C l -2, 0) p02IF (M l , C l, 0) THEN (M l +3, C l, 1) q30IF (M l, C l, 0) THEN (M l, C l +3, 1) q03IF (M l, C l, 0) THEN (M l +2, C l +1, 1) q21IF (M l, C l, 0) THEN (M l +1, C l +1, 1) q11IF (M l, C l, 0) THEN (M l +1, C l, 1) q10IF (M l, C l, 0) THEN (M l, C l +1, 1) q01IF (M l, C l, 0) THEN (M l +2, C l, 1) q20IF (M l, C l, 0) THEN (M l, C l +2, 1) q02第二种方法:将规则集综合在一起,简化表示。
传教士和野人问题实验报告
传教士和野人问题实验报告1.上机内容传教士与野人问题求解(宽度搜索算法)二二问题背景:从前有一条河,河的左岸有 m 个传教士(Missionary)和 m 个野人(Cannibal),和一艘最多可乘 n 人的小船。
约定左岸,右岸和船上或者没有传教士,或者野人数量少于传教士,否则野人会把传教士吃掉。
三三实验内容:编程,接收 m 和 n,搜索一条可让所有的野人和传教士安全渡到右岸的方案,例如下图: (M 表示传教士(Missionary),C 表示野人(Cannibal))初态目标 Left Bank River Right bankLeft Bank River Right bank M....M....C....C....注:本实验的举例均以 3 个传教士和 3 个野人同在左岸作为初始状态。
四四实验方案和算法:1 .数据结构:本实验需要用到的数据结构主要是队列和堆栈,其实现均包含于 dso.h 头文件中,分别命名为 class stack 和 class queue。
2 2 .宽度搜索算法:(1) 结点结构:class Move {public:int missionary;//要移动的传教士数量int cannibal;//野人}; class ElemType : Move {//继承 Move 类,获得传教士,野人数据成员。
private:bool boat;//船是否在左岸?public:ElemType_flag;// 标示前一状态即扩展出本结点的父结点信息ElemType(int MA__PEOPLE) {//创建初始状态missionary = cannibal = MA__PEOPLE;boat = true;flag = NULL;} ......在这里,Elemtype 集成了 Move,从而获得 Move 类的传教士和野人数据成员。
以上两个类的数据成员用于保存所有扩展生成的结点。
野蛮人过河问题算法说明及程序
传教士与野人问题算法及程序说明0810504班一.问题说明有3个传教士和3个野蛮人来到河边,打算乘一只船从左岸渡到右岸。
该船的负载能力为2人,在任何时刻如果野蛮人人数超过传教士人数,野蛮人就会把传教士吃掉。
他们怎样才能用这条船安全让所有人都渡过河。
二.算法说明采用递归算法。
因为每次过河都要遵循几个约定,一为两边岸上野蛮人的数量必须大于传教士的数量,二为船上最多只能装两个人,所以采用递归算法不断嵌套循环模拟每次过河的过程,同时加上若干递归中止返回条件,则可以推得过河的方法。
三.数据结构船结构:即表示船上野蛮人和传教士的个数typedef struct Boat{int numX; /// 传教士个数int numY; /// 野蛮人个数}Boat;从左岸到右岸时船上装的人的种类,有3种,即2个野人和0个传教士,0个野人和2个传教士,1个野人和1个传教士。
Boat LtoR[3]={{2,0},{0,2},{1,1}};从右岸回左岸时船上装的人的种类,有2种,即1个野人或1个传教士Boat RtoL[2]={{1,0},{0,1}};递归函数1: int fnPassRiver1(x1,y1,x2,y2)表示每次由一个野蛮人驾船从右岸回左岸后,再向右过河的过程递归函数2: int fnPassRiver2(x1,y1,x2,y2)表示每次由一个传教士驾船从右岸回左岸后,再向右过河的过程四.具体算法第一次过河时,有三种情况,即2个野人和0个传教士,0个野人和2个传教士,1个野人和1个传教士,所以在主函数中用参数是k的三重for循环,确定整体过河框架。
在接下来的从左向右的过河之前,存在两种可能,即驾船从右边回来的是野蛮人或传教士,因此用两个递归函数fnPassRiver1()和fnPassRiver2()分类。
函数fnPassRiver1()和fnPassRiver2()的内容相似,即先递归中判断止条件,若满足三个条件中的任意一个,都跳出此次循环,回到上一级递归;若不满足,则进入下一级循环,此时改变了函数fnPassRiver1(x1,y1,x2,y2)和fnPassRiver2(x1,y1,x2,y2)中的传递参数x1,y1,x2,y2,改变的依据是数组LtoR[3]中的三组值。
传教士野人过河问题-两种解法思路
实验 传教士野人过河问题37030602 王世婷一、实验问题传教士和食人者问题(The Missionaries and Cannibals Problem )。
在河的左岸有3个传教士、1条船和3个食人者,传教士们想用这条船将所有的成员运过河去,但是受到以下条件的限制:(1)传教士和食人者都会划船,但船一次最多只能装运两个;(2)在任何岸边食人者数目都不得超过传教士,否则传教士就会遭遇危险:被食人者攻击甚至被吃掉。
此外,假定食人者会服从任何一种过河安排,试规划出一个确保全部成员安全过河的计划。
二、解答步骤(1) 设置状态变量并确定值域M 为传教士人数,C 为野人人数,B 为船数,要求M>=C 且M+C <= 3,L 表示左岸,R 表示右岸。
初始状态 目标状态L R L RM 3 0 M 0 3C 3 0 C 0 3B 1 0 B 0 1(2) 确定状态组,分别列出初始状态集和目标状态集用三元组来表示f S :(ML , CL , BL )(均为左岸状态)其中03,03ML CL ≤≤≤≤,BL ∈{ 0 , 1}0S :(3 , 3 , 1) g S : (0 , 0 , 0)初始状态表示全部成员在河的的左岸;目标状态表示全部成员从河的左岸全部渡河完毕。
(3) 定义并确定规则集合仍然以河的左岸为基点来考虑,把船从左岸划向右岸定义为Pij 操作。
其中,第一下标i 表示船载的传教士数,第二下标j 表示船载的食人者数;同理,从右岸将船划回左岸称之为Qij 操作,下标的定义同前。
则共有10种操作,操作集为F={P01,P10,P11,P02,P20,Q01,Q10,Q11,Q02,Q20}P 10 if ( ML ,CL , BL=1 ) then ( ML –1 , CL , BL –1 )P 01 if ( ML ,CL , BL=1 ) then ( ML , CL –1 , BL –1 )P 11 if ( ML ,CL , BL=1 ) then ( ML –1 , CL –1 , BL –1 )P 20 if ( ML ,CL , BL=1 ) then ( ML –2 , CL , BL –1 )P 02 if ( ML ,CL , BL=1 ) then ( ML , CL –2 , BL –1 )Q 10 if ( ML ,CL , BL=0 ) then ( ML+1 , CL , BL+1 )Q 01 if ( ML ,CL , BL=0 ) then ( ML , CL+1 , BL +1 )Q 11 if ( ML ,CL , BL=0 ) then ( ML+1 , CL +1, BL +1 )Q20 if ( ML ,CL , BL=0 ) then ( ML+2 , CL +2, BL +1 )Q02if ( ML ,CL , BL=0 ) then ( ML , CL +2, BL +1 )(4)当状态数量不是很大时,画出合理的状态空间图图1 状态空间图箭头旁边所标的数字表示了P或Q操作的下标,即分别表示船载的传教士数和食人者数。
野人与传教士问题A算法
野人与传教士问题(A*算法)SY0903620 赵磊一、实验题目请用A*算法实现传教士和野人问题问题:设有3个传教士和3个野人来到河边,打算乘一只船从右岸渡到左岸去。
该船的负载能力为两人。
在任何时候,如果野人人数超过传教士人数,那么野人就会把传教士吃掉。
他们怎样才能用这条船安全地把所有人都渡过河去?算法设计要求给出:状态表示,规则库,启发函数等二、实验目的通过具体问题的编程求解,利用A*算法解决此经典问题,了解人工智能的启发式搜索算法的基本过程与原理。
三、设计思想1、编程工具采用C++语言在Visual Studio 6.0环境下编写;2、整体思想(1)把初始结点So放入OPEN 表中,计算f(So)。
(2)如果OPEN为空,则搜索失败,退出。
(3)把OPEN中的第一个节点(记为节点n)从表中移出放入CLOSED表。
(4)考察节点n是否为目标节点。
若是,则求得问题的解,退出。
(5)若节点n不可扩展,则转第(2)步。
(6)扩展节点n,用估价函数f(x)计算每个子节点的估价值,并为每个子节点配置指向父节点的指针,把这些子节点都送到OPEN表中,然后对OPEN表中的全部节点按估价值从小到大的顺序排列。
3、具体说明用A*算法求解传教士与野人问题。
M=C=5, K=3。
节点估价值设为f(n)=h(n)+g(n),g(n)设为节点搜索深度,而h(n)= m(n) + c(n) - 2b(n),其中m:河左岸的传教士人数;c:河左岸的野人人数;b:船是否在左岸,1:表示在左岸,0:表示不在左岸。
采用结构体定义形式,定义状态节点*NewNode(int m, int c, int b),其中包含m左岸传教士人数、c左岸野人人数、b船状态(左或右)。
开始状态为(3,3,1),目标状态为(0,0,0)。
若需要条件满足,即任何时候,如果野人人数超过传教士人数,那么野人就会把传教士吃掉,要对状态结点的安全性进行判断,判断一个状态是否为安全的,即是否满足在河的任何一岸,传教士人数不少于野人人数,或者只有野人而没有传教士。
传教士与野人过河问题
传教士-野人问题有N个传教士和N个野人要过河,现在有一条船只能承载K个人(包括野人),K<N,在任何时刻,如果有野人和传教士在一起,必须要求传教士的人数多于或等于野人的人数。
设M为传教士的人数,C为野人的人数,用状态空间发求解此问题的过程如下:M、C = N,boat = k,要求M>=C且M+C <= K初始状态目标状态L R L RM 3 0 M 0 3C 3 0 C 0 3B 1 0 B 0 1(1)用三元组来表示(ML , CL , BL)其中0<=ML , CL <= 3 , BL ∈{ 0 , 1}(3 , 3 , 1) (0 , 0 , 0)(2)规则集合P10if ( ML ,CL , BL=1 ) then ( ML–1 , CL , BL –1 )P01if ( ML ,CL , BL=1 ) then ( ML , CL–1 , BL –1 )P11if ( ML ,CL , BL=1 ) then ( ML–1 , CL–1 , BL –1 )P20if ( ML ,CL , BL=1 ) then ( ML–2 , CL , BL –1 )P02if ( ML ,CL , BL=1 ) then ( ML , CL–2 , BL –1 )Q10if ( ML ,CL , BL=0 ) then ( ML+1 , CL , BL+1 )Q01if ( ML ,CL , BL=0 ) then ( ML , CL+1 , BL +1 )Q11if ( ML ,CL , BL=0 ) then ( ML+1 , CL +1, BL +1 )Q20 if ( ML ,CL , BL=0 ) then ( ML+2 , CL +2, BL +1 )Q02if ( ML ,CL , BL=0 ) then ( ML , CL +2, BL +1 )(3)寻找一个启发式函数引导规则的选用右岸总人数6 – ML – CL 两岸中传教士数目>=野人数目f =–∞其它f=3 Q 01f=2 P 02 f=1 Q 01f=1 Q 11f=1 P 01 f=2 P 11 (3,3,1) (3,2,0)(2,2,0) (3,1,0) (3,2,1) (3,0,0) f=3 P 02(3,1,1) f=2 Q 01(1,1,0) f=4 P 20(2,2,1) f=2 Q 11(1,1,0) f=4 P 20(2,2,1) f=2 Q 11(0,2,0) f=4 P 20(0,3,1)f=3 Q 01(0,1,1)f=5 P 02(0,2,1) f=4 Q 01 (0,0,0)f=3 Q 01(1,1,1) f=4 Q 106.2.3 用状态空间法求解传教士和食人者问题例6-2 传教士和食人者问题(The Missionaries and Cannibals Problem)。
传教士野人问题参考答案
传教士-野人问题有N个传教士和N个野人要过河,现在有一条船只能承载K个人(包括野人),K<N,在任何时刻,如果有野人和传教士在一起,必须要求传教士的人数多于或等于野人的人数。
设M为传教士的人数,C为野人的人数,用状态空间发求解此问题的过程如下:M、C = N,boat = k,要求M>=C且M+C <= K初始状态目标状态L R L RM 3 0 M 0 3C 3 0 C 0 3B 1 0 B 0 1(1)用三元组来表示(ML , CL , BL)其中0<=ML , CL <= 3 , BL ∈{ 0 , 1}(3 , 3 , 1) (0 , 0 , 0)(2)规则集合P10if ( ML ,CL , BL=1 ) then ( ML–1 , CL , BL –1 )P01if ( ML ,CL , BL=1 ) then ( ML , CL–1 , BL –1 )P11if ( ML ,CL , BL=1 ) then ( ML–1 , CL–1 , BL –1 )P20if ( ML ,CL , BL=1 ) then ( ML–2 , CL , BL –1 )P02if ( ML ,CL , BL=1 ) then ( ML , CL–2 , BL –1 )Q10if ( ML ,CL , BL=0 ) then ( ML+1 , CL , BL+1 )Q01if ( ML ,CL , BL=0 ) then ( ML , CL+1 , BL +1 )Q11if ( ML ,CL , BL=0 ) then ( ML+1 , CL +1, BL +1 )Q20 if ( ML ,CL , BL=0 ) then ( ML+2 , CL +2, BL +1 )Q02if ( ML ,CL , BL=0 ) then ( ML , CL +2, BL +1 )(3)寻找一个启发式函数引导规则的选用右岸总人数6 – ML – CL 两岸中传教士数目>=野人数目f =–∞其它f=3 Q 01f=2 P 02 f=1 Q 01f=1 Q 11f=1 P 01 f=2 P 11 (3,3,1) (3,2,0)(2,2,0) (3,1,0) (3,2,1) (3,0,0) f=3 P 02(3,1,1) f=2 Q 01(1,1,0) f=4 P 20(2,2,1) f=2 Q 11(1,1,0) f=4 P 20(2,2,1) f=2 Q 11(0,2,0) f=4 P 20(0,3,1)f=3 Q 01(0,1,1)f=5 P 02(0,2,1) f=4 Q 01 (0,0,0)f=3 Q 01(1,1,1) f=4 Q 106.2.3 用状态空间法求解传教士和食人者问题例6-2 传教士和食人者问题(The Missionaries and Cannibals Problem)。
用Prolog求解传教士和野人问题
用Prolog求解传教士和野人问题实验七用Prolog求解传教士和野人问题 1、实验目的复习经典谓词演算中的归结原理,掌握人工智能程序设计语言Prolog,理解通过搜索求解问题实现人工智能的思想。
2、实验原理谓词演算中的消解法,3、实验内容设有3个传教士和3个野人同在河的左岸,他们都要到对岸去;河里只有一条船,他们都会划船,但每次渡船至多只能乘两人;如果在任何一边河岸上,野人的数量超过传教士,野人就要吃掉传教士,问怎样才能用船将3个传教士和3个野人从左岸都渡到右岸,又不会发生传教士被吃的事件呢,通过Prolog程序,给出乘船过河的动作序列。
4、实验步骤(1) 设计该问题的状态。
例如:((左岸牧师数,左岸野人数),(右岸牧师数,右岸野人数),船的位置)。
(2) 定义目标状态。
这里是:((0,0),(3,3),1)3) 描述可能的动作。
船上所能够载人的状态就是可能的操作。
用谓词(move表示。
(4) 判断合法状态(5) 深度优先搜索三个传教士和三个野人的示例程序如下:move(1,0).move(0,1).move(0,2).move(2,0).move(1,1).legal((X,Y,_)):-legal1(X),legal1(Y). legal1((X,Y)):-X=:=0,Y>=0,!. legal1((X,Y)):-Y=:=0,X>=0,!. legal1((X,Y)):-X>=Y,X>=0,Y>=0.update((X,Y,0),Move,Statu1):-(A,B)=X,(C,D)=Y,(E,F)=Move,C1 is C+E,D1 is D+F,A1 is A-E,B1 is B-F,Statu1=((A1,B1),(C1,D1),1). update((X,Y,1),Move,Statu1):- (A,B)=X, (C,D)=Y,(E,F)=Move,C1 is C-E,D1 is D-F,A1 is A+E,B1 is B+F,Statu1=((A1,B1),(C1,D1),0). connect(Statu,Statu1):- move(X,Y),update(Statu,(X,Y),Statu1), legal(Statu1).findroad(X,X,L,L):-write(L). findroad(X,Y,L,L1):-connect(X,Z),not(member(Z,L)),findroad(Z,Y,[Z|L],L1).传教士和野人问题有三个牧师和三个野人过河,只有一条能装下两个人的船,在河的任何一方或者船上,如果野人的人数大于牧师的人数,那么牧师就会有危险。
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
传教士和野人问题(Missionaries and Cannibals)传教士和野人问题是一个经典的智力游戏问题。
在这个问题中,实际上隐含了这样一个条件:如果在河的某一岸只有野人,而没有传教士,也同样被认为是合法状态。
在具体书写某些条件时,为了简便,这一点有时并没有考虑,但我们默认这个条件是被考虑了的。
有N个传教士和N个野人来到河边准备渡河,河岸有一条船,每次至多可供k人乘渡。
问传教士为了安全起见,应如何规划摆渡方案,使得任何时刻,在河的两岸以及船上的野人数目总是不超过传教士的数目。
即求解传教士和野人从左岸全部摆渡到右岸的过程中,任何时刻满足M(传教士数)≥C (野人数)和M+C≤k的摆渡方案。
设N=3,k=2,则给定的问题可用图1.2表示,图中L和R表示左岸和右岸,B=1或0分别表示有船或无船。
约束条件是:两岸上M≥C,船上M+C≤2。
图1.2 M-C问题实例
由于传教士和野人数是一个常数,所以知道了一岸的情况,另一岸的情况也就知道了。
因此为了简便起见,在描述问题时,只描述一岸--如左岸--的情况就可以了。
另外,该问题我们最关心的是在摆渡过程中,两岸状态的变化情况,因此船上的情况并不需要直接表达出来。
在一次摆渡过程中,船上究竟有几个传教士和野人,可以通过两个相连的状态简单得到。
这样表达更简练,突出了问题的重点。
(1)综合数据库:用三元组表示左岸的情况,即(,,),其中0≤,≤3,∈{0,1}
,其中表示在左岸的传教士人数,表示在左岸的野人数,=1表示船在左岸,=0表示船在右岸。
则此时问题描述可以简化为:(3,3,1)→(0,0,0)
N=3的M-C问题,状态空间的总状态数为4×4×2=32,根据约束条件的要求,可以看出只有20个合法状态。
再进一步分析后,又发现有4个合法状态实际上是不可能达到的。
因此实际的问题空间仅由16个状态构成。
下表列出分析的结果:
(
)
(001)达不到(传教士(
)(000)
均在右,船在左)
(011)
(021)
(031)
(101)不合法(右岸野人多)
(111)
(121)不合法(左岸野人多)
(131)不合法(左岸野人多)
(201)不合法(右岸野人多)
(211)不合法(右岸野人多)
(221)
(231)不合法(左岸野人多)
(301)达不到(311)
(321)
(331)(010)
(020)
(030)达不到
(100)不合法(右岸野人多)
(110)
(120)不合法(左岸野人多)
(130)不合法(左岸野人多)
(200)不合法(右岸野人多)
(210)不合法(右岸野人多)
(230)不合法(右岸野人多)
(300)
(220)
(310)
(320)
(330)达不到
规则集可以划分为两组:一组是从左岸到右岸,称为p 操作,另一组是从右岸到左岸,称为q操作。
按道理,在规则的前件中应该附加必要的条件,使得产生的状态是合法的。
在下一章有关搜索算法的讨论中我们会看到,在每一种搜索算法中,都有一处判断新产生的状态是否合法。
对于不合法的状态,算法会进行相应的处理。
因此在表达规则时,那些通过状态的合法性就可以判断的前提条件可以不在规
则中出现。
这样可以简化规则的表达。
比如在第一条规则中,在规则后件中出现了"ML-1",按道理应该要求ML>0,否则的话,在左岸的传教士人数就是负数了。
但这一点完全可以通过定义什么是合法状态来判断,因此就没有必要将这个条件写入规则中了。
但为什么在规则中写入"B L=1"、"B=0"这样的条件呢?其实这样的条件也不是一定要写的,因为它同样可以通过定义合法状态来判断。
但由于写上这些条件后,会使得规则表达更清晰,通过BL的取值就可以看出规则所表达的是船从左岸到右岸,还是从右岸到左岸。
而且从左到右,或者从右到左,是交替进行的,因此把这样的条件明确表达出来,可以提高问题的求解效率。
所以说,对于通过状态的合法性可以判断的条件,是否在规则中明确表达出来,具有一定的灵活性,可以从规则的清晰性、易懂性,以及求解效率等方面综合考虑。
而对于某些不能通过状态的合法性来判断的条件,则必须在规则中明确表达出来。
在传教士和野人问题中,假定了传教士和野人都可以划船,由于每次摆渡船上最多可以有2个人,最少也必须有一个人(船不会自己前进),因此在船上共有(2,0)、(0,2)、(1,1)、(1,0)和(0,1)这5种组合。
其中第一个数字表示在船上的传教士数,第二个数字表示在船上的野人数。
再加上从左岸到右岸和从右岸到左岸这两种情况,所以共有10种摆渡方法。
在该例题中,将这10种摆渡方法全部以规则的形式,一一列举出来。
这种方法的好处是,规则简单、易懂,但不足也很明显:繁琐。
尤其是对于实际的复杂问题,如果要全部一一列举出所有规则,其数量太大。
表示规则的另一种方式就是引入变量,通过引入变量,将相近的几条规则组合在一条规则中表示。
同样是传教士和野人问题,我们引入i和j两个变量,分别表示此次摆渡时,过河的传教士数和野人数,则可以将10条规则组合为两条规则:
IF (m, c, 1) AND 1≤i+j≤2 THEN (m-i, c-j, 0) //从左岸到右岸IF (m, c, 0) AND 1≤i+j≤2 THEN (m+i, c+j, 0)//从右岸到左
岸
(也可以表示为:
IF (m, c, b=1) AND 1≤i+j≤2 THEN (m-i, c-j, b-1)
IF (m, c, b=0) AND 1≤i+j≤2 THEN (m+i, c+j, b+1)
)
这样表达的规则更加精练,但程序设计要复杂的多,因为需要对变量进行解释。
(2)规则集合:由摆渡操作组成。
该问题主要有两种操作:操作(规定为从左岸划向右岸)和操作(从右岸划向左
岸)。
每次摆渡操作,船上人数有五种组合,因而组成有10条规则的集合。
(3)初始和目标状态:即(3,3,1)和(0,0,0)。
和八数码游戏的问题一样,建立了产生式系统描述之后,就可以通过控制策略,对状态空间进行搜索,求得一个摆渡操作序列,使其能够达到目标状态。
在讨论用产生式系统求解问题时,有时引入状态空间图的概念很有帮助。
状态空间图是一个有向图,其节点可表示问题的各种状态(综合数据库),节点之间的弧线代表一些操作(产生式规则),它们可把一种状态导向另一种状态。
这样建立起来的状态空间图,描述了问题所有可能出现的状
态及状态和操作之间的关系,因而可以较直观地看出问题的解路径及其性质。
实际上只有问题空间规模较小的问题才可能作出状态空间图,例如N=3的M-C问题,其状态空间图如图1.3所示。
由于每个摆渡操作都有对应的逆操作,即
对应,所以该图也可表示成具有双向弧的形式。
从状态空间图看出解序列相当之多,但最短解序列只有4个,均由11次摆渡操作构成。
若给定其中任意两个状态分别作为初始状态和目标状态,就立即可找出对应的解序列来。
在一般情况下,求解过程就是对状态空间搜索出一条解路径的过程。
以上两个例子说明了建立产生式系统描述的过程,这也就是所谓问题的表示。
对问题表示的好坏,往往对求解过程的效率有很大影响。
一种较好的表示法会简化状态空间和规则集表示,例如八数码问题中,如用将牌移动来描述规则,则8块将牌就有32条的规则集,显然用空格走步来描述就简单得多。
又如M-C问题中,用3×2的矩阵给出左、右岸的情况来表示一种状态当然可以,但显然仅用描述左岸的三元组描述就足以表示出整个情况,因此必须十分重视选择较好的问题表示法。
以后的讨论还可以看到高效率的问题求解过程与控制策略有关,合适的控制策略可缩小状态空间的搜索范围,提高求解的效率。
图1.3 M-C问题状态空间图。