Gekko,将动态参数传递给 pwl

Gekko, pass dynamic parameter to pwl

这个示例代码完美地演示了我的问题

from gekko import GEKKO
model = GEKKO(remote=False)
x = model.Array(model.Var,(10),lb=0, ub=2,value=0)

b = model.Array(model.Var,(3))
p = []
p.append(model.Param(sum(x)/10+0.25))
p.append(model.Param(sum(x)/10))
d = 1e-5
x_data = [-1e5,0.25,0.25+d,1,1+d,1.5,1.5+d,1e5]
y_data = [0.1,0.1,0.75,0.75,1.25,1.25,1.7,1.7]
model.pwl(p[0], b[0], x_data, y_data)
model.pwl(p[1], b[1], x_data, y_data)
model.pwl(x[0], b[2], x_data, y_data)

model.options.IMODE = 2
model.options.SOLVER = 1
model.Obj(-1*(b[0]+b[1]))
model.solve()
print(x)
print(p)
print(b)

这是一个成功的解决方案,objective 为 7.6(甚至不确定它来自哪里),但所有 x 值都设置为 0,除了 x[1] 为 1,这意味着p[0] 为 0.35 而 p[1] 为 0.1。情况并非如此,因为两者都等于零。 b[0] 和 b[1] 等于 1.7,即使 p[0] 和 p[1] 正确,情况也不应该如此。 b[2] 正确设置为 0.75.

p[0]p[1]为参数时,值在初始化时指定,不会用x的新值更新。要使用 x 的值更新它们,您可以将它们指定为变量 m.Var() 并添加几个方程式。

from gekko import GEKKO
model = GEKKO(remote=False)
x = model.Array(model.Var,10,lb=0, ub=2,value=0)

b = model.Array(model.Var,3)
p = model.Array(model.Var,2)
model.Equation(p[0]==model.sum(x)/10+0.25)
model.Equation(p[1]==model.sum(x)/10)
d = 1e-5
x_data = [-1e5,0.25,0.25+d,1,1+d,1.5,1.5+d,1e5]
y_data = [0.1,0.1,0.75,0.75,1.25,1.25,1.7,1.7]
model.pwl(p[0], b[0], x_data, y_data)
model.pwl(p[1], b[1], x_data, y_data)
model.pwl(x[0], b[2], x_data, y_data)

model.options.IMODE = 3
model.options.SOLVER = 1
model.Maximize(b[0]+b[1])
model.solve()
print('x:' + str(x))
print('p:' + str(p))
print('b:' + str(b))

我还切换到 model.Maximize() 而不是 model.Obj(-1*()) 并将 Python sum 替换为效率更高的 gekko model.sum() ,尤其是对于大型-规模问题。您也可以 运行 in IMODE=3 因为您只有一个模型实例已求解。 IMODE=2 适用于数据回归问题,其中您有多个数据点并且对每个数据点应用相同的模型。更新后的问题给出了解决方案:

x:[[1.0] [0.54918319668] [0.54918319668] [0.54918319668] [0.54918319668]
 [0.54918319668] [0.54918319668] [0.54918319668] [0.65581762324] [2.0]]
p:[[1.00001] [0.75001]]
b:[[1.7] [1.7] [0.75]]

PWL 松弛变量可能对 objective 函数有一些贡献。我建议您不要使用求解器 objective,而是在报告解决方案后重新计算 objective。详见PWL function are given in the documentation.