工作记忆&对象在Drools中的插入行为

时间:2014-10-17 08:11:19

标签: java drools business-rules

我是Drools的新手并且阅读了一些文档和教程,当然,我的问题有一个简单的解决方案。 我使用onle规则文件和类Counter,如下所示。环境是:Wintel JDK 1.7(71),DROOLS 6.1.0

public class DroolsInsertionTester {
private Logger log = Logger.getLogger(this.getClass().getName());

private KieSession getNewStatefullKIESession (){
   KieContainer kContainer = KieServices.Factory.get().getKieClasspathContainer();

   KieSession kSession = kContainer.newKieSession("test");
   return kSession;
}
public static void main(String[] args) {
    // TODO Auto-generated method stub
    DroolsInsertionTester tester =  new DroolsInsertionTester();
    tester.test(); 


}

private void test() {
    KieSession kSession = getNewStatefullKIESession();

    Counter cnt1 = new Counter(1);
    Counter cnt2 = new Counter(2);

    FactHandle fact1, fact2;

    // STEP 1
    fact1 = kSession.insert(cnt1);
    kSession.fireAllRules();

    // STEP 2
    fact2 = kSession.insert(cnt2);
    kSession.fireAllRules();
}

 public class Counter {
      public int count;
      public Counter (int cnt){
           this.count = cnt;
 }

有一条规则

 rule "Counter shower 1" 
    when $Counter  : Counter() 
 then 
    System.out.println("Counter there (1) : " + $Counter.count);
 end

 rule "Counter shower 2" 
when 
    $Counter  : Counter()  
    accumulate (Counter() ; $cnt : count())
then 
    System.out.println("Counter there (2) : " + $Counter.count);
end 

rule "Counter shower 3" 
when 
    Counter()  
then 
System.out.println("Counters there (3) : ");
end 

rule "Counter creator" 
    when $Counter  : Counter(count == 2) 
then 
    insert (new Counter(3)); // STEP 3
     System.out.println("new Counter created ");
end

rule "Counter remover" 
    when 
    $Counter  : Counter(count == 1)
    exists Counter (count == 3) 
then 
    retract ($Counter) ; // STEP 4
     System.out.println("retract counter with ID = 1");
end

这是kModule

<?xml version="1.0" encoding="UTF-8" ?>
<kmodule xmlns="http://jboss.org/kie/6.0.0/kmodule">
<kbase name="rules" packages="rules">
        <ksession name="test" />
 </kbase>
</kmodule>

跑步的结果

Counter there (1) : 1
Counter there (2) : 1
Counters there (3) : 
Counter there (1) : 2
Counter there (2) : 1
Counter there (2) : 2
Counters there (3) : 
new Counter created 
Counter there (1) : 3
Counter there (2) : 1
Counter there (2) : 2
Counter there (2) : 3
Counters there (3) : 
retract counter with ID = 1
Counter there (2) : 2
Counter there (2) : 3

我的问题是:

  1. 程序代码不包含任何“kSession.delete”,所有事实都保存在工作内存中。因此,在我看来,每个fireAllRules调用后,应该为工作内存中的每个Counter对象触发规则“Counter shower 1”..“Counter shower 3”。一个用于STEP 1,两个用于STEP2,三个用于STEP3,例如但是输出列表只有“反向淋浴2”以这种方式工作。 “计数器淋浴1”和“计数器淋浴3”只能通过一次火灾一次性召唤。

  2. 为什么规则“反阵雨1”只能抓住最后插入的事实?那里有隐藏的行为吗?

  3. 3.为什么在使用count == 1收回对象计数器之后只有“Counter shower 2”会发生火灾?其他规则怎么样?

    感谢您的帮助。

2 个答案:

答案 0 :(得分:1)

问题1:程序代码不包含任何“kSession.delete”,所有事实都保存在工作内存中。因此,在我看来,规则&#34;反阵雨1&#34; ..&#34;柜台淋浴3&#34;应在每个fireAllRules调用后为工作内存中的每个Counter对象触发。一个用于STEP 1,两个用于STEP2,三个用于STEP3,例如但输出清单只有&#34;反击淋浴2&#34;以这种方式工作。 &#34;柜台淋浴1&#34;和#34;反向淋浴3&#34;只能通过一次fireAllRules召唤一次。

您应该了解fireAllRules并未实际触发知识库中的所有规则。这个名字有点误导。 :)

而不是谈论规则&#34;解雇&#34;,对于他们而言,最好是激活&#34;激活&#34;。您有一个有状态会话,因此当您第一次调用fireAllRules时,会根据您最初插入的Counter激活三条规则。当您再次致电insert / fireAllRules时,这些规则仍会针对初始Counter激活!他们不需要再次激活。除非工作记忆的状态已经改变,导致规则停用并重新激活,否则你的右手边不会发现任何事情。

这实际上是有状态会话的重点。您的知识库可以逐步地学习&#34;事实并可以根据现有知识评估新事实。

从零知识假设中评估每一个事实是无状态会话的目的。

问题2:为什么要统治&#34;反击淋浴1&#34;只捕获最后插入的事实?

您有一个有状态会话,因此在第一个Counter上激活fireAllRules的初始插入匹配。从那以后,工作内存中没有任何变化影响初始激活,因此再次fireAllRules时不再需要激活它。

问题3:为什么在收回对象计数器后只计数== 1&#34;计数器淋浴2&#34;火灾?其他规则怎么样?

&#34;反击淋浴2&#34;规则是受撤销影响的唯一规则,因为它有一个累加器来计算您的Counter事实。

答案 1 :(得分:0)

这是一个关于所发生情况的逐个说明,注释显示在哪里可以找到Q1,Q2和Q3的答案。以&#39;!&#39;开头的行是您的Java或DRL代码中的语句,如执行,#&#39;#&#39;表示我的评论,并输出其他行。

! fact1 = kSession.insert(new Counter(1) );
# "Counter shower 1" matches; an activation binding $Counter to the inserted
# fact1 is created
# "Counter shower 2" matches; an activation binding $Counter to the inserted
# fact1 is created
# "Counter shower 3" matches; an activation with the inserted fact1
#  is created
! kSession.fireAllRules();
# The Agenda contains three activations; the consequences of these rules are
# executed
Counter there (1) : 1
Counter there (2) : 1
Counters there (3) 
! fact2 = kSession.insert(new Counter(2) );
# "Counter shower 1" matches; an activation binding $Counter to the inserted
# fact2 is created
# "Counter shower 2" matches; an activation binding $Counter to the inserted
# fact2 is created
# The accumulate changes as it now accumulates two Counter facts; therefore
# another activation is created with $Counter being bound to fact1, which
# is still (half-cocked) bound to this rule; the activation is completed due
# to the change in the accumulate.
# "Counter shower 3" matches; an activation with the inserted fact2
# is created
# Nothing has happened with fact1, so there is (by definition) no reason to
# recreate activations in relation to fact1. (Q1, Q2)
# With a Counter(2) present, also "Counter creator" is activated and put on
# the agenda.
! kSession.fireAllRules();
Counter there (1) : 2 
Counter there (2) : 1 
Counter there (2) : 2 
Counters there (3)
new Counter created
! insert( new Counter(3) );
# "Counter shower 1" matches; an activation binding $Counter to the inserted
# fact3 is created
# "Counter shower 2" matches; an activation binding $Counter to the inserted
# fact3 is created
# The accumulate changes as it now accumulates three Counter facts; therefore
# another activation is created with $Counter being bound to fact1 and also
# to fact2, both of which are still (half-cocked) bound to this rule; the
# activation is completed due to the change in the accumulate. (Q3)
# "Counter shower 3" matches; an activation with the inserted fact2
# is created
# Nothing has happened with fact1 and fact3, so there is (by definition) no
# reason to recreate activations in relation to rules simply matching fact1 
# and fact2. (Q1, Q2)
# With a Counter(1) and a Counter(3) present, "Counter remover" is activated
# and put on the agenda.
Counter there (1) : 3 
Counter there (2) : 1
Counter there (2) : 2
Counter there (2) : 3
Counters there (3)
retract counter with ID = 1
# We have the three half-cocked activations of "Counter shower 2", where the
# set of accumulated Counter facts changed due to the retraction of
# Counter(1). The one with this Counter being bound to $Counter is a goner
# now, but the other two are reactivated with a shortened list of Counter
# facts to be counted.
Counter there (2) : 2
Counter there (2) : 3