scipy.optimize.minimize 结果在 Python 2.x-3.x 之间不同
scipy.optimize.minimize results differ between Python 2.x-3.x
基本上,我在 scipy.optimize.minimize 中使用 SLSQP 求解器处理非线性约束问题。不幸的是,问题(相同的文件,相同的代码)在不同的计算机(一台 Windows,一台 Linux)上返回不同的结果。 scipy 版本相同 (1.2.1)。这是我的代码:
import numpy as np
from scipy.optimize import minimize
class OptimalAcc():
def __init__(self, v0, tg, tr, D0, sgr, l, t0, a0, b0,
rho_t=0.5, rho_u=0.5, vM=15, vm=2.78, aM=2.5, am=-2.9):
# Problem constants
self.v0 = v0
self.D0 = D0
self.sgr = sgr
self.l = l
self.T = tg + tr
self.D = tg / self.T
self.t0 = t0
self.a0 = a0
self.b0 = b0
self.rho_t = rho_t
self.rho_u = rho_u
self.vM = vM
self.vm = vm
self.aM = aM
self.am = am
def cost_fn(self, x):
# Acceleration profile variables
t = x[:1]
a = x[1:2]
b = x[2:3]
# Objective function
f = self.rho_t*x[:1]+self.rho_u*(a**2*t**3/3 +
a*b*t**2 +
b**2*t)
return f
def solve(self):
# Inequality constraints
ineq = ({'type':'ineq',
'fun':lambda x: np.array([self.aM - x[2],
x[2]-self.am,
x[0],
self.vM - (self.v0 + x[2]*x[0] + 0.5*x[1]*x[0]**2),
self.v0 + x[2]*x[0] + 0.5*x[1]*x[0]**2 - self.vm,
np.sin(np.pi*self.D - np.pi/2)-
np.sin(2*np.pi*(x[0] -((self.D0*self.T)/abs(self.sgr-2)))/self.T + 3*np.pi/2 - np.pi*self.D)])})
# Equality constraints
eq = ({'type':'eq',
'fun':lambda x: np.array([x[1]*x[0] + x[2],
self.v0*x[0] + 0.5*x[2]*x[0]**2 + x[1]*x[0]**3/6 - self.l])})
# Starting points
x0 = np.array([self.t0, self.a0, self.b0])
# Solve optimization problem
res = minimize(self.cost_fn,
x0=x0,
constraints=[ineq,eq],
options={'disp': True})
return res
if __name__== "__main__":
v0 = 1
tg = 20
tr = 20
D0 = 1
sgr = 1
l = 70
t0 = 10
a0 = -0.1
b0 = 1.5
# Create instance of optimization problem class
obj = OptimalAcc(v0, tg, tr, D0, sgr, l, t0, a0, b0)
# Solve problem and return optimal profile
u_t = obj.solve().x
print('x_1:',u_t[0])
print('x_2:',u_t[1])
print('x_3:',u_t[2])
Windows 机器产量:
Optimization terminated successfully. (Exit mode 0)
Current function value: 8.696191258640086
Iterations: 7
Function evaluations: 35
Gradient evaluations: 7
x_1: 13.508645429307041
x_2: -0.06874922875473621
x_3: 0.9287089606820067
我相信这些结果是局部最优的,我可以在 MATLAB 中使用 fmincon 验证相同的输出。
然而,Linux 机器产量:
Positive directional derivative for linesearch (Exit mode 8)
Current function value: 14.4116342889
Iterations: 17
Function evaluations: 147
Gradient evaluations: 13
x_1: 7.65875894797259
x_2: -0.241800477348664
x_3: 2.5000000000000053
很明显,优化器卡在了 Linux 计算机中。是什么原因造成的?我唯一的猜测是 numpy 中有一些精度会影响数字。
正如评论中所讨论的那样,这个问题很可能与 Windows 与 Linux 无关,但更多的是 Python 2 与 Python 3 一个.例如,术语
a**2*t**3/3
Python 2 和 3 可能看起来不同,因为可能只涉及整数(您的代码中有更多这样的示例)。
一个简单的解决方法可能是包括
from __future__ import division
在脚本的顶部,它会处理 Python 2 和 3 中除法执行方式的差异。
基本上,我在 scipy.optimize.minimize 中使用 SLSQP 求解器处理非线性约束问题。不幸的是,问题(相同的文件,相同的代码)在不同的计算机(一台 Windows,一台 Linux)上返回不同的结果。 scipy 版本相同 (1.2.1)。这是我的代码:
import numpy as np
from scipy.optimize import minimize
class OptimalAcc():
def __init__(self, v0, tg, tr, D0, sgr, l, t0, a0, b0,
rho_t=0.5, rho_u=0.5, vM=15, vm=2.78, aM=2.5, am=-2.9):
# Problem constants
self.v0 = v0
self.D0 = D0
self.sgr = sgr
self.l = l
self.T = tg + tr
self.D = tg / self.T
self.t0 = t0
self.a0 = a0
self.b0 = b0
self.rho_t = rho_t
self.rho_u = rho_u
self.vM = vM
self.vm = vm
self.aM = aM
self.am = am
def cost_fn(self, x):
# Acceleration profile variables
t = x[:1]
a = x[1:2]
b = x[2:3]
# Objective function
f = self.rho_t*x[:1]+self.rho_u*(a**2*t**3/3 +
a*b*t**2 +
b**2*t)
return f
def solve(self):
# Inequality constraints
ineq = ({'type':'ineq',
'fun':lambda x: np.array([self.aM - x[2],
x[2]-self.am,
x[0],
self.vM - (self.v0 + x[2]*x[0] + 0.5*x[1]*x[0]**2),
self.v0 + x[2]*x[0] + 0.5*x[1]*x[0]**2 - self.vm,
np.sin(np.pi*self.D - np.pi/2)-
np.sin(2*np.pi*(x[0] -((self.D0*self.T)/abs(self.sgr-2)))/self.T + 3*np.pi/2 - np.pi*self.D)])})
# Equality constraints
eq = ({'type':'eq',
'fun':lambda x: np.array([x[1]*x[0] + x[2],
self.v0*x[0] + 0.5*x[2]*x[0]**2 + x[1]*x[0]**3/6 - self.l])})
# Starting points
x0 = np.array([self.t0, self.a0, self.b0])
# Solve optimization problem
res = minimize(self.cost_fn,
x0=x0,
constraints=[ineq,eq],
options={'disp': True})
return res
if __name__== "__main__":
v0 = 1
tg = 20
tr = 20
D0 = 1
sgr = 1
l = 70
t0 = 10
a0 = -0.1
b0 = 1.5
# Create instance of optimization problem class
obj = OptimalAcc(v0, tg, tr, D0, sgr, l, t0, a0, b0)
# Solve problem and return optimal profile
u_t = obj.solve().x
print('x_1:',u_t[0])
print('x_2:',u_t[1])
print('x_3:',u_t[2])
Windows 机器产量:
Optimization terminated successfully. (Exit mode 0)
Current function value: 8.696191258640086
Iterations: 7
Function evaluations: 35
Gradient evaluations: 7
x_1: 13.508645429307041
x_2: -0.06874922875473621
x_3: 0.9287089606820067
我相信这些结果是局部最优的,我可以在 MATLAB 中使用 fmincon 验证相同的输出。
然而,Linux 机器产量:
Positive directional derivative for linesearch (Exit mode 8)
Current function value: 14.4116342889
Iterations: 17
Function evaluations: 147
Gradient evaluations: 13
x_1: 7.65875894797259
x_2: -0.241800477348664
x_3: 2.5000000000000053
很明显,优化器卡在了 Linux 计算机中。是什么原因造成的?我唯一的猜测是 numpy 中有一些精度会影响数字。
正如评论中所讨论的那样,这个问题很可能与 Windows 与 Linux 无关,但更多的是 Python 2 与 Python 3 一个.例如,术语
a**2*t**3/3
Python 2 和 3 可能看起来不同,因为可能只涉及整数(您的代码中有更多这样的示例)。
一个简单的解决方法可能是包括
from __future__ import division
在脚本的顶部,它会处理 Python 2 和 3 中除法执行方式的差异。