Timefold能否生成多个调度方案?如何配置实现多提案输出
如何用Timefold获取多个调度方案而非仅最优解
你的现有模型无需修改核心结构,只需要通过求解器配置或API即可收集多个可行/次优解,以下是具体实现方式:
方法一:通过事件监听收集多个不同解
利用求解器的事件监听机制,捕获每次最优解更新的事件,筛选并收集不同的调度方案,直到凑够5个:
// 构建求解器 SolverFactory<PlanningSolution> solverFactory = SolverFactory.createFromXmlResource("solverConfig.xml"); Solver<PlanningSolution> solver = solverFactory.buildSolver(); // 用于存储候选方案的列表 List<PlanningSolution> candidateSolutions = new ArrayList<>(5); // 添加最优解变更监听器 solver.addEventListener(event -> { if (event instanceof BestSolutionChangedEvent<PlanningSolution> bestEvent) { PlanningSolution newSolution = bestEvent.getNewBestSolution(); // 判断当前解是否与已收集的解唯一(避免重复的分配方案) boolean isUnique = candidateSolutions.stream() .noneMatch(existing -> { // 先比较分数,再比较订单的配送分配细节 if (!existing.getScore().equals(newSolution.getScore())) { return false; } // 逐订单检查配送分配是否完全一致 for (int i = 0; i < existing.getOrders().size(); i++) { Order existingOrder = existing.getOrders().get(i); Order newOrder = newSolution.getOrders().get(i); if (!Objects.equals(existingOrder.getAssignedDelivery(), newOrder.getAssignedDelivery())) { return false; } } return true; }); if (isUnique) { // 克隆解,避免求解器后续修改实例 candidateSolutions.add(solver.createClone(newSolution)); // 收集够5个就提前终止求解 if (candidateSolutions.size() >= 5) { solver.terminateEarly(); } } } }); // 启动求解 solver.solve(initialPlanningSolution); // candidateSolutions 中即为最多5个不同的调度方案
方法二:收集Pareto最优解(多目标场景)
如果你的调度需求涉及多个优化目标(如最小化配送成本、最短配送时间),可以启用Pareto最优解模式,收集非支配的最优解集合,再从中选取前5个:
- 在求解器配置文件
solverConfig.xml中添加以下配置:
<solver> <!-- 其他基础配置(如求解终止条件、启发式算法) --> <scoreDirectorFactory> <!-- 根据你的目标设置分数类型,比如HARD_SOFT对应多目标 --> <scoreDefinitionType>HARD_SOFT</scoreDefinitionType> </scoreDirectorFactory> <!-- 启用Pareto解模式 --> <paretoSolutionMode>ENABLED</paretoSolutionMode> <!-- 限制收集的Pareto解数量为5 --> <termination> <bestSolutionCountLimit>5</bestSolutionCountLimit> </termination> </solver>
- 求解完成后获取解集合:
Solver<PlanningSolution> solver = solverFactory.buildSolver(); solver.solve(initialPlanningSolution); // 获取所有Pareto最优解,最多5个 Collection<PlanningSolution> paretoSolutions = solver.getBestSolutions();
关键注意事项
- 你的
PlanningSolution类缺少@PlanningScore字段,这是Timefold评估解优劣的核心,必须添加:@PlanningScore private HardSoftScore score; // 可根据实际需求选择分数类型(如SimpleScore、HardMediumSoftScore) - 保存解时必须调用
solver.createClone(),因为求解器内部会复用同一个解决方案实例,直接添加会导致后续修改覆盖已收集的解。 - 仅通过分数判断解的唯一性不可靠,不同的配送分配可能得到相同分数,因此需要额外检查订单的配送分配细节。
内容的提问来源于stack exchange,提问作者R S
相关产品推荐
相关产品推荐

