实验1:猴子摘香蕉问题的VC编程实现
一、实验目的
利用一阶谓词逻辑求解猴子摘香蕉问题并通过编程来实现
二、编程环境
本文主要编译环境是Windows10VisualStudio2015在Ubuntu12.0用gcc编译来演示问题的另外几种状态的解法
三、问题描述
房内有一个猴子,一个箱子,天花板上挂了一串香蕉,其位置如图所示,猴子为了拿到香蕉,它必须把箱子搬到香蕉下面,然后再爬到箱子上。
请定义必要的谓词,列出问题的初始化状态(即下图所示状态),目标状态(猴子拿到了香蕉,站在箱子上,箱子位于位置b)。
四、解决方案
1.定义描述环境状态的谓词。
AT(x,y):x在y处,个体域:x{monkey,box,banana},y{a,b,c};
HAND(s):猴子手中拿着s,个体域:s{box,banana};
ONBOX(monkey):猴子在箱子上;
2.使用谓词、连结词、量词来表示环境状态。
问题的初始状态可表示为:
S o :AT(monkey,a)~HAND(s)AT(box,c)~ONBOX(monkey)AT(banana,b)
要达到的目标状态为:
S g :AT(box,b)ONBOX(monkey)HAND(banana)AT(monkey,b)AT(banana,b)
3. 从初始状态到目标状态的转化,猴子需要完成一系列操作,定义操作类谓词表示
其动作。
go(m,n):猴子从m 走到n 处,个体域:m,n{a,b,c};
movebox(m,n):猴子把箱子从m 处移动到n 处,个体域:m,n{a,b,c};
onbox(m):猴子在m 处爬上箱子,个体域:m{a,b,c};
catch(banana):猴子摘到香蕉;
这3个操作也可分别用条件和动作来表示。
条件直接用谓词公式表示,是为完成相应操作所必须具备的条件;当条件中的事实使其均为真时,则可激活操作规则,于是可执行该规则中的动作部分。
动作通过前后状态的变化表示,即通过从动作前删除或增加谓词公式来描述动作后的状态。
go(m,n):猴子从m 走到n 处
条件:AT(monkey,m)
动作:⎩⎨⎧),()
,(n monkey AT m monkey AT 增加:删除:
movebox(m,n):猴子把箱子从m 处移动到n 处
条件:AT(monkey,m))~HAND(s)AT(box,m)
动作:⎩⎨⎧∧∧∧ n)
AT(monkey,n)AT(box,HAND(s)增加: m)AT(box,HAND(s)~删除: onbox(m):猴子在m 处爬上箱子
条件:AT(monkey,m)~HAND(s)AT(box,m)AT(banana,m)~ONBOX(monkey)
动作:⎩⎨⎧ey)
ONBOX(monk 增加:ey)ONBOX(monk ~删除:
catch(m):猴子摘到香蕉
条件:AT(monkey,m)~HAND(s)AT(box,m)AT(banana,m)ONBOX(monkey)
动作:⎩⎨⎧ a)
HAND(banan 增加: HAND(s)~删除: 4. 按照行动计划,一步步进行状态替换,直至目标状态。
5. AT(monkey,a)~HAND(s)AT(box,c)~ONBOX(monkey)AT(banana,b)
AT(monkey,c)HAND(box)AT(box,c)~ONBOX(monkey)AT(banana,b)
AT(monkey,b)~HAND(s)AT(box,b)~ONBOX(monkey)AT(banana,b)
AT(monkey,b)~HAND(s)AT(box,b)ONBOX(monkey)AT(banana,b)
AT(box,b)ONBOX(monkey)HAND(banana)AT(monkey,b)AT(banana,b)
(目标得解)
猴子行动的规则序列是:go(a,c)→movebox(c,b)→onbox(b)→catch(bananan)
四、源代码
#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>
int i;
void go(char x,char y)
{
printf("step%d:monkey从%c走到%c\n",++i,x,y);//x表示猴子的位置,y为箱子的位置
}
void movebox(char x,char y)
{
printf("step%d:monkey把箱子从%c运到%c\n",++i,x,y);//x表示箱子的位置,y为香蕉的位置
}
void onbox()
{
printf("step%d:monkey爬上箱子\n",++i);
}
void catch()
{
printf("step%d:monkey摘到香蕉\n",++i);
}
void main()
{
char monkey,box,banana;
printf("请用abc来表示猴子箱子香蕉的位置\n");
printf("monkey\tbox\tbanana\n");
scanf("%c",&monkey);
getchar();
printf("\t");
scanf("%c",&box);
getchar();
printf("\t\t");
scanf("%c",&banana);
getchar();
printf("\n操作步骤如下\n");
if(monkey!=box)
{
go(monkey,box);
}
if(box!=banana)
{
movebox(box,banana);
}
onbox();
catch();
printf("\n");
getchar();
}
五、实验结果相关截图
VisualStudio2015截图(图一)
图一
Ubuntu截图(图二)
图二
六、心得体会
通过这次实验,我学会了如何用谓词来表示生活中的某些具体事务,并通过编程给出具体的操作步骤,感觉获益匪浅,在实验中也遇到了一些问题,比如一开始用谓词描述的不准确,还有逻辑上也不知怎么表达,后来通过查找资料解决,成功实现了预期的目标,美中不足的是,用户在输入字母后,三个字母没有保持在同一行,看起来不是很美观,今后如果有机会,编个图形界面就可解决。