Timefold中如何在@PlanningListVariable中固定选定项?
在OptaPlanner的@PlanningListVariable中固定指定项的解决方案
问题根源
你在Audit类上添加@PlanningPin无效,核心原因是:
Audit虽然标注了@PlanningEntity,但它没有可直接修改的规划变量——dayPlanning是@InverseRelationShadowVariable,其值完全由DayPlanning的audits列表(真正的@PlanningListVariable)决定。@PlanningPin的作用是标记拥有规划变量的实体是否允许被修改,而Audit并非实际的规划主体,所以该注解无法生效。
可行解决方案
无需切换到时间粒度模式,也不需要硬约束,可通过**自定义移动过滤器(MoveFilter)**实现固定指定Audit的需求:
1. 实现自定义MoveFilter
创建过滤器,拒绝所有涉及固定Audit的移动操作:
public class PinnedAuditMoveFilter implements MoveFilter<Planning> { @Override public boolean accept(ScoreDirector<Planning> scoreDirector, Move<Planning> move) { // 处理列表项变更移动 if (move instanceof ListVariableChangeMove) { ListVariableChangeMove<DayPlanning, Audit> listMove = (ListVariableChangeMove<DayPlanning, Audit>) move; if (listMove.getItem().isPinned()) { return false; // 拒绝移动固定的Audit } } // 处理列表项交换移动 if (move instanceof ListVariableSwapMove) { ListVariableSwapMove<DayPlanning, Audit> swapMove = (ListVariableSwapMove<DayPlanning, Audit>) move; if (swapMove.getLeftItem().isPinned() || swapMove.getRightItem().isPinned()) { return false; // 拒绝涉及固定Audit的交换 } } // 其他列表相关移动类型同理处理 return true; } }
2. 配置过滤器到求解器
XML配置方式
在solverConfig.xml中添加:
<solver> <!-- 其他配置 --> <moveFilterClass>your.package.PinnedAuditMoveFilter</moveFilterClass> </solver>
Java API配置方式
SolverFactory<Planning> solverFactory = SolverFactory.create(new SolverConfig() .withSolutionClass(Planning.class) .withEntityClasses(DayPlanning.class) .withMoveFilterClass(PinnedAuditMoveFilter.class) // 其他求解器配置(如计分器、终止条件等) );
额外优化
可以去掉Audit类上的@PlanningEntity注解——因为它没有独立的规划变量,仅作为DayPlanning列表变量的元素存在,无需标记为规划实体。
内容的提问来源于stack exchange,提问作者bever
相关产品推荐
相关产品推荐

