人工智能导论基于产生式的动物识别专家系统的C++实现

可完成的功能有正向推理和逆向推理,正向推理可以根据事实指出运用了那些规则推出了何种结论;当事实不足以推出最终动物时,可以让用户继续添加事实,直到推出最终动物。逆向推理可以显示动态数据库。

规则库如下:

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 该动物是信天翁

代码如下:

#include<iostream>
#include<iomanip>
using namespace std;
char *animal[]= {"企鹅","信天翁","鸵鸟","斑马","长颈鹿","虎","金钱豹"};
char *feature[]= {"有毛","产奶","有羽毛","会飞","会下蛋","吃肉","有犬齿","有爪","眼睛盯前方","有蹄","反刍","黄褐色","有斑点",
                  //0 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
typedef struct { //存放规则的结构体
	int relation[5];
	int name;
} Rule;
Rule rule[15]= {
	{{0,-1},20}	,
	{{1,-1},20},
	{{2,-1},21},
	{{3,4,-1},21},
	{{20,5,-1},22},
	{{6,7,8,-1},22},
	{{20,9,-1},23},
	{{20,10,-1},23},
	{{20,22,11,12,-1},30},
	{{20,22,11,13,-1},29},
	{{23,14,15,12,-1},28},
	{{23,13,-1},27},
	{{21,14,15,16,-1},26},
	{{21,17,18,16,-1},24},
	{{21,19,-1},25}
};
int flag[23]= {0}; //标记各个特征是否选择
int IsAnimal(int a);
int inference();
void input();
void menu();
void menu() {//用户选择界面 
	int i=0;
	for(i=0; i<24; i++) {
		if(i%4==0&&i!=0) {
			cout<<endl;
		}
		printf("%-3d.%-15s",i,feature[i]);
		//%s ,它的原理其实也是通过字符串首地址输出字符串,printf("%s ", s); 传给它的其实是s所保存的字符串的地址
	}
}

void input() {//输入 
	int ti=0;
	for(int i=0; i<24; i++) {
		flag[i]=0;
	}
	while(ti!=-1) {
		cout<<"\n 输入选择(-1 结束):";
		cin>> ti;
		if(ti>=0&&ti<=23)
			flag[ti]=1;
		else if(ti!=-1) {
			cout<<"输入错误!请输入 0~23 之间的数字!"<< endl; //notanimal=25
			cin.clear();//清除流错误错误标
			cin.sync(); //清空输入缓冲区
		}
	}
}
int IsAnimal(int a) { //结论是否是动物 
	if(a>=24&&a<=30)
		return 1;
	else
		return 0;
}
int inference() { //正向推理
	int ti;
	int i,j;
	int tres;
	cout<<endl;
	for(i=0; i<15; i++) {
		j=0;
		ti=rule[i].relation[j];
		while(ti!=-1) { //-1 作为结束  判断是否可以推出某一事实 
			if(flag[ti]==0)
				break;
			j++;
			ti=rule[i].relation[j];
		}
		if(ti==-1) { //ti==-1 代表规则满足 显示运用了那一规则推出了何种结论 
			tres=rule[i].name;
			flag[tres]=1;
			printf("运用了规则%d : ",i+1);
			j=0;
			while(rule[i].relation[j]!=-1) {
				cout<<feature[rule[i].relation[j]]<<" ";
				j++;
			}
			cout<<"====> "<<feature[tres]<<endl;
			if(IsAnimal(tres)) {
				cout<<"该动物为:"<<feature[tres]<<endl;
				return 1;
			}
		}
	}
	if(i==sizeof(rule)/sizeof(rule[0])) {//控制没有推出最终动物时追加条件 
		cout<<"没有这种动物,是否要追加条件(Y/N)?";
		char q;
		cin>>q;
		if(q!='N') {
			while(ti!=-1) {
				cout<<"\n 输入选择(-1 结束):";
				cin>> ti;
				if(ti>=0&&ti<=23)
					flag[ti]=1;
				else if(ti!=-1) {
					cout<<"输入错误!请输入 0~23 之间的数字!"<< endl; //notanimal=25
					cin.clear();//清除流错误错误标
					cin.sync(); //清空输入缓冲区
				}
			}
			inference();
		}
	}
	return -1;
}
void  backword() { //逆向推理
	cout<<endl;
	cout<<"输入事实数据库:"<<endl;
	input();
	cout<<"请选择动物种类编号"<<endl;
	int ti=0;
	int j;
	int tres;
	bool key=1;
	cin>>ti;

	if(ti>=24&&ti<=30) { //输入不为动物时重新输入 
		flag[ti]=1;
	} else {
		while(ti<24||ti>30) {
			cout<<"无该动物种类,请重新输入"<<endl;
			cin>>ti;
		}
	}
	int *real;//满足结论是该动物的规则 
	for(int i=0; i<15; i++) {//满足该动物的事实 
		if(rule[i].name==ti) {
			j=0;
			cout<<feature[ti]<<','<<"事实列表为:";
			while(rule[i].relation[j]!=-1) {
				cout<<feature[rule[i].relation[j]]<<" ";
				j++;
			}
			cout<<endl;
			real = rule[i].relation;
			
		}
	}
	for(int i=0; i<8; i++) {//根据已知事实推出可得到事实,将所有事实加入到事实数据库 
		j=0;
		ti=rule[i].relation[j];
		while(ti!=-1) { //-1 作为结束
			if(flag[ti]==0)
				break;
			j++;
			ti=rule[i].relation[j];
		}
		if(ti==-1) { //ti==-1 代表规则满足,将该规则加入到事实数据库 
			tres=rule[i].name;
			flag[tres]=1;
			cout<<"添加事实数据库:“"<<feature[tres]<<"”"<<endl; 
		}
	}

  for(int i=0;i<sizeof(real)/sizeof(real[0]);i++){//事实数据库与事实列表做比较,若事实数据库可满足事实列表则匹配成功 
  	if(flag[real[i]]==0){
  		key=0;
	  }
  }
  cout<<"事实数据库为:"; 
  for(int i=0;i<24;i++){
  	if(flag[i]!=0){
  		cout<<feature[i]<<" ";
	  }
  }
  cout<<endl;
  if(key==0)
  cout<<"匹配失败"<<endl;
  else
  cout<<"匹配成功"<<endl;
}
int main() {
	char q;int m=2;
	while(q!='n') {
		cout<<"请选择正向推理(0)或者逆向推理(1)"<<endl; 
		cin>>m;
		if(m==0){
			menu();
		input();
		inference();
		}else{
			menu();
			cout<<endl;
			for(int i=0;i<7;i++){
					printf("%-3d.%-15s",i+24,animal[i]); 
					if(i==3)
					cout<<endl;
			}
			backword();
		}
		cout<<"\n 继续?(Y/N)"<<endl; 
		cin>>q;
		system("cls");
	}
	
}

 

  • 1
    点赞
  • 15
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值