我有几个域规则(我将它们称为'前置条件'),我将其描述为Drools Rules。例如,要将学生视为HasGoodGrades
,他们必须保持GPA> 3.0。我也有规则,这些规则基本上是这些前置条件的布尔逻辑分组 - 例如IsInHonorRoll
。要使IsInHonorRoll
成立,则需要满足规则HasGoodGrades
,或(HasOkGrades
和HasPerfectAttendance
)。
我如何处理这个问题是在满足规则时插入PreconditionResult
个事实。然后,在这些较大的“分组”规则中,我正在检查这些PreconditionResult
事实并在那里执行布尔逻辑:
rule "IsInHonorRoll"
dialect "mvel"
when
$s : Student()
PreconditionResult( id == "HasGoodGrades", student == $s)
or
( PreconditionResult( id == "HasOkGrades", student == $s)
and
PreconditionResult( id == "HasPerfectAttendance", student == $s) )
then
System.out.print("Student is in the Honor Roll.");
end
rule "HasOkGrades"
dialect "mvel"
when
$s : Student( gpa > 2.0 )
then
insert(new PreconditionResult("HasOkGrades", $s))
end
rule "HasGoodGrades"
dialect "mvel"
when
$s : Student( gpa < 3.0 )
then
insert(new PreconditionResult("HasGoodGrades", $s))
end
rule "HasPerfectAttendance"
dialect "mvel"
when
$s : Student( daysAbsent == 0 )
then
insert(new PreconditionResult("HasPerfectAttendance", $s))
end
这似乎有效,但感觉不自然,我确信在Drools中有更好的方法来做这类事情。更重要的是,如果给出足够的这些规则以及大而复杂的布尔子句,Drools就会因为Out of Memory错误而开始死亡,即使是非常大的堆大小。
处理Drools规则的这些布尔逻辑“分组”的最佳方法是什么?谢谢!
答案 0 :(得分:0)
在流口水中重用前提条件的更自然的方法是DSL。然后,您可以根据需要组合为复杂的逻辑语句。例如
rule Test2
when
There is a ShoppingCart that
- worth a discount
then
print eligible price
end
DSL
[when]worth a discount =
(total price is not less than 500
and not over limit
or total price is greater than 5000)
// stupid condition just for demonstration
[when]over limit = ((total price + total price * 0.05) > total price + 50)
[when]total price = totalPrice
查看完整答案here
答案 1 :(得分:0)
您是对的,这是Drools的方式(采取婴儿步骤-每个步骤都是自己的规则)。只需将第一个规则分成两个单独的规则,就不需要任何OR。
有不同的策略可以避免占用大量内存。一种想法是仅将单个学生的数据插入会话中,运行该数据,然后为下一个学生创建新会话,然后再次运行所有规则。除此以外,还存在其他策略。