Gekko,PWL 函数结果不符合预期
Gekko, PWL function result is not as expected
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 保持原样。可能有一种更简单的方法来完成我正在尝试做的事情,但我也想了解为什么这种方法会产生这种结果。
编辑
添加一个 objective 函数 - 就像 model.Obj(model.sum(z2))
- 似乎使求解器也操纵了这些变量,这至少可以说是不受欢迎的。如果当前设置无法生成解决方案,我希望看到错误而不是“固定”变量的变化
我希望 z2 为 [[1],[1],[1]]
,因为 PWL 输出在 0
和 +1e-5
(输入)之间从 0
上升到 1
。以下是接近解决方案的一些事项:
- 使用
m.options.SOLVER=1
尝试 APOPT
解算器。它是一个活动集求解器,而不是使用障碍方法的默认 IPOPT
求解器。活动集求解器倾向于 return 更精确的解决方案,尤其是在定义解决方案时涉及障碍项的情况下。
- 为
z2
使用整数变量(使用 APOPT
求解器)。如果这是一个约束,这也将帮助您找到一个整数解决方案。
- 使用更严格的解决方案公差,例如
m.options.RTOL=1e-9
。默认容差为 1e-6
。如果您需要更精确的 objective 函数,您可能还需要调整 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 函数使用松弛变量。包含另一个 objective 可能会干扰正确的 PWL 解决方案。处理的方法是 model.Obj(model.sum(z2))
的相对 objective 具有比 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 功能。
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 保持原样。可能有一种更简单的方法来完成我正在尝试做的事情,但我也想了解为什么这种方法会产生这种结果。
编辑
添加一个 objective 函数 - 就像 model.Obj(model.sum(z2))
- 似乎使求解器也操纵了这些变量,这至少可以说是不受欢迎的。如果当前设置无法生成解决方案,我希望看到错误而不是“固定”变量的变化
我希望 z2 为 [[1],[1],[1]]
,因为 PWL 输出在 0
和 +1e-5
(输入)之间从 0
上升到 1
。以下是接近解决方案的一些事项:
- 使用
m.options.SOLVER=1
尝试APOPT
解算器。它是一个活动集求解器,而不是使用障碍方法的默认IPOPT
求解器。活动集求解器倾向于 return 更精确的解决方案,尤其是在定义解决方案时涉及障碍项的情况下。 - 为
z2
使用整数变量(使用APOPT
求解器)。如果这是一个约束,这也将帮助您找到一个整数解决方案。 - 使用更严格的解决方案公差,例如
m.options.RTOL=1e-9
。默认容差为1e-6
。如果您需要更精确的 objective 函数,您可能还需要调整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 函数使用松弛变量。包含另一个 objective 可能会干扰正确的 PWL 解决方案。处理的方法是 model.Obj(model.sum(z2))
的相对 objective 具有比 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 功能。