2

我在 gekko-python 中定义 max 函数时遇到问题。

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()

~\Anaconda3\lib\site-packages\gekko\gk_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]

~\Anaconda3\lib\site-packages\gekko\gk_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()
4

1 回答 1

3

Hedengren教授的回答:

您需要使用内置的 GEKKOmax2max3函数。否则,Python 函数会创建一个不具有连续一阶或二阶导数的表达式,并且基于梯度的求解器可能无法找到解决方案。

您需要使用pip install gekko==0.2rc6升级到最新的 gekko 版本 (>0.2rc5)才能使用max2max3Gekko 功能。

以下是max2max3您也可以在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 或二进制变量的附加信息。这里还有一个额外的例子

于 2019-04-24T08:02:43.190 回答