如果我有一个像 python 中那样的字符串列表,如下所示:
my_list = ["x", "y", "x", "x", "x", "x", "y"]
我想最大化“x”的数量,同时也最大化两个索引之外的“y”的数量
我该如何使用 GEKKO 来做到这一点?
这是我的想法:
from gekko import GEKKO
m = GEKKO(remote=False)
def count_x(lst):
return sum([1 if item == 'x' else 0 for item in lst])
def count_y(lst):
return len(lst) - count_x(lst)
my_list = ["x", "y", "x", "x", "x", "x", "y"]
def loss_function(x) -> int:
x_0 = int(str(x[0].value))
x_1 = int(str(x[1].value))
return -1*count_y(my_list[:x_0]) - count_x(my_list[x_0:x_1]) - count_y(my_list[x_1:])
x = m.Array(m.Var, 2, lb=0, ub=len(my_list),integer=True)
m.Minimize(loss_function(x))
m.Equation(x[0] <= x[1])
m.solve()
print(x)
当我取出 x_0 和 x_1 时,出现此错误:
TypeError: slice indices must be integers or None or have an __index__ method
当我离开 x_0 和 x_1 时,我得到以下输出:
WARNING: objective equation 2 has no variables ss.Eqn(2) 0 = -4
我期望得到的是 [[2.0] [6.0]] 但我得到的是 [[0.0] [0.0]]
预先感谢您的帮助!
Gekko 构建模型一次,然后将其传递给混合整数非线性规划求解器 (APOPT)。 Python 函数没有回调。这是解决问题的一种方法,使用二进制变量来指示在选择中最大化
x
和最小化 y
的部分。
from gekko import GEKKO
import numpy as np
m = GEKKO(remote=False)
def opt_seg(z):
nz = len(z)
zb = [1 if i=='x' else 0 for i in z]
b = m.Array(m.Var,nz,value=1,lb=0,ub=1,integer=True)
[m.Maximize(zb[i]*b[i]) for i in range(nz)]
[m.Minimize(2*(1-zb[i])*b[i]) for i in range(nz)]
d = [m.Intermediate(b[i]-b[i-1]) for i in range(1,nz)]
m.Equation(m.sum(d)==0)
m.options.SOLVER = 1
m.solve(disp=False)
return (np.argmax(d)+1,np.argmin(d)+1)
z = ["x", "y", "x", "x", "x", "x", "y"]
print('-'*10)
print(z)
print(opt_seg(z))
z = ["x", "y", "y", "x", "x", "y", "y"]
print('-'*10)
print(z)
print(opt_seg(z))
z = ["y", "x", "x", "x", "y", "x", "y", "y", "x", "x", "y"]
print('-'*10)
print(z)
print(opt_seg(z))
对解进行后处理以获得范围。这是几个不同测试条件下的输出:
----------
['x', 'y', 'x', 'x', 'x', 'x', 'y']
(2, 6)
----------
['x', 'y', 'y', 'x', 'x', 'y', 'y']
(3, 5)
----------
['y', 'x', 'x', 'x', 'y', 'x', 'y', 'y', 'x', 'x', 'y']
(1, 4)