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

如何通过SolverConfigOverride让用户自定义Timefold求解器各阶段终止时长?

解决方案与最佳实践

一、实现阶段时长自定义覆盖

要实现按用户设定总时长分配各阶段运行时间,你需要通过SolverConfigOverride不仅覆盖全局终止规则,还要针对性配置构造启发式(CH)和每个局部搜索(LS)阶段的终止时长,同时保留XML中原有的算法参数配置。

步骤1:计算各阶段时长

先从用户输入获取总时长,再按比例计算各阶段的分钟数:

// 示例:从用户输入获取总时长,替换为实际获取逻辑
Long userTotalMinutes = 305L;
// 构造启发式占总时长10%
Long chMinutes = Math.round(userTotalMinutes * 0.1);
// 每个局部搜索阶段占总时长45%
Long eachLsMinutes = Math.round(userTotalMinutes * 0.45);

步骤2:构造覆盖配置

在SolverConfigOverride中配置全局终止、CH阶段和两个LS阶段的终止规则,同时保留XML中的算法参数(如acceptor、forager):

SolverConfigOverride<Timetable> configOverride = new SolverConfigOverride<Timetable>()
        // 全局终止:确保总运行时长不超过用户设定值
        .withTerminationConfig(new TerminationConfig().withMinutesSpentLimit(userTotalMinutes))
        // 配置构造启发式阶段的终止时长及原有配置
        .withConstructionHeuristicConfig(new ConstructionHeuristicConfig()
                .withTerminationConfig(new TerminationConfig().withMinutesSpentLimit(chMinutes))
                .withConstructionHeuristicType(ConstructionHeuristicType.ALLOCATE_ENTITY_FROM_QUEUE)
                .withEntitySorterManner(EntitySorterManner.DECREASING_DIFFICULTY_IF_AVAILABLE)
                .withValueSorterManner(ValueSorterManner.DECREASING_STRENGTH_IF_AVAILABLE))
        // 配置两个局部搜索阶段的终止时长及原有算法参数
        .withLocalSearchConfigList(List.of(
                new LocalSearchConfig()
                        .withTerminationConfig(new TerminationConfig().withMinutesSpentLimit(eachLsMinutes))
                        .withAcceptorConfig(new AcceptorConfig().withLateAcceptanceSize(900))
                        .withForagerConfig(new ForagerConfig().withAcceptedCountLimit(10)),
                new LocalSearchConfig()
                        .withTerminationConfig(new TerminationConfig().withMinutesSpentLimit(eachLsMinutes))
                        .withAcceptorConfig(new AcceptorConfig().withEntityTabuSize(10))
                        .withForagerConfig(new ForagerConfig().withAcceptedCountLimit(1200))
        ));

步骤3:应用覆盖配置

将上述配置传入solveBuilder,替换原有的withConfigOverride逻辑:

solverManager.solveBuilder()
        .withProblemId(jobId)
        .withConfigOverride(configOverride)
        .withProblemFinder(jobId_ -> jobIdToJob.get(jobId).timetable)
        .withBestSolutionConsumer(solution -> jobIdToJob.put(jobId, Job.ofTimetable(solution)))
        .withExceptionHandler((jobId_, exception) -> {
            jobIdToJob.put(jobId, Job.ofException(exception));
            LOGGER.error("Failed solving jobId ({}).", jobId, exception);
        })
        .run();

二、XML配置最佳实践:是否需要给构造启发式设置耗时限制?

  • 默认推荐:不需要手动设置
    构造启发式的核心目标是快速生成可行初始解,通常几秒到几分钟就能完成(取决于问题规模)。让求解器自动终止CH(即所有实体分配完成后结束),能保证初始解的质量,为后续局部搜索打下更好的基础,最终得到更优的结果。

  • 特殊场景:建议设置
    如果你的总时间预算非常紧张(比如总时长仅几分钟),或者CH在极端场景下运行时间过长,这时设置CH的时间限制是合理的,避免它占用过多时间导致局部搜索没有足够时长优化解。

  • 配置建议
    XML中保留基础的阶段结构和算法参数(如CH类型、LS的acceptor/forager配置),把动态调整的参数(如终止时长)放到代码中通过SolverConfigOverride覆盖,这样既保证算法稳定性,又能灵活响应用户需求。

内容的提问来源于stack exchange,提问作者Diallo Francis Patrick

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.24 13:59:55