前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >Python 非线性规划 scipy.optimize.minimize

Python 非线性规划 scipy.optimize.minimize

作者头像
为为为什么
发布2023-03-19 09:54:49
4.6K0
发布2023-03-19 09:54:49
举报
文章被收录于专栏:又见苍岚

在 python 里用非线性规划求极值,最常用的就是 scipy.optimize.minimize(),本文记录相关内容。

简介

scipy.optimize.minimize() 是 Python 计算库 Scipy 的一个功能,用于求解函数在某一初始值附近的极值,获取 一个或多个变量的标量函数的最小化结果 ( Minimization of scalar function of one or more variables. )。

注意:**这个函数常用于非线性规划的极值求解,只给出一个极值,并且不保证全局最优

函数定义

函数格式
代码语言:javascript
复制
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

要最小化的目标函数。fun(x, *args) -> float ​其中 $x$ 是一个带有形状($n$)的一维数组,$args$ 是完全指定函数所需的固定参数的元组。

x0

ndarray, shape (n,)

初始猜测: 大小为($n$)的实元素的数组,其中 $n$ 是变量的数目。

args

tuple, optional

额外的参数传递给目标函数及其导数(fun、 jac 和 hess 函数)。

method

str or callable, optional

求解器的类型,如果没有给出,则根据问题是否有约束或边界,选择 BFGS、 L-BFGS-B、 SLSQP 中的一个。

jac

{callable, ‘2-point’, ‘3-point’, ‘cs’, bool}, optional

梯度向量的计算方法。只适用于 CG,BFGS,Newton-CG,L-BFGS-B,TNC,SLSQP,dogleg,trust-ncg,trust-krylov,trust-fine 和 trust-Constr。如果它是可调用的,那么它应该是一个返回梯度向量的函数

hess

{callable, ‘2-point’, ‘3-point’, ‘cs’, HessianUpdateStrategy}, optional

计算 Hessian 矩阵的一种方法。只适用于 Newton-CG,dogleg,trust-ncg,trust-krylov,trust-fine 和 trust-constr. 。如果它是可调用的,它应该返回黑森矩阵

hessp

callable, optional

目标函数的 Hessian 乘以任意向量 p。只适用于 Newton-CG,trust-ncg,trust-krylov,trust-Constr。只需要一个 Hessp 或者 Hess 就够了。如果提供 hess,那么 hessp 将被忽略。Hessp 必须计算 Hessian 乘以任意向量。

bounds

sequence or Bounds, optional

Nelder-Mead,L-BFGS-B,TNC,SLSQP,Powell 和 trust-conr 方法的变量界。

constraints

{Constraint, dict} or List of {Constraint, dict}, optional

约束条件。仅适用于 COBYLA、 SLSQP 和 trust-Constr。

tol

float, optional

终止公差。 指定 tol 后,所选的最小化算法会将一些相关的特定于求解器的公差设置为 tol。 要进行详细控制,请使用特定于求解器的选项。

options

dict, optional

求解器选项字典。除 TNC 外的所有方法都接受以下通用选项:maxiter **int:**要执行的最大迭代次数。 根据方法,每次迭代可能使用多个函数评估。disp bool: 设置为 True 可打印消息。

callback

callable, optional

在每次迭代之后调用。对于“ trust-conr”,它是一个带有签名的可调用函数

res

Optimize Result

优化结果表示为 OptimizeResult 对象。 重要的属性有:x 解决方案数组success 一个布尔标志,指示优化器是否成功退出,以及描述终止原因的消息。 有关其他属性的说明,请参阅 OptimizeResult。

method 支持的算法

求解器

中文名

jac要求

hess要求

边界约束

条件约束

求解规模

Nelder-Mead

单纯形法

可选

Powell

鲍威尔法

可选

CG

共轭梯度法

可选

中小

BFGS

拟牛顿法

可选

中大

L-BFGS-B

限制内存BFGS法

可选

可选

中大

TNC

截断牛顿法

可选

可选

中大

COBYLA

线性近似法

可选

中大

SLSQP

序列最小二乘法

可选

可选

可选

中大

trust-constr

信赖域算法

可选

可选

可选

中大

Newton-CG

牛顿共轭梯度法

必须

可选

dogleg

信赖域狗腿法

必须

可选

中大

trust-ncg

牛顿共轭梯度信赖域法

必须

可选

trust-exact

高精度信赖域法

必须

可选

trust-krylov

子空间迭代信赖域法

必须

可选

注: jac可选,代表jac有五种选项{callable, 2-point, 3-point, cs, bool},可任选其一。默认为None,即采用有限差分近似计算;2/3-point 或者 cs 采用2点、3点、中心差分近似计算;若为True,则目标函数需返回目标函数值和jac向量;若为callable,则提供jac计算函数。 hess 也有五种选项{callable, 2-point, 3-point, cs, HessianUpdateStrategy},但要注意,只有jac提供计算函数,hess才可以使用差分近似,我想这也是避免因差分二次近似导致数值耗散的缘故。

constraints
  • COBYLASLSQP 的约束定义为字典列表:

参数

类型

含义

type

str

eq 表示等式约束,ineq 表示不等式约束(函数结果非负)。

fun

callable

定义约束的函数。

jac

callable, optional

fun 的 Jacobian 矩阵(对于 SLSQP)

args

sequence, optional

要传递给函数和 Jacobian 的额外参数。

COBYLA 只支持不等式约束。

使用示例

例一
  • 计算 1/x+x 的最小值
代码语言:javascript
复制
# coding=utf-8
from scipy.optimize import minimize
import numpy as np
 
#demo 1
#计算 1/x+x 的最小值
 def fun(args):
     a=args
     v=lambda x:a/x[0] +x[0]
     return v
 
 if __name__ == "__main__":
     args = (1)  #a
     x0 = np.asarray((2))  # 初始猜测值
     res = minimize(fun(args), x0, method='SLSQP')
     print(res.fun)
     print(res.success)
     print(res.x)

输出:

代码语言:javascript
复制
2.0000000815356342
True
[1.00028559]

事实上 1/x+x 是没有最小值的,这里能求解是因为在正数范围内 x=1 时取到极小值,负数范围内没有最小值,因此如果初始值选择负数则无法找到极小值:

代码语言:javascript
复制
# x0 = np.asarray((-2))  # 初始猜测值

-->
-2980232238769551.0
False
[-2.98023224e+15]
例二
  • 计算 (2+x_1)/(1+x_2) - 3x_1+4x_3 的最小值 x_1,x_2,x_3 的范围都在 0.1到0.9 之间

带约束的优化问题需要用到约束条件

代码语言:javascript
复制
# coding=utf-8
from scipy.optimize import minimize
import numpy as np
 
# demo 2
#计算  (2+x1)/(1+x2) - 3*x1+4*x3 的最小值  x1,x2,x3的范围都在0.1到0.9 之间
def fun(args):
    a,b,c,d=args
    v=lambda x: (a+x[0])/(b+x[1]) -c*x[0]+d*x[2]
    return v
def con(args):
    # 约束条件 分为eq 和ineq
    #eq表示 函数结果等于0 ; ineq 表示 表达式大于等于0  
    x1min, x1max, x2min, x2max,x3min,x3max = args
    cons = ({'type': 'ineq', 'fun': lambda x: x[0] - x1min},\
              {'type': 'ineq', 'fun': lambda x: -x[0] + x1max},\
             {'type': 'ineq', 'fun': lambda x: x[1] - x2min},\
                {'type': 'ineq', 'fun': lambda x: -x[1] + x2max},\
            {'type': 'ineq', 'fun': lambda x: x[2] - x3min},\
             {'type': 'ineq', 'fun': lambda x: -x[2] + x3max})
    return cons
 
if __name__ == "__main__":
    #定义常量值
    args = (2,1,3,4)  #a,b,c,d
    #设置参数范围/约束条件
    args1 = (0.1,0.9,0.1, 0.9,0.1,0.9)  #x1min, x1max, x2min, x2max
    cons = con(args1)
    #设置初始猜测值  
    x0 = np.asarray((0.5,0.5,0.5))
    
    res = minimize(fun(args), x0, method='SLSQP',constraints=cons)
    print(res.fun)
    print(res.success)
    print(res.x)

输出

代码语言:javascript
复制
-0.773684210526435
True
[0.9 0.9 0.1]

例三
  • 最小化函数: \log _{2}\left(1+\frac{x[0] 2}{3}\right)+\log _{2}\left(1+\frac{x[1] 3}{4}\right)
  • 约束条件: \log 2\left(1+\frac{x[0] 2}{5}\right) \geq 5 , \log 2\left(1+\frac{x[1] 6}{4}\right) \geq 5
代码语言:javascript
复制
# coding=utf-8
from scipy.optimize import minimize
from scipy.optimize import NonlinearConstraint
import numpy as np


# 目标函数
def fun(a,b,c,d):
    def v(x):
        return np.log2(1+x[0]*a/b)+np.log2(1+x[1]*c/d)
    return v
#限制条件函数
def con(a,b,i):
    def v(x):
        return np.log2(1 + x[i] * a / b)-5
    return v



if __name__ == "__main__":
    # 定义常量值
    args = [2, 1, 3, 4]  # a,b,c,d
    args1 = [2, 5, 6, 4] 
    # 设置初始猜测值
    x0 = np.asarray((0.5, 0.5))
    #设置限制条件
    '''Equality constraint means that the constraint function result is
     to be zero whereas inequality means that it is to be non-negative'''
    cons = ({'type': 'ineq', 'fun': con(args1[0],args1[1],0)},
            {'type': 'ineq', 'fun': con(args1[2],args1[3],1)},
            )

    res = minimize(fun(args[0],args[1],args[2],args[3]), x0, constraints=cons)
    print(res.fun)
    print(res.success)
    print(res.x)

输出:

代码语言:javascript
复制
11.329796332293162
True
[77.5        20.66666658]

例四
  • 最小化 8xyz
  • 约束条件 : x ^2+ y ^2+z ^2=1x,y,z>0
代码语言:javascript
复制
from scipy.optimize import minimize
import numpy as np
e = 1e-10 # 非常接近0的值
fun = lambda x : 8 * (x[0] * x[1] * x[2]) # f(x,y,z) =8 *x*y*z
cons = ({'type': 'eq', 'fun': lambda x: x[0]**2+ x[1]**2+ x[2]**2 - 1}, # x^2 + y^2 + z^2=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)

输出:

代码语言:javascript
复制
最大值: 1.5396007243645415
最优解: [0.57735022 0.57735022 0.57735038]
迭代终止是否成功: True
迭代终止原因: Optimization terminated successfully

参考资料

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2023年3月16日,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 简介
  • 函数定义
    • 函数格式
      • 参数含义
        • method 支持的算法
        • constraints
    • 使用示例
      • 例一
        • 例二
          • 例三
            • 例四
            • 参考资料
            领券
            问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档