Timefold中链式规划变量实体的PlanningPin配置问题咨询
链式规划变量下的实体固定(Pin)配置调整
核心问题分析
使用@PlanningPin固定链式实体时,默认会锁定该实体的前后链节点关系,导致求解器无法在固定工单的前后添加新工单。这是因为默认的Pin逻辑会把实体的所有规划变量(包括链式的previous/next关联)都标记为不可修改。
调整方案
1. 自定义Pin过滤器(替代默认注解行为)
移除WorkOrder类上的@PlanningPin注解,自定义过滤器仅固定技术人员分配和开始时间,放开链式邻接的修改权限:
public class WorkOrderPinFilter implements EntityPinFilter<WorkOrder> { @Override public boolean isPin(ScoreDirector<YourSolution> scoreDirector, WorkOrder workOrder) { return workOrder.isPinned(); } @Override public boolean isPin(ScoreDirector<YourSolution> scoreDirector, WorkOrder workOrder, String variableName) { // 仅固定技术人员和开始时间变量,允许修改链式的previous/next节点 return workOrder.isPinned() && (variableName.equals("technician") || variableName.equals("startTime")); } }
在求解器配置中注册该过滤器:
<solver> <!-- 其他配置项 --> <entityPinFilterClass>com.yourpackage.WorkOrderPinFilter</entityPinFilterClass> </solver>
2. 调整移动选择器(允许修改固定实体的邻接链)
默认移动选择器会跳过与固定实体相关的链式操作,需明确允许修改固定实体的前后链:
<solver> <constructionHeuristic> <forager> <acceptedCountLimit>1000</acceptedCountLimit> </forager> </constructionHeuristic> <localSearch> <moveSelector> <chainMoveSelector> <!-- 允许针对固定实体的邻接链执行移动操作 --> <ignoreEntityPins>false</ignoreEntityPins> <subChainChangeMoveSelector/> <subChainSwapMoveSelector/> <tailChainSwapMoveSelector/> </chainMoveSelector> </moveSelector> <!-- 其他局部搜索配置 --> </localSearch> </solver>
其中ignoreEntityPins=false是核心配置,它让求解器不忽略与固定实体相关的链式移动,支持在固定工单前后插入新工单。
3. 添加硬约束(确保固定属性不被篡改)
为了防止固定实体的技术人员和开始时间被意外修改,在约束流中添加硬约束:
Constraint fixedWorkOrderTechnician(ConstraintFactory factory) { return factory.from(WorkOrder.class) .filter(WorkOrder::isPinned) .penalize("固定工单的技术人员不可变更", HardSoftScore.ONE_HARD, workOrder -> !workOrder.getTechnician().equals(workOrder.getOriginalTechnician())) .asConstraint(); } Constraint fixedWorkOrderStartTime(ConstraintFactory factory) { return factory.from(WorkOrder.class) .filter(WorkOrder::isPinned) .penalize("固定工单的开始时间不可变更", HardSoftScore.ONE_HARD, workOrder -> !workOrder.getStartTime().equals(workOrder.getOriginalStartTime())) .asConstraint(); }
需要在WorkOrder类中新增originalTechnician和originalStartTime字段,在标记工单为pinned时保存原始值。
效果验证
配置完成后,求解器会实现:
- 保持固定WorkOrder的技术人员和开始时间不变
- 允许在该WorkOrder的前后链中插入、调整其他WorkOrder,分配给同一位技术人员
内容的提问来源于stack exchange,提问作者Kirk
相关产品推荐
相关产品推荐

