Python——使用scipy求解带约束的最优化问题

系统 2751 0

我们要求解的最优化问题的形式如下:
m i n   f ( x ) s . t . g i ( x ) > 0 , i = 1 , . . . , m h j ( 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} m i n   f ( x ) s . t . g i ( x ) h j ( x ) > 0 , i = 1 , . . . , m = 0 , j = 1 , . . . , n
其中 x x x 是一个向量, g i ( x ) g_i(x) g i ( x ) 是非等式约束, h j ( x ) h_j(x) h j ( x ) 是等式约束。

示例

x , y , z > 0 , x y z = 1 x,y,z>0,xyz=1 x , y , z > 0 x y z = 1 的条件下,求解 ( x − 2 / 3 ) / ( x + y + z − 2 ) (x-2/3)/(x+y+z-2) ( 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 > 0 x>0 x > 0 的条件可以写为 x − e ≥ 0 x-e\ge0 x e 0 ,其中 e e e 是一个尽可能小的值。
  • 其实,在本题中,可以直接让 x > 0 x\gt0 x > 0 ,因为有约束 x y z = 1 xyz=1 x y z = 1 ,所以不必担心最后解为 x = 0 x=0 x = 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-ncg hess hessp 只需要给出一个即可。如果提供了 hess ,则 hessp 会被忽略。如果两者都没有提供,则二阶导矩阵会被自动计算。
  • bounds : sequence, optional
    bounds 是参数的界限,只适用于 L-BFGS-B , TNC SLSQP ,每个参数对应一个 (min, max) ,表示参数的上下限。如果只有一边界限,则另一边置为 None 。当约束是针对 x x x 中的单个元素的上下限时,就可以用 bounds 参数来设置。
  • constraints : dict or sequence of dict, optional
    约束定义,只适用于 COBYLA SLSQP 。每个约束定义为一个词典,键值对包括:
    • fun : callable。定义了约束函数。
    • type : str。约束类型: eq ’ 表示等式约束( fun 等于0), ineq 表示不等式约束( fun 大于等于0)。 COBYLA 只支持不等式约束。
    • jac : callable, optional。 fun 的梯度矩阵,只适用于 SLSQP
    • args : sequence, optional。传递给 fun jac 的额外参数。
  • tol : float, optional
    迭代终止的允许误差。
  • options : dict, optional
    求解器的选项字典。所有的算法都接受以下的通用选项:
    • maxiter : int。迭代的最大次数。
    • disp : bool。如果是 True 则打印出收敛信息。
  • callback : callable, optional
    每次迭代之后调用的函数,参数为 xk ,表示当前的参数向量。

返回值

res:优化结果。

优化结果是 OptimizeResult 对象,重要属性如下:

  • fun 是最优值。
  • x 是最优解。
  • success 表示求解器是否成功退出。
  • message 描述了求解器退出的原因。

更多文章、技术交流、商务合作、联系博主

微信扫码或搜索:z360901061

微信扫一扫加我为好友

QQ号联系: 360901061

您的支持是博主写作最大的动力,如果您喜欢我的文章,感觉我的文章对您有帮助,请用微信扫描下面二维码支持博主2元、5元、10元、20元等您想捐的金额吧,狠狠点击下面给点支持吧,站长非常感激您!手机微信长按不能支付解决办法:请将微信支付二维码保存到相册,切换到微信,然后点击微信右上角扫一扫功能,选择支付二维码完成支付。

【本文对您有帮助就好】

您的支持是博主写作最大的动力,如果您喜欢我的文章,感觉我的文章对您有帮助,请用微信扫描上面二维码支持博主2元、5元、10元、自定义金额等您想捐的金额吧,站长会非常 感谢您的哦!!!

发表我的评论
最新评论 总共0条评论