人工智能理论实验一

实验一 用谓词表示问题 ---- 知识的表示与推理实验

(一)猴子摘香蕉问题

实验内容:
利用一阶谓词逻辑求解猴子摘香蕉问题:房内有一个猴子,一个箱子,天花板上挂了一串香蕉,其位置如图1所示,猴子为了拿到香蕉,它必须把箱子搬到香蕉下面,然后再爬到箱子上。请定义必要的谓词,列出问题的初始化状态(即下图所示状态),目标状态(猴子拿到了香蕉,站在箱子上,箱子位于位置b)。(附加:从初始状态到目标状态的谓词演算过程。)
在这里插入图片描述
1.定义描述环境状态的谓词。
AT(x,w):x在w处,个体域:x?{monkey},w?{a,b,c,box};
HOLD(x,t):x手中拿着t,个体域:t?{box,banana};
EMPTY(x):x手中是空的;
ON(t,y):t在y处,个体域:y?{b,c,ceiling};
CLEAR(y):y上是空的;
BOX(u):u是箱子,个体域:u?{box};
BANANA(v):v是香蕉,个体域:v?{banana};
2.使用谓词、连结词、量词来表示环境状态。
问题的初始状态可表示为:So:AT(monkey,a)?EMPTY(monkey)?ON(box,c)?ON(banana,ceiling)?CLEAR(b)?BOX(box)?BANANA(banana)
要达到的目标状态为:Sg:
AT(monkey,box)?HOLD(monkey,banana)?ON(box,b)?CLEAR(ceiling)?CLEAR©?BOX(box)?BANANA(banana)
3.从初始状态到目标状态的转化, 猴子需要完成一系列操作, 定义操作类谓词表示其动作。
WALK(m,n):猴子从m走到n处,个体域:m,n?{a,b,c};
CARRY(s,r):猴子在r处拿到s,个体域:r?{c,ceiling},s?{box,banana};
CLIMB(u,b):猴子在b处爬上u;
这3个操作也可分别用条件和动作来表示。条件直接用谓词公式表示,是为完成相应操作所必须具备的条件;当条件中的事实使其均为真时,则可激活操作规则,于是可执行该规则中的动作部分。动作通过前后状态的变化表示,即通过从动作前删除或增加谓词公式来描述动作后的状态。
WALK(m,n):猴子从m走到n处
条件:AT(monkey,m)
动作:(1)删除:AT(monkey,m); (2)增加:AT(monkey,n)
CARRY(s,r):猴子在r处拿到s
条件:AT(monkey,r)?EMPTY(monkey)?ON(s,r)?BOX(box)?BANANA(banana)
动作:(1)删除:EMPTY(monkey) ^ ON(s,r); (2)增加:HOLD(monkey,s) ^ CLEAR®
CLIMB(u,b):猴子在b处爬上u
条件:AT(monkey,b)?HOLD(monkey,u)?CLEAR(b)?BOX(box)?BANANA(banana)
动作:(1)删除:AT(monkey,b) ^ HOLD(monkey,u) ^ CLEAR©; (2)增加:AT(monkey,u)EMPTY(monkey) ^ ON(u,c)
4.按照行动计划, 一步步进行状态替换, 直至目标状态
AT(monkey,a)?EMPTY(monkey)?ON(box,c)?ON(banana,ceiling)?CLEAR(b)?BOX(box)?BANANA(banana)
AT(monkey,c)?EMPTY(monkey)?ON(box,c)?ON(banana,ceiling)?CLEAR(b)?BOX(box)?BANANA(banana)
AT(monkey,c)?HOLD(monkey,box)?ON(banana,ceiling)?CLEAR(b)?CLEAR©?BOX(box)?BANANA(banana)
AT(monkey,b)?HOLD(monkey,box)?ON(banana,ceiling)?CLEAR(b)?CLEAR©?BOX(box)?BANANA(banana)
AT(monkey,box)?EMPTY(monkey)?ON(box,b)?ON(banana,ceiling)?CLEAR©?BOX(box)?BANANA(banana)
AT(monkey,box)?HOLD(monkey,banana)?ON(box,b)?CLEAR(ceiling)?CLEAR©?BOX(box)?BANANA(banana)(目标得解)
猴子行动的规则序列是:WALK(a,c)→CARRY(c,box)→WALK(c,b)→CLIMB(box,b)→
CARRY(banana,ceiling)
5.参考代码

#include <stdio.h>
struct State
{
    
    
	int monkey; /*-1:Monkey at A;0: Monkey at B;1:Monkey at C;*/
	int box; /*-1:box at A;0:box at B;1:box at C;*/
	int banana; /*Banana at B,Banana=0*/
	int monbox; /*-1: monkey on the box;1: monkey  the box;*/
};
struct State States[150];
const char* routesave[150];
/*function monkeygoto,it makes the monkey goto the other place*/
void monkeygoto(int b, int i)
{
    
    
	int a;
	a = b;
	// 判断箱子是否在A位置
	if (a == -1)
	{
    
    
		routesave[i] = "Monkey go to A";
		States[i + 1] = States[i];
		States[i + 1].monkey = -1;
	}
	// 判断箱子是否在B位置
	else if (a == 0)
	{
    
    
		routesave[i] = "Monkey go to B";
		States[i + 1] = States[i];
		States[i + 1].monkey = 0;
	}
	// 判断箱子是否在C位置
	else if (a == 1)
	{
    
    
		// 猴子跑到C处
		routesave[i] = "Monkey go to C";
		// 将上一个状态传给下一个状态
		States[i + 1] = States[i];
		// 更新猴子的位置
		States[i + 1].monkey = 1;
	}
	// 否则出错
	else
	{
    
    
		printf("parameter is wrong");
	}
}
/*end function monkeyygoto*/
/*function movebox,the monkey move the box to the other place*/
void movebox(int a, int i)
{
    
    
	int B;
	B = a;
	// 要把箱子移动到A
	if (B == -1)
	{
    
    
		routesave[i] = "monkey move box to A";
		States[i + 1] = States[i];
		States[i + 1].monkey = -1;
		States[i + 1].box = -1;
	}
	// 要把箱子移动到B
	else if (B == 0)
	{
    
    
		routesave[i] = "monkey move box to B";
		States[i + 1] = States[i];
		// 改变猴子和箱子的状态
		States[i + 1].monkey = 0;
		States[i + 1].box = 0;
	}
	// 要把箱子移动到C
	else if (B == 1)
	{
    
    
		routesave[i] = "monkey move box to C";
		States[i + 1] = States[i];
		States[i + 1].monkey = 1;
		States[i + 1].box = 1;
	}
	else
	{
    
    
		printf("parameter is wrong");
	}
}
/*end function movebox*/
/*function climbonto,the monkey climb onto the box*/
void climbonto(int i)
{
    
    
	routesave[i] = "Monkey climb onto the box";
	States[i + 1] = States[i];
	// 猴子爬上盒子
	States[i + 1].monbox = 1;
}
/*function climbdown,monkey climb down from the box*/
void climbdown(int i)
{
    
    
	routesave[i] = "Monkey climb down from the box";
	States[i + 1] = States[i];
	States[i + 1].monbox = -1;
}
/*function reach,if the monkey,box,and banana are at the same place,the monkey reach banana*/
void reach(int i)
{
    
    
	routesave[i] = "Monkey reach the banana";
}
/*output the solution to the problem*/
void showSolution(int i)
{
    
    
	int c;
	printf("%s \n", "Result to problem:");
	for (c = 0; c < i + 1; c++)
	{
    
    
		printf("Step %d : %s \n", c + 1, routesave[c]);
	}
	printf("\n");
}
/*perform next step*/
void nextStep(int i)
{
    
    
	int c;
	int j;
	// 如果超过150步
	if (i >= 150)
	{
    
    
		printf("%s  \n", "steplength reached 150,have problem ");
		return;
	}
	for (c = 0; c < i; c++) /*if the current state is same to previous,retrospect*/
	{
    
    
		if (States[c].monkey == States[i].monkey && States[c].box == States[i].box && States[c].banana == States[i].banana && States[c].monbox == States[i].monbox)
		{
    
    
			return;
		}
	}
	// 如果各个状态都满足条件,则成功,退出...
	if (States[i].monbox == 1 && States[i].monkey == 0 && States[i].banana == 0 && States[i].box == 0)
	{
    
    
		showSolution(i);
		printf("Press any key to continue \n");
		getchar();/*to save screen for user,press any key to continue*/
		return;
	}
	j = i + 1;
	// 判断第i步,猴子的是否在B位置
	if (States[i].monkey == 0)
	{
    
    
		// 判断第i步,箱子是否在B位置
		if (States[i].box == 0)
		{
    
    
			if (States[i].monbox == -1)
			{
    
    
				climbonto(i);
				reach(i + 1);
				nextStep(j);
				/*monkeygoto(-1,i);
				nextStep(j);
				monkeygoto(0,i);
				nextStep(j);
				movebox(-1,i);
				nextStep(j);
				movebox(0,i);
				nextStep(j);*/
			}
			else
			{
    
    
				reach(i + 1);
				nextStep(j);
				/*climbdown(i);
				nextStep(j);*/
			}
		}
		// 判断第i步,箱子是否在C位置
		else if (States[i].box == 1)
		{
    
    
			/*monkeygoto(-1,i);
			nextStep(j);*/
			monkeygoto(1, i);
			nextStep(j);
			movebox(0, i);
			nextStep(j);
			climbonto(i);
			reach(i + 1);
			nextStep(j);
		}
		// 判断第i步,箱子是否在A位置
		else /*box==-1*/
		{
    
    
			monkeygoto(-1, i);
			nextStep(j);
			movebox(0, i);
			nextStep(j);
			climbonto(i);
			reach(i + 1);
			nextStep(j);
		}
	}
	/*end if*/
	// 判断第i步,猴子的是否在A位置
	if (States[i].monkey == -1)
	{
    
    
		// 判断第i步,箱子是否在A位置
		if (States[i].box == -1)
		{
    
    
			if (States[i].monbox == -1)
			{
    
    
				movebox(0, i);
				nextStep(j);
				climbonto(i);
				reach(i + 1);
				nextStep(j);
			}
			else
			{
    
    
				climbdown(i);
				nextStep(j);
				movebox(0, i);
				nextStep(j);
				climbonto(i);
				reach(i + 1);
				nextStep(j);
			}
		}
		// 判断第i步,箱子是否在B位置
		else if (States[i].box == 0)
		{
    
    
			monkeygoto(0, i);
			nextStep(j);
			climbonto(i);
			reach(i + 1);
			nextStep(j);
		}
		// 判断第i步,箱子是否在C位置
		else
		{
    
    
			// 1:代表要移动到的位置
			monkeygoto(1, i);
			// 进行下一步
			nextStep(j);
			// 移动箱子,0:代表要把箱子移动到的位置
			movebox(0, i);
			// 继续执行下一步
			nextStep(j);
			// 猴子上箱子
			climbonto(i);
			// 获得香蕉
			reach(i + 1);
			// 进行下一步
			nextStep(j);
		}
	}
	/*end if*/
	// 判断第i步,猴子的是否在C位置
	if (States[i].monkey == 1)
	{
    
    
		if (States[i].box == 1)
		{
    
    
			if (States[i].monbox == -1)
			{
    
    
				movebox(0, i);
				nextStep(j);
				climbonto(i);
				reach(i + 1);
				nextStep(j);
			}
			else
			{
    
    
				climbdown(i);
				nextStep(j);
				movebox(0, i);
				nextStep(j);
				climbonto(i);
				reach(i + 1);
				nextStep(j);
			}
		}
		else if (States[i].box == -1)
		{
    
    
			monkeygoto(-1, i);
			nextStep(j);
			movebox(0, i);
			nextStep(j);
			movebox(0, i);
			nextStep(j);
			climbonto(i);
			reach(i + 1);
			nextStep(j);
		}
		else
		{
    
    
			monkeygoto(0, i);
			nextStep(j);
			movebox(0, i);
			nextStep(j);
			climbonto(i);
			reach(i + 1);
			nextStep(j);
		}
	}
	/*end if*/
}/*end nextStep*/
int main()
{
    
    
	// 定义初始状态
	States[0].monkey = -1;
	States[0].box = 1;
	States[0].banana = 0;
	States[0].monbox = -1;
	nextStep(0);
}

在这里插入图片描述

(二)传教士(牧师)与野人问题

问题描述:
有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->000
Successed or Failed?: Successed

猜你喜欢

转载自blog.csdn.net/wjl__ai__/article/details/108667075