#python #numpy #gekko
#python #numpy #gekko
Вопрос:
У меня возникла проблема с определением максимальной функции в gekko-python.
Функция sum работает нормально, но когда я создаю другую функцию, просто заменяя sum на max, она выдает следующую ошибку:
Это описание сценария, который я использую (с моделью, некоторыми данными и результатами)
#Model
import numpy as np
from gekko import GEKKO
import numpy as np
import pandas as pd
from pandas import ExcelWriter
from pandas import ExcelFile
m = GEKKO() # Initialize gekko
m.options.SOLVER = 3 # IPOPT is an NLP solver
m.options.MAX_ITER = 10000 # maximum number of iterations
m.options.MAX_MEMORY = 6 # (2-10) memory allocation
R_sect_bin = {'W1': {'S1': 1}, 'W2': {'S1': 1, 'S2': 1, 'S4': 1}, 'W3': {'S1': 1, 'S2': 1, 'S3': 1, 'S4': 1, 'S5': 1, 'S6': 1}, 'W4': {'S4': 1}, 'W5': {'S4': 1, 'S5': 1, 'S6': 1}, 'W6': {'S6': 1}}
Input_Services_nonZero = {'S1': {'L1': 1, 'L3': 1}, 'S2': {'L2': 1}, 'S3': {'L4': 1}, 'S4': {'L1': 1}, 'S5': {'L3': 1}, 'S6': {'L1': 1, 'L2': 1}}
V = {}
for w in R_sect_bin:
V[w] = {}
for s in R_sect_bin[w]:
V[w][s] = {}
for l in Input_Services_nonZero[s]:
V[w][s][l] = m.Var(value=10, lb=0, ub=100)
#functions:
sum_Vws1 = {}
def VWS1():
global sum_Vws1
for w in R_sect_bin:
sum_Vws1[w] = {}
for s in R_sect_bin[w]:
sum_Vws1[w][s] = m.Intermediate(sum([V[w][s][l] for l in Input_Services_nonZero[s]]))
return sum_Vws1
vws1 = VWS1()
sum_Vws2 = {}
def VWS2():
global sum_Vws2
for w in R_sect_bin:
sum_Vws2[w] = {}
for s in R_sect_bin[w]:
sum_Vws2[w][s] = m.Intermediate(max([V[w][s][l] for l in Input_Services_nonZero[s]]))
return sum_Vws2
vws2 = VWS2()
TypeError Traceback (most recent call last)
<ipython-input-225-b48377242060> in <module>
89 sum_Vws2[w][s] = m.Intermediate(max([V[w][s][l] for l in Input_Services_nonZero[s]]))
90 return sum_Vws2
---> 91 vws2 = VWS2()
92
93 #sum_Vws = {}
<ipython-input-225-b48377242060> in VWS2()
87 sum_Vws2[w] = {}
88 for s in R_sect_bin[w]:
---> 89 sum_Vws2[w][s] = m.Intermediate(max([V[w][s][l] for l in Input_Services_nonZero[s]]))
90 return sum_Vws2
91 vws2 = VWS2()
~Anaconda3libsite-packagesgekkogk_operators.py in __len__(self)
23 return self.name
24 def __len__(self):
---> 25 return len(self.value)
26 def __getitem__(self,key):
27 return self.value[key]
~Anaconda3libsite-packagesgekkogk_operators.py in __len__(self)
132
133 def __len__(self):
--> 134 return len(self.value)
135
136 def __getitem__(self,key):
TypeError: object of type 'int' has no len()
Ответ №1:
Ответ профессора Хеденгрена:
Вам нужно будет использовать встроенные функции GEKKO max2
или max3
. В противном случае функция Python создает выражение, которое не имеет непрерывных первых или вторых производных, и решатели на основе градиента, скорее всего, не смогут найти решение.
Вам нужно будет обновиться до последней версии gekko (> 0.2rc5) с помощью pip install gekko==0.2rc6, чтобы использовать функции max2
или max3
Gekko.
Ниже приведен исходный код для max2
or 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 или двоичные переменные. Здесь также есть дополнительный пример.