如何在GurobiPy与Pyomo中使用绝对值?目标函数报错求助
解决Pyomo中绝对值目标函数的线性化问题
问题分析
Pyomo的线性规划求解器无法直接处理abs()函数,你尝试的gp.abs_()属于非线性建模组件(需搭配非线性求解器),平方开根号也属于非线性形式,因此会失效。正确做法是通过引入辅助变量+线性约束来线性化绝对值项。
具体实现步骤
假设m.v0[i,j]是已知参数,m.v[i,j]是决策变量,按以下步骤改造代码:
- 定义辅助变量
新增辅助变量m.abs_v[i,j],用来等价表示|m.v[i,j] - m.v0[i,j]|:
m.abs_v = pyo.Var(m.I, m.J, domain=pyo.NonNegativeReals)
- 添加绝对值线性化约束
对每个i,j添加两个约束,等价实现绝对值的定义:
def abs_constraint_upper(m, i, j): return m.abs_v[i,j] >= m.v[i,j] - m.v0[i,j] m.AbsConstraintUpper = pyo.Constraint(m.I, m.J, rule=abs_constraint_upper) def abs_constraint_lower(m, i, j): return m.abs_v[i,j] >= -(m.v[i,j] - m.v0[i,j]) m.AbsConstraintLower = pyo.Constraint(m.I, m.J, rule=abs_constraint_lower)
- 修改目标函数
将原目标中的abs(m.v[i,j]-m.v0[i,j])替换为辅助变量m.abs_v[i,j]。注意:如果m.xr[i,j]是决策变量,不能用if m.xr[i,j] !=0过滤(变量求解过程中值会变化,初始值不代表最终结果),可通过m.xr[i,j]作为系数控制项的激活:
def obj_expression(m): return sum(sum(m.xr[i,j] * (m.xr[i,j] - m.x[i,j]) + m.gamma * m.xr[i,j] * m.abs_v[i,j] for j in m.J) for i in m.I) model.OBJ = pyo.Objective(rule=obj_expression, sense=pyo.minimize) # 可根据需求调整sense为maximize
关键说明
- 若
m.xr[i,j]是二进制变量(0或1),用其乘以目标项的方式可实现“仅当xr[i,j]=1时该项计入目标”的效果,比初始化时的if判断更严谨。 - 辅助变量
abs_v需定义为非负实数域(NonNegativeReals),匹配绝对值的非负特性。
内容的提问来源于stack exchange,提问作者unknownperson
相关产品推荐
相关产品推荐

