2014-02-13 3 views
4

Какой рекомендуемый пакет для ограниченной нелинейной оптимизации в python?Ограниченная нелинейная оптимизация на основе Python

Конкретная проблема, которую я пытаюсь решить это:

У меня есть неизвестное X (Nx1), у меня есть M (NX1) u векторы и M (NxN) s матрицы.

max [5th percentile of (ui_T*X), i in 1 to M] 
st 
0<=X<=1 and 
[95th percentile of (X_T*si*X), i in 1 to M]<= constant 

Когда я начинал эту проблему, я только имел одну точечную оценку для u и s, и я был в состоянии решить эту проблему выше cvxpy.

Я понял, что вместо одной оценки для u и s у меня было все распределение значений, поэтому я хотел изменить свою целевую функцию, чтобы я мог использовать весь дистрибутив. Описание проблемы выше - моя попытка включить эту информацию в значимый путь.

cvxpy не может быть использован для решения этой проблемы, я пробовал scipy.optimize.anneal, но я не могу установить границы по неизвестным значениям. Я тоже посмотрел на pulp, но он не позволяет нелинейные ограничения.

+1

Вопросы, предлагающие нам рекомендовать или находить инструмент, библиотеку или любимый внешний ресурс вне темы для переполнения стека, поскольку они склонны привлекать упрямые ответы и спам. Вместо этого опишите проблему и то, что было сделано до сих пор, чтобы ее решить. – jonrsharpe

+1

Несомненно. Когда я начал эту проблему, у меня была только одна оценка точки для u и s, и я смог решить проблему выше с помощью cvxpy. Я понял, что вместо одной оценки для u и s у меня было все распределение значений, поэтому я хотел изменить свою целевую функцию, чтобы я мог использовать весь дистрибутив. Описание проблемы выше - моя попытка включить эту информацию в значимый путь. cvxpy не может быть использован для решения этой проблемы, я пробовал scipy.optimize.anneal, но я не могу установить границы на неизвестные значения. Я тоже посмотрел на целлюлозу, но это не допускает нелинейных ограничений. – akhil

ответ

4

scipy имеет впечатляющий пакет для ограниченной нелинейной оптимизации.

Вы можете начать с чтения optimizedoc, но вот пример с SLSQP:

minimize(func, [-1.0,1.0], args=(-1.0,), jac=func_deriv, constraints=cons, method='SLSQP', options={'disp': True}) 
+1

Спасибо Слейтеру, но вычисление якобиана проблемы выше не кажется простым, по крайней мере для меня. – akhil

+0

@akhil jacobian - дополнительный вход. Чтение через фактические документы может сделать больше, чтобы помочь вам встать и работать, чем я могу. –

+0

Да, это так. Я смог решить вышеупомянутую проблему. Спасибо, vm! – akhil

1

Обычно для установки вы можете использовать scipy.optimize функции или lmfit, который просто расширяет пакет scipy.optimize, чтобы сделать его легче передавать такие вещи, как оценки. Лично мне нравится использовать kmpfit, часть библиотеки kapteyn и основана на реализации C MPFIT.

scipy.optimize.minimize(), вероятно, самый простой в использовании и обычно используется.

+0

Спасибо псевдокубику. Эти пакеты выглядят великолепно. Я попробую их сейчас. Просто интересно, есть ли простой способ сделать матричное умножение? Или мне нужно расширять каждый термин? – akhil

+0

На самом деле моя проблема не является подходящей проблемой. – akhil

2

Как прокомментировали другие, пакет минимизации SciPy - это хорошее место для начала. Я привел пример ниже (Hock Schittkowski # 71 benchmark), который включает объективную функцию, ограничение равенства и ограничение неравенства.

import numpy as np 
from scipy.optimize import minimize 

def objective(x): 
    return x[0]*x[3]*(x[0]+x[1]+x[2])+x[2] 

def constraint1(x): 
    return x[0]*x[1]*x[2]*x[3]-25.0 

def constraint2(x): 
    sum_eq = 40.0 
    for i in range(4): 
     sum_eq = sum_eq - x[i]**2 
    return sum_eq 

# initial guesses 
n = 4 
x0 = np.zeros(n) 
x0[0] = 1.0 
x0[1] = 5.0 
x0[2] = 5.0 
x0[3] = 1.0 

# show initial objective 
print('Initial SSE Objective: ' + str(objective(x0))) 

# optimize 
b = (1.0,5.0) 
bnds = (b, b, b, b) 
con1 = {'type': 'ineq', 'fun': constraint1} 
con2 = {'type': 'eq', 'fun': constraint2} 
cons = ([con1,con2]) 
solution = minimize(objective,x0,method='SLSQP',\ 
        bounds=bnds,constraints=cons) 
x = solution.x 

# show final objective 
print('Final SSE Objective: ' + str(objective(x))) 

# print solution 
print('Solution') 
print('x1 = ' + str(x[0])) 
print('x2 = ' + str(x[1])) 
print('x3 = ' + str(x[2])) 
print('x4 = ' + str(x[3])) 

Существует также более подробное обсуждение нить на nonlinear programming solvers for Python если SLSQP не может решить вашу проблему. Мой материал курса по Engineering Design Optimization доступен, если вам нужна дополнительная информация о методах решателя.

+0

Благодарим вас за ответ, здесь, в 'def constraint2 (x)' вы можете предоставить 'sum_eq' функции ограничения без hardcoding, как' def constraint2 (x, sum_eq) '? Я намерен использовать ограничение на точечное произведение, например 'np.linalg.dot (x, p) == 0', где' p' - статический вектор, который я вычисляю вне процедуры оптимизации. Спасибо. – Rhubarb

3

Хотя алгоритм SLSQP в scipy.optimize.minimize хорош, у него есть куча ограничений. Первый из них - это решатель QP, поэтому он работает для уравнений, которые хорошо вписываются в квадратичную парадигму программирования. Но что произойдет, если у вас есть функциональные ограничения? Кроме того, scipy.optimize.minimize не является глобальным оптимизатором, поэтому вам часто нужно начинать очень близко к конечным результатам.

Существует ограниченный пакет нелинейной оптимизации (называемый mystic), который существует почти столько же, сколько и scipy.optimize - я бы предложил его в качестве решения для любой ограниченной ограниченной нелинейной оптимизации.

Например, ваша проблема, если я понимаю ваш псевдо-код, выглядит примерно так:

import numpy as np 

M = 10 
N = 3 
Q = 10 
C = 10 

# let's be lazy, and generate s and u randomly... 
s = np.random.randint(-Q,Q, size=(M,N,N)) 
u = np.random.randint(-Q,Q, size=(M,N)) 

def percentile(p, x): 
    x = np.sort(x) 
    p = 0.01 * p * len(x) 
    if int(p) != p: 
     return x[int(np.floor(p))] 
    p = int(p) 
    return x[p:p+2].mean() 

def objective(x, p=5): # inverted objective, to find the max 
    return -1*percentile(p, [np.dot(np.atleast_2d(u[i]), x)[0] for i in range(0,M-1)]) 


def constraint(x, p=95, v=C): # 95%(xTsx) - v <= 0 
    x = np.atleast_2d(x) 
    return percentile(p, [np.dot(np.dot(x,s[i]),x.T)[0,0] for i in range(0,M-1)]) - v 

bounds = [(0,1) for i in range(0,N)] 

Так, чтобы справиться с вашей проблемой в mystic, вам просто нужно указать границы и ограничения.

from mystic.penalty import quadratic_inequality 
@quadratic_inequality(constraint, k=1e4) 
def penalty(x): 
    return 0.0 

from mystic.solvers import diffev2 
from mystic.monitors import VerboseMonitor 
mon = VerboseMonitor(10) 

result = diffev2(objective, x0=bounds, penalty=penalty, npop=10, gtol=200, \ 
       disp=False, full_output=True, itermon=mon, maxiter=M*N*100) 

print result[0] 
print result[1] 

Результат выглядит примерно так:

Generation 0 has Chi-Squared: -0.434718 
Generation 10 has Chi-Squared: -1.733787 
Generation 20 has Chi-Squared: -1.859787 
Generation 30 has Chi-Squared: -1.860533 
Generation 40 has Chi-Squared: -1.860533 
Generation 50 has Chi-Squared: -1.860533 
Generation 60 has Chi-Squared: -1.860533 
Generation 70 has Chi-Squared: -1.860533 
Generation 80 has Chi-Squared: -1.860533 
Generation 90 has Chi-Squared: -1.860533 
Generation 100 has Chi-Squared: -1.860533 
Generation 110 has Chi-Squared: -1.860533 
Generation 120 has Chi-Squared: -1.860533 
Generation 130 has Chi-Squared: -1.860533 
Generation 140 has Chi-Squared: -1.860533 
Generation 150 has Chi-Squared: -1.860533 
Generation 160 has Chi-Squared: -1.860533 
Generation 170 has Chi-Squared: -1.860533 
Generation 180 has Chi-Squared: -1.860533 
Generation 190 has Chi-Squared: -1.860533 
Generation 200 has Chi-Squared: -1.860533 
Generation 210 has Chi-Squared: -1.860533 
STOP("ChangeOverGeneration with {'tolerance': 0.005, 'generations': 200}") 
[-0.17207128 0.73183465 -0.28218955] 
-1.86053344078 

mystic является очень гибким и может обрабатывать любой тип ограничений (например, Равенство, неравенство), включая символические и функциональные ограничения. Я указал ограничения как «штрафы» выше, что является традиционным способом, поскольку они применяют штраф к цели при нарушении ограничения. mystic также обеспечивает нелинейные преобразования ядра, которые ограничивают пространство решений путем сокращения пространства допустимых решений (т. Е. Путем пространственного преобразования или преобразования ядра).

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

"Pressure Vessel Design" 

def objective(x): 
    x0,x1,x2,x3 = x 
    return 0.6224*x0*x2*x3 + 1.7781*x1*x2**2 + 3.1661*x0**2*x3 + 19.84*x0**2*x2 

bounds = [(0,1e6)]*4 
# with penalty='penalty' applied, solution is: 
xs = [0.72759093, 0.35964857, 37.69901188, 240.0] 
ys = 5804.3762083 

from mystic.symbolic import generate_constraint, generate_solvers, simplify 
from mystic.symbolic import generate_penalty, generate_conditions 

equations = """ 
-x0 + 0.0193*x2 <= 0.0 
-x1 + 0.00954*x2 <= 0.0 
-pi*x2**2*x3 - (4/3.)*pi*x2**3 + 1296000.0 <= 0.0 
x3 - 240.0 <= 0.0 
""" 
cf = generate_constraint(generate_solvers(simplify(equations))) 
pf = generate_penalty(generate_conditions(equations), k=1e12) 


if __name__ == '__main__': 

    from mystic.solvers import diffev2 
    from mystic.math import almostEqual 
    from mystic.monitors import VerboseMonitor 
    mon = VerboseMonitor(10) 

    result = diffev2(objective, x0=bounds, bounds=bounds, constraints=cf, penalty=pf, \ 
        npop=40, gtol=50, disp=False, full_output=True, itermon=mon) 

    assert almostEqual(result[0], xs, rel=1e-2) 
    assert almostEqual(result[1], ys, rel=1e-2) 

Найти это, и примерно 100 примеров нравится, здесь: https://github.com/uqfoundation/mystic.

Я автор, поэтому я слегка пристрастен. Однако смещение очень слабое. mystic является и зрелым, и хорошо поддержанным, и не имеет себе равных в способности решать жестко ограниченные задачи нелинейной оптимизации.

+0

Дополнительные примеры с нелинейными ограничениями здесь: http://stackoverflow.com/a/42299338/2379433 –

+0

Звучит многообещающе, но главная страница проекта связана с https://pypi.org/project/mystic/ (http: // www. cacr.caltech.edu/~mmckerns) нарушается! – feetwet

+0

@feetwet: эта страница была перенесена в http: //trac.mystic.cacr.caltech.Edu/проект/мистика/wiki.html. Ссылка на pypi будет обновлена ​​в предстоящем выпуске. –

Смежные вопросы