JESS vs DROOLS: обратная цепочка
Я пытаюсь заменить Джесс на Drools в качестве движка правил обратной цепочки в нашем проекте. Я искал простые примеры того, как обратное связывание выполняется с Drools. Интересно, что на каждом сайте есть только 1 такой же пример (который я не понимаю, как это до н.э., но давайте пока забудем об этом).
Очень тривиальный пример БК в Джесс:
//q is a fact template with a slot named 'n'
//when there's a q with n==8 print something
//I need a q with n==8 to fire a rule so I will insert it myself!
(deftemplate q (slot n))
(do-backward-chaining q)
(defrule printq (q (n 8)) => (printout t "n is eight! yeah!" crlf))
(defrule iNeedn8 (need-q (n 8)) => (assert (q (n 8))))
(reset)
(run 1)
//fires printq and prints to console...
Эквивалент в Drools:
package com.example;
declare Q
n : int
end
rule "print q"
when
Q(n == 8)
then
System.out.println("n is eight by drools!");
end
//I'M LOST HERE! HELP!
Как я могу добиться того же поведения с Drools?
2 ответа
В Drools общая идея BC - использовать запросы. В дополнение к вашему правилу "print q" вам нужно:
query noQ( int $num )
Goal(num==$num) and not Q(num == $num)
end
rule goal when
Goal( $n: num )
noQ($n;)
then
Q q = new Q($n);
insert( q );
end
rule go when
then
insert( new Goal( 8 ) );
end
Нет никакого способа поручить Друлам обнаружить пропущенный факт сам по себе; Вы должны предоставить цель и запросы, чтобы "преодолеть разрыв".
Вдохновленный особенностью Jess, есть экспериментальная, находящаяся в разработке функция, которая дает вам похожее поведение. Вот как будет выглядеть тест:
@Test
public void testFindQ8() {
String droolsSource =
" package org.drools.abductive.test; " +
" " +
" import " + Abducible.class.getName() + "; " +
" global java.util.List list; \n " +
" " +
" declare Q " +
" @Abducible " +
" id : int @key " +
" end \n " +
" " +
" query foo( int $x ) " +
" @Abductive( target=Q.class ) " +
" not Q( $x; ) " +
" end \n " +
" " +
" rule R1 " +
" when " +
" $x := foo( 8 ; ) " +
" then " +
" System.out.println( 'R1 returned ' + $x ); " +
" end \n " +
" " +
" rule R2 " +
" when " +
" $q : Q( 8; ) " +
" then " +
" System.out.println( 'We have 8!' ); " +
" end ";
/////////////////////////////////////
KieHelper kieHelper = new KieHelper();
kieHelper.addContent( droolsSource, ResourceType.DRL ).build().newKieSession().fireAllRules();
}