關鍵字:人工智能,專家系統,產生式系統
Production system
Abstract: Constructs the knowledge system and cognitive model often used in the form of knowledge representation system. E. 1943 post first will he come up with a form of computing system named production system. The late 50 s, a. Newell and H.A. Simon in the study of human cognitive model of problem solving when the term is also used by the production system. Production system has become an artificial intelligence system in modern times, with one of the most typical architecture. This paper mainly discusses the computer science and technology under the junior in professional class "artificial intelligence" third experiment algorithm.
Keywords: Artificial intelligence, expert system, production system
1,問題重述
知識表示為產生式知識表示方法,設計並實現具有15條規則能自動識別7種動物的產生式系統。知識庫與控制系統相互獨立,系統完成后除了能識別已有的7種動物外,按產生式知識表示方法向知識庫中添加、修改新的知識后,系統能在不修改控制系統程序的情況下仍然能正確識別。
2,問題分析
2.1.事實的表示:
事實可看成是斷言一個語言變量的值或是多個語言變量間的關系的陳述句,語言變量的值或語言變量間的關系可以是一個詞。不一定是數字。一般使用三元組(對象,屬性,值)或(關系,對象1,對象2)來表示事實,其中對象就是語言變量,若考慮不確定性就成了四元組表示(增加可信度)。這種表示的機器內部實現就是一個表
2.2.規則的表示:
規則用於表示事物間的因果關系,以if conditionthen action 的單一形式來描述,將規則作為知識的單位。其中的condition 部分稱為條件式前件或模式,而action部分稱作動作、后件或結論。
產生式一般形式為:前件 后件。前件和后件也可以是有“與”、“或”、“非”等邏輯運算符的組合的表達式。條件部分常是一些事實的合取或析取,而結論常是某一事實B。如果不考慮不確定性,需另附可信度度量值。
產生式過則的含義是:如果前件滿足,則可得到后件的結論或者執行后件的相應動作,即后件由前件來觸發。一個產生式生成的結論可以作為另一個產生式的前提或語言變量使用,進一步可構成產生式系統。
蘊涵式表示的知識只能是精確的,產生式表示的知識可以是不確定的,原因是蘊涵式是一個邏輯表達式,其邏輯值只有真和假。蘊含式的匹配一定要求是精確的,而產生式的匹配可以是不確定的,原因是產生式的前提條件和結論都可以是不確定的,因此其匹配也可以是不確定的。
3,設計文檔
<知識庫>
<事實>
<條件>
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:企鵝 31:信天翁
</結論>
</事實>
<規則>
有毛->哺乳類
產奶->哺乳類
有羽毛->鳥類
會飛,會下蛋->鳥類
哺乳類,吃肉->食肉類
有犬齒,有爪,眼盯前方->食肉類
哺乳類,有蹄->蹄類
哺乳類,反芻->蹄類
食肉類,黃褐色,有斑點->金錢豹
食肉類,黃褐色,有黑色條紋->虎
蹄類,長脖,長腿,有斑點->長頸鹿
蹄類,有黑色條紋->斑馬
鳥類,長脖,長腿,會飛->鴕鳥
鳥類,會游泳,黑白二色,會飛->企鵝
鳥類,善飛->信天翁
</規則>
</知識庫>
**規則符號化
1->21 //有毛->哺乳類
2->21 //產奶->哺乳類
3->22 //有羽毛->鳥類
4,5->22 //會飛,會下蛋->鳥類
21,6->23 //哺乳類,吃肉->食肉類
7,8,9->23 //有犬齒,有爪,眼盯前方->食肉類
21,10->24 //哺乳類,有蹄->蹄類
21,11->24 //哺乳類,反芻->蹄類
23,12,13->25 //食肉類,黃褐色,有斑點->金錢豹
23,12,14->26 //食肉類,黃褐色,有黑色條紋->虎
24,15,16,13->27 //蹄類,長脖,長腿,有斑點->長頸鹿
24,14->28 //蹄類,有黑色條紋->斑馬
22,15,16,4->29 //鳥類,長脖,長腿,會飛->鴕鳥
22,18,19,4->30 //鳥類,會游泳,黑白二色,會飛->企鵝
22,20->31 //鳥類,善飛->信天翁
**
**測試用例
2,10,13,15,16 -> 27
產奶,有蹄,有斑點,長脖,長腿 -> 長頸鹿
*/
4,程序設計

1 #include<iostream> 2 #include<string> 3 #include<cstdlib> 4 #include<iomanip> 5 #include<list> 6 7 using namespace std; 8 9 const int fact_num = 31; //知識庫中的知識:31種知識 10 const int rule_num = 15; //知識庫中的規則:15條規則 11 const int rule_volume = 4; //規則中每個結果最多有4個前提條件 12 const int object_range_begin = 25; //從第25個知識開始 13 const int object_range_end = 31; //到第31個知識為目標結論 14 const int object_middle_begin = 21; //中間結果起始位置 15 16 string fact[fact_num] = 17 { 18 "有毛發","產奶","有羽毛","會飛","會下蛋", 19 "吃肉","有犬齒","有爪","眼盯前方","有蹄", 20 "反芻","黃褐色","有斑點","有黑色條紋","長脖", 21 "長腿","不會飛","會游泳","黑白二色","善飛", 22 "哺乳類","鳥類","食肉類","蹄類","金錢豹", 23 "虎","長頸鹿","斑馬","鴕鳥","企鵝","信天翁" 24 }; 25 26 int rule_prerequisite[rule_num][rule_volume] = 27 { 28 {1,0,0,0}, 29 {2,0,0,0}, 30 {3,0,0,0}, 31 {4,5,0,0}, 32 {21,6,0,0}, 33 {7,8,9,0}, 34 {21,10,0,0}, 35 {21,11,0,0}, 36 {23,12,13,0}, 37 {23,12,14,0}, 38 {24,15,16,13}, 39 {24,14,0,0}, 40 {22,15,16,4}, 41 {22,18,19,4}, 42 {22,20,0,0} 43 }; 44 45 int rule_result[rule_num] = 46 { 47 21, 48 21, 49 22, 50 22, 51 23, 52 23, 53 24, 54 24, 55 25, 56 26, 57 27, 58 28, 59 29, 60 30, 61 31 62 }; 63 64 bool backward_reasoning(int num,int message[]) ; 65 bool inference(int num,int message[]) //迭代推理機 66 { 67 int ii, ij, ik,im,in; 68 int hit_num = 0; //輸入前提也規則前提重合數 69 int prerequisite_num; //規則前提數 70 int *message_c; //迭代前提 71 int num_c; //迭代前提數量 72 for (ik = 0; ik < num; ik++) //剪枝函數 73 { 74 if (message[ik] >= object_range_begin&&message[ik] <= object_range_end) 75 { 76 cout << "歸並信息:" << fact[message[ik] - 1] << endl; 77 cout << "推理成功!" << endl<<endl; 78 system("pause"); 79 exit(0); 80 } 81 } 82 for (ii = 0; ii < rule_num; ii++) //遍歷規則匹配 83 { 84 prerequisite_num = 0; 85 hit_num = 0; 86 for (ij = 0; ij < rule_volume; ij++) //計算規則集前提數 87 { 88 if (rule_prerequisite[ii][ij] == 0) 89 { 90 break; 91 } 92 prerequisite_num++; 93 } 94 for (ij = 0; ij < prerequisite_num; ij++) 95 { 96 for (ik = 0; ik < num; ik++) 97 { 98 if (rule_prerequisite[ii][ij] == message[ik]) 99 { 100 hit_num++; 101 } 102 } 103 } 104 if (hit_num == prerequisite_num) //滿足某個規則集全部前提 105 { 106 bool flag; 107 for (ik = 0; ik < num; ik++) 108 { 109 if (message[ik] == rule_result[ii]) 110 { 111 break; 112 } 113 } 114 if (ik == num) 115 { 116 num_c=num - hit_num+1; 117 flag = true; 118 } 119 else 120 { 121 num_c = num - hit_num; 122 flag = false; 123 } 124 message_c = new int[num_c]; 125 in = 0; 126 for (ik = 0; ik < num; ik++) 127 { 128 for (im = 0; im < hit_num; im++) 129 { 130 if (rule_prerequisite[ii][im] == message[ik]) 131 { 132 break; 133 } 134 } 135 if (im < hit_num) 136 { 137 continue; 138 } 139 message_c[in++] = message[ik]; 140 } 141 if (flag == true) 142 { 143 message_c[in] = rule_result[ii]; 144 } 145 cout << "推導信息:"; 146 for (int iz = 0; iz < num; iz++) 147 { 148 cout << fact[message[iz]-1] << " "; 149 } 150 cout << endl; 151 return inference(num_c,message_c); 152 } 153 } 154 cout << "歸並信息:"; 155 for (int iz = 0; iz < num; iz++) 156 { 157 cout << fact[message[iz]-1] << " "; 158 } 159 cout << endl; 160 backward_reasoning(num,message); 161 return false; 162 } 163 164 bool backward_reasoning(int num,int message[]) //反向推理 165 { 166 int ii,ij,ik; 167 int prerequisite_num = 0; 168 int hit_num = 0; 169 int need_rule_number[rule_num]; 170 int hit_rule_number[rule_num]; 171 float hit_rule_rate[rule_num]; 172 float best_hit_rule_rate=0; 173 int best_hit_rule_number; 174 int *new_message; 175 for (ii = 0; ii < rule_num; ii++) //遍歷規則匹配 176 { 177 prerequisite_num=0; 178 hit_num=0; 179 for (ij = 0; ij < rule_volume; ij++) //計算規則集前提數 180 { 181 if (rule_prerequisite[ii][ij] == 0) 182 { 183 break; 184 } 185 prerequisite_num++; 186 } 187 need_rule_number[ii]=prerequisite_num; 188 for (ij = 0; ij < prerequisite_num; ij++) //計算輸入信息命中規則集中的前提數 189 { 190 for (ik = 0; ik < num; ik++) 191 { 192 if (rule_prerequisite[ii][ij] == message[ik]) 193 { 194 hit_num++; 195 } 196 } 197 } 198 hit_rule_number[ii]=hit_num; 199 hit_rule_rate[ii]=(float)hit_num/prerequisite_num; //命中率 200 for(ij=0;ij<num;ij++) 201 { 202 if(message[ij]==rule_result[hit_rule_number[ii]]) 203 { 204 break; 205 } 206 } 207 if(hit_rule_rate[ii]==1&&ij==num) 208 { 209 new_message=new int[num+1]; 210 for(ik=0;ik<num;ik++) 211 { 212 new_message[ik]=message[ik]; 213 } 214 new_message[num]=rule_result[hit_rule_number[ii]]; 215 num++; 216 return inference(num,new_message); 217 } 218 cout<<"rule "<<setw(2)<<ii<<" -> "<<setw(8)<<fact[rule_result[ii]-1] 219 <<"命中率:"<<hit_rule_rate[ii]<<endl; 220 } 221 best_hit_rule_number=-1; 222 for(ii=0;ii<rule_num;ii++) 223 { 224 if(best_hit_rule_rate<hit_rule_rate[ii]&& 225 rule_result[ii]>=object_middle_begin) 226 { 227 best_hit_rule_rate=hit_rule_rate[ii]; 228 best_hit_rule_number=ii; 229 } 230 } 231 if(best_hit_rule_number==-1) 232 { 233 cout<<"您輸入的信息對本系統無效!按任意鍵退出..."<<endl<<endl; 234 system("pause"); 235 exit(0); 236 } 237 cout<<endl; 238 cout<<"best_hit_rule_number="<<best_hit_rule_number<<endl; 239 cout<<"best_hit_rule_rate="<<best_hit_rule_rate<<endl; 240 cout<<"最佳匹配最終結果="<<fact[rule_result[best_hit_rule_number]-1]<<endl; 241 for(ii=0;ii<need_rule_number[best_hit_rule_number];ii++) 242 { 243 for(ij=0;ij<num;ij++) 244 { 245 if(rule_prerequisite[best_hit_rule_number][ii]==message[ij]) 246 { 247 break; 248 } 249 } 250 if(ij!=num) 251 { 252 continue; 253 } 254 else 255 { 256 if(rule_prerequisite[best_hit_rule_number][ii]<object_middle_begin) 257 { 258 cout<<endl<<"請問您持有的信息是否包含\""; 259 cout<<fact[rule_prerequisite[best_hit_rule_number][ii]-1]; 260 cout<<"\"?(y or n)"<<endl; 261 char input; 262 while(true) 263 { 264 cin>>input; 265 if(input=='n') 266 { 267 new_message=new int[num]; 268 for(ik=0;ik<num;ik++) 269 { 270 new_message[ik]=message[ik]; 271 } 272 break; 273 } 274 else if(input=='y') 275 { 276 new_message=new int[num+1]; 277 for(ik=0;ik<num;ik++) 278 { 279 new_message[ik]=message[ik]; 280 } 281 new_message[num]=rule_prerequisite[best_hit_rule_number][ii]; 282 num++; 283 return inference(num,new_message); 284 } 285 else 286 { 287 cout<<"請重新輸入(y or n)!"; 288 } 289 } 290 } 291 else //詢問是否有中間結果rule_prerequisite[best_hit_rule_number][ii] 292 { 293 int middle_result=rule_prerequisite[best_hit_rule_number][ii]; 294 for(ii=0;ii<rule_num;ii++) 295 { 296 if(rule_result[ii]==middle_result) 297 { 298 for(ik=0;ik<need_rule_number[ii];ik++) 299 { 300 if(rule_prerequisite[ii][ik]>=object_middle_begin-1) 301 { 302 continue; 303 } 304 for(ij=0;ij<num;ij++) 305 { 306 if(rule_prerequisite[ii][ik]==message[ij]) 307 { 308 break; 309 } 310 } 311 if(ij!=num) 312 { 313 continue; 314 } 315 else 316 { 317 cout<<endl<<"請問您持有的信息是否包含\""; 318 cout<<fact[rule_prerequisite[ii][ik]-1]; 319 cout<<"\"?(y or n)"<<endl; 320 char input; 321 while(true) 322 { 323 cin>>input; 324 if(input=='n') 325 { 326 break; 327 } 328 else if(input=='y') 329 { 330 new_message=new int[num+1]; 331 for(int iq=0;iq<num;iq++) 332 { 333 new_message[iq]=message[iq]; 334 } 335 new_message[num]=rule_prerequisite[best_hit_rule_number][ii]; 336 num++; 337 return inference(num,new_message); 338 } 339 else 340 { 341 cout<<"請重新輸入(y or n)!"; 342 } 343 } 344 } 345 } 346 } 347 } 348 } 349 } 350 } 351 } 352 353 int main(int argc, char **argv) 354 { 355 bool flag; 356 int num; 357 int *message; 358 int ii,ij; 359 cout<<"《知識庫》"<<endl; 360 for(ii=0;ii<fact_num;ii++) 361 { 362 cout<<setiosflags(ios::left); 363 cout<<setw(2)<<ii+1<<":"<<setw(10)<<fact[ii]<<" "; 364 if(ii%4==0) 365 { 366 cout<<endl; 367 } 368 } 369 cout <<endl<<endl<< "請輸入初始信息個數:(數字)" << endl; 370 cin >> num; 371 message = new int[num]; 372 cout << "請輸入已有信息:(不重復的數字,以空格隔開)" << endl; 373 for (ii = 0; ii < num; ii++) 374 { 375 cin >> message[ii]; 376 } 377 cout << endl << "初始信息:"; 378 for (ij = 0; ij < num; ij++) 379 { 380 cout << fact[message[ij]-1] << " "; 381 } 382 cout << endl<<endl; 383 if(!inference(num,message)) 384 { 385 cout<<"通過您的輸入無法得出結果!"<<endl; 386 } 387 system("pause"); 388 return 0; 389 }