【问题标题】:Scipy minimize ignores constraintScipy最小化忽略约束
【发布时间】:2018-05-26 17:58:59
【问题描述】:

我有以下代码:

def constraint(params):
    if abs(params[0] - 15) < 2 and abs(params[1] + 10) < 2:
        return -1
    else:
        return 0

def f(params):
    x, z = params
    if abs(x - 15) < 2 and abs(z + 10) < 2:
        return -9999999

    return (x - 15) ** 2 + (z + 10) ** 2 * numpy.sqrt(numpy.abs(numpy.sin(x)))

# Last: 15.00024144, -9.99939634

result = optimize.minimize(f, (-15, -15),
                           bounds=((-15.01, 15.01,), (-15.01, 15.01,),),
                           method="SLSQP",
                           options={'maxiter': 1024 * 1024},
                           jac=False,
                           constraints={
                               'type': 'ineq',
                               'fun': constraint,
                           })

print(result)
print(f(result.x))

它给出了以下结果:

fun: -9999999.0
     jac: array([0., 0.])
 message: 'Optimization terminated successfully.'
    nfev: 12
     nit: 7
    njev: 3
  status: 0
 success: True
       x: array([ 15.01      , -11.60831378])
-9999999

给定值 [ 15.01, -11.60831378] 应该被约束删除(它们是:如果我添加更多详细日志记录,我看到 constraint 函数返回 -1,但 scipy 忽略它。为什么?

我离数据科学和数学还很远,所以如果出现愚蠢的错误,我很抱歉。

【问题讨论】:

    标签: python scipy minimization


    【解决方案1】:

    为了帮助算法找到正确的方向,你需要分离你的约束:

    def f(params):
        print(params)
        x, z = params
        if abs(x - 15) < 2 and abs(z + 10) < 2:
            return -9999999
    
        return (x - 15) ** 2 + (z + 10) ** 2 * numpy.sqrt(numpy.abs(numpy.sin(x)))
    
    # Last: 15.00024144, -9.99939634
    
    result = optimize.minimize(f, (-15, -15),
                               bounds=((-15.01, 15.01,), (-15.01, 15.01,),),
                               method="SLSQP",
                               options={'disp':True, 'maxiter': 1024 * 1024},
                               jac=False,
                               constraints=({
                                   'type': 'ineq',
                                   'fun': lambda params : abs(params[0] - 15) -2,
                               },
                               {
                                   'type': 'ineq',
                                   'fun': lambda params : abs(params[1] + 10) -2,
                               },)
            )
    
    print(result)
    print(f(result.x))
    

    给予:

    Optimization terminated successfully.    (Exit mode 0)
                Current function value: 6.5928117149596535
                Iterations: 6
                Function evaluations: 24
                Gradient evaluations: 6
         fun: 6.5928117149596535
         jac: array([-1.2001152,  2.5928117])
     message: 'Optimization terminated successfully.'
        nfev: 24
         nit: 6
        njev: 6
      status: 0
     success: True
           x: array([13., -8.])
    [13. -8.]
    6.5928117149596535
    

    宾果游戏!

    【讨论】:

    • @arts777 我意识到约束中有一个错字,你实际上可以用你原来的 f 函数得到结果,但是 Yakim 有一点说把一个大的正值作为一个更明智的默认。
    猜你喜欢
    • 2013-12-03
    • 2016-05-27
    • 2020-08-08
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-07-07
    • 1970-01-01
    • 2017-08-01
    相关资源
    最近更新 更多