Gekko,PWL功能结果不符合预期

2024-04-29 03:07:09 发布

您现在位置:Python中文网/ 问答频道 /正文

z的值是在我的原始代码中计算的,这里我已经 给他们这些计算结果的值 它们在我的原始代码中看起来也像model.Equation(z[i] == someCalculation)

from gekko import GEKKO
model = GEKKO(remote=False)

z = model.Array(model.Var,(3))
model.Equation(z[0] == 1e-5)
model.Equation(z[1] == 4)
model.Equation(z[2] == 5.99999)

z2 = model.Array(model.Var,(3))
for i in range(3):
    d = 1e-5
    x_data = [-1e5, 0, 0+d, 6]
    y_data = [0, 0, 1, 1]
    model.pwl(z[i], z2[i], x_data, y_data)
    
model.solve()
print(z)
print(z2)

我期望z2是[[0] [1] [1]],但是我得到[[0.99035520756] [0.97749877939] [0.97771605357]],z保持它应该保持的状态。也许有一种更简单的方法来做我想做的事情,但我也想理解为什么这种方法会产生这样的结果

编辑

添加一个目标函数,比如model.Obj(model.sum(z2)),似乎使解算器也对这些变量进行了加总,这至少是不希望的。如果当前设置无法生成解决方案,我希望看到错误,而不是“固定”变量的更改


Tags: 方法代码fromimportdatamodelvararray
1条回答
网友
1楼 · 发布于 2024-04-29 03:07:09

我希望z2是[[1],[1],[1]],因为PWL输出在0+1e-5(输入)之间从0上升到1。以下是一些更接近解决方案的方法:

  • 使用m.options.SOLVER=1尝试APOPT解算器。它是一个活动集解算器,而不是使用屏障方法的默认IPOPT解算器。活动集解算器倾向于返回更精确的解,尤其是在定义解时涉及到障碍项的情况下
  • z2使用整数变量(使用APOPT解算器)。这也将帮助您找到一个整数解决方案,如果这是一个约束的话
  • 使用更严格的解决方案容差,例如m.options.RTOL=1e-9。默认公差为1e-6。如果需要更精确的目标函数,可能还需要调整m.options.OTOL

我将方程切换到model.Equation(z[0] == -1e-5),以显示[[0],[1],[1]]的解

from gekko import GEKKO
model = GEKKO(remote=False)

z = model.Array(model.Var,(3))
model.Equation(z[0] == -1e-5)
model.Equation(z[1] == 4)
model.Equation(z[2] == 5.99999)

z2 = model.Array(model.Var,(3)) #,integer=True)
for i in range(3):
    d = 1e-5
    x_data = [-1e5, 0, 0+d, 6]
    y_data = [0, 0, 1, 1]
    model.pwl(z[i], z2[i], x_data, y_data)

#model.options.RTOL = 1e-9
model.options.SOLVER = 1
model.solve()
print(z)
print(z2)

编辑

正如您所发现的,PWL函数使用slack变量。包括另一个目标可能会干扰正确的PWL解决方案。处理这个问题的方法是model.Obj(model.sum(z2))的相对目标的梯度比PWL函数的梯度小。这是一个最小化0.1*sum(z2)并最大化0.01*sum(z)的示例

from gekko import GEKKO
model = GEKKO(remote=False)

z = model.Array(model.Var,(3),value=1)

z2 = model.Array(model.Var,(3)) #,integer=True)
for i in range(3):
    d = 1e-5
    x_data = [-1e5, 0, 0+d, 6]
    y_data = [0, 0, 1, 1]
    model.pwl(z[i], z2[i], x_data, y_data)

# first most important objective is PWL (gradient = 1)

# second most important objective is to minimize z2 
model.Minimize(0.1*model.sum(z2))

# third most important objective is to maximize z
model.Maximize(0.01*model.sum(z))

model.options.SOLVER = 1
model.solve()
print(z)
print(z2)

这正确地给出了解决方案:

[[0.0] [0.0] [0.0]]
[[0.0] [0.0] [0.0]]

或者,您可以使用以下方法最大化0.1*sum(z2)和最小化0.01*sum(z)

from gekko import GEKKO
model = GEKKO(remote=False)

z = model.Array(model.Var,(3),value=1)

z2 = model.Array(model.Var,(3)) #,integer=True)
for i in range(3):
    d = 1e-5
    x_data = [-1e5, 0, 0+d, 6]
    y_data = [0, 0, 1, 1]
    model.pwl(z[i], z2[i], x_data, y_data)

# first most important objective is PWL (gradient = 1)

# second most important objective is to minimize z2 
model.Maximize(0.1*model.sum(z2))

# third most important objective is to maximize z
model.Minimize(0.01*model.sum(z))

model.options.SOLVER = 1
model.solve()
print(z)
print(z2)

给予:

[[1e-05] [1e-05] [1e-05]]
[[1.0] [1.0] [1.0]]

我很感激这个警告信息。然而,当语法正确时,通常很难在模型中找到错误,但存在可能导致不希望的解决方案的配置。希望您的优秀问题能够帮助其他人完成PWL功能

相关问题 更多 >