在AND / OR组中分组Drools规则

时间:2013-06-27 13:53:20

标签: java drools

我有几个域规则(我将它们称为'前置条件'),我将其描述为Drools Rules。例如,要将学生视为HasGoodGrades,他们必须保持GPA> 3.0。我也有规则,这些规则基本上是这些前置条件的布尔逻辑分组 - 例如IsInHonorRoll。要使IsInHonorRoll成立,则需要满足规则HasGoodGrades,或(HasOkGradesHasPerfectAttendance)。

我如何处理这个问题是在满足规则时插入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规则的这些布尔逻辑“分组”的最佳方法是什么?谢谢!

2 个答案:

答案 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。

有不同的策略可以避免占用大量内存。一种想法是仅将单个学生的数据插入会话中,运行该数据,然后为下一个学生创建新会话,然后再次运行所有规则。除此以外,还存在其他策略。