Ограниченная оптимизация в Python

В Python, используя SciPy, мне нужно найти максимум функции Q*((1+y)*2-3*Q-0.1)-y**2 С учетом ограничения (1-z)*(Q*((1+y)*2-3*Q-0.1))-y**2=0. Для z я хотел бы ввести некоторые значения, чтобы найти аргументы, которые максимизируют функцию при этом значении z.

Я пробовал много способов использовать функции оптимизации SciPy, но не могу понять, как это сделать. Мне удалось это сделать с помощью WolframAlpha, но это не дает мне ответа на следующие вопросы Вот этот.

Пытаться:

from scipy.optimize import minimize

def equilibrium(z):
    #Objective function
    min_prof = lambda(Q,y): -1*(Q*((1+y)*2-3*Q-0.1)-y**2)

    #initial guess
    x0 = (0.6,0.9)

    #Restriction function
    cons = ({'type': 'eq', 'fun': lambda (Q,y): (1-z)*(Q*((1+y)*2-3*Q-0.1))-y**2})

    #y between 0 and 1, Q between 0 and 4
    bnds = ((0,4),(0,1))

    res = minimize(min_prof,x0, method='SLSQP', bounds=bnds ,constraints=cons)

    return res.x

from numpy import arange

range_z = arange(0,1,0.001)

print equilibrium(range_z)

Ошибка:

---------------------------------------------------------------------------
ValueError                                Traceback (most recent call last)
<ipython-input-20-527013574373> in <module>()
     21 range_z = arange(0,1,0.01)
     22 
---> 23 print equilibrium(range_z)

<ipython-input-20-527013574373> in equilibrium(z)
     14     bnds = ((0,4),(0,1))
     15 
---> 16     res = minimize(min_prof,x0, method='SLSQP', bounds=bnds ,constraints=cons)
     17 
     18     return res.x

/Users/Joost/anaconda/lib/python2.7/site-packages/scipy/optimize/_minimize.pyc in minimize(fun, x0, args, method, jac, hess, hessp, bounds, constraints, tol, callback, options)
    456     elif meth == 'slsqp':
    457         return _minimize_slsqp(fun, x0, args, jac, bounds,
--> 458                                constraints, callback=callback, **options)
    459     elif meth == 'dogleg':
    460         return _minimize_dogleg(fun, x0, args, jac, hess,

/Users/Joost/anaconda/lib/python2.7/site-packages/scipy/optimize/slsqp.pyc in _minimize_slsqp(func, x0, args, jac, bounds, constraints, maxiter, ftol, iprint, disp, eps, callback, **unknown_options)
    324             + 2*meq + n1 + ((n+1)*n)//2 + 2*m + 3*n + 3*n1 + 1
    325     len_jw = mineq
--> 326     w = zeros(len_w)
    327     jw = zeros(len_jw)
    328 

ValueError: negative dimensions are not allowed

person Joost Bouten    schedule 12.06.2017    source источник
comment
Вышеупомянутая ссылка представляет собой пример выполнения ограниченной оптимизации. Если вы попытаетесь решить свою проблему и столкнетесь с проблемой, поделитесь своей попыткой кода и конкретной ошибкой, с которой вы столкнулись, и мы сможем помочь оттуда.   -  person Cory Kramer    schedule 12.06.2017
comment
@CoryKramer Я перефразировал свою проблему, теперь у меня есть решение для определенного значения для z (которое было 0,3), теперь я хотел бы изучить, как эти оптимумы реагируют на значение z.   -  person Joost Bouten    schedule 12.06.2017


Ответы (1)


Вам нужно оценивать свою функцию по одному z за раз. Минимальная модификация для работы вашего кода выглядит следующим образом:

print [equilibrium(z) for z in z_range]

В вашем текущем коде функция, описывающая ограничения, возвращает вектор вместо скаляра, что приводит к сообщению об ошибке.

Вместо численной оптимизации вы можете заметить, что ваша проблема решается аналитически:

a = 0.1
Q = (6-3*a+3**.5 *(4-4*a+a**2-4*z+4*a*z-a**2 *z)**.5)/(6*(2+z))
y = Q*(1-z)+(Q*(-1+z)*(-2+a+Q*(2+z)))**.5

Вы можете проверить это и убедиться, что он дает тот же результат (с точностью до числовой точности), что и численная оптимизация. (Я тестировал z = 0,745 - вам нужно проверить вторую производную, чтобы выбрать правильный максимум в целом. Но это выполнимо.)

person Andi    schedule 14.06.2017