SciPy Optimize minimize函数未迭代,x值无变化问题求助
问题分析与修复
你的优化结果未更新,是因为SciPy SLSQP默认的数值梯度计算精度不足,导致算法误判初始点为最优解。先拆解你的目标函数和约束,明确最优方向:
目标函数简化与最优方向
先看成本项的计算:
x3*147187.0 + 20326.0 + 147187.0*(1-x3)
展开后x3的项会完全抵消,结果固定为147187+20326=167513。因此目标函数可简化为:
obj = -[ (128375 + 147187x3)*149.12*(1+x1) - C*(1+x2) ]
其中C是常数。由此可知:
x1越大,目标函数越小(符合最小化目标),因此最优x1应取边界上限0.75x2越小,目标函数越小,最优x2应取边界下限-1.0x3越大,目标函数越小,结合约束(1-x3)*147187 ≥128375,最优x3约为0.1278
修复方案1:提供精确梯度(推荐)
SLSQP默认用数值梯度,当函数值变化幅度大时,数值梯度容易有误差。显式定义目标函数的梯度和约束的雅可比矩阵,让算法获得精确的方向信息:
修改后的代码:
import numpy as np from scipy.optimize import minimize def objective_fcn(x): x1 = x[0] x2 = x[1] x3 = x[2] profit = (128375.0 + x3*147187.0)*149.12*(1+x1) - (44.92*(1+x2))*(167513.0) # 直接用简化后的常数项 return profit * -1 def objective_gradient(x): x1 = x[0] x3 = x[2] d_dx1 = - (128375.0 + x3*147187.0)*149.12 d_dx2 = 44.92 * 167513.0 d_dx3 = -147187.0 * 149.12 * (1 + x1) return np.array([d_dx1, d_dx2, d_dx3]) def ineq_const(x): x3 = x[2] return (1-x3)*147187.0 - 128375.0 def ineq_const_jac(x): # 约束对x1、x2偏导为0,对x3偏导为-147187 return np.array([0.0, 0.0, -147187.0]) x0 = [0.1,0.0,0.1] bounds_x1 = (-1.0, 0.75) bounds_x2 = (-1.0, 1.0) bounds_x3 = (-1.0, 1.0) bounds = [bounds_x1, bounds_x2, bounds_x3] const1 = {'type': 'ineq', 'fun': ineq_const, 'jac': ineq_const_jac} consts = [const1] # 传入精确梯度 result = minimize(objective_fcn, x0, method='SLSQP', bounds=bounds, constraints=consts, jac=objective_gradient) print("The full result is: ") print(result)
修复方案2:调整优化参数(备选)
如果不想写梯度,可以调小收敛阈值或数值梯度步长,让算法更敏感:
# 调小收敛阈值ftol,同时缩小数值梯度步长eps result = minimize(objective_fcn, x0, method='SLSQP', bounds=bounds, constraints=consts, options={'ftol': 1e-9, 'eps': 1e-8})
修复后结果
运行修改后的代码,会得到符合预期的最优解:
x1接近0.75,x2接近-1.0,x3接近0.1278
内容的提问来源于stack exchange,提问作者ConfusedWithPython
相关产品推荐
相关产品推荐

