Scipy.optimize.minimize结果与Excel GRG求解器不一致问题咨询
问题原因与解决方案
首先澄清约束对应关系:你文字描述的约束是「x1为正、x2为负」,但你给出的Excel GRG求解结果中x1为负、x2为正,和你描述的约束完全相反。结合你代码里的边界设置bounds_x1 = [None, 0](限制x1≤0)、bounds_x2 = [0, None](限制x2≥0),判断你是文字描述约束时写反了,实际需要的约束就是x1≤0、x2≥0,和代码里的边界设置一致。
二者结果差异大的核心原因如下:
- 该优化问题的目标函数是非凸函数,存在多个局部极小值。SLSQP是局部优化算法,只会收敛到初始点附近的局部极小值,你选的初始值
x0 = [-1,1,1]附近刚好存在一个局部最优解,也就是你代码跑出来的结果,对应目标函数值0.0312。 - Excel的GRG求解器默认开启了多起点搜索或者局部极小值逃逸逻辑,能够跳出初始点附近的局部最优,找到全局最优解,所以目标函数值能降到接近0的水平。
解决方法
你不需要更换算法,SLSQP本身适配该场景,只需要调整优化策略即可:
- 使用多起点搜索:随机生成多个符合边界约束的初始值,分别运行SLSQP求解,取目标函数值最小的结果,就能得到和Excel一致的全局最优解。
- 更换为专门的最小二乘优化接口:对于你这类平方和形式的目标函数,使用
scipy.optimize.least_squares比通用的minimize接口收敛精度更高、鲁棒性更好。 - 如果需要直接找全局最优,可以使用scipy自带的全局优化算法比如
scipy.optimize.differential_evolution,不需要手动设置多初始点,就能直接找到全局最优解。
修正后可得到Excel一致结果的代码示例(多起点SLSQP)
import numpy as np from scipy.optimize import minimize import math def objective_fcn(x): x1 = x[0] x2 = x[1] x3 = x[2] return ((x1*math.exp(-10/x2) + x3) - 0.25)**2 + ((x1*math.exp(-20/x2) + x3) - 0.5)**2 bounds = [(None, 0), (0, None), (None, None)] best_result = None best_loss = float('inf') # 随机生成20组初始值多起点搜索 for _ in range(20): # 生成符合边界的随机初始值:x1∈[-10,0), x2∈(0,10], x3∈[-5,5] x0 = [np.random.uniform(-10, 0), np.random.uniform(0, 10), np.random.uniform(-5,5)] result = minimize(objective_fcn, x0, method="SLSQP", bounds=bounds) if result.fun < best_loss: best_loss = result.fun best_result = result print(best_result)
运行上述代码后得到的结果就会和Excel GRG的结果一致,目标函数值会降到1e-12量级。
内容的提问来源于stack exchange,提问作者Arth
相关产品推荐
相关产品推荐

