升级TimeFold后@PlanningVariable(nullable=true)的null赋值被过滤问题
解决TimeFold中@PlanningVariable(nullable=true)的null赋值纳入搜索问题
针对你遇到的TimeFold过滤null->null移动导致测试失败的问题,可以通过以下几种方式调整配置,让null相关移动纳入穷举搜索:
1. 禁用默认的可执行移动过滤器
TimeFold默认会过滤掉“无实际状态变化”的移动(比如null->null),而OptaPlanner 9.44.0没有这个默认过滤逻辑。你可以显式配置移动选择器不使用任何过滤器:
XML配置示例
<solver> <solutionClass>your.package.YourSolution</solutionClass> <entityClass>your.package.YourEntity</entityClass> <termination> <exhaustiveSearch/> </termination> <heuristic> <exhaustiveSearch> <moveSelector> <!-- 禁用默认过滤器,允许所有移动(包括null->null) --> <filter class="org.optaplanner.core.impl.heuristic.selector.common.decorator.NoneFilter"/> </moveSelector> </exhaustiveSearch> </heuristic> </solver>
Java配置示例
SolverFactory<YourSolution> solverFactory = SolverFactory.create(new SolverConfig() .withSolutionClass(YourSolution.class) .withEntityClasses(YourEntity.class) .withTerminationConfig(new TerminationConfig().withExhaustiveSearch(true)) .withHeuristicConfig(new ExhaustiveSearchConfig() .withMoveSelectorConfig(new MoveSelectorConfig() // 禁用默认过滤器 .withFilterClass(NoneFilter.class))));
2. 自定义选择过滤器允许null相关移动
如果你不想完全禁用过滤器,只想放行null->null或涉及null的移动,可以自定义一个过滤器类:
public class AllowNullMoveFilter implements SelectionFilter<Move<YourSolution>> { @Override public boolean accept(ScoreDirector<YourSolution> scoreDirector, Move<YourSolution> move) { if (move instanceof ChangeMove) { ChangeMove<?> changeMove = (ChangeMove<?>) move; Object oldValue = changeMove.getOldValue(); Object newValue = changeMove.getNewValue(); // 放行所有涉及null的移动,包括null->null return oldValue == null || newValue == null; } return true; // 其他类型移动默认放行 } }
然后在配置中指定这个过滤器:
<filter class="your.package.AllowNullMoveFilter"/>
3. 确认值范围配置
确保你的@ValueRangeProvider确实包含null值。虽然@PlanningVariable(nullable = true)允许变量为null,但如果值范围里没有null,穷举搜索也不会生成null赋值的移动。可以显式将null加入值范围:
@ValueRangeProvider(id = "yourValueRange") public List<Object> getValueRange() { List<Object> range = new ArrayList<>(existingValues); range.add(null); // 显式添加null到值范围 return range; }
差异原因说明
TimeFold对默认选择过滤器做了优化,默认过滤掉不会改变解决方案状态的移动(比如同一个值的赋值,包括null->null),而OptaPlanner 9.44.0没有这个默认行为。你的单元测试依赖于这些无变化移动的存在,所以需要调整配置来匹配旧行为。
内容的提问来源于stack exchange,提问作者marinier
相关产品推荐
相关产品推荐

