带非负约束的线性优化问题求解异常:Python实现疑问
你的线性规划代码问题分析与修复方案
嘿,我帮你找到了代码出问题的关键原因,还有更贴合需求的解决办法:
1. 最核心的错误:约束类型设置错误
你要的约束是严格等式 x + 2y + 4z = 5,但代码里把它定义成了不等式约束(type='ineq'),这会让优化器认为只要满足x + 2y + 4z ≥ 5就符合要求,完全偏离了你的原始需求!
正确的做法是把约束类型改成'eq',并且去掉约束函数里多余的sign参数——等式约束只要求函数返回值等于0就行。
2. 修正后的SLSQP版本代码
我调整了约束和目标函数的写法,现在能输出你期望的结果:
import numpy as np from scipy.optimize import minimize def objective(x): # 因为minimize默认求最小值,所以返回目标函数的相反数来实现最大化 return -(2*x[0] + 4*x[1] + 10*x[2]) def constraint_eq(x): # 等式约束:返回值必须等于0 return x[0] + 2*x[1] + 4*x[2] - 5 # 初始猜测值 x0 = [0, 0, 0] # 变量非负约束 bnds = [(0, None), (0, None), (0, None)] # 定义等式约束 cons = [{'type': 'eq', 'fun': constraint_eq}] # 求解 sol = minimize(objective, x0, method='SLSQP', bounds=bnds, constraints=cons) # 打印结果(取整是因为优化器可能返回极小的小数) print("最优解:") print(f"x = {round(sol.x[0])}, y = {round(sol.x[1])}, z = {round(sol.x[2])}") print(f"最大化的f值:{round(-sol.fun)}")
运行这段代码就能得到x=1, y=0, z=1,f=12的结果。
3. 更高效的选择:用线性规划专用工具
你的问题是标准的线性规划(目标函数和约束都是线性的),用scipy.optimize.linprog会比通用的SLSQP更合适,不需要手动转最大化逻辑:
from scipy.optimize import linprog # linprog默认求最小值,所以传入目标函数的相反数系数 c = [-2, -4, -10] # 等式约束的矩阵和右侧值 A_eq = [[1, 2, 4]] b_eq = [5] # 变量非负约束 bounds = [(0, None), (0, None), (0, None)] # 求解(推荐用highs方法,效率更高) res = linprog(c, A_eq=A_eq, b_eq=b_eq, bounds=bounds, method='highs') print("最优解:") print(f"x = {round(res.x[0])}, y = {round(res.x[1])}, z = {round(res.x[2])}") print(f"最大化的f值:{round(-res.fun)}")
为什么理想解是x=1,y=0,z=1?
线性规划的最优解一定在可行域的顶点上。咱们算下每个变量的"性价比":
- z:每消耗4个B值,带来10的f,性价比2.5
- x:每消耗1个B值,带来2的f,性价比2
- y:每消耗2个B值,带来4的f,性价比2
所以优先把B值分配给z,最多能分配4(对应z=1),剩下的1个B值分配给x或y都能得到2的f,所以x=1,y=0,z=1和x=0,y=0.5,z=1都是最优解,f都是12——你想要的整数解只是其中一个顶点罢了。
内容的提问来源于stack exchange,提问作者Arindam
相关产品推荐
相关产品推荐

