使用二进制选择器的边界优化求和函数 - GEKKO

Optimizing Summation function with bounds from binary selector - GEKKO

我正在尝试优化求和函数。从类似的 中,我找到了我问题的一半答案(我已经使我的 objective 函数类似于那个问题中的函数)。

问题:

尝试:

from gekko import GEKKO
import numpy as np
from scipy.special import factorial

m = GEKKO(remote=False)
x = m.sos1([1,2,3])
yb = m.Array(m.Var,3,lb=0,ub=1,integer=True)
m.Equation(m.sum(yb)==1)
y = m.sum([yb[i]*(i+1) for i in range(3)])
m.Equation(m.sum([yb[i]*(i+1) for i in range(3)])<2)
yf = factorial(np.linspace(0,len(yb),len(yb)+1))
obj = m.exp(x)
for j in range(0,len(yb)):
    obj += x**j/yf[j]
    m.Maximize(obj*yb[j])
m.solve()
print('x='+str(x.value[0]))
print('y='+str(y.value[0]))
print('Objective='+str(-m.options.objfcnval))

这有效,但仅当我在 for 循环中添加 m.Maximize 时才有效。 运行 与循环内没有 m.Maximize 相同会产生错误的结果(如下所示)。问题是二进制选择器 yb。当 yb = [0,1,0] => y=2 时,求和范围将是 i=0 到 2。但我无法获得此行为。我不能 运行 带有 range(y) 的 for 循环,因为它是一个 GKVariable 并且它还会随着变量值的变化而改变方程的大小。

obj = m.exp(x) + x**0/yf[0]
for j in range(1,len(yb)+1):
    obj += x**j/yf[j]*yb[j-1] # It non-zero only when yb[j-1]=1 and misses the values before that.
#Without it I'm computing the entire bound everytime and changing yb has no impact.
m.Maximize(obj)

在工作解决方案中,Gekko 是如何给我正确结果的?当函数是如下约束时(即不在 for 循环内使用 m.maximize),如何重现此行为?谢谢。

编辑: (修改了上面的python代码)。下图说明了这个问题。考虑 yb=[0,1,0] => y=2。所以总和应该停止在 i=0 to 1

如果 xyb 是普通列表,我可以很容易地做到这一点,然后我可以从下面得到预期的结果。

import numpy as np
from scipy.special import factorial

x = 3
yb = [0,1,0]
y = np.sum([yb[i]*(i+1) for i in range(3)])
yf = factorial(np.linspace(0,len(yb),len(yb)+1))
obj = np.exp(x)
for j in range(0,y):
    obj += x**j/yf[j] 
print(obj)

如果我不希望最终的方程大小随变量而变化,我可以执行以下操作。

x = 3
yb = [0,1,0]
y = np.sum([yb[i]*(i+1) for i in range(3)])
yf = factorial(np.linspace(0,len(yb),len(yb)+1))
obj = np.exp(x)
for i in range(0,y):
    yb[i] = 1
for j in range(0,len(yb)):
    obj += (x**j/yf[j]) * yb[j]
print(obj)

我不能用 Gekko 做这两个选项,因为 xyb 是 GKVariable(设计变量)并且不能解释为整数(即​​)range(y) 不起作用.有什么解决方法吗?谢谢。

由于没有任何回复,我将分享我想出的解决方法。这可能不是一种有效的方法,但它确实有效。

m = GEKKO(remote=False)
x = m.sos1([1,2,3])
yb = m.Array(m.Var,3,lb=0,ub=1,integer=True)
m.Equation(m.sum(yb)==1)
y = m.sum([yb[i]*(i+1) for i in range(3)])
#m.Equation(m.sum([yb[i]*(i+1) for i in range(3)])<2)
yf = factorial(np.linspace(0,len(yb),len(yb)+1))
obj = m.exp(x) + x**0/yf[0]
obj_temp=[]
for j in range(1,len(yb)+1):
    obj_temp.append(x**j/yf[j])
    for k in range(j):
        obj+= obj_temp[k] * yb[j-1]
m.Maximize(obj)        
m.solve()
print('x='+str(x.value[0]))
print('y='+str(y.value[0]))
print('Objective='+str(-m.options.objfcnval))

但是,我不知道 Gekko 如何在内部复制这个额外的 for loop 以及为什么它只在求和函数是 objective (m.Maximze) 时起作用,而在它时失败是一个约束(m.Equation)。