?? an.h
字號:
/*==========================================================================
《用C++建造專家系統(tǒng)》書上的動物識別專家系統(tǒng)的程序
本人做了比較詳細的注釋,并對源程序略作修改。適合初學者研究!
QQ:185119416
CI OpenForum Group QQ:9874319
===========================================================================*/
#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"};
//規(guī)則之前件(條件)集,注意與下面對應
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}};
//規(guī)則之后件(結論)集,注意與上面對應
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 事實類構造函數(shù),由它激活事實對象集 />
<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 前提鏈表類構造函數(shù) />
<para> Num:事實ID </para>
*/
list(int Num)
{
Number=Num;
Next=NULL;
}
int GetNumber(){return Number;} //獲取前提ID(也就是事實ID)
}; //end list
class rule{ //規(guī)則類
char *Name; //規(guī)則名
list *Pre; //規(guī)則前件(前提、條件)鏈表頭指針
int Conc; //規(guī)則后件(結論)ID(也是事實ID)
public:
rule *Next; //規(guī)則鏈表后繼指針
rule(char *N,int P[],int C); //規(guī)則類構造函數(shù)
~rule(); //析構函數(shù)
int Query(); //推理機函數(shù)
void GetName(){ printf("%s%",Name);} //輸出規(guī)則名
};
/* <Function 規(guī)則類構造函數(shù),激活規(guī)則對象集 />
<para>N:規(guī)則名</para>
<para>P:規(guī)則前件數(shù)組</para>
<para>C:規(guī)則后件ID</para>
*/
rule::rule(char *N,int P[],int C)
{
int i;list *L;
Pre=NULL; //前提鏈頭指針初始化
Next=NULL; //規(guī)則鏈后繼指針初始化
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; //填入規(guī)則后件(結論)
}
/* <Function 釋放規(guī)則鏈表節(jié)點之前提鏈空間 />
<Note 規(guī)則鏈本身空間為釋放 />
*/
rule::~rule()
{
list *L;
while(Pre)
{
L=Pre->Next;
delete Pre;
Pre=L;
}
delete Name;
}
/* <Function 主要實現(xiàn)推理機 />
<Return 規(guī)則使用成功與否 />
*/
int rule::Query()
{
// int i;
char c; //保存用戶輸入按鍵符號
list *L; //臨時前提鏈
fact *F; //臨時事實鏈
L=Pre; //L指向前提鏈
F=Fact;
if(L==NULL) printf("\nError!"); //如果推理時,本規(guī)則前提鏈為空,出錯,后面while循環(huán)也退出!
while(L!=NULL) //前提鏈未處理完
{
F=Fact; //F指向事實鏈表
for(;;) //以當前前提,在事實鏈表中查詢(根據(jù)ID)
{ //因為前提為“-事實ID”,表示該事實不成立,所以取絕對值
if(abs(L->GetNumber())==F->GetNumber()) break;
//一旦查詢到,有這樣的前提(不管其是否成立)則中止查詢。我們的知識庫必須保證一定能查許到,否則dead loop
F=F->Next; //查詢下一事實
} //退出循環(huán)時,F(xiàn)指向查詢到的事實節(jié)點
if(L->GetNumber()>0) //如果前提為真
{
if((F->GetSucc())==True){ //而且事實鏈表中的這個事實斷言也為真
L=L->Next; //則本規(guī)則的當前前提在推理中滿足
continue; //繼續(xù)下一前提的判斷
}
if((F->GetSucc())==False) //Sorry,該前提在事實鏈表中斷言不成立
return False; //該規(guī)則推理使用結束,直接返回
}
else //如果前提為假,表現(xiàn)為-ID
{
if((F->GetSucc())==True) //Sorry,該前提在事實鏈表中斷言卻為真
return False; //該規(guī)則推理使用結束,直接返回
if((F->GetSucc())==False){ //同上類似
L=L->Next;
continue;
}
} //end if-else
printf("%s(Y/N)",F->GetName()); //向用戶提問,這里簡單以事實名為問題
c=getchar(); //接受用戶輸入
flushall();
/*注意:事實鏈表中節(jié)點的Succ域指:該事實的用戶斷言或中間推出的斷言*/
if((c=='Y')||(c=='y')) //回答“是”
{
if(L->GetNumber()>0) F->PutAct(1,True); //且當前規(guī)則中的當前前提要求為“真”,置激活和“真”斷言
if(L->GetNumber()<0){ //且若當前規(guī)則中的當前前提要求為“假”
F->PutAct(1,True); //置激活和用戶的斷言
return False; //本規(guī)則推理結束,不成功;后面的前提不判斷了!
}
}
else
{ //分析同上
if(L->GetNumber()<0) F->PutAct(-1,False);
if(L->GetNumber()>0){
F->PutAct(-1,False);
return False;
}
}
L=L->Next; //用戶斷言和當前規(guī)則的當前前提符合,則取當前規(guī)則的下一前提進行判斷!
} //end while
//只要上述while循環(huán)正常退出,表明當前規(guī)則的所有前件都滿足,下面要得出當前規(guī)則的推理結論了
F=Fact;
for(;;)
{
if(Conc==F->GetNumber()) break; //在事實表中查找與當前規(guī)則得后件相同得事實(結論性)
F=F->Next;
}
if(Conc<24) //如果規(guī)則后件(結論)不是最終最終性得(即不是7種要識別得動物)
{
F->PutAct(1,True); //那就是中間事實性結論,設置其激活和中間推理確證了的斷言
return False; //然后返回,本規(guī)則并不能結束整個推理
}
//當前規(guī)則之后件是最終結論,得出要識別的動物,返回真!
printf("\nThis annimal is %s",F->GetName());
return True;
}
#endif
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -