基本程序分析: ide
1.加載事實信息和規則信息
XmlDocument rules = new XmlDocument();
string directory = AppDomain.CurrentDomain.BaseDirectory + @"\..\..\..\RuleExample.xml";//規則鏈條
rules.Load(directory); 函數
ROM rom = Compiler.Compile(rules);//加載,並確認 事實與規則之間的關係 測試
每一個鏈表規則的對應的Fact,都存入DependentEvidence List中。 this
2. 加載須要的參數,也能夠說是激活的一種方式。
//模型
XmlDocument model = new XmlDocument();
model.LoadXml("<a><number1>10</number1><number2>1</number2><result2/></a>");
rom.AddModel("bob", model); lua
這種激活方式,是不須要匹配的,而是把全部的鏈表規則通通執行一遍, 測試例子上是由於在此數據時事實的參數,而鏈表規則的條件是此事實的參數的計算而獲得的真假。 spa
<Rule id="Rule1" desc="" chainable="True"> <Condition><![CDATA[ NOT(F2>F1) ]]></Condition> .net
<Fact id="F1" desc="1" type="double" modelId="bob">
<xpath><![CDATA[ a/number1 ]]></xpath>
</Fact> 設計
3.引發所有規則計算 xml
rom.Evaluate(); 排序
調用Decisions類的.Evaluate()方法。
經過上面11個圖。能夠看出具體的加載以後的數據的存儲,數據類型與數據之間的關係了。
4.核心的推理函數
public void Evaluate(Dictionary<string, IEvidence> evidenceCollection, Dictionary<string, List<string>> factRelationships) { #region register all evidences in this rom with this instance of decision foreach (IEvidence evidence in evidenceCollection.Values) { evidence.CallbackLookup += RaiseCallback; evidence.EvidenceLookup += RaiseEvidenceLookup; evidence.ModelLookup += RaiseModelLookup; evidence.Changed += delegate(object sender, ChangedArgs args) { IEvidence evidence1 = (IEvidence)sender; if (!(evidence1 is IFact)) return; //找出這ifact模型 IFact fact = (IFact)evidence1; IEvidenceValue value = (IEvidenceValue)fact.ValueObject; string modelId = value.ModelId; //遍歷全部ifacts並添加這些到相同的模型來執行列表 foreach(IEvidence evidence2 in evidenceCollection.Values) { //排除全部不IFact證據類型 if (!(evidence2 is IFact)) continue; //排除本身 if (evidence2.ID == evidence1.ID) continue; //排除全部那些不一樣的ifacts模型 if (evidence2.ValueObject.ModelId != modelId) continue; //加入list executionList.Add(evidence2); } }; } #endregion #region load up the execution list with facts //加載執行列表與事實 foreach (IEvidence fact in evidenceCollection.Values) { if (!(fact is IFact)) continue; executionList.Add(fact); Debug.WriteLine("Added fact to execution list: " + fact.ID); } #endregion #region load up the execution list with chainable rules //加載執行列表鏈式規則 foreach (IEvidence rule in evidenceCollection.Values) { if (rule is IRule && ((IRule)rule).isChainable) { executionList.Add(rule); Debug.WriteLine("Added rule to execution list: " + rule.ID); } } #endregion #region execute list //執行列 //Debug.WriteLine("Iteration"); //Debug.IndentLevel++; while (executionList.HasNext) { Trace.WriteLine("Execution List: " + executionList.ToString()); Trace.WriteLine("Processing"); //Debug.IndentLevel++; //最低優先級做爲計算List第一項。 string evidenceId = executionList.Read(); IEvidence evidence = evidenceCollection[evidenceId]; Trace.WriteLine("EvidenceId: " + evidence.ID); //計算證實 evidence.Evaluate(); //若是證實有子句的,增長它的行爲 if (evidence.ClauseEvidence!=null) { foreach (string clauseEvidenceId in evidence.ClauseEvidence) { Evidence.IEvidence clauseEvidence = (Evidence.IEvidence)evidenceCollection[clauseEvidenceId]; executionList.Add(clauseEvidence); Trace.WriteLine("增長證據執行列表: " + clauseEvidence.ID); } } //執行列表的鏈式的相關的事實 if (factRelationships.ContainsKey(evidence.ID)) { List<string> dependentFacts = factRelationships[evidence.ID]; foreach (string dependentFact in dependentFacts) { Evidence.IEvidence dependentEvidence = (Evidence.IEvidence)evidenceCollection[dependentFact]; executionList.Add(dependentEvidence); Trace.WriteLine("加入鏈式的相關事實到執行列表: " + dependentEvidence.ID); } } //Debug.IndentLevel--; Trace.WriteLine("End Processing"); Trace.WriteLine(""); } //Debug.IndentLevel--; Trace.WriteLine("End Iteration"); #endregion } |
//加載執行列表與事實
//加載執行列表鏈式規則
while (executionList.HasNext)//這裏是核心的推理。
你們也看到了 發佈的推理中間結果輸出有點混亂。我會專門搞一篇,把中間結果的推理過程寫出來的。
從 rule1的 execute 推到 rule2
利用嵌套方式來 獲得的。 可是推理過程並非那麼明晰。
F1。 刪除F1
不是fact 繼續, 是fact 下一步。 ID同樣, 繼續, 不同下一步,
是fact了。 而後ID不一樣了。 model是一個組。 加入。 F2 true false 此ID 若以存在則返回, 若不存在,則加入。--
計算完成。
找到 其action 找到是不是別的鏈條的表達式的值。 F1、F2是 rule1的。 條件中的。 把rule1 加入到 執行列表。 此ID 若以存在則返回, 若不存在,則加入。--
result了
獲得XML的值,false
則F1沒有。 則插入F1 可估算 由於插入後成 True, F2, False, Rule3, Rule1,F1
而後排序。 排成
False, F1, True, F2, Rule3, Rule1
而後隨着走。 走到。Rule3, Rule1
以Rule1來看。
規則的Evaluate()
這裏能夠看出, 表達式,事實,規則 都有本身的解析程序。
計算規則的後綴表達式的值,獲得結果。
Rule1 有兩個處理語句。是行爲處理表達式。
把表達式加入 LIST
Rule1-Rule2-1, Rule1-F2-0
執行表達式Rule1-Rule2-1
行爲處理表達式的 執行, 下一條的規則是Rule2
rule2加入規則。
List變成 Rule1-F2-0, Rule2
而後執行Rule1-F2-0。 操做fact的表達式。
這個是一個表達式。 F2+1。 計算表達式,獲得值,返回。
並賦值給 Fact, 輸出。
此表達式引起事實改變, 事實是F2. 把F2加入List
加入時,由於F2已經不在其中。因此把F2加入時,引起全部的事實都加入了。
由於在計算時。 IFact fact = RaiseEvidenceLookup(this, new EvidenceLookupArgs(operatingId)) as IFact; 會由於F2的方法。
觸發了綁定的Changed方法。
List變成 F1, F2, False, True, Result,Rule2
ExpressionEvaluator FACT F2 = 1 ExpressionEvaluator 1 + 1 = 2
而後再次計算。
最後獲得 ExpressionEvaluator FACT F2 = 2 ExpressionEvaluator FACT F1 = 10 ExpressionEvaluator 2 > 10 = False ExpressionEvaluator NOT False = True |
大嘴巴一下:
這種推理引擎把事實做爲一個能夠操做的數據處理,對錶達式的處理更是很是棒,
我必需要根據這個推理引擎,從新設計一下個人專家系統的了。
本人聲明:沐海(http://my.oschina.net/mahaisong) 以上文章是通過本人設計實踐和閱讀其餘文檔得出。若是須要探討或指教能夠留言!歡迎