1、实验目的
理解和掌握产生式系统的推理方法,能够用选定的编程语言实现推理机。
2、实验内容和要求
(1)以实验1的动物识别系统的规则库和综合数据库为基础;
(2)用选定的编程语言开发一个推理机,该推理机能利用实验1的规则库和综合数据库进行推理。
话不多说,直接上代码
C++版本
运行截图
#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;
}
Python 图形交互与语音播报
运行截图
# __author__:cv调包侠
from tkinter.filedialog import *
from tkinter import ttk
import tkinter
import tkinter.messagebox
import pyttsx3
import pyttsx3.drivers
import pyttsx3.drivers.sapi5
teacher = pyttsx3.init('sapi5')
voices = teacher.getProperty('voices')
# for i in voices:
# teacher.setProperty('voice', i.id)
# teacher.say('asdjfadf')
# teacher.say('aaaaa')
# __author__:cv调包侠
import tkinter as tk
import csv
mammal1 = ["有奶"]
mammal2 = ["有毛发"]
Ungulates1 = ["有蹄", "mammal"]
Ungulates2 = ["mammal", "嚼反刍动物"]
birds1 = ["有羽毛"]
birds2 = ["会飞", "下蛋"]
Carnivores1 = ["吃肉"]
Carnivores2 = ["有犬齿", "有爪", "眼盯前方"]
leopard = ["Carnivores", "mammal", "黄褐色", "暗斑点"]
tiger = ["Carnivores", "mammal", "黄褐色", "黑色条纹"]
ostrich = ["bird", "长脖子", "长腿", "不会飞", "黑白二色"]
penguin = ["bird", "会游泳", "不会飞", "黑白二色"]
Albatross = ["bird", "会飞"]
zebra = ["Ungulates", "黑色条纹"]
giraffe = ["长脖子", "长腿", "暗斑点", "Ungulates"]
mammal = [mammal1, mammal2]
Ungulates = [Ungulates1, Ungulates2]
birds = [birds1, birds2]
Carnivores = [Carnivores1, Carnivores2]
class Surface(ttk.Frame):
pic_path = ""
viewhigh = 600
viewwide = 600
update_time = 0
thread = None
thread_run = False
camera = None
def __init__(self, win):
ttk.Frame.__init__(self, win)
frame_left = ttk.Frame(self)
frame_right1 = ttk.Frame(self)
frame_right2 = ttk.Frame(self)
win.title("动物识别系统")
# win.state("zoomed") # 全屏
# win.configure(background='pink') # 去掉注释换颜色
self.pack(fill=tk.BOTH, expand=tk.YES, padx="5", pady="5")
frame_left.pack(side=LEFT, expand=1, fill=BOTH)
frame_right1.pack(side=TOP, expand=1, fill=tk.Y)
frame_right2.pack(side=RIGHT, expand=0, fill='both')
ttk.Label(frame_left, text='').pack(anchor="nw")
ttk.Label(frame_right1, text='').grid(column=0, row=0, sticky=tk.W)
from_world_ctl = ttk.Button(frame_right2, text="输入特征", width=40, command=self.input)
from_pic_ctl = ttk.Button(frame_right2, text="输出特征", width=40, command=self.output)
# from_pic_ctl2 = ttk.Button(frame_right2, text="继续输入", width=40, command=self.output1)
self.text = Entry(win, show=None, width=41, bg='cyan') # 括号内增加 ,bg ='cyan' 文本框换颜色
self.image_ctl = ttk.Label(frame_left)
self.image_ctl.pack(anchor="nw")
self.roi_ctl = ttk.Label(frame_right1)
self.roi_ctl.grid(column=0, row=1, sticky=tk.W)
ttk.Label(frame_right1, text='识别结果:').grid(column=0, row=2, sticky=tk.W)
self.r_ctl = ttk.Label(frame_right1, text="")
self.r_ctl.grid(column=0, row=3, sticky=tk.W)
self.color_ctl = ttk.Label(frame_right1, text="", width="40")
self.color_ctl.grid(column=0, row=4, sticky=tk.W)
# from_vedio_ctl.pack(anchor="se", pady="5")
# from_pic_ctl3.pack(anchor="se", pady="5")
self.text.pack(anchor="se", pady="5")
# from_vedio_ctl1.pack(anchor="se", pady="5")
# from_vedio_ctl2.pack(anchor="se", pady="5")
from_world_ctl.pack(anchor="se", pady="5")
from_pic_ctl.pack(anchor="se", pady="5")
def from_words(self):
pass
def parse(self):
worlds = self.text.get()
k = 0
if not worlds:
k = 1
tkinter.messagebox.showwarning('警告', '输入为空,请重新输入!')
# worlds = "暗斑点 长脖子 长腿 有奶 有蹄"
features = [i for i in worlds.split(' ')]
print(features)
flag = 0
for mammals in mammal:
i = 0
for feature in features:
if feature in mammals:
features.append('mammal')
i = 1
flag = 1
tkinter.messagebox.showinfo('识别过程', '这个动物属于:mamals')
for i in voices:
teacher.setProperty('voice', i.id)
teacher.say('识别成功,这个动物属于:mamals(哺乳动物)')
teacher.runAndWait()
break
# if i == 1:
# return
for Ungulate in Ungulates:
i = 0
for feature in features:
if feature in Ungulate:
features.append('Ungulates')
if flag == 1:
break
tkinter.messagebox.showinfo('识别过程', '这个动物属于:Ungulates(有蹄类动物)')
for i in voices:
teacher.setProperty('voice', i.id)
teacher.say('识别成功,这个动物属于:Ungulates(有蹄类动物)')
teacher.runAndWait()
i = 1
break
if i == 1:
break
for bird in birds:
i = 0
for feature in features:
if feature in bird:
features.append('bird')
if flag == 1:
break
teacher.say('识别成功,这个动物属于:bird(鸟类动物)')
teacher.runAndWait()
tkinter.messagebox.showinfo('识别过程', '这个动物属于:bird(鸟类动物)')
i = 1
break
if i == 1:
break
for Carnivores1 in Carnivores:
i = 0
for feature in features:
if feature in Carnivores1:
features.append('Carnivores')
if flag == 1:
break
tkinter.messagebox.showinfo('识别过程', '这个动物属于:Carnivores')
teacher.say('识别成功,这个动物属于:Carnivores(食肉动物)')
teacher.runAndWait()
i = 1
break
if i == 1:
break
if k == 1:
return
return self.parse_animal(features)
# __author__:cv调包侠
def parse_animal(self, parse):
print(parse)
i = 0
name = ''
for animl in leopard:
if animl not in parse:
i += 1
best = 1 - i / len(leopard)
best_name = 'leopard'
string1 = 'leopard命中率:' + '{}'.format(str(1 - i / len(leopard)))
if i == 0:
name = 'leopard'
print('leopard')
# return name
i = 0
for animl in tiger:
if animl not in parse:
i += 1
string2 = 'tiger命中率:' + '{}'.format(str(1 - i / len(tiger)))
if 1 - i / len(tiger) >best:
best = 1 - i / len(tiger)
best_name = 'tiger'
if i == 0:
name = 'tiger'
print('tiger')
# return name
i = 0
for animl in ostrich:
if animl not in parse:
i += 1
string3 = 'ostrich命中率:' + '{}'.format(str(1 - i / len(ostrich)))
if 1 - i / len(ostrich) >best:
best = 1 - i / len(ostrich)
best_name = 'ostrich'
if i == 0:
name = 'ostrich'
print('ostrich')
# return name
i = 0
for animl in penguin:
if animl not in parse:
i += 1
string4 = 'penguin命中率:' + '{}'.format(str(1 - i / len(penguin)))
if 1 - i / len(penguin) > best:
best = 1 - i / len(penguin)
best_name = 'penguin'
if i == 0:
name = 'penguin'
print('penguin')
# return name
i = 0
for animl in Albatross:
if animl not in parse:
i += 1
string5 = 'Albatross命中率:' + '{}'.format(str(1 - i / len(Albatross)))
if 1 - i / len(Albatross) > best:
best = 1 - i / len(Albatross)
best_name = 'Albatross'
if i == 0:
name = 'Albatross'
print('Albatross')
# return name
i = 0
for animl in zebra:
if animl not in parse:
i += 1
string6 = 'zebra命中率:' + '{}'.format(str(1 - i / len(zebra)))
if 1 - i / len(zebra) > best:
best = 1 - i / len(zebra)
best_name = 'zebra'
if i == 0:
name = 'zebra'
print('zebra')
# return name
i = 0
for animl in giraffe:
if animl not in parse:
i += 1
string7 = 'giraffe命中率:' + '{}'.format(str(1 - i / len(giraffe)))
if 1 - i / len(giraffe) > best:
best = 1 - i / len(giraffe)
best_name = 'giraffe'
if i == 0:
name = 'giraffe'
print('giraffe')
# return name
string = string1 + '\n' + string2 + '\n' + string3 + '\n' + string4 + '\n' + string5 + '\n' + string6 + '\n' + string7
print(string)
if best != 0:
tkinter.messagebox.showinfo('识别结果', '这是动物:{}--->置信度:{}'.format(best_name,best), )
teacher.say('前馈推理识别动物为:{}置信度为:{}'.format(best_name,best))
teacher.runAndWait()
return string
def output(self):
result = self.parse()
if result:
tkinter.messagebox.showinfo('命中率', result,)
# else:
# tkinter.messagebox.showwarning('识别结果', '识别失败,请重新输入!')
def input(self):
tkinter.messagebox.showinfo('成功', '数据导入成功')
with open('./knowledge.csv', 'r', encoding='utf-8') as f:
reader = csv.reader(f)
for row in reader:
for i in row[0].split(' '):
if 'mammal' in i:
mammal1 = row[0].split(' ')[1]
print('features: ', mammal1)
return mammal1
if 'birds' in i:
birds1 = row[0].split(' ')[1]
return birds1
if __name__ == '__main__':
win = tk.Tk()
surface = Surface(win)
# parse = surface.parse('a')
# print(parse)
# surface.parse_animal(parse)
# __author__:cv调包侠
# win.protocol('WM_DELETE_WINDOW', close_window)
win.mainloop()