Docplex CP minimize_static_lex使用问题及约束更新咨询
问题解答
问题1:替代分两次优化的可行方法
针对静态字典序优化未找到第一个目标最优解的情况,除了分两次求解,还有以下几种思路:
调整静态字典序的子问题参数
静态字典序优化的第一个阶段(优化工人数量)可能使用了默认的MIP参数,和单独优化时的参数策略不一致,导致搜索效率低。可以给第一个目标的子问题单独设置参数,比如限制时间、调高启发式力度,强制求解器在第一个阶段快速找到工人数量的最优解:from docplex.mp.model import Model model = Model() # 假设已定义worker_count(工人数量变量)和makespan(完工时间变量) # 给第一个子问题设置和单独优化一致的参数 sub_params = {'time_limit': 10, 'mip_strategy_heuristic_effort': 10} model.minimize_static_lex([worker_count, makespan], subproblem_params=[sub_params, {}]) sol = model.solve()这样第一个阶段会用10秒优先锁定工人数量的最优解,再进入第二个阶段优化完工时间。
注入初始解
将单独优化得到的2名工人的可行解作为初始解传入字典序优化,让求解器从这个最优起点开始搜索,避免在第一个阶段走弯路:# 先单独优化工人数量得到最优解 model_single = Model() # 复用原模型的变量和约束(或直接复制) model_single.minimize(worker_count) sol_single = model_single.solve(time_limit=10) # 整理初始解的变量值字典 mip_start = {var: sol_single.get_value(var) for var in model.iter_variables()} # 给字典序模型添加初始解 model.add_mip_start(mip_start) # 执行静态字典序优化 sol_lex = model.minimize_static_lex([worker_count, makespan]).solve()使用动态字典序优化
静态字典序是先完全优化第一个目标再处理第二个;动态字典序则通过给第一个目标设置一个远大于第二个目标的权重,近似实现字典序优先级,同时可能提升搜索效率:# 设置权重,确保工人数量的优先级绝对高于完工时间 model.minimize(1000 * worker_count + makespan) sol = model.solve()注意权重需足够大,避免出现为减少完工时间而增加工人数量的情况。
问题2:求解过程中动态更新约束(无需重建模型)
完全可以在不重建模型的前提下动态更新约束,步骤如下:
先优化第一个目标并记录最优值
model = Model() # 定义变量、约束... # 以工人数量为目标优化,设置时间限制 model.minimize(worker_count) sol_first = model.solve(time_limit=10) best_worker_num = sol_first.get_value(worker_count)添加工人数量的上限约束
直接在原模型中添加约束,无需重新创建模型:# 保存约束对象,方便后续修改/移除(可选) worker_cap_constraint = model.add_constraint(worker_count <= best_worker_num, name="worker_cap")切换目标并重新求解
修改模型的目标为最小化完工时间,然后调用求解即可:model.minimize(makespan) sol_final = model.solve()
如果需要迭代更新约束(比如多次优化第一个目标得到更优的工人数量),还可以移除旧约束后添加新约束:
# 移除旧的工人数量约束 model.remove_constraint(worker_cap_constraint) # 添加更紧的新约束 new_worker_cap = model.add_constraint(worker_count <= new_best_num)
Docplex会自动处理模型的修改,求解器在下次调用solve()时会重新初始化问题,无需重新定义变量和其他约束。
内容的提问来源于stack exchange,提问作者Yop
相关产品推荐
相关产品推荐

