Подтвердить что ты не робот

Поток слюни

У меня странная проблема с drools:

У меня есть следующие правила:

rule "is my dog a baby?"
  ruleflow-group "dog"
  salience 10
  when 
     dog : Dog(age <1 )
  then 
     dog.setIsBaby(true);
end


rule "baby dog"
    ruleflow-group "dog"
    salience 9
    when
        myData : MyData( myDog.isBaby() == false)
    then
        System.out.println(myData.getMyDog().getIsBaby());
end

Я вставляю в свою сессию myData и myData.getMyDog(), где myData.getMyDog.isBaby==false

Первое правило увольняется, и моя собака настроена на то, чтобы быть ребенком. Затем второй запускается, и даже он печатает true (даже если условие было ложным)

И когда я тестирую после запуска всех правил, myDog в myData устанавливается как ребенок.

Что я здесь делаю неправильно? Почему второе правило уволено? проблема в сессии (состояние в моем случае)?

Я думаю, что мне нужно сказать, что я изменяю myData: myDog где-то, но я не уверен, где.

Надеюсь, мой вопрос ясен, если не скажу.

4b9b3361

Ответ 1

Когда вы изменяете факты рабочей памяти, вам нужно сообщить Drools, что данные были изменены, чтобы они могли переоценить все соответствующие правила.

Drools оценивает факты перед тем, как запускать любые согласованные правила. Если у вас есть собака с возрастом = 0 и ребенок = ложь, оба правила будут активированы. Когда вы запускаете правило is my dog a baby?, это не меняет того факта, что, когда Drools оценил правило baby dog, условие myDog.isBaby() == false было истинным.

Чтобы сообщить Drools, что вы изменили какой-то факт, используйте метод поддержки update(). Имейте в виду, что Drools связывает фактические ручки с конкретным объектом. Если правило ссылается на MyData, и вы хотите, чтобы это правило было переоценено при изменении объекта MyData.myDog, вам нужно использовать update() для объекта MyData; просто update() на вашем объекте Dog не приведет к переоценке правила baby dog.

Попробуйте изменить правило is my dog a baby? на следующее:

rule "is my dog a baby?"
    ruleflow-group "dog"
    salience 10
    when 
        dog : Dog(age < 1, baby == false)
        myData : MyData(myDog == dog)
    then
        dog.setIsBaby(true);
        update(dog);
        update(myData);
    end

Ответ 2

Вам нужно сделать

then 
    dog.setIsBaby(true);
    update( dog ) 

в вашем первом правиле и перепишите , когда вашего второго правила, например

when
    dog :    Dog( isBaby == false)
    myData : MyData( myDog == dog)

Правило должно быть записано таким образом, поэтому drools может автоматически определять, какие правила он должен запускать снова после изменения факта.

Каждый раз, когда вы изменяете факт в движке правил, вам нужно сообщить рабочей памяти, что вы изменили ее с обновлением.

Я не использовал drools с версии 4, но я предполагаю, что это все еще применяется.

Ответ 3

Да, вы должны обновить как собаку, так и карту. Приветствия

Ответ 4

Вы можете обновить собаку в рабочей памяти с помощью методов помощи modify или update. Если вы можете использовать любую из вышеперечисленных функций, Drools снова переоценит правила, и вы закончите бесконечный цикл. поэтому вам также понадобится атрибут no-loop в вашем правиле или измените условие на

dog : Dog(age <1, isBaby == false )

чтобы в следующий раз он снова не оценил одно и то же правило и снова и снова обновил isBaby до true.