optaplanner 域设计中多对多关系的最佳方法

Best approach for many to many relationships in an optaplanner domain design

你好我想问一下在为我试图解决的问题设计域时采用什么方法,正如我在示例中看到的那样,设计往往类似于实体关系模型,例如很多对多关系通过在两个实体之间放置一个关联实体来解决。 我的问题是为什么这样对性能有帮助,我应该遵循这种设计模式吗?

双方都是问题的多对多关系属性(例如,如果双方class都是问题事实)

关联实体的使用是可选的:这是您的设计要求。 OptaPlanner 不关心,但 Drools 关心,因此它会影响您的分数 DRL 的性能。

例如,假设我们在 EmployeeSkill 之间存在多对多关系。一名员工拥有多项技能,一项技能由多名员工获得。我写了大部分示例,我更喜欢使用关联实体 - 所以我在这里使用 SkillAttained class(尽管新示例 taskassigning 将避免使用这些关联实体作为演示和以提高测试覆盖率)。

至于性能影响,这完全取决于散列和组合的计算方式。以及这如何影响增量分数计算(请参阅有关最后一个概念的文档)。 在任何情况下,避免在 DRL 中使用不需要的 accumulatescollect,因为它们尚未完全增量工作,因此会降低增量分数的增益计算。

使用 SkillAttained 通常更容易获得良好的性能和设计规则。

when
    ShiftAssignment($s : shift, $e : employee) // The when side must always contain a planning entity
    SkillRequired(shift == $s, $s : skill) // Small perf opportunity: ShiftAssigment.getEmployee().getRequiredSkills() would avoid a lookup
    not SkillAttained(employee == $e, skill == $s) // Good: the skill matching uses hashing for scalability if there are many skills
then
    ...addHard(-1); // Fires once per 1 missing skill

没有它,通常更难编写 - 不使用 accumulates 或 collects。 然而,像Employee.hasSkill(Skill)这样的方法(假设员工的技能在LinkedHashSet)是非常有效的。

when
    ShiftAssignment($c : countMissingSkills())
then
    ...addHard(- $c); // Fires once per ShiftAssignment with at least 1 missing skill

所以在这个例子中,ShiftAssignment.countMissingSkills() 必须非常有效(例如使用 LinkedHashSet/Maps 等)。

多对多关系 @PlanningVariabe

目前OptaPlanner 6.4还不支持规划变量的多对多关系。 Vote for this jira. 所以现在需要一个关联实体来解决这个问题。