动物识别系统的规则库
一、题目这是一个用以识别虎、金钱豹、斑马、长颈鹿、企鹅、鸵鸟、信天翁七种动物的产生式系统。为了实现对这些动物的识别,该系统建立了如下规则库:R1: IF该动物有毛 THEN该动物是哺乳动物R2: IF该动物有奶 THEN该动物是哺乳动物R3: IF该动物有羽毛 THEN该动物是鸟R4: IF该动物会飞 AND该动物会下蛋 THEN 该动物是鸟R5: IF该动物吃肉
一、题目
这是一个用以识别虎、金钱豹、斑马、长颈鹿、企鹅、鸵鸟、信天翁七种动物的产生式系统。为了实现对这些动物的识别,该系统建立了如下规则库:
- 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 该动物是信天翁
二、实现过程
最开始我就是直接通过给出的判决条件,用简单的if…else语句来实现这个推理系统,直接给出所有的判决条件,让用户输入,而用户未知的条件让用户进行否决,但是这样会带来问题,比如说会飞、会下蛋可以退出是鸟类动物,但是如果我已知是鸟类了,再去推导企鹅的过程中就会否定之前的条件,因为企鹅有一个不会飞,和之前的会飞推出的是鸟类产生冲突。所以可以先画出推理图,进行层次划分,如下图所示:
图中括号后的数字可以忽略,这个是我第一个版本的判决条件的编号。通过这个推理图,可以简单的将整个推理过程分为两大部分,其中的哺乳动物和食肉动物可以组成一个部分,鸟类单独作为一个部门,另外,值得注意的是,食肉动物不能单独推出金钱豹和虎,但是哺乳动物可推出斑马,这在这个图中容易引起读者的错误思考。
三、代码
#include<stdio.h>
int main() {
printf("\n\n=====动物识别系统=====\n\n");
printf("判决条件:\n");
printf(" 1. 有毛 2.有奶 3.有羽毛 4.会飞 5.会下蛋 6.眼盯前方\n");
printf(" 7. 有蹄 8.反刍动物 9.吃肉 10.有犬齿 11.有爪 \n");
printf("12.长脖子 13.长腿 14.暗斑点 15.有黑色条纹\n");
printf("16.黄褐色 17.不会飞 18.黑白二色 19.会游泳 20.善飞\n");
printf("\n请输入已知条件序号(如2,输入999结束。):\n");
const int num = 20; //条件个数
int inputs[num] = { 0 };
int i = 0;
while (i < num) {
int temp;
scanf_s("%d", &temp);
if (temp == 999) break;
if (temp < 1 || temp >20) {
printf("序号有误,请重新输入: \n");
continue;
}
inputs[i] = temp;
i++;
}
int sign[num] = { 0 }; //标志每一个条件(有就标志为1,没有就标志为0)
int bf[num] = { 0 }; //用于备份
int j = 0;
while (inputs[j] != 0) {
sign[inputs[j] - 1] = 1;
bf[inputs[j] - 1] = 1;
j++;
}
if (sign[0] || sign[1]) {
// 满足哺乳动物条件
if (bf[0]) {
printf("\n使用规则:有毛--->哺乳动物\n");
}
else {
printf("\n使用规则:有奶--->哺乳动物\n");
}
sign[0] = 0, sign[1] = 0;
//printf("=====该动物是哺乳动物=====\n\n");
if (sign[6] || sign[7]) {
// 满足有蹄类动物条件
if (bf[6]) {
printf("\n使用规则:哺乳动物+有蹄--->有蹄类动物\n");
}
else {
printf("\n使用规则:哺乳动物+反刍动物--->有蹄类动物\n");
}
sign[6] = 0, sign[7] = 0;
//printf("=====该动物是有蹄类动物=====\n\n");
if (sign[11] && sign[12] && sign[13]) {
sign[11] = sign[12] = sign[13] = 0;
printf("\n使用规则:有蹄类动物+有长脖子+有长腿+有暗斑点--->长颈鹿\n");
printf("\n\n======该动物是长颈鹿======\n\n");
}
else if(sign[14]){
sign[14] = 0;
printf("\n使用规则:有蹄类动物+有黑色条纹--->斑马\n");
printf("\n\n======该动物是斑马======\n\n");
}
else {
printf("\n\n======无法具体判断=====\n\n");
}
}
else if (sign[8] || (sign[5] && sign[9] && sign[10])) {
if (sign[8]) {
printf("\n使用规则:吃肉--->食肉动物\n");
}
else {
printf("\n使用规则:有犬齿+有爪+眼盯前方--->食肉动物\n");
}
sign[8] = sign[5] = sign[9] = sign[10] = 0;
// 满足食肉动物条件
//printf("=====该动物是食肉动物=====\n\n");
if (sign[13] && sign[15]) {
sign[13] = sign[15] = 0;
printf("\n使用规则:食肉动物+哺乳动物+黄褐色+有暗斑点--->金钱豹\n");
printf("\n\n======该动物是金钱豹======\n\n");
}
else if (sign[14] && sign[15]) {
sign[14] = sign[15] = 0;
printf("\n使用规则:食肉动物+哺乳动物+黄褐色+黑色条纹--->虎\n");
printf("\n\n======该动物是虎======\n\n");
}
}
else {
printf("\n\n======无法具体判断=====\n\n");
}
}
else if (sign[2] || (sign[3] && sign[4])) {
// 满足鸟类条件
if (sign[2]) {
printf("\n使用规则:有羽毛--->鸟类\n");
}
else {
printf("\n使用规则:会飞+会下蛋--->鸟类\n");
}
sign[2] = 0, sign[3] = 0, sign[4] = 0;
//printf("\n\n=====该动物是鸟类=====\n\n");
if (sign[11] && sign[12] && sign[16] && sign[17]) {
sign[11] = sign[12] = sign[16] = sign[17] = 0;
printf("\n使用规则:鸟类+有长脖子+有长腿+不会飞+有黑白二色--->鸵鸟\n");
printf("\n\n======该动物是鸵鸟======\n\n");
}
else if (sign[16] && sign[17] && sign[18]) {
sign[16] = sign[17] = sign[18] = 0;
printf("\n使用规则:鸟类+会游泳+不会飞+有黑白二色--->企鹅\n");
printf("\n\n======该动物是企鹅======\n\n");
}
else if (sign[19]) {
sign[19] = 0;
printf("\n使用规则:鸟类+善飞--->信天翁\n");
printf("\n\n======该动物是信天翁======\n\n");
}
else {
printf("\n\n======无法具体判断=====\n\n");
}
}
else {
printf("\n\n======无法具体判断=====\n\n");
}
int xx = 0; //标记
for (int i = 0; i < num; i++) {
if (sign[i]) {
printf("\n\n推理最可能动物时,存在多余条件, 序号是 %d\n",i+1);
xx = 1;
}
}
if (xx == 1) printf("\n\n=======以上推理失效=======\n");
}
代码中的bf数组,是用于存放用户输入条件的备份数组,因为原始的数组在后期一旦经过判断,就将这个条件置0,也就是不能再使用了,另外最后一个标记循环,只能说是在已经进入第二层或者第三层 的情况下,给出了多余的条件,这个循环才会生效,不然测试一种失败条件时很可能所有的条件都会直接给出。
四、总结
通过本次对动物识别系统的规则库的实现,对产生式系统的机制如推理方式等等有了一个基本的了解和认识。在对程序的改进过程中,弥补了最开始逻辑的漏洞,以及最开始仅仅是根据题目直接用if…else语句进行推导,到后来做出推理图,才真正对题目有了较为深刻的理解,对用户暂时还没有输入的条件进行全盘否定的做法进行了改正,并且在最后将具体的推理过程展现给用户。这不仅是对上课所学的内容有了基本巩固,同时,对此类题目出现的逻辑思维和程序设计思想也有了进一步的提升。这是一个简单的if…else语句实现,读者可以根据自己的需要进行修改。
开放原子开发者工作坊旨在鼓励更多人参与开源活动,与志同道合的开发者们相互交流开发经验、分享开发心得、获取前沿技术趋势。工作坊有多种形式的开发者活动,如meetup、训练营等,主打技术交流,干货满满,真诚地邀请各位开发者共同参与!
更多推荐
所有评论(0)