基于产生式系统方法实现动物识别系统

    xiaoxiao2022-07-09  196

    1   产生式系统用来描述若干个不同的以一个基本概念为基础的系统。这个基本概念就是产生式规则或产生式条件和操作对象的概念。

    2   在产生式系统中,论域的知识分为两部份:

         (1)事实:用于表示静态知识,如事物、事件和它们之间的关系;

         (2)规则:用于表示推理过程和行为

    3   一个产生式系统由三个部分组成,如图所示:

         (1)综合数据库:用来存放与求解问题有关的数据以及推理过程环境的当前状态的描述。

         (2)产生式规则库:主要存放问题求解中的规则。

         (3)控制策略:其作用是说明下一步应该选用什么规则,也就是说如何应用规则。


    规则库:

    规则号前提结论r1该动物有毛发是哺乳动物r2该动物有奶

    是哺乳动物

    r3该动物有羽毛

    是鸟

    r4该动物会飞   AND  会下蛋是鸟r5该动物吃肉

    是食肉动物

    r6

    该动物有犬齿  AND  有爪  AND  眼盯前方

    是食肉动物r7

    该动物是哺乳动物  AND  有蹄 

    是蹄类动物

    r8

     该动物是哺乳动物  AND  是反刍动物 

    是蹄类动物

    r9

    该动物是哺乳动物   AND  是食肉动物 AND  是黄褐色  AND  身上有暗斑点

    是金钱豹r10

    该动物是哺乳动物   AND  是食肉动物  AND  是黄褐色  AND  身上有黑色条纹

    是虎r11

    该动物是蹄类动物   AND  有长脖子  AND  有长腿  AND  身上有暗斑点

    是长颈鹿  r12该动物是蹄类动物  AND  身上有黑色条纹

    是斑马

    r13

    该动物是鸟   AND  有长脖子  AND  有长腿 AND  不会飞  AND  有黑白二色

    是鸵鸟

    r14

    该动物是鸟  AND 会游泳 AND 不会飞  AND  有黑白二色

    是企鹅    r15该动物是鸟   AND  善飞

    是信天翁

     

     

     

     

     

     

     

     

     

     

     

     

     

     

     

     

     

     


    1、知识表示

    将规则中的动物特征前提事实和动物结论分别以features.txt和animals.txt存入,将规则库写入ruleBase.txt中。 


    2、状态空间


    3、程序清单

    test1.h 

    #include<bits/stdc++.h> using namespace std; const int MAX_SIZE=50; struct Node{ //特征类 int id; //编号 char name[MAX_SIZE]; //名称 }; struct Statu{ //状态类 int statu; //0未使用 1使用过一次 2没有使用但不影响 int id; }; //可替换修改 struct Fact{ //数据库 int st_num; //初始事实数 int now_num; //当前事实数,不断更新加入中间结论 int neFlag; //条件不足置1 Statu data[MAX_SIZE]; //特征数组 }; struct Rule{ //规则库 int result; //最终结论 int data_num; //前提个数 int id_set[10]; //前提编号数组 int matched; //是否已匹配成功 0 1 }rule[MAX_SIZE]; //规则库 Node goal[20]; //目标动物 Node data[MAX_SIZE]; //特征数据 Fact indata; //输入数据 int rule_num=0; //规则条数 int data_num=24; //特征数

    test1.cpp

    #include<bits/stdc++.h> #include "test1.h" using namespace std; void readFeature(){ //读取特征库 FILE *fp; if((fp=fopen("features.txt","r"))==NULL){ printf("Cant open features.txt!\n"); exit(0); } int i=0; while((fscanf(fp,"%d %s",&data[i].id,&data[i].name))!=EOF) i++; //读入 fclose(fp); } void readRule(){ //读取规则库 FILE *fp; if((fp=fopen("ruleBase.txt","r"))==NULL){ printf("Cant open ruleBase.txt!\n"); exit(0); } int i=0; char ch; rule[i].data_num=0; int t=1; while((ch=fgetc(fp))!=EOF){ //文件结尾 int cnt=0; //规则前提个数 while(ch!='\n'&&ch!=EOF){ //每一条规则 int tmp_id=0; while(ch>='0'&&ch<='9'){ tmp_id=tmp_id*10+ch-'0'; ch=fgetc(fp); } rule[i].id_set[cnt++]=tmp_id; tmp_id=0; //处理结论 if(ch=='='){ ch=fgetc(fp); while(ch>='0'&&ch<='9'){ tmp_id=tmp_id*10+ch-'0'; ch=fgetc(fp); } rule[i].result=tmp_id; } else if(ch=='&') ch=fgetc(fp); } rule[i].data_num=cnt; //该规则前提数 i++; } rule_num=i; //规则条数 fclose(fp); // for(int i=0;i<rule_num;i++){ // for(int j=0;j<rule[i].data_num;j++){ // printf("%s",data[rule[i].id_set[j]].name); // printf("%c",j==rule[i].data_num-1?'=':'&'); // } // printf("%s\n",data[rule[i].result].name); // } } void readAnimal(){ //读取目标库 FILE *fp; if((fp=fopen("animals.txt","r"))==NULL){ printf("Cant open animals.txt!\n"); exit(0); } int i=0; while((fscanf(fp,"%d %s",&goal[i].id,&goal[i].name))!=EOF) i++; //读入 fclose(fp); } int valueInput(){ //输入是否有效 int tmp; //输入序号 int cnt=0,inflag=1; //特征数,有效输入标记 do{ scanf("%d",&tmp); indata.data[cnt++].id=tmp; if(tmp>=data_num||tmp<-1){ //越界 printf("特征序号只能在0-%d之间,请重新输入:\n",data_num-1); fflush(stdin); inflag=0; } }while(tmp!=-1&&tmp<data_num&&tmp>=0); indata.st_num=cnt-1; //输入的特征数 indata.now_num=indata.st_num; return inflag; } int isOther(int in_id,int result){ //消解冲突 int queue[MAX_SIZE],vis[MAX_SIZE]; //加入队列标记 int head=0,tail=1; int flag=0; queue[0]=result; vis[result]=1; while(head!=tail&&flag!=1){ for(int i=0;i<rule_num;i++) if(queue[head]==rule[i].result){ //结果匹配规则结论 for(int j=0;j<rule[i].data_num;j++) if(indata.data[in_id].id==rule[i].id_set[j]) flag=1; else{ if(vis[rule[i].id_set[j]]!=1){ queue[tail++]=rule[i].id_set[j]; vis[rule[i].id_set[j]]=1; } } } head++; } return flag; } bool isContract(int result){ //是否冲突 for(int i=0;i<indata.now_num;i++) if(indata.data[i].statu==0&&indata.data[i].id!=result){ //未访问的输入特征 if(isOther(i,result)) indata.data[i].statu=2; else return true; } return false; } void isMatch(int result,int *finish){ //匹配最终结论 if(result >=data_num){ //已推理出动物 *finish=1; //任务完成 if(isContract(result)) printf("条件冲突,没有这样的动物!\n"); else printf("它是 %s.\n",goal[result-data_num].name); } } void addToFact(int rule_id,int *finish){ //匹配更新 for(int i=0;i<rule[rule_id].data_num;i++) //标记访问 for(int k=0;k<indata.now_num;k++) if(indata.data[k].id==rule[rule_id].id_set[i]) indata.data[k].statu=1; rule[rule_id].matched=1; int vis=0; //标记结论是否存在 for(int i=0;i<indata.now_num;i++) if(indata.data[i].id==rule[rule_id].result){ //匹配结论 vis=1;break; } if(vis==0){ indata.data[indata.now_num].id=rule[rule_id].result; //printf("add the %d\n",indata.data[indata.now_num].id); indata.now_num++; } isMatch(rule[rule_id].result,finish); } void count_unum(int *unusef,int *u_num){ //未访问特征数 int vis[MAX_SIZE]; //未访问事实加组标记 memset(vis,0,sizeof(vis)); for(int i=0;i<indata.now_num;i++){ if(indata.data[i].statu==0&&vis[indata.data[i].id]!=1){ unusef[*u_num]=indata.data[i].id; ++(*u_num); vis[indata.data[i].id]=1; } } } void mayMatch(int tflag,int rule_id,int *getflag){ //匹配可能性结论 Node *res; int res_id; res=data; //printf("result=%d\n",rule[rule_id].result); res_id=rule[rule_id].result; getflag[rule[rule_id].result]=1; if(res_id>23){ res=goal; res_id-=24; } if(tflag==0) printf("条件不完全,但它有%s",res[res_id].name); else printf("和%s",res[res_id].name); } void guess(){ //可能结论 int tflag,ecnt; //相同个数 int unusef[MAX_SIZE],u_num=0; int getflag[MAX_SIZE];//若已推出这个"可能结论",就置为1 memset(getflag,0,sizeof(getflag)); count_unum(unusef,&u_num); tflag=0; for(int i=0;i<rule_num;i++){ ecnt=0; for(int j=0;j<rule[i].data_num;j++) for(int k=0;k<u_num;k++) if(unusef[k]==rule[i].id_set[j]) ecnt++; if(ecnt*2>=rule[i].data_num&&getflag[rule[i].result]!=1){ mayMatch(tflag,i,getflag); tflag=1; } } if(tflag==0) printf("条件不足,不能推出它是什么动物!\n"); else printf("的部分特征.\n"); } void forwardWork(){ //正向推理 int finish=0; //推理是否完成 0 1 int factNew=1; //一次推理是否得出新事实 int fitFlag; //1 可推理 int fitPart; //1 部分符合 while(!finish&&factNew==1){ factNew=0; for(int i=0;i<rule_num&&rule[i].matched!=1&&finish==0;i++){ //取出一条规则 if(indata.now_num>=rule[i].data_num){ //现有事实数不小于当前规则条件数 fitFlag=1; for(int j=0;j<rule[i].data_num&&fitFlag==1;j++){ //比较是否匹配该规则 fitPart=0; for(int k=0;k<indata.now_num;k++) if(indata.data[k].id==rule[i].id_set[j]) fitPart=1; //部分匹配 fitFlag=fitPart; } if(fitFlag==1){ //与该规则匹配 //printf("匹配第%d条规则\n",i); factNew=1; addToFact(i,&finish); //更新到事实库 fitFlag=0; } } } } if(factNew==0) //当没有推出任何动物,看是否极有可能得出一些结论 guess(); }

    main.cpp

    #include<bits/stdc++.h> #include "test1.cpp" using namespace std; void read(){ //读取库 //读取文件 readFeature(); readRule(); readAnimal(); } void init(){ //初始化状态值 for(int i=0;i<MAX_SIZE;i++){ rule[i].matched=0; //未匹配成功 indata.neFlag=0; indata.data[i].statu=0; //特征未访问 } } void interface(){ //界面 printf("\n\t******************动物识别系统******************\t\n\n\t"); for(int i=0,j=1;i<data_num;i++,j++){ printf("[-] %-12s",data[i].id,data[i].name); if(j%3==0) printf("\n\t"); } printf("\n\t***********************************************\t\n"); } int main(){ //处理主函数 read(); char ch; do { init(); system("cls"); interface(); printf("请输入已知动物特征的序号,以-1结束:\n"); while(valueInput()==0); //直到输入有效 forwardWork(); //正向推理 printf("\n按任意键继续,按'n'或'N'退出:"); ch=getchar();ch=getchar(); } while(ch!='n'&&ch!='N'); //结束标记 return 0; }

     

    最新回复(0)