3

我有几个域规则(我将它们称为“先决条件”),我将它们描述为 Drools 规则。例如,对于被视为 的学生HasGoodGrades,他们必须保持 GPA > 3.0。我还有一些规则,这些规则基本上是这些先决条件的布尔逻辑分组——例如IsInHonorRoll. 要IsInHonorRoll为真,HasGoodGrades需要满足规则,OR ( HasOkGradesAND 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 就会开始因内存不足错误而死亡,即使堆大小非常大。

处理 Drools 规则的这些布尔逻辑“分组”的最佳方法是什么?谢谢!

4

2 回答 2

0

在 drools 中重用前置条件的更自然的方式是 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

在此处查看完整答案

于 2020-04-05T21:32:53.087 回答
0

你是对的,这是 Drools 的方式(采取婴儿步骤 - 每一步都是它自己的规则)。只需将第一条规则分成两个单独的规则,这样您就不需要任何 OR。

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

于 2020-04-14T10:41:14.763 回答