2016-11-02 4 views
1

Рассмотрим простую задачу:ошибка домена Math вследствие неуважительно ограничения в SciPy SLSQP минимизировать

Чтобы решить эту проблему с scipy.optimize.minimize:

import numpy as np 
from scipy.optimize import minimize 
from math import log 

def func(x): 
    return log(x[0]) 

def func_deriv(x): 
    return np.array([1/x[0]]) 

cons = ({'type': 'ineq', 
     'fun' : lambda x: x[0] - 1e-4, 
     'jac' : lambda x: np.array([1])}) 
minimize(func, [1.0], jac=func_deriv, constraints=cons, method='SLSQP') 

Сценарий встречает ValueError, потому что log(x) оценивается с отрицательным x. Кажется, что значение функции оценивается, даже если ограничение не выполняется.

Я понимаю, что использование bounds в minimize() могло бы избежать проблемы, но это просто упрощение моей исходной проблемы. В моей первоначальной задаче ограничение x >= 1e-4 не может быть легко представлено в виде x, но имеет форму g(x) >= C, поэтому bounds не помогло бы.

+0

Я всегда использую границы для этой цели даже за счет дополнительных переменных или ограничений (но я использую обычно более сложные алгоритмы, чем scipy.optimize). Например. в вашем случае я бы добавил 'y = g (x)', а затем положил границы на 'y'. Вместо этого вы можете уйти с возвращаемыми значениями функции ограничений, которые являются (очень) отрицательными (то есть неосуществимыми). –

+0

@ErwinKalvelagen Это решение, но я должен придумать модифицированную версию 'log (x)', которая очень отрицательна и выводима, даже если 'x' немного меньше нуля. Могу ли я спросить, какие расширенные алгоритмы вы обычно используете? – peter

+0

@peter Я думаю, он ссылается на коммерческие инструменты, такие как Knitro, Baron, Conopt и co. (или вообще NLP-решатели, поддерживаемые AMPL). Альтернатива с открытым исходным кодом, которую вы можете изучить, будет ipopt (или другие, если ваша полная проблема является выпуклой). – sascha

ответ

0

Если мы только заботимся о значении функции с помощью x > ε, можно определить безопасную функцию, расширяющую домен.

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

safe_log(x) = log(x) if x > ε else a * (x - b)**3 

Для расчета a и b, мы должны удовлетворять:

log(ε) = a * (ε - b)**3 
1/ε = 3 * a * (ε - b)**2 

Следовательно safe_log функция:

eps = 1e-3 

def safe_log(x): 
    if x > eps: 
     return log(x) 
    logeps = log(eps) 
    a = 1/(3 * eps * (3 * logeps * eps)**2) 
    b = eps * (1 - 3 * logeps) 
    return a * (x - b)**3 

И это выглядит следующим образом:

Plot of safe_log(x)