Optaplanner约束流加入List属性

时间:2020-11-10 23:17:12

标签: optaplanner

我正在将Drools语法中的一些约束重写为新的Constraint Streams API。我更喜欢使用Constraint Streams语法,但是我不确定如何复制在Drools中使用的某种技术,该技术涉及对从PlanningEntity的属性提供的列表的每个元素进行匹配。

就像这个简化的例子:

rule "My Rule"
when
  $e = MyEntity(selected)
  $s = Map.Entry($k:key, $v:value) from $e.scores
then
  scoreHolder.addSoftConstraintMatch(kcontext, (int)$k, (int)$v);
end

是否可以使用ConstraintStreams API进行这种匹配?我可以使用groupBy做类似的事情,但是我必须根据实体的所有得分的总和来得分,而不是针对每个得分单独进行匹配。我希望分别匹配每个分数,以得到更清晰的分数解释。

编辑以获取更多详细信息。

基本上,我只想在constraintStreams API中使用flatMap()函数。我面临的挑战是,我还有一个附加的可选标准,用户可以将其应用于每个planningEntity。这些标准带有级别,权重和计分功能。我想分别匹配每个可选条件,根据所选实体和权重计算得分函数,然后将其应用于给定级别(使用BendableScore)。

使用groupBy,我可以使计划实体与其可选标准的列表相匹配,然后可以对其进行评估和汇总。但我想对分数说明中的每个可选条件分别进行匹配。例如而不是计划实体的一个匹配项,而是10个子条件,我希望与计划实体和单个子条件的匹配项平面图为10。

我发现约束流无论如何都不适合我的目的,因为在使用奖励或惩罚功能时,我无法基于匹配实体控制分数级别。我将继续使用drools语法。

2 个答案:

答案 0 :(得分:1)

这些示例有点抽象,以识别最适合的示例,我希望scores没有OptaPlanner的Score类的实例,但也许ifExists()可以满足您的需求。

f.from(MyEntity.class)
.filter(MyEntity::isSelected) // Obsolete if that is a null check on your planning var
ifExists(MyFact.class, equal(MyEntity::this, MyFact::getMyEntity))

尽管它似乎很适合groupBy()

f.from(MyFact.class)
.groupBy(MyFact::getMyEntity, count())
.filter((myFact, count) -> count > 5)
.penalize(...)

明智地寻求理由,请详细说明您的挑战。

答案 1 :(得分:0)

您可以使用的一个技巧是仅收集整个Constraint Stream并放入Apples : Bananas : Potatoes: ,因为现在您已经离开ConstraintStream的边界,并且可以使用Java Stream API返回匹配权重。由于我从未使用过BendableScore,因此不确定是否对您有帮助。不过,对ConstraintStream API的更多支持甚至更好。

相关问题