实验内容:
要求:
设计一个动物识别专家系统,规则库至少包含15条规则,可以识别至少7种动物,规则可增加;
界面显示要求:
1)有若干选择动物特征的选择列表;
2)表现判断动物时,使用了哪些规则;
3)表现数据库的变化;
4)显示规则的调用次序;
5)显示最后的结果,包含动物能识别出来和动物不能识别出来两种情况;
6)至少检查两个例子实现正向推理和反向推理的区别?
实验思路:
(1)、建立知识库利用二维数组features[][11]储存,其中存放的是定义的动物特征,
? ? ? ? ? ? 利用getNUM()可以获取知识库元素个数
(2)、规则利用三维数组expr[][2][4]建立,其中存放的是相应的动物特征的编号组合,
? ? ? ? ? ? 利用getrule_NUM()可以获取到规则的个数
(3)、在正向推理中,
? ? ? ? ? ? 第一步:将输入的特征值存放在数组condition_chose[24]中,
? ? ? ? ? ? 用指向此数组的指针去匹配规则expr[][0]即规则的前件(在函数match中实现)。
? ? ? ? ? ? 第二步:如果匹配到规则那么将已经匹配成功的特征在condition_chose[24]中消去
? ? ? ? ?(置为-2),并将匹配到的结论加入到condition_chose[24]中,同时输出匹配成功的规则
? ? ? ? ?(在函数inference中实现)。
? ? ? ? ? ? 第三步:循环到第一步直到找到的对应的动物结束,若匹配失败输出未匹配成功。
(4)、在逆向推理中,
? ? ? ? ? ? 第一步:将输入的动物编号存放在数组condition_chose[24]中,
? ? ? ? ? ? 用指向此数组的指针去匹配规则expr[][1]即规则的后件(在函数match中实现)。
? ? ? ? ? ? 第二步: 如果匹配到规则那么将已经匹配成功的结论在condition_chose[24]中消去
? ? ? ? ? (置为-2),并将匹配到的特征加入到condition_chose[24]中,
? ? ? ? ? ? ?同时输出匹配成功的规则(在函数inference中实现)。
? ? ? ? ? ? 第三步:循环到第一步直到找到的所有的动物特征结束,若匹配失败输出未匹配成功。
实验代码:
在Visio Stduio中建立如下文件:
?各个文件代码如下:
<database.h>
#pragma once
#include<stdio.h>
#include<string.h>
char features[][11]= { "有毛", "产奶", "有羽毛", "会飞", "会下蛋", "吃肉", "有犬齿", "有爪", "眼睛盯前方", "有蹄",
"反刍", "黄褐色", "有斑点", "有黑色条纹", "长脖", "长腿", "不会飞", "会游泳", "黑白两色", "善飞",
"哺乳类", "鸟类", "肉食类", "蹄类", "企鹅", "海燕", "鸵鸟", "斑马", "长颈鹿", "虎", "金钱豹" };
//指向事实库的指针
char (*point)[11] = features;
//获取数据的个数
int getNUM() {
int num = 0;
while (*point[num] != NULL) {
num++;
}
return num;
}
<rule.h>
#pragma once
#include<stdio.h>
#include"database.h"
int expr[][2][4] = { {{1, -1, -1, -1}, { 21 }},
{{21, 9, -1, -1}, { 24 }},
{{23, 12, 13, -1}, { 31 }},
{{4, 5, -1, -1}, { 22 }},
{{7, 8, 9, -1}, { 23 }},
{{24, 15, 16, 13}, { 29 }},
{{22, 15, 16, 17}, { 27 }},
{{21, 10, -1, -1}, { 24 }},
{{23, 12, 14, -1}, { 30 }},
{{22, 18, 19, 17}, { 25 }},
{{24, 14, -1, -1}, { 28 }},
{{22, 20, -1, -1}, { 26 }},
{{2, -1, -1, -1}, { 21 }},
{{3, -1, -1, -1}, { 22 }} };
//获取规则个数
int getrule_NUM() {
int num = 0;
num = sizeof(expr)/sizeof(expr[0]);
return num;
}
<interface.h>
#pragma once
#include<stdio.h>
#include"database.h"
void interface(char *a) {
//事实库选择列表
printf("\t\t--------------------------------------------------------------\n");
printf("\t\t----------------------------知识库----------------------------\n");
//int count1 = getNUM();
int count1 = getNUM() - 7;
int count2 = count1; //记录count1
while (count1) {
for (int i = 1; i < count2+1; i++) {
printf("%d.%s \t", i, point[i - 1]);
count1--;
//每行输出六个
if (i % 6 == 0) {
printf("\n");
}
}
}
if (a != NULL) {
count2++;
printf("%d.%s ", count2, a);
}
printf("\n");
printf("\t\t--------------------------------------------------------------\n");
printf("请输入选择的特征数字:");
//printf("请输入选择的动物数字:");
}
<positive.cpp>正向推理
#define _CRT_SECURE_NO_WARNINGS
#include"database.h"
#include"interface.h"
#include"rule.h"
#include<stdio.h>
#include<stdlib.h>
using namespace std;
int condition_chose[24]; //选择的动物特征
int count_num = 0; //记录输入特征个数
int rule_Max = 4; //规则前件最大为4
int rule_number = -1; //匹配规则标号
//匹配规则右部分
bool match(int *p) {
int k;
int j;
int count_elem = 0;
int flag = 0;
for (rule_number = 0;rule_number < getrule_NUM();rule_number++) {
count_elem = 0;
for (int j = 0;j < count_num;j++) {
for (int k = 0;k < 4;k++) {
if (expr[rule_number][0][k] != -1) {
count_elem++;
}
if (p[j] == expr[rule_number][0][k]) {
flag++;
}
}
}
if (flag == (count_elem/count_num)) {
return true;
}
flag = 0;
}
return false;
}
//找到结论
void inference(int *p) {
printf("--------------------使用规则-----------------------\n");
int u;
int l;
int count = 1;
int result; //记录结论
while (match(p)) {
u = 0;
result = expr[rule_number][1][0];
for (int i = 0;i < count_num;i++) {
for (int j = 0;j < 4;j++) {
if (expr[rule_number][0][j] == -1) {
u++;
}
if (p[i] == expr[rule_number][0][j]) {
p[i] = -2; //删除已经用过的前件
}
}
}
l = rule_Max - (u/count_num);
printf("%d、 IF ",count);
printf("%s", features[expr[rule_number][0][0]-1]);
for (int i = 1;i < l;i++) {
printf(" AND %s", features[expr[rule_number][0][i]-1]);
}
printf(" THEN %s\n", features[result - 1]);
count++; //规则计数器
p[count_num] = result;
count_num++;
if (match(p) == false && result <= 24) {
printf("---------------------------------------------------\n");
printf("--------------------匹配结果-----------------------\n");
printf("没有匹配到动物\n");
return;
}
if (match(p) == false && result > 24) {
printf("--------------------匹配结果-----------------------\n");
printf("匹配到的动物是:%s\n", features[result - 1]);
printf("\n");
//更新知识库
printf("-------------------更新知识库----------------------\n");
interface(features[result - 1]);
return;
}
}
printf("没有匹配到动物\n");
}
int main() {
int chose; //记录输入的特征
int k = 0; //控制condition_chose数组
int* p = condition_chose; //操作选项
interface(NULL); //界面
while (scanf("%d",&chose)) {
condition_chose[k] = chose;
k++;
count_num++;
}
inference(p);
system("pause");
return 0;
}
<negative.cpp>逆向推理
#define _CRT_SECURE_NO_WARNINGS
#include"database.h"
#include"interface.h"
#include"rule.h"
#include<stdio.h>
#include<stdlib.h>
using namespace std;
int condition_chose[24]; //选择的动物特征
int count_num = 0; //记录输入特征个数
int rule_Max = 4; //规则前件最大为4
int rule_number = -1; //匹配规则标号
//匹配规则左部分
bool match(int* p) {
int k;
int j;
int count_elem = 0;
int flag = 0;
for (rule_number = 0;rule_number < getrule_NUM();rule_number++) {
count_elem = 0;
for (int j = 0;j < count_num;j++) {
if (expr[rule_number][1][0] != -1) {
count_elem++;
}
if (p[j] == expr[rule_number][1][0]) {
flag++;
}
}
if (flag == (count_elem / count_num)) {
return true;
}
flag = 0;
}
return false;
}
//找到结论
void inference(int* p) {
printf("--------------------使用规则-----------------------\n");
int u;
int l;
int result_count = 0;
int count = 1;
int result1;
int result[4]; //记录结论
while (match(p)) {
u = 0;
for (int j = 0;j < rule_Max;j++) {
result[j] = expr[rule_number][0][j];
}
result1 = expr[rule_number][1][0];
for (int i = 0;i < count_num;i++) {
if (expr[rule_number][1][0] == -1) {
u++;
}
if (p[i] == expr[rule_number][1][0]) {
p[i] = -2; //删除已经用过的结论
}
}
l = rule_Max - (u / count_num);
printf("%d、 IF ", count);
printf("%s", features[expr[rule_number][0][0] - 1]);
for (int i = 1;i < l;i++) {
printf(" AND %s", features[expr[rule_number][0][i] - 1]);
}
printf(" THEN %s\n", features[result1 - 1]);
//推理得到的前件加入到p中
for (int k = count_num;k < count_num + 4;k++) {
p[k] = result[result_count];
result_count++;
}
result_count = 0;
count_num = count_num + 4;
if (match(p) == false) {
printf("--------------------匹配结果-----------------------\n");
for (int o = 0;o < count_num;o++) {
if (p[o] != -1 && p[o] != -2) {
printf("匹配到的动物特征:%s\n", features[p[o] - 1]);
}
}
printf("\n");
return;
}
}
printf("没有此动物特征\n");
}
int main() {
int chose; //记录输入的特征
int k = 0; //控制condition_chose数组
int* p = condition_chose; //操作选项
interface(NULL); //界面
while (scanf("%d", &chose)) {
condition_chose[k] = chose;
k++;
count_num++;
}
inference(p);
system("pause");
return 0;
}
测试数据:
正向推理:1 10 14 END
逆向推理:30 END
实验结果:
正向推理:
逆向推理:
|