代码之家  ›  专栏  ›  技术社区  ›  artem

Scipy最小化忽略约束

  •  3
  • artem  · 技术社区  · 6 年前

    我有以下代码:

    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 ,但希皮对此视而不见。为什么?

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

    1 回复  |  直到 6 年前
        1
  •  4
  •   Jacques Gaudin    6 年前

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

    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
    

    答对 了