OptaPlanner:如何结合forEachIncludingNullVars与IfNotExist
问题核心
你的原约束仅能处理非空WorkItem的场景,但WorkItem作为可空规划实体/其slot为可空规划变量时,无法覆盖所有未被使用的Slot检测。
解决方案
无需通过join关联流,直接在ifNotExists中传入包含可空WorkItem的流即可,具体分两种场景处理:
场景1:WorkItem本身是可空规划实体(实体集合存在null实例)
protected Constraint somePenalty(ConstraintFactory constraintFactory) { return constraintFactory.forEach(Slot.class) // 传入包含null实体的WorkItem流,检查当前Slot是否无关联WorkItem .ifNotExists(constraintFactory.forEachIncludingNullEntities(WorkItem.class), Joiners.equal(Function.identity(), WorkItem::getSlot)) .groupBy((slot) -> 1, ConstraintCollectors.count()) .penalizeConfigurable((a, countRes) -> countRes) .asConstraint(MeetingConstraintConfiguration.UNUSED_SLOT); }
场景2:WorkItem的slot是可空规划变量(实体非null,但slot字段可为null)
protected Constraint somePenalty(ConstraintFactory constraintFactory) { return constraintFactory.forEach(Slot.class) // 传入包含空规划变量的WorkItem流,检查当前Slot是否无关联WorkItem .ifNotExists(constraintFactory.forEachIncludingNullVars(WorkItem.class), Joiners.equal(Function.identity(), WorkItem::getSlot)) .groupBy((slot) -> 1, ConstraintCollectors.count()) .penalizeConfigurable((a, countRes) -> countRes) .asConstraint(MeetingConstraintConfiguration.UNUSED_SLOT); }
关键说明
forEachIncludingNullEntities:用于包含集合中null的规划实体实例。forEachIncludingNullVars:用于包含规划变量值为null的实体实例。ifNotExists直接接收上述流,即可覆盖所有WorkItem场景,无需额外join操作。
内容的提问来源于stack exchange,提问作者Christian
相关产品推荐
相关产品推荐

