Gekko Нелинейная оптимизация, ошибка типа объекта в функции оценки ограничений if - PullRequest
5 голосов
/ 31 марта 2019

Я пытаюсь решить задачу нелинейной оптимизации.Я продублировал свою проблему, создав код ниже.Python возвращает TypeError: object of type 'int' has no len().Как включить оператор IF в функции ограничения?

Консоль печатает следующее:

  File "<ipython-input-196-8d29d410dcea>", line 1, in <module>
    runfile('C:/Users/***/Documents/***/Project/untitled.py', wdir='C:/Users/***/Documents/***/***/Project')

  File "C:\Users\***\Anaconda3\lib\site-packages\spyder_kernels\customize\spydercustomize.py", line 704, in runfile
    execfile(filename, namespace)

  File "C:\Users\***\Anaconda3\lib\site-packages\spyder_kernels\customize\spydercustomize.py", line 108, in execfile
    exec(compile(f.read(), filename, 'exec'), namespace)

  File "C:/Users/***/Documents/***/***/Project/untitled.py", line 27, in <module>
    m.Equation(Cx(x1,x2,x3,x4) < 0)

  File "C:/Users/***/Documents/***/***/Project/untitled.py", line 17, in Cx
    if K > 15:

  File "C:\Users\***\Anaconda3\lib\site-packages\gekko\gk_operators.py", line 25, in __len__
    return len(self.value)

  File "C:\Users\***\Anaconda3\lib\site-packages\gekko\gk_operators.py", line 134, in __len__
    return len(self.value)

TypeError: object of type 'int' has no len()

-

from gekko import GEKKO
m = GEKKO()


def Cr(x1,x2,x3,x4):
    return (x1*x4*(x1+x2+x3)+x3**2)

def Cw(x1,x2,x3,x4):
    return x1*x2*x3*x4

def Ck(x1,x2,x3,x4):
    return x1*x2*x3*x4+1

def Cx(x1,x2,x3,x4):
    K = Ck(x1,x2,x3,x4)
    if K > 15:  #Issue here
        K = 15
    return x1**2+x2**2+x3**2+x4**2 - K

x1 = m.Var(value=1,lb=-5000,ub=5000)
x2 = m.Var(value=1,lb=-5000,ub=5000)
x3 = m.Var(value=1,lb=-5000,ub=5000)
x4 = m.Var(value=1,lb=-5000,ub=5000)

m.Equation(Cw(x1,x2,x3,x4) >= 14)
m.Equation(Cx(x1,x2,x3,x4) < 0)

m.Obj(Cr(x1,x2,x3,x4))

m.solve(disp=False)
print(x1.value)
print(x2.value)
print(x3.value)
print(x4.value)

-

Iя надеюсь, что GEKKO запустится с оператором IF в ограничении, меня не интересует, есть ли решение проблемы оптимизации в коде.Заранее спасибо.

Ответы [ 2 ]

2 голосов
/ 02 апреля 2019

Я рекомендую использовать функции min2 или min3 или недавно добавленную функцию if3 в GEKKO.

K = m.min3(Ck(x1,x2,x3,x4),15)

Вот дополнительная информация о MPCC и переменных двоичного переключения . Вы не можете использовать функции с непостоянными градиентами, потому что это вызывает проблемы с решателями и тем, как они ищут решение. Функции min3 и if3 используют бинарные переменные и решают проблему как проблему со смешанным целым числом, а min2 используют MPCC. Вот короткий пример, демонстрирующий использование min2 и min3 .

Example use of min2 and min3 functions

import numpy as np
import matplotlib.pyplot as plt
from gekko import GEKKO
m = GEKKO(remote=False) 
p = m.Param(value=np.linspace(10,20,21))
x = m.Var()
m.Equation(x==p)
# with MPCCs
y2 = m.min2(p,15)
# with integer variables
y3 = m.min3(p,16)
m.options.IMODE = 2
m.solve()
plt.plot(p,x,'b-',label='x')
plt.plot(p,y2,'g:',label='MPCC')
plt.plot(p,y3,'r--',label='Integer Switch')
plt.legend()
plt.xlabel('x')
plt.ylabel('y')
plt.show()
1 голос
/ 31 марта 2019

(Отказ от ответственности: я не знаю эту библиотеку или что она будет делать для вас)

Оператор if делает эту проблему недифференцируемой, что делает недействительным допущение решателей НЛП (например, Ipopt).

С точки зрения решателей MINLP (Bonmin, Couenne), это может быть достигнуто путем переформулировки (и получающаяся в результате проблема дифференцируема, когда необходимые вспомогательные двоичные переменные были ослаблены). Вряд ли можно ожидать, что библиотека сделает это за вас.

Так что, похоже, вам нужно играть по правилам некоторой модели MINLP, как, например, описано Bonmin здесь . Понятия "ветвление на основе if" не существует.

Либо введите переменную-индикатор, как это принято в мире MIP, см. здесь . Игнорируя накладные расходы, идея будет выглядеть примерно так:

K_ = Ck(x1,x2,x3,x4)
I = K_ > 15 (binary variable; see link for formulation idea)

return x1**2+x2**2+x3**2+x4**2 - I*15 - (1-I) * K_

Это MINLP тогда.

Вы можете уйти, не используя дополнительную двоичную переменную (и не касаясь MINLPs) при интерпретации вашего уравнения, например:

return x1**2+x2**2+x3**2+x4**2 - min(Ck(x1,x2,x3,x4), 15)

Это также недифференцируемо, но может быть легко переформулировано (с причудой) как:

return x1**2+x2**2+x3**2+x4**2 - A

# extra constraints
A <= Ck(x1,x2,x3,x4)
A <= 15

, если бы мы могли обеспечить движение к максимально возможному значению . Это означает, что это должно быть частью цели:

m.Obj(Cr(x1,x2,x3,x4) + c * A) (if it's a maximization problem)

Тогда это будет НЛП , но значение c требует некоторого внимания (оно должно быть достаточно большим).

...