Optaplanner 约束流加入列表 属性

Optaplanner constraint streams join on List property

我正在将一些约束从 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 个匹配项与规划实体和一个子条件。

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

这些示例有点抽象,无法识别最适合的示例,我希望 scores 没有 OptaPlanner 的 Score class 的实例,但也许 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(...)

ConstraintMatches 明智的理由,请详细说明您的挑战。

您可以使用的一个技巧是只收集整个约束流并投入 .penelizeConfig(..., collection) 因为现在您已经离开了约束流的边界并且您可以使用 Java 流 API 到 return 匹配权重。不确定这是否对您有帮助,因为我从未使用过 BendableScore。不过,ConstraintStream API 中的更多支持甚至更好。