Ответ профессора Хеденгрена:
Вам нужно будет использовать встроенные функции GEKKO max2
или max3
. В противном случае функция Python создает выражение, которое не имеет непрерывных первых или вторых производных, и решатели на основе градиента, скорее всего, не смогут найти решение.
Вам потребуется обновить до последней версии gekko (> 0.2rc5) с помощью pip install gekko == 0.2rc6 , чтобы использовать функции max2
или max3
Gekko.
Ниже приведен источник max2
или max3
, который вы также можете найти в источнике Gekko .
def max2(self,x1,x2):
""" Generates the maximum value with continuous first and
second derivatives. The traditional method for max value (max) is not
continuously differentiable and can cause a gradient-based optimizer
to fail to converge.
Usage: y = m.max2(x1,x2)
Input: GEKKO variable, parameter, or expression
Output: GEKKO variable
"""
# verify that x1 and x2 are valid GEKKO variables or parameters
if isinstance(x1,(GKVariable,GKParameter)):
xin1 = x1
else:
# create input variable if it is an expression
xin1 = self.Var()
self.Equation(xin1==x1)
if isinstance(x2,(GKVariable,GKParameter)):
xin2 = x2
else:
# create input variable if it is an expression
xin2 = self.Var()
self.Equation(xin2==x2)
# build max object with unique object name
max_name = 'max2_' + str(len(self._objects) + 1)
self._objects.append(max_name + ' = max')
# add connections between x and max object attribute x
self._connections.append(xin1.name + ' = ' + max_name+'.x[1]')
self._connections.append(xin2.name + ' = ' + max_name+'.x[2]')
# add connections between y and max object attribute y
y = self.Var()
self._connections.append(y.name + ' = ' + max_name+'.y')
return y
def max3(self,x1,x2):
""" Generates the maximum value with a binary switch variable.
The traditional method for max value (max) is not continuously
differentiable and can cause a gradient-based optimizer to fail
to converge.
Usage: y = m.max3(x1,x2)
Input: GEKKO variable, parameter, or expression
Output: GEKKO variable
"""
# add binary (intb) and output (y) variable
intb = self.Var(0,lb=0,ub=1,integer=True)
y = self.Var()
# add equations for switching conditions
# intb=0 when x1>x2 and y=x1
# intb=1 when x2>x1 and y=x2
self.Equation((1-intb)*(x2-x1) <= 0)
self.Equation(intb*(x1-x2) <= 0)
self.Equation(y==(1-intb)*x1+intb*x2)
# change default solver to APOPT (MINLP)
self.options.SOLVER = 1
return y
Функция max2 использует MPCC, а max3 использует двоичные переменные. Функции помогают использовать эти более сложные формы моделирования, просто используя вызов функции. Вы можете сравнивать только два значения с max2 или max3, поэтому если у вас есть список, вам нужно сделать что-то вроде:
y[0] = m.max3(x[0],x[1])
y[1] = m.max3(x[2],y[0])
y[2] = m.max3(x[3],y[1])
и т.д.
Вот дополнительная информация о , почему вам нужно использовать MPCC или двоичные переменные . Здесь также есть дополнительный пример .