【问题标题】:Ineq and eq constraints with scipy.optimize.minimize()Ineq 和 eq 约束与 scipy.optimize.minimize()
【发布时间】:2017-01-23 00:45:16
【问题描述】:

我正在尝试了解 scipy.optimize.minimize 中约束的行为:

首先,我创建了 4 个资产和 100 个回报场景。平均回报资金是为了最好的情况D > B > A > C

#seed first 
np.random.seed(1)

df_returns = pd.DataFrame(np.random.rand(100,4) - 0.25, columns =list('ABCD'))
df_returns.head()

    A           B           C           D
0   0.167022    0.470324    -0.249886   0.052333
1   -0.103244   -0.157661   -0.063740   0.095561
2   0.146767    0.288817    0.169195    0.435220
3   -0.045548   0.628117    -0.222612   0.420468
4   0.167305    0.308690    -0.109613   -0.051899

还有一组权重

weights = pd.Series([0.25, 0.25, 0.25, 0.25], index=list('ABCD'))

    0
A   0.25
B   0.25
C   0.25
D   0.25

我们创建一个目标函数:

def returns_objective_function(weights, df_returns):
    result = -1. * (df_returns * weights).mean().sum()
    return result

以及约束和界限

cons = ({'type': 'eq', 'fun': lambda weights: np.sum(weights) -1  })
bnds = ((0.01, .8), (0.01, .8), (0.01, .8), (0.01, .75))

让我们优化

optimize.minimize(returns_objective_function, weights, (df_returns),
                              bounds=bnds, constraints=cons, method= 'SLSQP')

And we get success.
  status: 0
 success: True
    njev: 8
    nfev: 48
     fun: -0.2885398923185326
       x: array([ 0.01,  0.23,  0.01,  0.75])
 message: 'Optimization terminated successfully.'
     jac: array([-0.24384782, -0.2789166 , -0.21977262, -0.29300382,  0.        ])
     nit: 8

现在我想添加以基本不等式开头的约束:

scipy.optimize.minimize 文档状态

等式约束意味着约束函数结果为零,而不等式意味着它是非负的。

cons = ( 
        {'type': 'eq', 'fun': lambda weights: np.sum(weights) -1  }
        ,{'type': 'ineq', 'fun': lambda weights: np.sum(weights) + x}
)

根据 x,我得到了意想不到的行为。

x = -100

基于边界,权重最大可以是 3.15,当然,必须通过第一个等式约束 np.sum(weights) - 1 求和为 1,但因此,np.sum(weights) + x 将始终为负数。我相信应该找不到解决方案,但 scipy.optimize.minimize 返回成功。

【问题讨论】:

    标签: python scipy mathematical-optimization


    【解决方案1】:

    使用更简单的模型我得到相同的行为:

    x = [1,2] 
    optimize.minimize(
        lambda x: x[0]**2+x[1]**2, 
        x, 
        constraints = (
            {'type':'eq','fun': lambda x: x[0]+x[1]-1},
            {'type':'ineq','fun': lambda x: x[0]-2}
                      ),
        bounds = ((0,None),(0,None)),
        method='SLSQP')
    

    结果:

       nfev: 8
        fun: 2.77777777777712
        nit: 6
        jac: array([  3.33333334e+00,   2.98023224e-08,   0.00000000e+00])
          x: array([  1.66666667e+00,   1.39888101e-14])
    success: True
    message: 'Optimization terminated successfully.'
     status: 0
       njev: 2
    

    应该有一些标志表明这是一个不可行的解决方案。

    SLSQP 也可从 R 获得:

    > slsqp(c(1,2),
    +       function(x) {x[1]^2+x[2]^2},
    +       heq=function(x){x[1]+x[2]-1},
    +       hin=function(x){x[1]-2},
    +       lower=c(0,0))
    $par
    [1] 1.666667e+00 4.773719e-11
    
    $value
    [1] 2.777778
    
    $iter
    [1] 105
    
    $convergence
    [1] -4
    
    $message
    [1] "NLOPT_ROUNDOFF_LIMITED: Roundoff errors led to a breakdown of the optimization algorithm. In this case, the returned minimum may still be useful. (e.g. this error occurs in NEWUOA if one tries to achieve a tolerance too close to machine precision.)"
    

    至少我们在这里看到了一些警告信号。

    【讨论】:

    • 这个小例子已添加到 SciPy 的错误跟踪器中:issue 5743
    • 感谢 Erwin - 我很想看到它的进展,并将继续跟进。
    猜你喜欢
    • 2014-08-15
    • 2015-01-02
    • 2021-11-13
    • 2019-04-10
    • 2015-03-07
    • 2016-02-04
    • 2016-06-08
    • 2022-01-15
    • 1970-01-01
    相关资源
    最近更新 更多