Drools冲突解决方案与突出问题

时间:2011-02-17 13:06:26

标签: drools rule

我发现了drools引擎的奇怪行为。 我有两个不同突出的规则。如drools文档中所述

  

3.3.4.1。冲突解决

     

何时需要解决冲突   有多个规则   议程。 (基本要点是   在“快速入门”一章中介绍。)作为   解雇规则可能会产生副作用   工作记忆,规则引擎   需要知道规则的顺序   应该开火(例如,开火   ruleA可能导致ruleB被删除   来自议程)。

     

默认的冲突解决方案   Drools采用的策略是:   显着性和LIFO(最后一个,第一个   出)。

     

最明显的是显着性(或   优先级),在这种情况下用户可以   指定某个规则有一个   更高的优先级(通过给它更高   数量)比其他规则。在那里面   案例,具有较高显着性的规则   将是首选。 LIFO的优先事项是   基于指定的工作记忆   动作计数器值,包含所有规则   在同一个动作中创建   收到相同的价值。该   一组点火的执行顺序   具有相同的优先级值是   任意的。

但是为每种类型执行我的两个规则,每个类型有5个对象会产生奇怪的结果 - 在某些对象上,带有突出显示1的规则比具有显着性的规则10更早执行。 如果我从规则中删除更新,则会执行具有突出显示10的第一个规则,然后才会突出显示1。

 package com.sample

import com.sample.DroolsTest.Message;
import com.sample.DroolsTest.Message2;



rule "Hello World2"
    salience 10
    when
        m : Message()
        m2 : Message2(status <0)
    then

        System.out.println( "Second Rule With Salience 10"); 
        System.out.println( "m status = "+m.getStatus()); 
        System.out.println( "m2 status = "+m2.getStatus()); 
        m2.setStatus(m2.getStatus()*(-1));
        update(m2);
end

rule "Hello World3"
    salience 1
    when
        m2 : Message2()
        m : Message()
    then
        System.out.println( "Third Rule With Salience 1"); 
        System.out.println( "m status = "+m.getStatus()); 
        System.out.println( "m2 status = "+m2.getStatus()); 
end

rule "GoodBye"
    salience 0
    when
        eval(true)
    then
        System.out.println( "End" );
end

这是让你更快地测试它的java代码

    package com.sample;

    import org.drools.KnowledgeBase;
    import org.drools.KnowledgeBaseFactory;
    import org.drools.builder.KnowledgeBuilder;
    import org.drools.builder.KnowledgeBuilderError;
    import org.drools.builder.KnowledgeBuilderErrors;
    import org.drools.builder.KnowledgeBuilderFactory;
    import org.drools.builder.ResourceType;
    import org.drools.io.ResourceFactory;
    import org.drools.logger.KnowledgeRuntimeLogger;
    import org.drools.logger.KnowledgeRuntimeLoggerFactory;
    import org.drools.runtime.StatefulKnowledgeSession;

    /**
     * This is a sample class to launch a rule.
     */
    public class DroolsTest {

        public static final void main(String[] args) {
            try {
                // load up the knowledge base
                KnowledgeBase kbase = readKnowledgeBase();
                StatefulKnowledgeSession ksession = kbase.newStatefulKnowledgeSession();
                KnowledgeRuntimeLogger logger = KnowledgeRuntimeLoggerFactory.newFileLogger(ksession, "test");
                // go !
                System.out.println("Start");
                for(int i=0; i<5; i++){
                    Message message = new Message(i);
                    ksession.insert(message);
                    Message2 message2 = new Message2(-i);
                    ksession.insert(message2);
                }
                ksession.fireAllRules();
                logger.close();
            } catch (Throwable t) {
                t.printStackTrace();
            }
        }

        private static KnowledgeBase readKnowledgeBase() throws Exception {
            KnowledgeBuilder kbuilder = KnowledgeBuilderFactory.newKnowledgeBuilder();
            kbuilder.add(ResourceFactory.newClassPathResource("Sample.drl"), ResourceType.DRL);
            KnowledgeBuilderErrors errors = kbuilder.getErrors();
            if (errors.size() > 0) {
                for (KnowledgeBuilderError error: errors) {
                    System.err.println(error);
                }
                throw new IllegalArgumentException("Could not parse knowledge.");
            }
            KnowledgeBase kbase = KnowledgeBaseFactory.newKnowledgeBase();
            kbase.addKnowledgePackages(kbuilder.getKnowledgePackages());
            return kbase;
        }

        public static class Message {

            private int status;

            public int getStatus() {
                return this.status;
            }

            public Message(int status) {
                super();
                this.status = status;
            }

            public void setStatus(int status) {
                this.status = status;
            }

        }

    public static class Message2 {

            private int status;

            public Message2(int status) {
                this.status = status;
            }

            public int getStatus() {
                return this.status;
            }

            public void setStatus(int status) {
                this.status = status;
            }

        }

}

谢谢,非常感谢您的帮助。 PS:我知道,依靠规则射击的顺序并不是一个好主意,但在我开始使用之前,显着性似乎值得信赖。

1 个答案:

答案 0 :(得分:3)

查看你的drl文件,你的条件是“当”部分m2:Message2(状态&lt; 0) ,请记住,LHS仅在断言时或在调用给定事实的modify()/ update()时进行评估。因此,在断言时,条件将评估为真并激活规则。您永远不会在同一个object.Message2上调用modify()/ update,因此,您的条件永远不会被重新评估。这就是为什么你会得到奇怪的行为。 这就是为什么你没有更新就会得到理想的行为。