基于产生式表示的动物识别系统

来源:互联网 发布:大数据产业园区 编辑:程序博客网 时间:2024/05/12 09:12
  实验目的

    理解和掌握产生式知识表示方法及产生式系统的基本过程,能够利用编程技术建立一个基于产生式知识表示的简单的智能系统。

例    建立一个动物识别系统的规则库,用以识别虎、豹、斑马、长颈鹿、企鹅、鸵鸟、信天翁等7种动物。
    解  为了识别这些动物,可以根据动物识别的特征,建立包含下述规则的规则库:             
    R1:if 动物有毛发  then  动物是哺乳动物
    R2:if 动物有奶  then  动物是哺乳动物
    R3:if 动物有羽毛  then  动物是鸟 

    R4:if 动物会飞  and  会生蛋 then  动物是鸟
    R5:if 动物吃肉 then 动物是食肉动物
    R6:if 动物有犀利牙齿 and 有爪 and 眼向前方 then 动物是食肉动物
    R7:if 动物是哺乳动物and有蹄then动物是有蹄类动物
    R8:if 动物是哺乳动物and反刍then动物是有蹄类动物
    R9:if 动物是哺乳动物and是食肉动物and有黄褐色 and 有暗斑点 then 动物是豹 

    R10:if 动物是哺乳动物 and是食肉动物and有黄褐色 and 有黑色条纹 then 动物是虎
    R11:if动物是有蹄类动物  and 有长脖子and有长腿and有暗斑点 then 动物是长颈鹿
    R12:if 动物是有蹄类动物 and有黑色条纹 then 动物是斑马
    R13:if 动物是鸟and不会飞 and有长脖子and有长腿 and有黑白二色 then 动物是鸵鸟
    R14:if 动物是鸟 and不会飞 and会游泳 and有黑白二色 then  动物是企鹅
    R15:if 动物是鸟 and善飞 then 动物是信天翁 

如果初始综合数据库包含的事实有:
    动物有暗斑点,有长脖子,有长腿,有奶,有蹄
    
    推理出是什么动物?(长颈鹿)


系统的推理过程
    (1) 先从规则库中取出第一条规则r1,检查其前提是否可与综合数据库中的已知事实相匹配。 r1的前提是“有毛发”,但事实库中无此事实,故匹配失败。然后取r2,该前提可与已知事实“有奶”相匹配,r2被执行,并将其结论“该动物是哺乳动物”作为新的事实加入到综合数据库中。此时,综合数据库的内容变为:      动物有暗斑,有长脖子,有长腿,有奶,有蹄,是哺乳动物。
     (2) 再从规则库中取r3,r4,r5,r6进行匹配,均失败。接着取r7,该前提与已知事实“是哺乳动物”相匹配,r7被执行,并将其结论“该动物是有蹄类动物” 作为新的事实加入到综合数据库中。此时,综合数据库的内容变为:动物有暗斑,有长脖子,有长腿,有奶,有蹄,是哺乳动物,是有蹄类动物。
    (3) 此后,r8,r9,r10均匹配失败。接着取r11,该前提 “该动物是有蹄类动物  AND  有长脖子  AND  有长腿  AND  身上有暗斑” 与已知事实相匹配,r11被执行,并推出“该动物是长颈鹿”。由于“长颈鹿”已是目标集合中的一个结论,即已推出最终结果,故问题求解过程结束。

产生式系统的问题求解基本过程

   (1) 初始化综合数据库,即把欲解决问题的已知事实送入综合数据库中;
   (2) 检查规则库中是否有未使用过的规则,若无转 (7);
   (3) 检查规则库的未使用规则中是否有其前提可与综合数据库中已知事实相匹配的规则,若有,形成当前可用规则集;否则转(6);
   (4) 按照冲突消解策略,从当前可用规则集中选择一个规则执行,并对该规则作上标记。把执行该规则后所得到的结论作为新的事实放入综合数据库;如果该规则的结论是一些操作,则执行这些操作;
   (5) 检查综合数据库中是否包含了该问题的解,若已包含,说明解已求出,问题求解过程结束;否则,转(2);
   (6) 当规则库中还有未使用规则,但均不能与综合数据库中的已有事实相匹配时,要求用户进一步提供关于该问题的已知事实,若能提供,则转(2);否则,执行下一步;
   (7) 若知识库中不再有未使用规则,也说明该问题无解,终止问题求解过程。
 
  说明:从第(3)步到第(5)步的循环过程实际上就是一个搜索过程 


代码如下:

#include <iostream>#include <algorithm>using namespace std;char *facts[]={"","反刍","有蹄","哺乳类","眼向前方","有爪",      //1-5"犬齿","吃肉","下蛋","能飞","有羽毛","蹄类","食肉类","鸟类","有奶","毛发","善飞","黑色白条纹","游泳","长腿","长脖子","黑条纹","暗斑点","黄褐色"};char *resultSet[]={"","信天翁","企鹅","鸵鸟","斑马","长颈鹿","虎","豹"  //1-7};struct factDB{         //综合数据库中的已知事实 int curNum; int fact[30]; int initNum;}factDb;struct Rule{          //规则 结构体int factNum;      int fact[5];bool endResult;     //是否为结果集int resultID;       //推出的结果IDbool used;//已使用过标志bool possible;      //是否可能标志,针对-9(不能飞)若Rule中有9,而综合数据库中有-9 则该规则标记不可能int needFactPos;    //通过事实比较,记录下一个需要的事实位置,方便下次比较开始点后移和首先寻找该位置值是否新增即可}*rule;bool findNeedFact(int factID,int pos)     //寻找needFactPos位置值是否存在于综合事实库中{int i=pos;for(;i<factDb.curNum;i++) {if(factID==factDb.fact[i])return true;if(factID<factDb.fact[i])return false;}return false;}bool cmpArray(Rule &r)      //两个数组的事实比较{int i,j;i=r.needFactPos;j=i;while(i<r.factNum){while(j<factDb.curNum){if(r.fact[i]==factDb.fact[j]){i++;if(i==r.factNum)return true;}else if(r.fact[i]<factDb.fact[j]){if(r.fact[i]<0 && findNeedFact(-r.fact[i],i))r.possible=false;   //当存在相反情况时,标记不可能r.needFactPos=i;return false;}j++;}if(i<r.factNum){r.needFactPos=i;return false;}}return true;}int cmpFact(Rule &r){if(r.factNum>factDb.curNum)return 0;        //已知事实还没有该规则事实多if(r.needFactPos){if(!findNeedFact(r.fact[r.needFactPos],r.needFactPos))return 0; //需要的值还不存在else r.needFactPos++;}if(cmpArray(r)){r.used=true;if(r.endResult)return 1;     //得到了最终结果else return 2;               //得到中间结果}else return 0;}int main(){freopen("in.txt","r",stdin);int n;cin>>n;rule=(Rule *)malloc(sizeof(Rule)*n);int i,j;for(i=0;i<n;i++){cin>>rule[i].factNum;for(j=0;j<rule[i].factNum;j++)cin>>rule[i].fact[j];sort(rule[i].fact,rule[i].fact+rule[i].factNum);cin>>rule[i].endResult>>rule[i].resultID;rule[i].used=false;rule[i].possible=true;rule[i].needFactPos=0;}cin>>factDb.initNum;factDb.curNum=factDb.initNum;cout<<"原始事实综合数据库:"<<endl;for(i=0;i<factDb.initNum;i++){cin>>factDb.fact[i];cout<<facts[factDb.fact[i]]<<"\t";}cout<<endl<<endl;sort(factDb.fact,factDb.fact+factDb.curNum);int res;bool isEnd=false;while(!isEnd){isEnd=true;for(i=0;i<n;i++) {if(rule[i].used || !rule[i].possible)continue;res=cmpFact(rule[i]); if(res==0)continue;//不匹配else if(res==1)   //匹配成功,得到最终结果{cout<<"得到最终结果:"<<resultSet[rule[i].resultID]<<endl;return 0;}else if(res==2)//匹配成功,得到中间结果{cout<<"得到中间结果:"<<facts[rule[i].resultID]<<endl;cout<<"\t将其加入到现有的事实数据库中。。。"<<endl<<endl;factDb.fact[factDb.curNum]=rule[i].resultID;factDb.curNum++;sort(factDb.fact,factDb.fact+factDb.curNum);      //这里是在有序数组里插入,应使用插入排序为宜isEnd=false;}}}cout<<"现有事实无法推断出结果!"<<endl;return 0;}


输入文件:

15       //规则数量
4         //事实条件数
22 23 12 3      
1 7     //1表示最终结果, 7为结果ID

4
21 23 12 3
1 6

4
22 19 20 11
1 5

2
21 11
1 4

5
17 19 20 13 -9
1 3

4
17 18 13 -9
1 2

2
16 13
1 1

1
15
0 3        //0表示中间结果,3表示结果ID

1
14
0 3

1
10
0 13

2
8 9
0 13

1
7
0 12

3
4 5 6
0 12

2
2 3
0 11

2
1 3
0 11
5
22 20 19 14 2          //有暗斑点,有长脖子,有长腿,有奶,有蹄  ==> 长颈鹿

3           //初始的事实数
1 15 21        //反刍、有毛发、黑条纹  ==>  斑马

输出结果 :


原创粉丝点击