全部的事实集(30个):
"反刍","有蹄","哺乳类","眼向前方","有爪",
"犬齿","吃肉","下蛋","能飞","有羽毛","蹄类","食肉类","鸟类","有奶","毛发",
"善飞","黑色白条纹","游泳","长腿","长脖子",
"黑条纹","暗斑点","黄褐色"
"信天翁","企鹅","鸵鸟","斑马","长颈鹿","虎","豹"
所有的规则(15条):
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>
using namespace std;
bool OK;
bool allzero = false;
typedef struct rule {
int factnum;
int fact[8];
int matchnum;
int result;
}start;
char *allfacts[] = { "f1:反刍","f2:有蹄","f3:哺乳类","f4:眼向前方","f5:有爪",
"f6:犬齿","f7:吃肉","f8:下蛋","f9:能飞","f10:有羽毛",
"f11:蹄类","f12:食肉类","f13:鸟类","f14:有奶","f15:毛发",
"f16:善飞","f17:黑白相间","f18:游泳","f19:长腿","f20:长脖子",
"f21:黑条纹","f22:暗斑点","f23:黄褐色" ,"f24:信天翁","f25:企鹅","f26:鸵鸟","f27:斑马",
"f28:长颈鹿","f29:虎","f30:豹" };
rule r[15] = {
{1,{15,0,0,0,0,0,0,0},0,3},{ 1,{14,0,0,0,0,0,0,0},0,3 },{ 1,{10,0,0,0,0,0,0,0},0,13 },
{2,{ 9,8,0,0,0,0,0,0 },0,13},{ 1,{ 7,0,0,0,0,0,0,0 },0,12 },{ 3,{ 6,5,4,0,0,0,0,0 },0,12 },
{ 2,{ 3,2,0,0,0,0,0,0 },0,11 },{ 2,{ 3,1,0,0,0,0,0,0 },0,11 },{ 4,{ 3,12,23,22,0,0,0,0 },0,30 },
{4,{ 3,12,23,21,0,0,0,0 },0,29},{ 4,{ 11,20,19,22,0,0,0,0 },0,28 },{ 2,{ 11,21,0,0,0,0,0,0 },0,27 },
{ 5,{ 13,-9,20,19,17,0,0,0 },0,26 },{ 4,{ 13,-9,18,17,0,0,0,0 },0,25 },{ 2,{ 13,16,0,0,0,0,0,0 },0,24 }
};
start s;
int match(rule r[], start s,int result)
{
int rule_num=0;
start s2 = s;//s2用于拷贝s,以免未匹配时fact数组值被修改
start s3 = s;//s3作为一条规则后s的更新情况
while (rule_num < 15)
{
for(int i=0;i<s.factnum;i++)
for (int j = 0; j < r[rule_num].factnum; j++)
{
if (s.result != 0 && s.result == r[rule_num].fact[j])
{
s.result = 0;
r[rule_num].matchnum++;
break;
}
if (s.fact[i] == r[rule_num].fact[j])
{
s.fact[i] = 0;
r[rule_num].matchnum++;
break;
}
}
if (r[rule_num].matchnum == r[rule_num].factnum)
{
s.result = r[rule_num].result;
s3 = s;
}
else
s = s3;
r[rule_num].matchnum = 0;//回归初始值
rule_num++;
}
for (int m = 0; m < 8; m++)//判断此时fact数组是否为空,为空则说明匹配成功
{
if (s.fact[m] != 0)
{
allzero = false;
break;
}
else
allzero = true;
}
if (allzero == true)
OK = true;
else
OK = false;
result = s.result;
return result;
}
start clean_re(start s)//去重函数
{
for (int i = s.factnum-1; i >0; i--)
{
for (int j = 0; j < i; j++)
{
if (s.fact[i] == s.fact[j])
s.fact[i] = 0;
else
continue;
}
}
return s;
}
int main()
{
bool exit_system=true;
char exit_sign;
for (int j = 0; j < 30; j++) //输出数据库中所有事实
cout << allfacts[j] << endl;
cout << "开发者:赵裴翔 201577D0556 欢迎您的使用" << endl;
int i;
int result=0;
while (exit_system)
{
cout << "请输入现有事实的数量:";
cin >> i;
s.factnum = i;
cout << "请依次输入每条事实:" << endl;
for (int num = 0; num < 8; num++)
if (num < i)
cin >> s.fact[num];
else
s.fact[num] = 0;
s = clean_re(s); //将现有的事实集去除重复事实
result = match(r, s, result);//匹配算法执行,获得最终结果
if (OK == true)
cout << result << " " << allfacts[result - 1] << endl << "是否退出识别系统?(Y/N):";
else
cout << "未找到匹配项"<<endl << "是否退出识别系统?(Y/N):";
while (cin >> exit_sign)
{
if (exit_sign == 'Y')
{
exit_system = false;
break;
}
else if (exit_sign == 'N')
{
exit_system = true;
break;
}
if (exit_sign != 'N' || exit_sign != 'Y')
cout << "输入错误请重新输入(Y/N):";
}
}
cout << "感谢您的使用,开发者:赵裴翔" << endl;
return 0;
}
设计的匹配原则是:将当前输入的事实集(start)中的fact数组以及非零的result结论与rule规则集的每一条规则里的fact进行比对,如果符合要求,则将start的fact数组中对应元素置0并将该条规则的matchnum加1,如此循环当matchnum与factnum相等时,即可判定匹配成功,此时将规则中的result赋给start中的result,继续进行匹配,直到与所有规则比较完毕,得到最终结论。
在整个系统运行过程中,我的匹配算法避免了输入事实的顺序问题以及解决了事实没有推理到最终结论的问题。我添加了去重函数(clean_re)解决了输入的事实重复的问题。