#ifndef ANIMAL_H
#define ANIMAL_H
#define True 1
#define False 0
#define DontKnow -1
#include<stdio.h>
#include<math.h>
#include<string.h>
//事实集(概念集)
char *str[]={"",
"chew_cud" /* 1 */, "hooves" /* 2 */, "mammal" /* 3 */,
"forward_eyes"/* 4 */, "claws" /* 5 */, "pointed_teeth" /* 6 */,
"eat_meat" /* 7 */, "lay_eggs" /* 8 */, "fly" /* 9 */,
"feathers" /* 10 */, "ungulate" /* 11 */, "carnivore" /* 12 */,
"bird" /* 13 */, "give_milk" /* 14 */, "has_hair" /* 15 */,
"fly_well" /* 16 */, "black&while_color"/* 17 */, "can_swim" /* 18 */,
"long_legs" /* 19 */, "long_neck" /* 20 */, "black_stripes" /* 21 */,
"dark_spots" /* 22 */, "tawny_color" /* 23 */, "albatross" /* 24 */,
"penguin" /* 25 */, "ostrich" /* 26 */, "zebra" /* 27 */,
"giraffe" /* 28 */, "tiger" /* 29 */, "cheetah" /* 30 */,
"\0"};
//规则之前件(条件)集,注意与下面对应
int rulep[][6]={{22,23,12,3,0,0}, {21,23,12,3,0,0}, {22,19,20,11,0,0},
{21,11,0,0,0,0}, {17,19,20,13,-9,0},{17,18,13,-9,0,0},
{16,13,0,0,0,0}, {15,0,0,0,0,0}, {14,0,0,0,0,0},
{10,0,0,0,0,0}, {8,7,0,0,0,0}, {7,0,0,0,0,0},
{4,5,6,0,0,0}, {2,3,0,0,0,0}, {1,3,0,0,0,0}};
//规则之后件(结论)集,注意与上面对应
int rulec[]={ 30, 29, 28,
27, 26, 25,
24, 3, 3,
13, 13, 12,
12, 11, 11}; //前7个是要识别的动物
//事实类
class fact{
private:
int Number; //事实ID
char Name[21]; //事实名
int Active; //激活标志
int Succ; //事实断言:真、假、不知道三种情况值
public:
fact *Next; //事实链表后继指针
/* <Function 事实类构造函数,由它激活事实对象集 />
<para> Num:事实ID </para>
<para> L:事实名 </para>
*/
fact(int Num,char *L)
{
strcpy(Name,L);
Number=Num;
Active=False; //初始不激活
Succ=DontKnow; //初始断言不确定
Next=NULL; //初始后继为空
}
char *GetName() //获取事实名
{
char *L;
L=new char[21];
strcpy(L,Name);
return L;
}
int GetNumber(){return Number;} //获取事实ID
int GetAct(){return Active; } //获取事实激活标志
int GetSucc(){return Succ;} //获取事实断言值
//设置事实激活标志和断言值
void PutAct(const int Act0,int Suc0)
{
Active=Act0;
Succ=Suc0;
}
}; //end fact
fact *Fact; //事实链表
class list{ //前提(前提来源与事实集)链表类
private:
int Number; //前提ID,即事实ID
public:
list *Next; //前提链表后继指针
/*<Function 前提链表类构造函数 />
<para> Num:事实ID </para>
*/
list(int Num)
{
Number=Num;
Next=NULL;
}
int GetNumber(){return Number;} //获取前提ID(也就是事实ID)
}; //end list
class rule{ //规则类
char *Name; //规则名
list *Pre; //规则前件(前提、条件)链表头指针
int Conc; //规则后件(结论)ID(也是事实ID)
public:
rule *Next; //规则链表后继指针
rule(char *N,int P[],int C); //规则类构造函数
~rule(); //析构函数
int Query(); //推理机函数
void GetName(){ printf("%s%",Name);} //输出规则名
/* <Function 规则类构造函数,激活规则对象集 />
<para>N:规则名</para>
<para>P:规则前件数组</para>
<para>C:规则后件ID</para>
*/
rule::rule(char *N,int P[],int C)
{
int i;list *L;
Pre=NULL; //前提链头指针初始化
Next=NULL; //规则链后继指针初始化
Name=new char[strlen(N)+1];
strcpy(Name,N);
i=0;
while(P[i]!=0){ //有前提情况下
L=new list(P[i++]); //加入前提链
L->Next=Pre; //注意:前插入
Pre=L;
}
Conc=C; //填入规则后件(结论)
}
/* <Function 释放规则链表节点之前提链空间 />
<Note 规则链本身空间为释放 />
*/
rule::~rule()
{
list *L;
while(Pre)
{
L=Pre->Next;
delete Pre;
Pre=L;
}
delete Name;
}
/* <Function 主要实现推理机 />
<Return 规则使用成功与否 />
*/
int rule::Query()
{
// int i;
char c; //保存用户输入按键符号
list *L; //临时前提链
fact *F; //临时事实链
L=Pre; //L指向前提链
F=Fact;
if(L==NULL) printf("\nError!"); //如果推理时,本规则前提链为空,出错,后面while循环也退出!
while(L!=NULL) //前提链未处理完
{
F=Fact; //F指向事实链表
for(;;) //以当前前提,在事实链表中查询(根据ID)
{ //因为前提为“-事实ID”,表示该事实不成立,所以取绝对值
if(abs(L->GetNumber())==F->GetNumber()) break;
//一旦查询到,有这样的前提(不管其是否成立)则中止查询。我们的知识库必须保证一定能查许到,否则dead loop
F=F->Next; //查询下一事实
} //退出循环时,F指向查询到的事实节点
if(L->GetNumber()>0) //如果前提为真
{
if((F->GetSucc())==True){ //而且事实链表中的这个事实断言也为真
L=L->Next; //则本规则的当前前提在推理中满足
continue; //继续下一前提的判断
}
if((F->GetSucc())==False) //Sorry,该前提在事实链表中断言不成立
return False; //该规则推理使用结束,直接返回
}
else //如果前提为假,表现为-ID
{
if((F->GetSucc())==True) //Sorry,该前提在事实链表中断言却为真
return False; //该规则推理使用结束,直接返回
if((F->GetSucc())==False){ //同上类似
L=L->Next;
continue;
}
} //end if-else
printf("%s(Y/N)",F->GetName()); //向用户提问,这里简单以事实名为问题
c=getchar(); //接受用户输入
flushall();
/*注意:事实链表中节点的Succ域指:该事实的用户断言或中间推出的断言*/
if((c=='Y')||(c=='y')) //回答“是”
{
if(L->GetNumber()>0) F->PutAct(1,True); //且当前规则中的当前前提要求为“真”,置激活和“真”断言
if(L->GetNumber()<0){ //且若当前规则中的当前前提要求为“假”
F->PutAct(1,True); //置激活和用户的断言
return False; //本规则推理结束,不成功;后面的前提不判断了!
}
}
else
{ //分析同上
if(L->GetNumber()<0) F->PutAct(-1,False);
if(L->GetNumber()>0){
F->PutAct(-1,False);
return False;
}
}
L=L->Next; //用户断言和当前规则的当前前提符合,则取当前规则的下一前提进行判断!
} //end while
//只要上述while循环正常退出,表明当前规则的所有前件都满足,下面要得出当前规则的推理结论了
F=Fact;
for(;;)
{
if(Conc==F->GetNumber()) break; //在事实表中查找与当前规则得后件相同得事实(结论性)
F=F->Next;
}
if(Conc<24) //如果规则后件(结论)不是最终最终性得(即不是7种要识别得动物)
{
F->PutAct(1,True); //那就是中间事实性结论,设置其激活和中间推理确证了的断言
return False; //然后返回,本规则并不能结束整个推理
}
//当前规则之后件是最终结论,得出要识别的动物,返回真!
printf("\n你可能患有",F->GetName());
return True;
}
#endif