Слюни разрешить конфликт с основной проблемой - PullRequest
3 голосов
/ 17 февраля 2011

Я обнаружил странное поведение двигателя слюни.У меня есть два правила с разными отличиями.Как описано в документации слюни

3.3.4.1.Разрешение конфликтов

Разрешение конфликтов требуется, когда в повестке дня несколько правил.(Основы этого описаны в главе «Быстрый запуск».) Поскольку запуск правила может иметь побочные эффекты для рабочей памяти, механизму правил необходимо знать, в каком порядке следует запускать правила (например, запуск правила A может вызвать правило B).должны быть удалены из повестки дня).

Стратегии разрешения конфликтов по умолчанию, используемые 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 Ответ

3 голосов
/ 28 апреля 2011

глядя на ваш файл drl, вы задаете условие "когда" часть м2: Сообщение 2 (статус <0) , Помните, что LHS оценивается только во время подтверждения или когда вызывается modify () / update () для данного факта. Таким образом, во время утверждения условие оценивается как истинное и активирует правило. Вы никогда не вызываете modify () / update для одного и того же объекта.Message2, и поэтому ваше состояние никогда не переоценивается. Вот почему вы получите странное поведение. Вот почему вы будете получать желаемое поведение без обновления. </p>

...