动物识别专家系统_动物产生式识别系统

摘要:构造知识型系统和建立认知模型时常用的知识表示的形式系统。1943年E.波斯特首先将他提出的一种计算形式体系命名为产生式系统。50年代末期,A.纽厄尔和H.A.西蒙在研究人类问题求解的认知模型时也使用了产生式系统这一术语。产生式系统现代已成为研制人工智能系统时采用的最典型的体系结构之一。本文主要论述计算机科学与技术专业大三下专业课《人工智能》第三个实验算法。
关键字:人工智能,专家系统,产生式系统
Production system

Abstract: Constructs the knowledge system and cognitive model often used in the form of knowledge representation system. E. 1943 post first will he come up with a form of computing system named production system. The late 50 s, a. Newell and H.A. Simon in the study of human cognitive model of problem solving when the term is also used by the production system. Production system has become an artificial intelligence system in modern times, with one of the most typical architecture. This paper mainly discusses the computer science and technology under the junior in professional class "artificial intelligence" third experiment algorithm.

Keywords: Artificial intelligence, expert system, production system
1,问题重述

通过理解并体会知识库与控制系统相互独立的智能产生式系统与一般程序的区别,为以后设计并实现复杂的专家系统奠定基础。

知识表示为产生式知识表示方法,设计并实现具有15条规则能自动识别7种动物的产生式系统。知识库与控制系统相互独立,系统完成后除了能识别已有的7种动物外,按产生式知识表示方法向知识库中添加、修改新的知识后,系统能在不修改控制系统程序的情况下仍然能正确识别。

90b8fe3f3dc15abef65ba79e74765b66.png


2,问题分析

2.1.事实的表示:

事实可看成是断言一个语言变量的值或是多个语言变量间的关系的陈述句,语言变量的值或语言变量间的关系可以是一个词。不一定是数字。一般使用三元组(对象,属性,值)或(关系,对象1,对象2)来表示事实,其中对象就是语言变量,若考虑不确定性就成了四元组表示(增加可信度)。这种表示的机器内部实现就是一个表

2.2.规则的表示:

规则用于表示事物间的因果关系,以if conditionthen action 的单一形式来描述,将规则作为知识的单位。其中的condition 部分称为条件式前件或模式,而action部分称作动作、后件或结论。

产生式一般形式为:前件 后件。前件和后件也可以是有“与”、“或”、“非”等逻辑运算符的组合的表达式。条件部分常是一些事实的合取或析取,而结论常是某一事实B。如果不考虑不确定性,需另附可信度度量值。

产生式过则的含义是:如果前件满足,则可得到后件的结论或者执行后件的相应动作,即后件由前件来触发。一个产生式生成的结论可以作为另一个产生式的前提或语言变量使用,进一步可构成产生式系统。

蕴涵式表示的知识只能是精确的,产生式表示的知识可以是不确定的,原因是蕴涵式是一个逻辑表达式,其逻辑值只有真和假。蕴含式的匹配一定要求是精确的,而产生式的匹配可以是不确定的,原因是产生式的前提条件和结论都可以是不确定的,因此其匹配也可以是不确定的。
3,设计文档

<知识库>

<事实>

<条件>

1:有毛发 2:产奶 3:有羽毛 4:会飞

5:会下蛋 6:吃肉 7:有犬齿 8:有爪

9:眼盯前方 10:有蹄 11:反刍 12:黄褐色

13:有斑点 14:有黑色条纹 15:长脖 16:长腿

17:不会飞 18:会游泳 19:黑白二色 20:善飞

</条件>

<中间结论>

21:哺乳类 22:鸟类 23:食肉类 24:蹄类

</中间结论>

<结论>

25:金钱豹 26:虎 27:长颈鹿 28:斑马 29:鸵鸟

30:企鹅 31:信天翁

</结论>

</事实>

<规则>

有毛->哺乳类

产奶->哺乳类

有羽毛->鸟类

会飞,会下蛋->鸟类

哺乳类,吃肉->食肉类

有犬齿,有爪,眼盯前方->食肉类

哺乳类,有蹄->蹄类

哺乳类,反刍->蹄类

食肉类,黄褐色,有斑点->金钱豹

食肉类,黄褐色,有黑色条纹->虎

蹄类,长脖,长腿,有斑点->长颈鹿

蹄类,有黑色条纹->斑马

鸟类,长脖,长腿,会飞->鸵鸟

鸟类,会游泳,黑白二色,会飞->企鹅

鸟类,善飞->信天翁

</规则>

</知识库>

**规则符号化

1->21 //有毛->哺乳类

2->21 //产奶->哺乳类

3->22 //有羽毛->鸟类

4,5->22 //会飞,会下蛋->鸟类

21,6->23 //哺乳类,吃肉->食肉类

7,8,9->23 //有犬齿,有爪,眼盯前方->食肉类

21,10->24 //哺乳类,有蹄->蹄类

21,11->24 //哺乳类,反刍->蹄类

23,12,13->25 //食肉类,黄褐色,有斑点->金钱豹

23,12,14->26 //食肉类,黄褐色,有黑色条纹->虎

24,15,16,13->27 //蹄类,长脖,长腿,有斑点->长颈鹿

24,14->28 //蹄类,有黑色条纹->斑马

22,15,16,4->29 //鸟类,长脖,长腿,会飞->鸵鸟

22,18,19,4->30 //鸟类,会游泳,黑白二色,会飞->企鹅

22,20->31 //鸟类,善飞->信天翁

**

**测试用例

2,10,13,15,16 -> 27

产奶,有蹄,有斑点,长脖,长腿 -> 长颈鹿

*/

4,程序设计

e77fec879800721486505faddf4892d5.png

4f456e9a4ef9a408a61029a4920356d4.png
#include<iostream>
#include<string>
#include<cstdlib>
#include<iomanip>
#include<list>

using namespace std;

const int fact_num = 31;      //知识库中的知识:31种知识
const int rule_num = 15;      //知识库中的规则:15条规则
const int rule_volume = 4;    //规则中每个结果最多有4个前提条件
const int object_range_begin = 25;  //从第25个知识开始
const int object_range_end = 31;    //到第31个知识为目标结论
const int object_middle_begin = 21;     //中间结果起始位置 

string fact[fact_num] =               
{
    "有毛发","产奶","有羽毛","会飞","会下蛋",
    "吃肉","有犬齿","有爪","眼盯前方","有蹄",
    "反刍","黄褐色","有斑点","有黑色条纹","长脖",
    "长腿","不会飞","会游泳","黑白二色","善飞",
    "哺乳类","鸟类","食肉类","蹄类","金钱豹",
    "虎","长颈鹿","斑马","鸵鸟","企鹅","信天翁"
};

int rule_prerequisite[rule_num][rule_volume] =      
{
    {1,0,0,0},
    {2,0,0,0},
    {3,0,0,0},
    {4,5,0,0},
    {21,6,0,0},
    {7,8,9,0},
    {21,10,0,0},
    {21,11,0,0},
    {23,12,13,0},
    {23,12,14,0},
    {24,15,16,13},
    {24,14,0,0},
    {22,15,16,4},
    {22,18,19,4},
    {22,20,0,0}
};

int rule_result[rule_num] =
{
    21,
    21,
    22,
    22,
    23,
    23,
    24,
    24,
    25,
    26,
    27,
    28,
    29,
    30,
    31
};

bool backward_reasoning(int num,int message[]) ;
bool inference(int num,int message[])         //迭代推理机
{
    int ii, ij, ik,im,in;
    int hit_num = 0;          //输入前提也规则前提重合数
    int prerequisite_num;     //规则前提数
    int *message_c;           //迭代前提
    int num_c;                //迭代前提数量
    for (ik = 0; ik < num; ik++)     //剪枝函数
    {
        if (message[ik] >= object_range_begin&&message[ik] <= object_range_end)
        {
            cout << "归并信息:" << fact[message[ik] - 1] << endl;
            cout << "推理成功!" << endl<<endl;
            system("pause");
            exit(0);
        }
    }
    for (ii = 0; ii < rule_num; ii++)   //遍历规则匹配
    {
        prerequisite_num = 0;
        hit_num = 0;
        for (ij = 0; ij < rule_volume; ij++)   //计算规则集前提数
        {
            if (rule_prerequisite[ii][ij] == 0)
            {
                break;
            }
            prerequisite_num++;
        }
        for (ij = 0; ij < prerequisite_num; ij++)
        {
            for (ik = 0; ik < num; ik++)
            {
                if (rule_prerequisite[ii][ij] == message[ik])
                {
                    hit_num++;
                }
            }
        }
        if (hit_num == prerequisite_num)  //满足某个规则集全部前提
        {
            bool flag;
            for (ik = 0; ik < num; ik++)
            {
                if (message[ik] == rule_result[ii])
                {
                    break;
                }
            }
            if (ik == num)
            {
                num_c=num - hit_num+1;
                flag = true;
            }
            else
            {
                num_c = num - hit_num;
                flag = false;
            }
            message_c = new int[num_c];
            in = 0;
            for (ik = 0; ik < num; ik++)
            {
                for (im = 0; im < hit_num; im++)
                {
                    if (rule_prerequisite[ii][im] == message[ik])
                    {
                        break;
                    }
                }
                if (im < hit_num)
                {
                    continue;
                }
                message_c[in++] = message[ik];
            }
            if (flag == true)
            {
                message_c[in] = rule_result[ii];
            }
            cout << "推导信息:";
            for (int iz = 0; iz < num; iz++)
            {
                cout << fact[message[iz]-1] << " ";
            }
            cout << endl;
            return inference(num_c,message_c);
        }
    }
    cout << "归并信息:";
    for (int iz = 0; iz < num; iz++)
    {
        cout << fact[message[iz]-1] << " ";
    }
    cout << endl;
    backward_reasoning(num,message);
    return false;
}

bool backward_reasoning(int num,int message[])   //反向推理
{
    int ii,ij,ik;
    int prerequisite_num = 0;
    int hit_num = 0;
    int need_rule_number[rule_num];
    int hit_rule_number[rule_num];
    float hit_rule_rate[rule_num];
    float best_hit_rule_rate=0;
    int best_hit_rule_number;
    int *new_message;
    for (ii = 0; ii < rule_num; ii++)   //遍历规则匹配
    {
        prerequisite_num=0;
        hit_num=0;
        for (ij = 0; ij < rule_volume; ij++)   //计算规则集前提数
        {
            if (rule_prerequisite[ii][ij] == 0)
            {
                break;
            }
            prerequisite_num++;
        }
        need_rule_number[ii]=prerequisite_num;
        for (ij = 0; ij < prerequisite_num; ij++)   //计算输入信息命中规则集中的前提数
        {
            for (ik = 0; ik < num; ik++)
            {
                if (rule_prerequisite[ii][ij] == message[ik])
                {
                    hit_num++;
                }
            }
        }
        hit_rule_number[ii]=hit_num;
        hit_rule_rate[ii]=(float)hit_num/prerequisite_num;  //命中率
        for(ij=0;ij<num;ij++)
        {
            if(message[ij]==rule_result[hit_rule_number[ii]])
            {
                break;
            }
        }
        if(hit_rule_rate[ii]==1&&ij==num)
        {
            new_message=new int[num+1];
            for(ik=0;ik<num;ik++)
            {
                new_message[ik]=message[ik];
            }
            new_message[num]=rule_result[hit_rule_number[ii]];
            num++;
            return inference(num,new_message);
        }
        cout<<"rule "<<setw(2)<<ii<<" -> "<<setw(8)<<fact[rule_result[ii]-1]
        <<"命中率:"<<hit_rule_rate[ii]<<endl;
    }
    best_hit_rule_number=-1;
    for(ii=0;ii<rule_num;ii++)
    {
        if(best_hit_rule_rate<hit_rule_rate[ii]&&
            rule_result[ii]>=object_middle_begin)
        {
            best_hit_rule_rate=hit_rule_rate[ii];
            best_hit_rule_number=ii;
        }
    }
    if(best_hit_rule_number==-1)
    {
        cout<<"您输入的信息对本系统无效!按任意键退出..."<<endl<<endl;
        system("pause");
        exit(0);
    }
    cout<<endl;
    cout<<"best_hit_rule_number="<<best_hit_rule_number<<endl;
    cout<<"best_hit_rule_rate="<<best_hit_rule_rate<<endl;
    cout<<"最佳匹配最终结果="<<fact[rule_result[best_hit_rule_number]-1]<<endl;
    for(ii=0;ii<need_rule_number[best_hit_rule_number];ii++)
    {
        for(ij=0;ij<num;ij++)
        {
            if(rule_prerequisite[best_hit_rule_number][ii]==message[ij])
            {
                break;
            }
        }
        if(ij!=num)
        {
            continue;
        }
        else
        {
            if(rule_prerequisite[best_hit_rule_number][ii]<object_middle_begin)
            {
                cout<<endl<<"请问您持有的信息是否包含"";
                cout<<fact[rule_prerequisite[best_hit_rule_number][ii]-1];
                cout<<""?(y or n)"<<endl;
                char input;
                while(true)
                {
                    cin>>input;
                    if(input=='n')
                    {
                        new_message=new int[num];
                        for(ik=0;ik<num;ik++)
                        {
                            new_message[ik]=message[ik];
                        }
                        break;
                    }
                    else if(input=='y')
                    {
                        new_message=new int[num+1];
                        for(ik=0;ik<num;ik++)
                        {
                            new_message[ik]=message[ik];
                        }
                        new_message[num]=rule_prerequisite[best_hit_rule_number][ii];
                        num++;
                        return inference(num,new_message);
                    }
                    else
                    {
                        cout<<"请重新输入(y or n)!";
                    }
                }
            }
            else      //询问是否有中间结果rule_prerequisite[best_hit_rule_number][ii]
            {    
                int middle_result=rule_prerequisite[best_hit_rule_number][ii];
                for(ii=0;ii<rule_num;ii++)
                {
                    if(rule_result[ii]==middle_result)
                    {
                        for(ik=0;ik<need_rule_number[ii];ik++)
                        {
                            if(rule_prerequisite[ii][ik]>=object_middle_begin-1)
                            {
                                continue;
                            }
                            for(ij=0;ij<num;ij++)
                            {
                                if(rule_prerequisite[ii][ik]==message[ij])
                                {
                                    break;
                                }
                            }
                            if(ij!=num)
                            {
                                continue;
                            }
                            else
                            {
                                cout<<endl<<"请问您持有的信息是否包含"";
                                cout<<fact[rule_prerequisite[ii][ik]-1];
                                cout<<""?(y or n)"<<endl;
                                char input;
                                while(true)
                                {
                                    cin>>input;
                                    if(input=='n')
                                    {
                                        break;
                                    }
                                    else if(input=='y')
                                    {
                                        new_message=new int[num+1];
                                        for(int iq=0;iq<num;iq++)
                                        {
                                            new_message[iq]=message[iq];
                                        }
                                        new_message[num]=rule_prerequisite[best_hit_rule_number][ii];
                                        num++;
                                        return inference(num,new_message);
                                    }
                                    else
                                    {
                                        cout<<"请重新输入(y or n)!";
                                    }
                                }
                            }
                        }
                    }
                }
            }
        }
    }
}

int main(int argc, char **argv)
{
    bool flag;
    int num;
    int *message;
    int ii,ij;
    cout<<"《知识库》"<<endl;
    for(ii=0;ii<fact_num;ii++)
    {
        cout<<setiosflags(ios::left);
        cout<<setw(2)<<ii+1<<":"<<setw(10)<<fact[ii]<<"  ";
        if(ii%4==0)
        {
            cout<<endl;
        }
    }
    cout <<endl<<endl<< "请输入初始信息个数:(数字)" << endl;
    cin >> num;
    message = new int[num];
    cout << "请输入已有信息:(不重复的数字,以空格隔开)" << endl;
    for (ii = 0; ii < num; ii++)
    {
        cin >> message[ii];
    }
    cout << endl << "初始信息:";
    for (ij = 0; ij < num; ij++)
    {
        cout << fact[message[ij]-1] << " ";
    }
    cout << endl<<endl;
    if(!inference(num,message))
    {
        cout<<"通过您的输入无法得出结果!"<<endl;
    }
    system("pause");
    return 0;
}
 
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值