仅存在一个Planning Entity时Constraint Rule未生效,求排查方案
问题描述
我有一个字段映射场景,需要基于多约束为单个源字段从100个目标字段中匹配最优项。已经编写了OptaPlanner的PlanningEntity和PlanningSolution代码,但因为仅存在一个FieldMapping实例,尝试的约束规则没有生效,请问问题出在哪里?
相关代码
PlanningEntity 代码
@PlanningEntity public class FieldMapping { @PlanningId private Long id; public FieldMapping() { } protected Field inputField; @PlanningVariable(valueRangeProviderRefs = { "targetFieldRange" }) protected Field targetField; }
PlanningSolution 代码
@PlanningSolution public class FieldMappingSolution { @ValueRangeProvider(id = "targetFieldRange") @ProblemFactCollectionProperty private List<PlanningRecommField> targetFields; @PlanningScore private HardSoftScore score; private SolverStatus solverStatus; }
尝试的约束规则
public Constraint requiredLeafNode(ConstraintFactory constraintFactory) { return constraintFactory.forEachUniquePair(FieldMapping.class, Joiners.equal(FieldMapping::getTargetField)) .filter((mapping1,mapping2) -> !mapping2.getTargetField().isLeafNode()) .penalize("Not leaf node", HardSoftScore.ONE_HARD); }
问题分析与修复
核心问题
- 约束触发条件不成立:你使用的
forEachUniquePair(FieldMapping.class)是用来遍历两个不同的FieldMapping实例对的,但你的场景中只有1个实例,无法形成配对,导致约束逻辑永远不会执行。 - 约束逻辑冗余:校验目标字段是否为叶子节点不需要对比两个实例,直接针对单个实例判断即可。
- 规划实体未被识别:你的
FieldMappingSolution中缺少@PlanningEntityCollectionProperty注解的集合——即使只有一个实例,OptaPlanner也需要通过这个注解来识别规划实体。
修复后的约束规则
public Constraint requiredLeafNode(ConstraintFactory constraintFactory) { return constraintFactory.forEach(FieldMapping.class) .filter(mapping -> !mapping.getTargetField().isLeafNode()) .penalize("目标字段非叶子节点", HardSoftScore.ONE_HARD); }
修复后的PlanningSolution
@PlanningSolution public class FieldMappingSolution { @ValueRangeProvider(id = "targetFieldRange") @ProblemFactCollectionProperty private List<PlanningRecommField> targetFields; @PlanningEntityCollectionProperty private List<FieldMapping> fieldMappings; // 存放唯一的FieldMapping实例 @PlanningScore private HardSoftScore score; private SolverStatus solverStatus; // 补充必要的构造方法、getter和setter }
内容的提问来源于stack exchange,提问作者bits1983
相关产品推荐
相关产品推荐

