Ограничения лучше как уравнения (жесткие) или объективные (мягкие)?

Как правило, оптимизатору на основе градиента (APOPT, IPOPT) в Gekko проще решить ограничение как целевую функцию (минимизировать до нуля) или как уравнение, в котором оно установлено равным нулю? В качестве примера я установил функцию Rosenbrock. Оптимальная цель может быть установлена ​​равной нулю как уравнение (жесткое ограничение) или минимизировано до нуля (мягкое ограничение).

from gekko import GEKKO
a=1; b=100
print('Exact: ',a,a**2)

m = GEKKO(remote=False)
x = m.Var(0); y=m.Var(0);
m.Minimize((a-x)**2 + b*(y-x**2)**2)
m.options.SOLVER=1; m.solve(disp=False)
print('Soft: ',x.value[0],y.value[0],'Iterations:',m.options.ITERATIONS)

m = GEKKO(remote=False)
x = m.Var(0); y=m.Var(0);
m.Equation((a-x)**2 + b*(y-x**2)**2==0)
m.options.SOLVER=1; m.solve(disp=False)
print('Hard: ',x.value[0],y.value[0],'Iterations:',m.options.ITERATIONS)

m = GEKKO(remote=False)
x = m.Var(0); y=m.Var(0);
m.Minimize((a-x)**2 + b*(y-x**2)**2)
m.Equation((a-x)**2 + b*(y-x**2)**2==0)
m.options.SOLVER=1; m.solve(disp=False)
print('Both: ',x.value[0],y.value[0],'Iterations:',m.options.ITERATIONS)

Это может быть слишком сложно обобщить для всех проблем, но меня интересуют компромиссы, особенно для крупномасштабных задач, где некоторые из ограничений могут быть мягкими, жесткими или и тем, и другим. Для задачи Розенброка результаты почти идентичны, но метод мягких ограничений имеет наименьшее количество итераций.

Exact:  1 1
Soft:  0.99999999441 0.99999999029 Iterations: 23
Hard:  0.99969681373 0.99942834333 Iterations: 26
Both:  0.99988305657 0.99978643823 Iterations: 27

person TexasEngineer    schedule 19.12.2019    source источник


Ответы (2)


Я использую жесткие ограничения, когда можно найти допустимое решение, и мягкие ограничения, когда трудно найти допустимое решение или когда нарушение ограничений допустимо, но не рекомендуется. Уравнения жестких ограничений лучше подходят для крупномасштабных приложений, потому что не все ограничения объединены в одно значение целевой функции. Оптимизатор использует информацию о градиенте из уравнений, чтобы найти направление поиска допустимого решения. Для сравнения вот scipy.optimize.minimize с такими же проблемами.

from scipy.optimize import minimize
def f(z):
    x,y=z
    return (a-x)**2 + b*(y-x**2)**2
sol = minimize(f,[0,0])
print('Soft:',sol.x,'Iterations:',sol.nit)

def f(z):
    return 0
def con(z):
    x,y=z
    return (a-x)**2 + b*(y-x**2)**2
hard = {'type': 'eq', 'fun': con}
sol = minimize(f,[0,0],constraints=hard)
print('Hard:',sol.x,'Iterations:',sol.nit)

def f(z):
    x,y=z
    return (a-x)**2 + b*(y-x**2)**2
def con(z):
    x,y=z
    return (a-x)**2 + b*(y-x**2)**2
hard = {'type': 'eq', 'fun': con}
sol = minimize(f,[0,0],constraints=hard)
print('Both:',sol.x,'Iterations:',sol.nit)

Первая форма (мягкое ограничение, целевая функция) имеет наименьшее количество итераций.

Exact:  1 1
Soft: [0.99999467 0.99998932] Iterations: 19
Hard: [0.99986205 0.99963916] Iterations: 22
Both: [1.00013127 1.00021689] Iterations: 23
person Eric Hedengren    schedule 19.12.2019

Чтобы ответить на вопрос о конкретных решателях в Gekko, вы можете запустить m.options.SOLVER=0, чтобы попробовать все доступные решатели и отобразить сводку производительности. С SOLVER=0 решение не возвращается в Gekko, поэтому есть ошибка, которую можно отловить с помощью блока try except.

from gekko import GEKKO
from scipy.optimize import minimize

# Rosenbrock function
a=1; b=100
print('Exact: ',a,a**2)

try:
    m = GEKKO(remote=False)
    x = m.Var(0); y=m.Var(0);
    m.Minimize((a-x)**2 + b*(y-x**2)**2)
    m.options.SOLVER=0; m.solve(disp=True,debug=0)
except:
    pass

try:
    m = GEKKO(remote=False)
    x = m.Var(0); y=m.Var(0);
    m.Equation((a-x)**2 + b*(y-x**2)**2==0)
    m.options.SOLVER=0; m.solve(disp=True,debug=0)
except:
    pass

try:
    m = GEKKO(remote=False)
    x = m.Var(0); y=m.Var(0);
    m.Minimize((a-x)**2 + b*(y-x**2)**2)
    m.Equation((a-x)**2 + b*(y-x**2)**2==0)
    m.options.SOLVER=0; m.solve(disp=True,debug=0)
except:
    pass

Все решатели (включая BPOPT) успешно работают с подходом с жесткими ограничениями. Итерации IPOPT не сообщаются автоматически, поэтому я взял их из распечатки решателя.

 Solver      Variables Equations Res Evals Jac Evals Iter Info   Objective  Solution Time  Status
 ----------- --------- --------- --------- --------- ---- ---- ------------ ------------- ---------
 APOPT (v1.0)           2         1        30        26   26    0  0.00000E+00         0.065 Success
 BPOPT (v1.0)           2         1         0        18   17    0  0.00000E+00         0.004 Success
 IPOPT (v3.12)          2         1        22        17   15    0  0.00000E+00         0.019 Success
 --------------------------------------------------------------------------------------------------
person John Hedengren    schedule 19.12.2019