http://hi.baidu.com/%B2%BD%D0%D0%D6%AE%C2%C3/blog/item/c3485eca9e397af753664fe5.html
先申明下,我也是菜鸟,所有以下介绍中出现有问题的地方,不要怪小弟,我们“机器人足球”老师(选修课)让我们做的一个程序,用到了Proglog语言,并且要求用VC++做界面,将信息存在Proglog语言中。所有我只是知道一点点东西,只具有刚好完成作业的“能力”。
先介绍下Proglog语言,我用的软件是Amzi! Prolog ,这个软件只有3M多,如果要下的话,到http://download.pchome.net/development/linetools/detail-10087.html进行下载。与其说这是一个开发Prolog语言的软件,不如说它提供的是一个库,这个库里有VC++与Prolog语言混合编程所需要的文件,这些文件也是VC++里面要用到的,由于在VC++库中没有,所有首先要将这些文件移到你所写程序的目录下,然后再加入到你所写程序的工程中。(所说的文件有amzi.h,amzi.lib,amzi.dll)
Prolog语言是“逻辑设计语言”,可以说是人工智能里不可或缺的一门语言,我知道最基础的一点点东西,我们学离散数学时,学到了谓词工式那一章,比如说R(x),表示的含义是任意的,一般程序是不管具体语义的,它只关心公式本身,而具体语义是编程人员需要在意的,而在Prolog语言中,数据是不用事先定义的,小写的“标识”是常量,大写的“标识符”是未知量,比如说有下面一段程序:
animal(dog):-can(noise_far),is(feed_animal).
animal(X):-can(noise_far),is(feed_animal).
上面一短程序中,只有X是未知的,其中“:-”表示“如果”的意思,“,”表示“且”,“.”表示一个规则完了,上面的意思翻译成中文就是:
有一个哺乳动物,并且能够嗅到很远,那么它就是狗。
能够嗅到很远的哺乳动物是什么呢?(X)
而Prolog语言就是由很多这样的规则和公式组成的一个关系型数据库而以,当用VC++程序进入输入相应需要知道的信息时,将这些信息传入到“Prolog文件(*.xpl)”中,然后这个文件就会将相应的信息返回,在VC++中捕获到这相应信息,再将这些信息经过转化,再将得到的具体信息输出,这就是用VC++与Prolog语言混合编程的思想吧,这跟用数据库编程差不多,主要区别就是:数据库里面有的是数据,而Prolog里面是规则,其实两者实质是一样的。
现在来介绍一下我的程序:首先来看一下VC++程序与Prolog语言相互传递信息的类,如下所示:
class AnimalMsg : public CLogicServer
{
public:
AnimalMsg(void);
~AnimalMsg(void);
public:
void AddAnimalMsg(CString msg);
CString GetAnimal(void);
private:
void error(CLSException & e);
};
AnimalMsg::AnimalMsg(void)//初始化类,并加载相应的prolog文件(animal.xpl)
{
try
{
Init("");
Load("animal.xpl");
}
catch(CLSException &e)//如果出现异常
{
error(e);
}
/*向Prolog中输入“问题”,这个问题就是给的条件,然后Prolog会跟据这些东西来分析,提供答案,但是这个问题还没有给完整,比如在Prolog文件中有以下信息:
animal(dog):-can(noise_far). %能够嗅很远的是狗
is(creature):-can(noise_far). %能够嗅很远的是生物
我们先不管这个例子所表示的具体含义,在下面的函数里只能提供右部分的信息,但是Prolog是不知道到底是返回dog还是creature,也就是说程序中还要用到另一个函数,提供右部的“谓词”公式,也就是在返回结果GetAnimal(void)中应用到了*/
void AnimalMsg::AddAnimalMsg(CString msg)
{
char *pBuf;
int size = msg.GetLength();
pBuf = new char[size];
for(int i=0; i<size; ++i)
{
pBuf[i] = (char)msg[i];
pBuf[i+1] = 0;
}
try
{
AssertzStr(pBuf);
}
catch(CLSException &e)
{
error(e);
}
}
CString AnimalMsg::GetAnimal(void)
{
char animal[50];
TERM t;
CString str(_T(""));
try
{
if(ExecStr(&t,"animal(X)"))
{
GetArg(t,1,cSTR,animal);
str.Format("%s",animal);
}
else
{
str = "不明生物";
}
}
catch(CLSException &e)
{
error(e);
}
return str;
}
void AnimalMsg::error(CLSException & e)
{
char buf[500];
e.GetMsg(buf, 500);
CString str;
str.Format("%s",buf);
AfxMessageBox(str);
throw("AnimalMsg error!");
}
由于Prolog里面是不能含有中文的,而界面上都是对应的中文信息,所以最好有两个数组,将相应的信息对应起来,下标应该是一样的,这样就比较方便了,不过我的程序是这样处理的,如下所示:
typedef struct tagAnimal//返回的结果也是英语,所以这个是用来将英语转化成中文的
{
CString name;//中文名字
CString id;// 对应的ID,也就是“英语”表示的
tagAnimal(CString na = _T(""), CString i = _T(""))
: name(na), id(i){}
} Animal;
typedef int TYPE;
typedef struct tagCharacter//特点的定义
{
TYPE type;//type=0,is(X);type=1,have(X);type=2,can(X).
CString msg;//属性
CString id;//属性id,就是“英语”表示的
tagCharacter(TYPE ty = 0, CString ms = _T(""), CString i = _T(""))
: type(ty), msg(ms), id(i){}
} Character;
然后再将信息输进这里面,我用的是向量:
///初始化特征值
m_character.push_back(Character(0,"01.哺乳动物","feed_animal"));
m_character.push_back(Character(0,"02.食肉动物","eat_animal"));
m_character.push_back(Character(0,"03.有蹄动物","hoof_animal"));
m_character.push_back(Character(1,"04.有奶","milk"));
m_character.push_back(Character(1,"05.有毛发","hair"));
m_character.push_back(Character(1,"06.有羽毛","feather"));
m_character.push_back(Character(1,"07.有爪","paw"));
m_character.push_back(Character(1,"08.有犬齿","tooth"));
m_character.push_back(Character(1,"09.有蹄","hoof"));
m_character.push_back(Character(1,"10.有黄褐色条纹","tawny"));
m_character.push_back(Character(1,"11.有黑色条纹","blackstripe"));
m_character.push_back(Character(1,"12.有黑色斑点","blackstain"));
m_character.push_back(Character(1,"13.有长腿","long_leg"));
m_character.push_back(Character(1,"14.有脖子","long_neck"));
m_character.push_back(Character(1,"15.有暗斑点","dimstain"));
m_character.push_back(Character(1,"16.有白色条纹","white"));
m_character.push_back(Character(2,"17.能目盯前方","see_ahead"));
m_character.push_back(Character(2,"18.能吃肉","eat_meat"));
m_character.push_back(Character(2,"19.能生蛋","egg"));
m_character.push_back(Character(2,"20.能飞","fly"));
///初始化,有那些动物
m_animal.push_back(Animal("无法推测","nul"));
m_animal.push_back(Animal("鸟","bird"));
m_animal.push_back(Animal("老虎","tiger"));
m_animal.push_back(Animal("金钱豹","money_panther"));
m_animal.push_back(Animal("长颈鹿","giraffe"));
m_animal.push_back(Animal("斑马","zebra"));
/*以下是程序中的分析函数,过程很简单,就没什么好说的,呵呵
void CAnimal分类Dlg::Analyse(void)
{
pMesg = new AnimalMsg();//重新建,防止信息重复
CString msg;
for(int i=0; i<m_ctrlAlready.GetCount(); ++i)
{
m_ctrlAlready.GetText(i,msg);
for(vector<Character>::iterator iter=m_character.begin();
iter!=m_character.end(); ++iter)
{
if(iter->msg == msg)
{
switch(iter->type)
{
case 0:msg = "is(" + iter->id + ")";break;
case 1:msg = "have(" + iter->id + ")";break;
case 2:msg = "can(" + iter->id + ")";break;
}
pMesg->AddAnimalMsg(msg);
break;
}
}
}
vector<Animal>::iterator iter;
for(iter=m_animal.begin(); iter!=m_animal.end(); ++iter)
if(iter->id == pMesg->GetAnimal())
break;
if(iter == m_animal.end())
GetDlgItem(IDC_RESULT)->SetWindowTextA("无法推测");
else
GetDlgItem(IDC_RESULT)->SetWindowTextA(iter->name);
}
本人自从这个例子里面略用了下Prolog,觉得它与我原来接触到的C/C++/C#/Java等是很不相同的,等把这学期的学习搞定后,花点时间再好好学下Prolog语言,觉得那个语言蛮不错的。希望到时能有所成就,再在博客上写点东西,到时希望大家支持哦,呵呵......