You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

升级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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.09 00:02:40