如何在OptaPlanner中排除特定匹配?约束流实现示例
用Constraint Streams实现Profile匹配的分配约束示例
核心需求
确保仅当ProjectMember与StockMember的profile属性完全匹配时,才能进行分配;不匹配的分配属于违反硬约束,必须被OptaPlanner禁止。
基础实体结构(基于需求假设)
假设你的规划实体、问题事实类结构如下(如果实际代码有差异,对应调整约束逻辑即可):
Planning Entity(分配实体)
@PlanningEntity public class Allocation { @PlanningId private Long id; // 需求方:ProjectMember(问题事实) private ProjectMember projectMember; // 待分配的库存:StockMember(规划变量) @PlanningVariable(valueRangeProviderRefs = "stockMemberRange") private StockMember stockMember; // 省略getter、setter }
问题事实类
// 需求对象 public class ProjectMember { private String profile; // 所需型材规格 // 省略其他属性、getter、setter } // 库存对象 public class StockMember { private String profile; // 库存型材规格 // 省略其他属性、getter、setter }
Planning Solution
@PlanningSolution public class AllocationSolution { @PlanningScore private HardSoftScore score; @ProblemFactCollectionProperty private List<ProjectMember> projectMemberList; @ProblemFactCollectionProperty private List<StockMember> stockMemberList; @PlanningEntityCollectionProperty private List<Allocation> allocationList; // 省略getter、setter }
修正后的Constraint Provider代码
通过Constraint Streams实现硬约束,强制profile匹配:
import org.optaplanner.core.api.score.buildin.hardsoft.HardSoftScore; import org.optaplanner.core.api.score.stream.Constraint; import org.optaplanner.core.api.score.stream.ConstraintFactory; import org.optaplanner.core.api.score.stream.ConstraintProvider; import java.util.Objects; public class AllocationConstraintProvider implements ConstraintProvider { @Override public Constraint[] defineConstraints(ConstraintFactory constraintFactory) { return new Constraint[] { profileMatchHardConstraint(constraintFactory) }; } private Constraint profileMatchHardConstraint(ConstraintFactory constraintFactory) { return constraintFactory.from(Allocation.class) // 过滤已分配库存的Allocation实例(未分配的无需检查) .filter(allocation -> allocation.getStockMember() != null) // 筛选出profile不匹配的无效分配 .filter(allocation -> !Objects.equals( allocation.getProjectMember().getProfile(), allocation.getStockMember().getProfile())) // 对每个无效分配施加硬惩罚(OptaPlanner会优先避免硬约束被违反) .penalize("Profile不匹配的无效分配", HardSoftScore.ONE_HARD); } }
代码逻辑说明
- 流起点:从
Allocation实体流开始,遍历所有分配实例 - 过滤未分配情况:排除还没分配
StockMember的实例,避免无意义检查 - 匹配检查:对比
ProjectMember和StockMember的profile,筛选出不匹配的分配 - 硬惩罚:对每个无效分配添加硬惩罚分数,OptaPlanner在求解时会优先保证硬约束不被违反,最终只会保留profile匹配的分配结果
适配不同实体结构的调整
如果你的Planning Entity直接是ProjectMember(规划变量为StockMember),只需修改约束逻辑的遍历对象:
private Constraint profileMatchHardConstraint(ConstraintFactory constraintFactory) { return constraintFactory.from(ProjectMember.class) .filter(projectMember -> projectMember.getAssignedStockMember() != null) .filter(projectMember -> !Objects.equals( projectMember.getProfile(), projectMember.getAssignedStockMember().getProfile())) .penalize("Profile不匹配的无效分配", HardSoftScore.ONE_HARD); }
内容的提问来源于stack exchange,提问作者Rahul Patil
相关产品推荐
相关产品推荐

