可完成的功能有正向推理和逆向推理,正向推理可以根据事实指出运用了那些规则推出了何种结论;当事实不足以推出最终动物时,可以让用户继续添加事实,直到推出最终动物。逆向推理可以显示动态数据库。
规则库如下:
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");
}
}