将边界转为不等式约束后scipy linprog未得到正确结果
线性规划求解结果不符问题排查
我有一个通用形式的线性规划问题:
近期我在调试scipy库的linprog线性规划求解接口,官方文档中提供了如下示例:
官方给出的示例代码如下:
c = [-1, 4] G = [[-3, 1], [1, 2]] h = [6, 4] x0_bounds = (None, None) x1_bounds = (-3, None) from scipy.optimize import linprog res = linprog(c, A_ub=A, b_ub=b, bounds=[x0_bounds, x1_bounds])
linprog无法直接处理“大于等于”类型的不等式约束,求解时需要转换为“小于等于”形式的约束。上述官方示例是通过bounds参数显式传入变量边界(即$x_1 \geq -3$这一约束)的。
我尝试换一种实现方式:不使用bounds参数,直接将变量边界约束合并到通用不等式矩阵G中传入求解,编写的自定义求解函数如下:
import numpy as np import matplotlib.pyplot as plt from scipy.optimize import linprog def LP(c,d,G,h,A,b, method = 'revised simplex'): res = linprog(c, A_ub = G, b_ub = h, A_eq = A, b_eq = b, method = method) if res.success == True: print('The optimization was successful in', res.nit, 'iterations') print('The optimal solution is:', res.x) print('The objective function is equal to:', res.fun+d) return res.x if res.success == False: print('The optimization was not successful') if res.status == 1: print('Iteration limit reached') if res.status == 2: print('Problem appears to be infeasible') if res.status == 3: print('Problem appears to be unbounded') if res.status == 4: print('Numerical difficulties encountered')
设置的求解参数如下:
c = [-1,4] d = 0 G = [[-3,1],[1,2],[0,-1]] h = [6,4,3] A = None b = None
运行上述代码后,得到的最优解为x = [4., 0.],对应目标函数值obj=-4,但官方文档标注的该示例最优解为[10., -3.],对应目标函数值obj=-22。验证可知两个解都满足我写入矩阵的约束,显然官方给出的解更优。为什么将边界约束合并到不等式矩阵后,无法得到和文档一致的正确结果?
问题根因
核心问题是对linprog接口的默认参数逻辑不熟悉:
- 当不显式传入
bounds参数时,linprog默认给所有决策变量添加非负约束,即要求所有$x_i \geq 0$。 - 你虽然把$x_1 \geq -3$的约束正确转换为$-x_1 \leq 3$写入了不等式矩阵,但没有覆盖默认的变量边界规则,求解器实际执行时额外要求$x_1 \geq 0$,直接把$x_1=-3$所在的可行域区域排除了,最终只能得到$x_1=0$边界上的次优解
[4, 0]。
你写的约束转换本身没有数学错误,问题完全出在隐式生效的默认非负约束上。
修正方案
只需要在调用linprog时显式指定所有变量无边界限制,让所有约束完全由传入的A_ub/A_eq矩阵定义即可:
- 修改自定义的LP函数,增加bounds入参,或者在函数内部固定将bounds设为每个变量都是
(None, None),覆盖默认值; - 传入修改后的bounds参数后重新求解,就能得到和官方示例一致的最优解
[10., -3.],对应目标函数值-22。
内容的提问来源于stack exchange,提问作者Robin Emanuelsson
相关产品推荐
相关产品推荐

