6. Scipy Tutorial-有约束优化
约束最优化问题(constrained optimization problem)是指具有约束条件的非线性规划问题。
若是极小化问题,其一般形式为: $$ \min\ F(x) $$ $$ \quad \quad \quad \quad \quad subject\ to: g_i(x) \ge 0(i = 1,2,\cdots,p) $$ $$ \quad \quad \quad \quad \quad \quad \qquad \quad \quad \qquad h_j(x) = 0 (i = q +1,p + 2,\cdots,q) $$ 其中:$g_i(x) \leq 0$为不等式约束,$h_j(x) = 0$为等式约束条件。
- 下面以$f(x) = 2xy + 2x - x^2 - 2y^2$这个$f(x)$函数为例,看在条件:
$$ x^3 - y = 0 $$ $$ y - 1 \ge 0 $$ 求最优值问题。
#coding:utf-8
import numpy as np
from scipy.optimize import minimize
def func(x, sign=1.0):
""" 定义目标函数F(x) """
return sign*(2*x[0]*x[1] + 2*x[0] - x[0]**2 - 2*x[1]**2)
def func_deriv(x, sign=1.0):
""" 梯度 jac"""
dfdx0 = sign*(-2*x[0] + 2*x[1] + 2)
dfdx1 = sign*(2*x[0] - 4*x[1])
return np.array([ dfdx0, dfdx1 ])
# 约束条件
cons = ({'type': 'eq',#等式约束条件
'fun' : lambda x: np.array([x[0]**3 - x[1]]),# 方程
'jac' : lambda x: np.array([3.0*(x[0]**2.0), -1.0])},# 导数
{'type': 'ineq',#不等式约束条件
'fun' : lambda x: np.array([x[1] - 1]),#方程
'jac' : lambda x: np.array([0.0, 1.0])})#导数
res = minimize(func, [-1.0,1.0], args=(-1.0,), jac=func_deriv,
method='SLSQP', options={'disp': True})
print(res.x)
res = minimize(func, [-1.0,1.0], args=(-1.0,), jac=func_deriv,
constraints=cons, method='SLSQP', options={'disp': True})
print(res.x)
程序执行结果:
Optimization terminated successfully. (Exit mode 0)
Current function value: -1.9999999999999996
Iterations: 4
Function evaluations: 5
Gradient evaluations: 4
[2. 1.]
Optimization terminated successfully. (Exit mode 0)
Current function value: -1.0000001831052137
Iterations: 9
Function evaluations: 14
Gradient evaluations: 9
[1.00000009 1. ]
- 下面以目标函数$f(x) = x_1^2 x_2$,在等式约束条件$h(x_1, x_2) = x_1^2 + x_2^2 - 1 = 0$的求最小值的最优解。 $$ min\quad f(x_1, x_2) = x_1^2 x_2 $$ $$ \quad \quad \qquad s.t.\quad h(x_1, x_2) = x_1^2 + x_2^2 - 1 = 0 $$
import numpy as np
from scipy.optimize import minimize
'''目标函数f(x)'''
def f(x):
return x[0]**2 * x[1]
'''梯度函数jac'''
def f_der(x):
der = [0, 0]
der[0] = 2 * x[0] * x[1]
der[1] = x[0] ** 2
return np.array(der)
'''等式约束条件h'''
def h(x):
return x[0] ** 2 + x[1] ** 2 - 1
res = minimize(f, [-1.0,1.0], jac=f_der, constraints={"fun": h, "type": "eq"}, method='SLSQP', options={'disp': True})
print res.x
程序执行结果:
Optimization terminated successfully. (Exit mode 0)
Current function value: 9.867387900889092e-15
Iterations: 7
Function evaluations: 10
Gradient evaluations: 7
[-9.93347264e-08 1.00000000e+00]
从程序的执行结果[-9.93347264e-08 1.00000000e+00]
可以近似认为$x_0 = 0, x_ 1 = 1$是目标函数$f(x)$的一个最优解。显然(0,1)满足$h(x_1, x_2)$函数。
- 下面以目标函数$f(x) = (x_1 - 2)^2 + (x_2 - 1)^2$,在等式约束条件$h(x_1, x_2) = x_1 + x_2 + 5 = 0$的求最小值的最优解。 $$ min\quad (x_1 - 2)^2 + (x_2 - 1)^2 $$ $$ \quad \quad \quad s.t.\ h(x_1, x_2) =x_1 + x_2 + 5 = 0 $$
import numpy as np
from scipy.optimize import minimize
'''目标函数f(x)'''
def f(x):
return (x[0]- 2)**2 + (x[1] - 1) ** 2
'''梯度函数jac'''
def f_der(x):
der = [0, 0]
der[0] = 2 * (x[0] - 2)
der[1] = 2 * (x[1] - 1)
return np.array(der)
'''等式约束'''
def h(x):
return x[0] + x[1] + 5
res = minimize(f, [-10.0,10.0], jac=f_der, constraints={"fun": h, "type": "eq"}, method='SLSQP', options={'disp': True})
print(res.x)
程序执行结果:
Optimization terminated successfully. (Exit mode 0)
Current function value: 32.00000013512923
Iterations: 4
Function evaluations: 6
Gradient evaluations: 4
[-1.99974007 -3.00025993]
结果里的[-1.99974007 -3.00025993]
可视为$x_1 = -2, x_2 = -3 $。