Animal_match簡單的動物匹配系統

全部的事實集(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)解決了輸入的事實重複的問題。


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章