OR Tools线性规划目标函数构建:实现决策变量邻近且远离区间边界
现有目标函数的失效原因
原目标函数max x - a1 + b2 - y本质只覆盖了三个诉求中的两个:
- 最大化
x - a1对应“x尽可能远离下界a1”的要求 - 最大化
b2 - y对应“y尽可能远离上界b2”的要求
目标中完全没有引入“x与y尽可能接近”的相关项,求解器在可行域中搜索最优解时,只会沿着目标值增大的方向走到可行域边界,自然会频繁出现x取a1、y取b2的极端边界解,完全无法匹配x和y接近的要求。
另外,本次使用的GLOP是纯线性规划求解器,不支持带绝对值的非线性目标,直接写|x-y|会触发求解错误,必须通过线性转换把差的绝对值拆解为可求解的线性结构。
符合线性求解器要求的建模方法
第一步:线性化“x与y尽可能接近”的诉求
引入非负辅助变量t,添加两个线性约束:
t >= x - y t >= y - x
此时t的取值会严格等于|x - y|,最小化t的取值就等价于让x和y的差尽可能小,全程没有非线性操作,完全可以被GLOP求解。
注意:t的定义域必须设置为非负,不需要额外设置上界,交给求解器自动计算即可。
第二步:根据实际需求选择多目标融合方式
因为三个诉求都是线性结构,有两种成熟的落地路径,完全适配OR Tools的求解框架:
路径1:加权和法(适合有明确权重偏好的场景)
把三个诉求全部转化为统一方向的目标项,搭配自定义权重组合成最终的最大化目标:
max w1*(x - a1) + w2*(b2 - y) - w3*t
- 所有权重
w1, w2, w3均为正实数,根据实际场景的优先级调整大小 - 如果“x和y尽可能接近”是核心诉求,就把w3设置为远大于w1、w2的值,求解器会优先压缩t的取值,再在可行范围内优化x远离a1、y远离b2的目标
- 若三个诉求重要程度相近,可根据三个项的实际取值范围缩放权重,避免某一项的量纲过大挤压其他目标的优化空间
对应的修改后代码示例:
solver = pywraplp.Solver.CreateSolver("GLOP") x = solver.NumVar(lb=a1, ub=a2, name="X") y = solver.NumVar(lb=b1, ub=b2, name="Y") # 新增非负辅助变量,用来等价表示x和y的绝对差 t = solver.NumVar(lb=0, ub=solver.infinity(), name="abs_diff") # 保留原有硬约束 solver.Add((1 - c1) * y >= (1 + c2) * x) # 新增两个线性约束,完成绝对值的线性转换 solver.Add(t >= x - y) solver.Add(t >= y - x) # 根据实际优先级调整权重值,示例中x与y接近的优先级更高 w1, w2, w3 = 1.0, 1.0, 5.0 solver.Maximize(w1*(x - a1) + w2*(b2 - y) - w3*t)
路径2:字典序分层优化(适合有严格优先级顺序的场景)
如果三个诉求有明确的先后优先级,不需要模糊加权,就可以分步求解,完全避免权重设置的问题:
- 第一层求解:仅优化最高优先级目标,也就是最小化t的取值(等价于最大化
-t),求解得到最优的最小差值t_opt - 第二层求解:把
t <= t_opt + 1e-6(预留浮点精度余量)作为硬约束加入模型,再优化次优先级目标,比如“x尽可能远离a1”,求解得到最优的x取值 - 第三层求解:把上一层得到的最优x取值作为硬约束加入,再优化最后一个目标“y尽可能远离b2”,最终得到的解会严格按照优先级满足所有诉求,不会为了追求x、y的位置边界导致两者差值过大。
常见注意事项
- 不要尝试在GLOP求解器中直接使用
abs()、平方等非线性操作,GLOP仅支持线性目标和约束 - 权重设置时不要差出几个数量级,避免出现数值稳定性问题,导致求解器返回精度不足的结果
- 分层求解时要确保每层的最优值保留足够的浮点精度,避免约束中因为精度问题出现无可行解的情况
内容的提问来源于stack exchange,提问作者Mert Akozcan
相关产品推荐
相关产品推荐

