《专家系统破解篇 9、Simple Rule Engine规则推理引擎二(基本程序分析)》

基本程序分析: 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

找到是不是别的链条的表达式的值。 F1F2是 rule1的。 条件中的。

rule1 加入到 执行列表。  

 此ID 若以存在则返回,

  若不存在,则加入。--

result

 获得XML的值,false

F1没有。 则插入F1 可估算

由于插入后成 True, F2, False, Rule3, Rule1F1

而后排序。 排成

 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(thisnew 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) 以上文章是通过本人设计实践和阅读其余文档得出。若是须要探讨或指教能够留言!欢迎
相关文章
相关标签/搜索