Scipy最小化约束功能

时间:2016-02-16 12:20:47

标签: python optimization scipy mathematical-optimization

我正在解决以下优化问题:

enter image description here

使用此Python代码:

from scipy.optimize import minimize
import math

def f(x):
    return math.log(x[0]**2 + 1) + x[1]**4 + x[0]*x[2]

x0 = [0, 0, 0]

cons=({'type': 'ineq',
       'fun': lambda x: x[0]**3 - x[1]**2 - 1},
      {'type': 'ineq',
       'fun': lambda x: x[0]},
      {'type': 'ineq',
       'fun': lambda x: x[2]})

res = minimize(f, x0, constraints=cons)
print res

我收到错误

  

消息:'不平等约束不兼容'

什么可能导致此错误?

2 个答案:

答案 0 :(得分:7)

问题似乎与您最初的猜测有关。如果我将您的起始值更改为

x0 = [1.0, 1.0, 1.0]

然后你的代码将执行正常(至少在我的机器上)

  

Python 3.5.1(v3.5.1:37a07cee5969,2015年12月6日,01:54:25)[MSC v.1900 64 bit(AMD64)] on win32

 message: 'Optimization terminated successfully.'
    njev: 10
     jac: array([ 1.,  0.,  1.,  0.])
     fun: 0.6931471805582502
     nit: 10
  status: 0
       x: array([  1.00000000e+00,  -1.39724765e-06,   1.07686548e-14])
 success: True
    nfev: 51

答案 1 :(得分:1)

Scipy的优化模块有很多选择。请参阅the documentationthis tutorial。由于您未在此处指定方法,因此它将使用顺序最小二乘编程(SLSQP)。另外,您可以使用信任区域约束算法(trust-const)。

对于这个问题,我发现trust-const的起始值似乎比SLSQP更健壮,可以处理从[-2,-2,-2][10,10,10]的起始值,尽管初始值是负数如您所料,迭代次数增加。低于-2的负值超过了最大迭代次数,尽管我怀疑如果增加最大迭代次数仍可能会收敛,尽管为x1x3指定负值当然是很愚蠢的,我只是这样做是为了了解它对一系列初始值的鲁棒性。

SLSQPtrust-const的规范在概念上是相同的,但是语法略有不同(特别是注意NonlinearConstraint的使用)。

from scipy.optimize import minimize, NonlinearConstraint, SR1

def f(x):
    return math.log(x[0]**2 + 1) + x[1]**4 + x[0]*x[2]

constr_func = lambda x: np.array( [ x[0]**3 - x[1]**2 - 1,
                                    x[0],
                                    x[2] ] )

x0=[0.,0.,0.]

nonlin_con = NonlinearConstraint( constr_func, 0., np.inf )

res = minimize( f, x0, method='trust-constr',
                jac='2-point', hess=SR1(),
                constraints = nonlin_con )

为简洁起见,以下是结果:

    fun: 0.6931502233468916
message: '`gtol` termination condition is satisfied.'
      x: array([1.00000063e+00, 8.21427026e-09, 2.40956900e-06])

请注意,函数值和x值与@CoryKramer的答案相同。乍看之下,x数组可能看起来表面上有所不同,但两个答案都舍入为[1, 0, 0]