使用Python优化(scipy.optimize)

use*_*925 7 python optimization mathematical-optimization scipy

我试图使用Python的scipy.optimize最大化以下功能.然而,经过大量的尝试,它似乎没有用.该函数和我的代码粘贴在下面.谢谢你的帮助!

问题

Maximize [sum (x_i / y_i)**gamma]**(1/gamma)
subject to the constraint sum x_i = 1; x_i is in the interval (0,1). 
Run Code Online (Sandbox Code Playgroud)

x是一个选择变量的向量; y是参数的矢量; gamma是一个参数.在x小号必须总和为1.每个x必须在区间(0,1).

def objective_function(x, y):
    sum_contributions = 0
    gamma = 0.2

    for count in xrange(len(x)):
        sum_contributions += (x[count] / y[count]) ** gamma
    value = math.pow(sum_contributions, 1 / gamma)
    return -value

cons = ({'type': 'eq', 'fun': lambda x: np.array([sum(x) - 1])})

y = [0.5, 0.3, 0.2]
initial_x = [0.2, 0.3, 0.5]

opt = minimize(objective_function, initial_x, args=(y,), method='SLSQP',  
constraints=cons,bounds=[(0, 1)] * len(x))
Run Code Online (Sandbox Code Playgroud)

CT *_*Zhu 3

有时,数值优化器由于某种原因不起作用。我们可以稍微不同地参数化问题,它就会起作用。(并且可能工作得更快)

例如,对于 的边界(0,1),我们可以有一个变换函数,使得 中的值在(-inf, +inf)变换后最终会变为(0,1)

我们可以用等式约束做类似的技巧。例如,我们可以将维度从 3 减少到 2,因为 中的最后一个元素x必须是1-sum(x)

如果它仍然不起作用,我们可以切换到不需要导数信息的优化器,例如Nelder Mead.

还有拉格朗日乘子

In [111]:

def trans_x(x):
    x1 = x**2/(1+x**2)
    z  = np.hstack((x1, 1-sum(x1)))
    return z

def F(x, y, gamma = 0.2):
    z = trans_x(x)
    return -(((z/y)**gamma).sum())**(1./gamma)
In [112]:

opt = minimize(F, np.array([0., 1.]), args=(np.array(y),),
               method='Nelder-Mead')
opt
Out[112]:
  status: 0
    nfev: 96
 success: True
     fun: -265.27701747828007
       x: array([ 0.6463264,  0.7094782])
 message: 'Optimization terminated successfully.'
     nit: 52
Run Code Online (Sandbox Code Playgroud)

结果是:

In [113]:

trans_x(opt.x)
Out[113]:
array([ 0.29465097,  0.33482303,  0.37052601])
Run Code Online (Sandbox Code Playgroud)

我们可以通过以下方式将其可视化:

In [114]:

x1 = np.linspace(0,1)
y1 = np.linspace(0,1)
X,Y = np.meshgrid(x1,y1)
Z = np.array([F(item, y) for item 
              in np.vstack((X.ravel(), Y.ravel())).T]).reshape((len(x1), -1), order='F')
Z = np.fliplr(Z)
Z = np.flipud(Z)
plt.contourf(X, Y, Z, 50)
plt.colorbar()
Run Code Online (Sandbox Code Playgroud)

在此输入图像描述