首页 > 解决方案 > 如何在 Gekko 中使用 if2/3

问题描述

我正在优化的问题是在传输网络中建造发电厂。为此,我将在每辆公共汽车上放置发电厂,并让优化告诉我应该建造哪些发电厂以最大限度地降低运行成本。

为了模拟植物的放置,我尝试使用一组二进制变量,如果完全使用植物,则标记为 1,否则标记为 0。然后在目标函数中最小化我将这个数组乘以一个常数:USEW

我做了几次尝试,没有任何工作。似乎有效的方法是直接在 Obj中使用if2函数。 Gekko功能 但是我得到了非常奇怪的结果。我的代码有点长,所以我将只发布相关行,希望这个想法会很清楚,如果不是,请告诉我,我会发布整个内容。

bus=node=24
t=24
Sbase=100.
Gen = 12
VOLL = 10000.
VOLW = 50.
USEW = 100.
Pw = m.Array(m.Var,(bus,t), lb=0., ub=0., value=0.)
for b in range(bus):
    m.Minimize( np.sum(VOLL*lsh[b,:] + VOLW*Pc[b,:])*Sbase \
               + m.if2(-1.*Sbase*m.sum(Pw[b,:]),1,0)*USEW )

问题出在if2零件上。如果我删除它,我会得到预期的结果,但是会失去放置哪种植物的决定。我也试过了,if3但也没有用。从我所见,优化器似乎正试图最小化Pw[b,:],因为结果只包含零。不知何故绕过if2部分并进入内部sum

根据文档,这部分:m.if2(-1.*Sbase*m.sum(Pw[b,:]),1,0)应该返回0或者1但似乎没有这样做。我乘以-1因为Pw总是积极的,我想检测什么时候Pw>0

我想获得有关如何为此目的正确使用条件函数的帮助。谢谢

EDIT1 考虑以下情况:

from gekko import GEKKO
m = GEKKO(remote=False)
Sbase=100.
Pw = array([[[0.0], [0.0], [0.0], [0.0], [0.0], [0.0], [0.0], [0.0], [0.0],
    [0.0], [0.0], [0.0], [0.0], [0.0], [0.0], [0.0], [0.0], [0.0],
    [0.0], [0.0], [0.0], [0.0], [0.0], [0.0]],
   [[10.0], [10.0], [10.0], [0.0], [0.0], [0.0], [0.0], [0.0], [0.0],
    [0.0], [0.0], [0.0], [0.0], [0.0], [0.0], [0.0], [0.0], [0.0],
    [0.0], [0.0], [0.0], [0.0], [0.0], [0.0]]], dtype=object)

# for np.sum(Pw[0,:])=0.0
print('sum of Pw[0,:]=', np.sum(Pw[0,:]))
print(m.if3(-1.*Sbase*np.sum(Pw[0,:]),1,0).value)
print(m.if3(-1.*Sbase*np.sum(Pw[0,:]),0,1).value)
# for np.sum(Pw[1,:])=30.0
print('sum of Pw[1,:]=', np.sum(Pw[1,:]))
print(m.if3(-1.*Sbase*np.sum(Pw[1,:]),1,0).value)
print(m.if3(-1.*Sbase*np.sum(Pw[1,:]),0,1).value)

结果总是一样的:0. 我是否交换x1以及x2条件 >=0 或 <0 都没有关系:

0.0
sum of Pw[0,:]= 0.0
0 #result 1
0 #result 2
sum of Pw[1,:]= 30.0
0 #result 3
0 #result 4

标签: gekko

解决方案


您可以尝试的一件事是使用 1e-3(或使用的某个最小值)而不是零的切换点。当开关点为零且条件1e-10为时,输出将是1因为它大于开关点。这是必需的,因为 Gekko 使用基于梯度的优化器,其解决方案容差为1e-6(默认),因此该容差内的解决方案是可以接受的。

文档中有几个示例也可能有所帮助。您可能还想查看sign2/sign3函数和max2/max3函数,它们也可能会为您提供所需的结果。

if2文档

IF 条件与互补约束开关变量。IF 语句的传统方法不是连续可微的,并且可能导致基于梯度的优化器无法收敛。该if2方法使用二进制切换变量来确定是y=x1(when condition<0) 还是y=x2(when condition>=0):

if3文档

IF 条件与二进制开关变量。IF 语句的传统方法不是连续可微的,并且可能导致基于梯度的优化器无法收敛。该if3方法使用二进制切换变量来确定是y=x1(when condition<0) 还是y=x2(when condition>=0)。

用法

y = m.if3(condition,x1,x2)

输入:

  • condition: GEKKO 变量、参数或表达式
  • x1and x2: GEKKO 变量、参数或表达式

输出:

  • y = x1什么时候condition<0
  • y = x2什么时候condition>=0
from gekko import GEKKO
m = GEKKO(remote=False)
p = m.Param()
y = m.if3(p-4,p**2,p+1)

# solve with condition<0
p.value = 3
m.solve(disp=False)
print(y.value)

# solve with condition>=0
p.value = 5
m.solve(disp=False)
print(y.value)

还有关于基于梯度的优化器的逻辑条件以及类型之间的区别的附加信息。2 (MPCC)3 (binary)

对 EDIT1 的回应

因为 Gekko 总是使用 的开关条件0,所以我们可以用 修改开关条件condition<swc并将其重新放入 gekko 形式中condition-swc<0。从我回复中的示例中,我们可以将开关条件移动swc=0.1.

swc = 0.1
y = m.if3(p-4-swc,p**2,p+1)

在您的情况下,您可以使用swc=1e-3或稍高一点的东西来避免在开关条件下的解决方案。虽然if3通常需要更长的时间来解决,但我通常会得到比 更好的结果if2,特别是如果存在干扰if2MPCC 的竞争目标。


推荐阅读