人工智能第二次实验报告产生式系统推理班级:姓名:学号:一、实验目的1.理解并掌握产生式系统的基本原理;2.掌握产生式系统的组成部分,以及正向推理和逆向推理过程。二、实验要求1.结合课本内容,以动物识别系统为例,实现小型产生式系统;2.要求:正向推理中能根据输入的初始事实,正确地识别所能识别的动物;逆向推理中能根据所给的动物给出动物的特征。三、实验算法1.如何表示事实和特征的知识;在本程序中,我将动物的特征写入data.txt,将规则记入rules.txt,将动物种类记为goal.txt。通过函数voidreadFiles(){readGoal();readCod();readRule();}读入所有数据分别存放于goal[],rule[],cod[]自定义数组中。2.指出综合数据库和规则库分别使用哪些函数实现的?综合数据库(包括特征和目标)typedefstruct{intxuh;//存放编号charvalu[50];//存放具体内容}Node;Nodegoal[20];Nodecod[50];规则库typedefstruct{intrslt;intcodNum;//记载前提的个数intcod[10];//记载前提的序号intused;//记载是否已匹配成功}Nrule;Nrulerule[50];voidreadRule(){FILE*fp;inti;inttempxuh,tempcodn;charch;if((fp=fopen(rules.txt,r))==NULL){printf(cannotopendata\n);exit(0);}i=0;rule[i].codNum=0;while((ch=fgetc(fp))!=EOF){if(i==14)i=i;tempcodn=0;while(ch!='\n'&&ch!=EOF)//每一条规则{tempxuh=0;while(ch='9'&&ch='0'){tempxuh=tempxuh*10+ch-'0';ch=fgetc(fp);}rule[i].cod[tempcodn++]=tempxuh;tempxuh=0;if(ch=='-')//下一个是结论{ch=fgetc(fp);ch=fgetc(fp);while(ch='9'&&ch='0'){tempxuh=tempxuh*10+ch-'0';ch=fgetc(fp);}rule[i].rslt=tempxuh;}//ifelseif(ch=='*'){ch=fgetc(fp);}rule[i].codNum++;}i++;}rulenum=i;fclose(fp);}3.规则库的匹配算法是什么?如何选用可用规则集中的规则?分别使用哪些函数实现的?程序中的正向与逆向搜索分别是在voidmain()中调用forwardFinger()和backFinger()来实现的。正向搜索从下向上的推理。由于建立规则库时的内在要求,即子规则必在父规则前,故进行正向推理的时候只要将规则库从前到后扫一遍看是否能由规则推出相应结果即可。如果能匹配推出结果则看该结果是否为动物,如果已经推出动物则推理成功。否则更新事实库,匹配下一个规则。代码如下:voidforwardFinger(){intflag;//1:工作已完成0:还未完成intflagFit;intflagCNew;//记录本次循环有没有推出新事实intfitPart;//1:有部分符合条件inti,j,k;flag=0;flagCNew=1;while(!flag&&flagCNew==1){flagCNew=0;for(j=0;jrulenum&&rule[j].used!=1&&flag==0;j++)//一条规则{if(rule[j].codNum=inpCod.curnum)//事实数不小于当前规则所要求的条件数{flagFit=1;for(i=0;irule[j].codNum&&flagFit==1;i++){fitPart=0;for(k=0;kinpCod.curnum;k++){if(rule[j].cod[i]==inpCod.cod[k].xuh){fitPart=1;}}flagFit=fitPart;}if(flagFit==1){flagCNew=1;fitOneRule(j,&flag);//有事实匹配时,就处理把结论加入事实库等事情flagFit=0;}}}//}//whileif(flagCNew==0){printf(条件不足,不能推出它是什么动物);}}逆向搜索反向推理比正向推理要复杂一些。采用的算法是从事实库的动物开始从前往后进行匹配,看是否能成功推出,如果都推不出能识别失败,若能推出其中一个则中止搜索,识别成功。推某一个事实时,仍然是从该事实的前提出发,逐个匹配,若所有的前提满足,则该事实满足。代码如下:voidbackFinger(){inti;bQueueNodemarkdCod[MAXNUM];//stat字段用来存它的结论的序号intflagFitAll;intmarkdCodNum;doublefitDegree;intflagExistAns;flagFitAll=0;flagExistAns=0;for(i=0;igoalnum&&flagFitAll==0;i++)//一种动物{initBack(&fitDegree,&markdCodNum,i);while(bqueue.head!=bqueue.tail){if(bqueue.head==9&&bqueue.tail==11){bqueue.head=bqueue.head;}findCod();recMarkdCod(markdCod,&markdCodNum);if(bqueue.bNode[bqueue.head].stat==0){addNodeToQueue();takeToClose(bqueue.bNode[bqueue.head].codXuh,bqueue.tail-1);}bqueue.head++;if(bqueue.head==bqueue.tail){if(close.head!=close.tail){takeTobqueue(close.head);}}}fitDegree=workFitDegree(markdCod,markdCodNum);if(fitDegree1e-5){if(StillCodNoUseAndContradict(i+codnum)){printf(它不是%s。\n,goal[i].valu);}else{bDisplayResult(fitDegree,i,&flagFitAll);}}else{printf(它不是%s。\n,goal[i].valu);}if(flagFitAll==1){flagExistAns=1;}}//forif(flagExistAns==0){printf(综上所述:没有完全符合这些特征的动物。\n);}}//backFinger()四、实验结果1.要求有实验运行结果截图,以及必要的说明;(1)有若干选择动物特征的选择列表;(2)输入特征后,询问使用者采用何种搜索方式(0:正向1:逆向)(3)正向搜索成功找到目标后,程序显示该动物名称,否则“显示条件不足无法判断”。(4)逆向搜索结果:2.对所实现的产生式系统进行性能分析。在数据量小的情况下识别速度较快。但是我觉得这种识别用处不够广泛。所有的规则必须人工输入不够灵活,不能适应突发状况(如白虎)。五、实验总结及体会虽然还没有具体学习过产生式算法,但是通过本次实践,对正向推理反向推理的过程可以说已经有了大概的了解喝一些自己的看法,对代码的控制能力也有了一定的提高,递归函数的设计,流程的控制都得到了一定的强化。我觉得本次实验的算法还是比较简单的,关键是数据结构的设计,我运用了很多自定义的结构体想使程序显得简单一些,但是效果并不好,别人很难分清那些结构体,太多了。。。。。