#drools
#пускает слюни
Вопрос:
У меня возникла проблема, когда правило не обновляет состояние и не запускается, когда оно не должно, я хочу, чтобы правило срабатывало только тогда, когда оба переключателя открыты.
For example:
In the following order I
open switcha
close switcha
open switchb
Оно запускает правило, когда оно не должно, поскольку switcha закрыт. Оно появляется, как только
Переключатель (имя == «switcha», статус == «Открыто) становится true, он сохраняет это состояние даже при повторном закрытии переключателя.
rule "Electrical Circuit Status"
when
Switch( name == "switcha", status == "Open" )
and
Switch( name == "switchb", status == "Open" )
then // Raise Alert
** Didn't write this code out as it works fine
end
Я ценю любую помощь.
Ответ №1:
Вероятно, вы неправильно понимаете состояние рабочей памяти. Однако, поскольку ваш вопрос чрезвычайно легок в деталях, я собираюсь сделать несколько предположений в своем объяснении, которое я изложу ниже.
Давайте предположим, что у нас есть два переключателя, которые находятся в следующих состояниях:
Switch( name == "switcha", status == "Closed")
Switch( name == "switchb", status == "Closed")
Мы передаем эти переключатели как есть в наши правила.
Когда мы работаем в облачном режиме, правила выполняются в течение мгновения времени, а не с течением времени (что было бы в потоковом режиме). Облачный режим — это режим по умолчанию, который используется большинством приложений. Поскольку вы не упоминаете потоки событий, я предполагаю, что вы работаете в этом режиме. (Если вы понятия не имеете, о чем я говорю, вы также, вероятно, работаете в облачном режиме; Потоковый режим является относительно новым дополнением.) Я также собираюсь принять сеанс с отслеживанием состояния.
Когда мы вызываем fireAllRules
, Drools просматривает входные данные правила и выясняет, какие правила имеют условия, соответствующие этим условиям. Он возьмет это подмножество правил, определит их порядок на основе значимости и естественного порядка, а затем выполнит их.
По мере выполнения этих правил вы можете изменять входные данные правила несколькими способами.
- Вызов
insert
. Это добавляет новый факт в рабочую память. - Вызов
modify
. Это изменяет существующие данные фактов. - Вызов
update
. Это также изменяет существующие данные фактов. - Измените данные на объекте напрямую, например, с помощью getter или setter.
В зависимости от того, как вы изменяете данные, это может изменить или не изменить способ оценки ваших правил.
Если вы изменяете данные напрямую, например, с помощью средства получения или установки, это не вызывает никакой переоценки правил. Любые изменения функционально «невидимы» для движка drools. Те же правила, которые изначально были определены как совпадающие, все еще выполняются, даже если условие больше не выполняется, потому что вы обновили данные таким образом, чтобы Drools не переоценивал эти условия.
При вызове update
Drools повторно оценит всю область действия правила. Это функционально эквивалентно изменению данных, а затем повторному обновлению правил сверху. Drools просмотрит все правила, используя новые данные в рабочей памяти, и повторит процесс сбора совпадений, их упорядочивания и запуска. С помощью вызовов чрезвычайно легко попасть в ситуацию «зацикливания» update
.
Если вы вызываете insert
, вы добавляете новую часть данных в рабочую память. Drools проведет частичную переоценку правил, чтобы выяснить, есть ли какие-либо новые правила, которые могут сработать, или если предыдущие совпадения теперь признаны недействительными. Оно не будет повторно запускать какие-либо правила, которые ранее соответствовали и были запущены. Аналогично, если вы вызываете modify
, вы каким-то образом изменяете существующие свойства объекта ввода правила, и Drools будет частично переоценивать на основе этих измененных условий.
(Это упрощено. Вы можете узнать больше о нюансах, прочитав исходный код или документацию.)
Поскольку вы показываете только одно частичное правило и говорите только, что оно срабатывает даже «при повторном закрытии переключателя», хотя и без объяснения того, как переключатель был закрыт, я могу предложить несколько возможных способов запуска этого условия на основе предыдущего объяснения того, как вы можете изменять данные с помощью (или без) повторного включения.-оценка условий правила.
Например, если вы измените состояние переключателя, вызвав setStatus("Closed")
метод, а не используя modify
, тогда правило не будет знать о новом состоянии.
rule "change switch state invisibly"
when
// some conditions
$b: Switch( name == "switchb", status == "Open" )
then
$b.setStatus("Closed");
end
rule "Electrical Circuit Status"
Switch( name == "switcha", status == "Open" ) // let's assume this is true
Switch( name == "switchb", status == "Open" ) // Also still true!
then
// show alert
end
Поскольку вы меняете состояние, используя setStatus
вместо modify
, Drools не переоценивал последующие совпадения правил и сохранял предыдущие совпадения. Поэтому условие осталось верным.
Чтобы исправить, вы должны либо использовать modify
, либо (менее рекомендуемую) update
рабочую память после вашего изменения (при том понимании, что все правила будут переоценены).
modify ($b) {
setStatus("Closed")
}
Комментарии:
1. Спасибо, что нашли время. Данные поступают с физических коммутаторов в объект данных. Например, выключатель света. Когда оба переключателя разомкнуты, цепь разомкнута (индикатор гаснет). Данные передают положение переключателя при физическом изменении. Как вы уже упоминали, оно не переоценивает все правило, следовательно, продолжает срабатывать, даже если один переключатель может быть закрыт. Я не уверен, как я смогу использовать обновление, когда данные поступают с физического устройства, похоже, мне нужно, чтобы оно переоценивало правило при каждом изменении переключателя. Все еще новичок, ценю помощь! Я немного почитаю.
2. Я вижу, что Drools бесполезен, когда у нас есть набор правил, зависящих от результата предыдущего правила. Даже разработчикам необходимо тщательно продумать ситуацию с обновлением и избегать бесконечного цикла, теперь нетехнический человек наверняка не сможет понять / поддерживать эти правила
3. Я немного озадачен, как ты пришел к такому выводу, @BabyishTank. Бизнес-аналитики в моей предыдущей компании были вполне способны понимать правила. Но да, вам нужно знать о циклических конструкциях всякий раз, когда вы повторно запускаете набор правил, точно так же, как всякий раз, когда вы пишете цикл for или while.