Python——使用scipy求解帶約束的最優化問題

我們要求解的最優化問題的形式如下:
min f(x)s.t.gi(x)>0,i=1,...,mhj(x)=0,j=1,...,n \begin{aligned} min \ f(x) \\ s.t.\quad g_i(x)& \gt 0, i = 1,...,m\\ \quad h_j(x)& = 0, j = 1,...,n \end{aligned}
其中 xx 是一個向量,gi(x)g_i(x) 是非等式約束,hj(x)h_j(x) 是等式約束。

示例

x,y,z>0xyz=1x,y,z>0,xyz=1 的條件下,求解 (x2/3)/(x+y+z2)(x-2/3)/(x+y+z-2) 的最小值。

from scipy.optimize import minimize
import numpy as np
e = 1e-10 # 非常接近0的值
fun = lambda x : (x[0] - 0.667) / (x[0] + x[1] + x[2] - 2) # 約束函數
cons = ({'type': 'eq', 'fun': lambda x: x[0] * x[1] * x[2] - 1}, # xyz=1
        {'type': 'ineq', 'fun': lambda x: x[0] - e}, # x>=e,即 x > 0
        {'type': 'ineq', 'fun': lambda x: x[1] - e},
        {'type': 'ineq', 'fun': lambda x: x[2] - e}
       )
x0 = np.array((1.0, 1.0, 1.0)) # 設置初始值
res = minimize(fun, x0, method='SLSQP', constraints=cons)
print('最小值:',res.fun)
print('最優解:',res.x)
print('迭代終止是否成功:', res.success)
print('迭代終止原因:', res.message)

輸出:

最小值: -0.18814357989751096
最優解: [0.29250894 1.84897232 1.84897233]
迭代終止是否成功: True
迭代終止原因: Optimization terminated successfully.

備註:

  • 若是求一個函數的最大值,則改爲求其相反數的最小值。
  • 因爲ineq的約束是表示非負,所以x>0x>0 的條件可以寫爲 xe0x-e\ge0,其中ee是一個儘可能小的值。
  • 其實,在本題中,可以直接讓 x>0x\gt0,因爲有約束 xyz=1xyz=1,所以不必擔心最後解爲 x=0x=0

函數介紹

scipy.optimize.minimize(fun, x0, args=(), method=None, jac=None, hess=None, hessp=None, bounds=None, constraints=(), tol=None, callback=None, options=None)

求取一個函數的最小值。函數的參數可以是多個,但函數值只能是標量。

參數

  • fun : callable
    目標函數
  • x0 : ndarry
    初始值
  • args : tuple, optional
    額外的參數,傳給目標函數和它的導數。
  • method : str or callable, optional
    求解問題的算法名,下面選其一:
    Nelder-Mead, Powell, CG, BFGS, Newton-CG, L-BFGS-B, TNC, COBYLA, SLSQP, dogleg, trust-ncg
    默認是 BFGS, L-BFGS-B, SLSQP 之一,根據問題是否含有約束和界限自動選擇。
  • jac : bool or callable, optional
    目標函數的梯度矩陣。只適用於 CG, BFGS, Newton-CG, L-BFGS-B, TNC, SLSQP, dogleg, trust-ncg。如果jac是一個 Boolean 且爲 True,則 fun 被認爲是梯度與目標函數一起返回。如果是False,則梯度會被自動地計算。jac也可以是一個函數,返回目標函數的梯度,且參數必須與fun相同。
  • hess, hessp : callable, optional
    目標函數的二階導矩陣,或者二階導矩陣乘以一個隨機向量p。只適用於Newton-CG,dogleg, trust-ncghesshessp只需要給出一個即可。如果提供了hess,則hessp會被忽略。如果兩者都沒有提供,則二階導矩陣會被自動計算。
  • bounds : sequence, optional
    bounds 是參數的界限,只適用於L-BFGS-B, TNCSLSQP,每個參數對應一個 (min, max),表示參數的上下限。如果只有一邊界限,則另一邊置爲None。當約束是針對 xx 中的單個元素的上下限時,就可以用 bounds 參數來設置。
  • constraints : dict or sequence of dict, optional
    約束定義,只適用於 COBYLASLSQP。每個約束定義爲一個詞典,鍵值對包括:
    • fun : callable。定義了約束函數。
    • type : str。約束類型: eq’ 表示等式約束(fun等於0),ineq 表示不等式約束(fun大於等於0)。COBYLA只支持不等式約束。
    • jac : callable, optional。fun 的梯度矩陣,只適用於SLSQP
    • args : sequence, optional。傳遞給funjac的額外參數。
  • tol : float, optional
    迭代終止的允許誤差。
  • options : dict, optional
    求解器的選項字典。所有的算法都接受以下的通用選項:
    • maxiter : int。迭代的最大次數。
    • disp : bool。如果是True則打印出收斂信息。
  • callback : callable, optional
    每次迭代之後調用的函數,參數爲xk,表示當前的參數向量。

返回值

res:優化結果。

優化結果是OptimizeResult對象,重要屬性如下:

  • fun 是最優值。
  • x 是最優解。
  • success 表示求解器是否成功退出。
  • message 描述了求解器退出的原因。
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章