如何在OR-Tools SCIP求解MIP时,每次分支切割后打印目标函数值?
在OR-Tools的SCIP求解器中打印分支切割迭代的目标函数值
要在SCIP每次分支切割迭代后打印目标函数相关值,你可以通过注册回调函数监听求解过程中的中间事件,具体实现步骤如下:
1. 定义回调类
创建继承自pywraplp.Solver.Callback的回调类,重写Callback方法来捕获MIP求解的迭代事件,并打印当前的目标函数边界值:
class MIPIterationCallback(pywraplp.Solver.Callback): def __init__(self, solver): super().__init__() self.solver = solver # 可选:设置打印间隔,避免输出过多 self.iter_count = 0 self.print_interval = 10 def Callback(self, where): # 仅处理MIP求解的迭代事件 if where == pywraplp.Solver.Callback.MIP: self.iter_count += 1 # 按间隔打印,可根据需求调整 if self.iter_count % self.print_interval == 0: # 获取松弛问题的下界(当前最优可能的最小值) lower_bound = self.solver.BestObjectiveBound() # 获取当前找到的最好可行解的目标值(上界) upper_bound = self.solver.Objective().Value() print(f"迭代次数: {self.iter_count} | 下界: {lower_bound:.4f} | 上界: {upper_bound:.4f}")
2. 在求解流程中注册回调
修改你的原有代码,在调用solver.Solve()之前注册上述回调:
solver = pywraplp.Solver_CreateSolver('SCIP') """ Problem Definition Is Omitted Here """ solver.Minimize(target_function) # 实例化回调并注册 iteration_callback = MIPIterationCallback(solver) solver.SetCallback(iteration_callback) # 启动求解 status = solver.Solve()
关键说明
BestObjectiveBound():返回当前分支切割树中松弛问题的最优目标值,是目标函数的下界,对于最小化问题,下界会随迭代推进逐渐增大。Objective().Value():返回当前找到的所有可行解中的最优目标值,是目标函数的上界,对于最小化问题,上界会随迭代推进逐渐减小。- 若不需要间隔打印,可直接去掉
iter_count和print_interval相关逻辑,每次迭代都输出。 - 回调中避免执行耗时操作,防止拖慢大规模问题的求解速度。
内容的提问来源于stack exchange,提问作者Ben Yan
相关产品推荐
相关产品推荐

