在Gurobi中替代abs()/sqrt()添加绝对值约束时报错如何解决
Gurobi 绝对值约束报错解决方案
错误原因梳理
- 内置函数调用错误:Python 原生的
sqrt、abs仅支持实数计算,不能直接作用于 Gurobi 的LinExpr(线性表达式)、QuadExpr(二次表达式)对象,因此第一种写法直接抛出类型错误。 - 通用约束参数不合法:
addGenConstrAbs的输入、输出参数必须为单个Gurobi变量对象,你两次报错的原因分别是:- 第一次传入了临时生成的线性表达式
y[i]-R*p[i],不是变量对象 - 第二次直接传入了存储变量的字典
E,不是单个变量E[i]
- 第一次传入了临时生成的线性表达式
解决方案1:按通用约束要求调整写法
首先新增辅助变量存储线性表达式的计算结果,再调用绝对值约束:
import gurobipy as gp from gurobipy import GRB # 第一步:新增辅助变量,存储y[i]-R*p[i]的结果,需设置上下界为无穷大允许正负值 expr_aux = {} for i in P: expr_aux[i] = model.addVar(lb=-GRB.INFINITY, ub=GRB.INFINITY, name=f"expr_aux_{i}") # 第二步:添加约束绑定线性表达式与辅助变量 for i in P: model.addConstr(expr_aux[i] == y[i] - R * p[i], name=f"lin_bind_{i}") # 第三步:调用绝对值通用约束,参数均为单个变量对象 for i in P: model.addGenConstrAbs(E[i], expr_aux[i], name=f"absConstr_{i}")
解决方案2:绝对值线性化(更高效,无需通用约束)
如果你的优化目标是最小化E[i]相关的项,直接用两组线性约束即可等价实现绝对值约束,性能比通用约束更优:
for i in P: model.addConstr(E[i] >= y[i] - R * p[i], name=f"abs_ub_{i}") model.addConstr(E[i] >= -(y[i] - R * p[i]), name=f"abs_lb_{i}")
内容的提问来源于stack exchange,提问作者炎天下修羅
相关产品推荐
相关产品推荐

