artikel ini pertama kali dipublikasikan pada situs gamedevid.org pada tanggal 8 Januari 2007.
beberapa waktu lalu gw lagi nyari-nyari referensi tentang mesin inferensi di http://www.sourceforge.net dan nemu contoh implementasi mesin inferensi yang cukup sederhana dalam bahasa Ruby -> SIE (Simple Inference Engine). karena gw lagi ngutak-atik irrlicht yang notabene pake C++ akhirnya gw port ke dalam C++ dengan memanfaatkan STL dan irrXML 1.2.mesin inferensi dan sistem pakarmesin inferensi merupakan elemen inti dari sistem pengambilan keputusan berbasis kaidah dalam intelejensia buatan. sistem pengambilan keputusan sendiri merupakan salah satu instans dari sistem berbasis pengetahuan (knowledge-based system) yang istilah populernya adalah sistem pakar (expert system).sistem pakar punya arsitektur umum yaitu terdiri dari 4 komponen :- knowledge base, atau mungkin lebih tepatnya rule-base
- working memory
- mesin inferensi
- user interface
rulebase, dalam bahasa indonesia berarti basis kaidah. isinya koleksi kaidah yang bisa di-inferensikan. setiap kaidah umumnya terdiri dari 2 bagian yaitu anteseden dan konsekuen dan dideskripsikan sebagai kaidah if-then seperti berikut :
IF anteseden THEN konsekuen
anteseden sederhananya adalah ekspresi boolean terhadap kebenaran suatu fakta. evaluasi kebenaran suatu fakta menggunakan acuan fakta-fakta yang ‘diketahui’ dalam ‘working memory’
konsekuen adalah aksi-aksi yang dieksekusi jika kondisi dalam anteseden terpenuhi. aksi yang dapat dilakukan bisa berupa penalaran fakta baru (fact assertion), pembantahan/penghapusan fakta dari working memory (fact retraction), ataupun modifikasi terhadap fakta yang ada
working memory, merupakan koleksi fakta yang didefinisikan sejak awal, atau dibuat secara run-time dari proses inferensi terhadap knowledge base.
mesin inferensi, mesin ini yang memproses kumpulan fakta dan kumpulan kaidah sehingga dibangkitkan fakta-fakta baru. kondisi berhenti mesin inferensi bisa saja ketika fakta tertentu yang menjadi tujuan(goal) muncul, ataupun tidak ada lagi aturan yang bisa dieksekusi (fired) berdasarkan fakta yang ada. untuk melakukan inferensi ada dua cara :
- inferensi maju (forward chaining), algoritma ini dimulai dengan
mencari kaidah yang sesuai dengan fakta yang ‘diketahui’.
kaidah yang dievaluasi akan menghasilkan fakta baru yang selanjut
nya akan menyebabkan kaidah lainnya untuk dievaluasi. algoritma
ini akan berhenti jika tidak ada lagi fakta yang memenuhi kaidah
dalam basis kaidah.
- inferensi mundur (backward chaining), algoritma ini merupakan
sistem pembuktian teorem (theorem proving). cara kerja algoritma
ini dimulai dengan fakta yang ingin dibuktikan kebenarannya,
lalu kaidah-kaidah yang ‘dicurigai’ akan membuktikan fakta tsb.
akan dievaluasi. algoritma ini akan berhenti jika fakta yang menjadi
goal berhasil dibuktikan atau tidak berhasil dibuktikan.
user interface, antarmuka untuk interaksi dengan pengguna. misalnya dalam kasus sistem pakar jaman dulu, antarmukanya dialog [i]terminal-like[/i] antara user(manusia) dengan ‘pakar’
Representasi Pengetahuan
fakta bisa didefinisikan sebagai suatu simbol (string?) yang punya nilai kebenaran (boolean?). simbol bisa jadi berupa suatu term/’nama’, proposisi dalam logika orde pertama (First Order Logic) seperti dalam prolog, sebuah pasangan (2-tuple)
mesin inferensi yang gw bikin pake representasi pasangan <attribute,value> dengan operasi evaluasinya hanya ’sama dengan’ (untuk atribut <a,v> maksudnya jadi apakah variabel A nilainya sama dengan V bernilai true atau tidak).
gile, teorinya panjang juga ya..? udah lah, segini aja. kalo yang mo penjelasan lebih lanjut, baca buku tentang AI aja
Time to code
contoh file masukan dalam XML
<knowledgebase></knowledgebase> <!-- contoh goal --> <goal></goal> <attribute></attribute>type.disease <text></text>Based on rudimentary knowledge, I believe the child has type.disease <!-- contoh kaidah --> <rules></rules> <rule></rule> <name></name>1 <conditions></conditions> <condition></condition> <attribute></attribute>active.temp.over.101 <value></value>yes <actions></actions> <action></action> <attribute></attribute>fever <value></value>yes <!-- contoh pertanyaan --> <questions></questions> <question></question> <attribute></attribute>squeaky.breath <text></text>Does the child squeake as he breaths? <response></response>yes <response></response>no
Knowledge Representation
representasi pengetahuannya pake model pair
class CKnowledgeAV { public: CKnowledgeAV(); CKnowledgeAV( string Name, string Value ); ~CKnowledgeAV(); string getValue(); void setValue(string Value); string getName(); string toString(); protected: string name; string value; };
Kaidah dan Pertanyaan
kelas kaidah
typedef map<string,></string,> knowledgebase; typedef map<string,></string,>::iterator kb_iterator; class CQuestion; class CRule { public: CRule(string Name); ~CRule(); void addCondition(CKnowledgeAV* cond); void addAction(CKnowledgeAV* act); string toString() ; string getName(); bool isActive(); void setActive(bool bValue); bool deactivate(); int getConditionCount(); bool isConditionMatch(knowledgebase knowledge); bool isConditionSatisfied(knowledgebase knowledge); bool isResolvable(map<string,></string,> questions ); vector<string></string> getConditionAttributes(); void OnRuleFire(knowledgebase * knowledge); knowledgebase getConditions(); knowledgebase getActions(); protected: string name; bool active; knowledgebase condition; //antecedent knowledgebase action; //consequent };
kelas pertanyaan di-sekip aja..
Mesin Inferensi
kelas mesin inferensi, di-embed ke XML Parser
//modification from simple inference engine in ruby class CXMLRuleReader { public: CXMLRuleReader(const char * filename); ~CXMLRuleReader(); void parse(); ie_state run(); void setQuestionHandler(IQuestionHandler* handler) ; ie_state getStatus(); protected: map<string,></string,> rules; map<string,></string,> facts; map<string,></string,> questions; IQuestionHandler* qHandler; ie_state status; CRule* current_rule; CQuestion* current_question; string fact_attr, fact_val; string q_attr;//needed for consult to user string goal_attr; string goal_text; IrrXMLReader* m_xml; //control to continue inference process bool isGoalKnown(); bool isFactKnown(string fact_attr); bool isQuestionExists(string fact_attr); CQuestion* getQuestion(string attr); void consult(string attr); };
algoritma inferensi
ie_state CXMLRuleReader::run() { bool didsomething = false; map<string,></string,>::iterator pos; int active_rule_count = rules.size(); status = IE_MORE; while ((active_rule_count > 0) && (status == IE_MORE)) for (pos = rules.begin(); pos != rules.end(); ++pos){ CRule* r = pos->second; if ( r->isActive() ){ if ( facts.size() > 0 ){ //printFactsKnown(); } //if //try to resolve current rule vector<string></string> rule_conds = r->getConditionAttributes(); bool rule_resolvable = true; for (int i = 0; i<rule_conds.size();></rule_conds.size();> if ( !isFactKnown( rule_conds[i] ) ) if ( isQuestionExists( rule_conds[i]) ) consult( rule_conds[i] ); else{ rule_resolvable = false; break; } } //for if ( !rule_resolvable ){ //continue to next rule continue; } //if //check if rule can be fired if ( r->isConditionSatisfied( facts ) ){ r->OnRuleFire( &facts ); r->deactivate(); active_rule_count--; //filter out non fireable rules //forall rule for (map<string,></string,>::iterator p = rules.begin(); p != rules.end(); ++p){ CRule* rule = p->second; knowledgebase kb = rule->getConditions(); //forall condition in rule that exist in knowledge base for (kb_iterator kpos = kb.begin(); kpos != kb.end(); ++kpos){ //if attribute known and doesnt satisfied then deactivate rule CKnowledgeAV* f = kpos->second; if ( isFactKnown(kpos->first) ){ if ( f->getValue() != facts[kpos->first]->getValue() ){ r->deactivate(); break; } //if } //if } //for } //for } //if if ( isGoalKnown() ){ string tmpresult = goal_text; CKnowledgeAV* fact = facts[goal_attr]; tmpresult = tmpresult.replace(tmpresult.find(goal_attr), goal_attr.length(), fact->getValue()); printFactsKnown(); status = IE_COMPLETE; return status; } //if } //if r.isactive } //for //no more rules return IE_COMPLETE; }
main program
int main(int argc, char *argv[]) { CXMLRuleReader* rules = new CXMLRuleReader(argv[1]); rules->parse(); IQuestionHandler* handler = new CQuestionConsole(); rules->setQuestionHandler( handler ); rules->run(); delete rules; delete handler; return 0; }
Thx, ilmunya, smoga bermanfaat, terutama bagi saya yang sedang yari bahan-bahan tentang AI