如何使用pyomo终止gurobi回调?

问题描述 投票:0回答:2

我正在使用 pyomo 及其“gurobi_persistent”接口来解决 MIP。我试图实现一个回调,它检查是否有足够小的最优性差距,如果达到,就会终止。当然,这必须以某种方式发生,当前的解决方案将被读回 pyomo 模型。我不知道该怎么做。当满足停止条件时,我得到

AttributeError:“GurobiPersistent”对象没有属性“terminate”

通常,在 gurobipy 中,语句 model.terminate() 应该有效。 另请参阅下面我的回调定义。

solver = pe.SolverFactory('gurobi_persistent')
solver.set_instance(m)

def my_callback(cb_m, cb_opt, cb_where):
    if cb_where == GRB.Callback.MIP:
        # General MIP callback
        objbst = cb_opt.cbGet(GRB.Callback.MIP_OBJBST)
        objbnd = cb_opt.cbGet(GRB.Callback.MIP_OBJBND)
        if abs(objbst - objbnd) < percentGap * (1.0 + abs(objbst)):
            print('Stop early - {} % gap achieved'.format(percentGap*100))
            # statement that does not exist
            cb_opt.terminate()
solver.set_callback(my_callback)
solver.solve(tee=True)

如果您提供一些有关如何实现所需行为的提示,我将不胜感激。 祝你有美好的一天!

callback pyomo gurobi
2个回答
0
投票

从检查 gurobi_directgurobi_persistent 上的 Pyomo 文档来看,这似乎根本不可能。您需要使用 Gurobi Python API 来实现回调。

实现特定 MIPGap 的另一种方法是简单地将此间隙设置为终止值


0
投票

我找到了一个解决方案来执行此回调以终止并使用 gurobi_persistent 跟踪 pyomo 中的上限和下限:

OPT_objective_values = []
OPT_Qdot_values = []
OPT_Qdot_loss_values = []
OPT_time_tracker = []
OPT_upper_bounds = []
OPT_lower_bounds = []
OPT_mipgaps = []
OPT_last_not_divergend_gap = None
OPT_last_change_time = None


def callback_from_gurobi(cb_m, cb_opt, cb_where):
    if cb_where == GRB.Callback.MIPSOL:
        cb_opt.cbGetSolution(
            vars=[model.Qdot[prod] for prod in model.Qdot]
        )
        OPT_Qdot_values.append(
            [model.Qdot[prod].value for prod in model.EDGES_prod]
        )
        lower_bound = cb_opt.cbGet(GRB.Callback.MIPSOL_OBJBND)
        upper_bound = cb_opt.cbGet(GRB.Callback.MIPSOL_OBJBST)
        current_gap = (upper_bound - lower_bound) / upper_bound
        OPT_lower_bounds.append(lower_bound)
        OPT_upper_bounds.append(upper_bound)
        OPT_mipgaps.append(-current_gap)
        now = datetime.datetime.now(datetime.timezone.utc).timestamp()
        OPT_time_tracker.append(now)
        if (
            OPT_last_not_divergend_gap is None
            or abs(current_gap - OPT_last_not_divergend_gap) > 0.01
        ):
            OPT_last_not_divergend_gap = current_gap
            OPT_last_change_time = datetime.datetime.now(
                datetime.timezone.utc
            ).timestamp()
        else:
            if now - OPT_last_change_time > 60:
                cb_opt._solver_model.terminate()

model_solver.set_callback(callback_from_gurobi)
© www.soinside.com 2019 - 2024. All rights reserved.