【问题标题】:How to use if2/3 in GekkoGekko中if 2/3的使用方法
【发布时间】:2020-09-05 21:09:54
【问题描述】:

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

为了模拟植物的放置,我尝试使用一组二进制变量来标记,即如果植物被使用则为 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) 应该返回 01,但似乎没有这样做。我乘以-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。如果我交换 x1x2 或者条件 >=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


    【解决方案1】:

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

    couple examples in the documentation 也可能有所帮助。您可能还想查看sign2/sign3 函数和max2/max3 函数,它们也可能会为您提供所需的结果。

    if2 文档

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

    if3 文档

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

    用法

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

    输入:

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

    输出:

    • y = x1condition<0
    • y = x2condition>=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)
    

    additional information 在基于梯度的优化器的逻辑条件下以及2 (MPCC)3 (binary) 类型之间的区别。

    对 EDIT1 的回应

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

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

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

    【讨论】:

    • 您好,感谢您的回复。您的答案的第一段包含几个我无法分开的概念。如何将开关点设置为 1e-3?如我所见,if2/3 到 0 的切换点都是硬编码的:条件=0。然后你说“当开关点为零时……”但在上一句中它被设置为 1e-3。我知道我的困惑很愚蠢,但请多多包涵。
    猜你喜欢
    • 1970-01-01
    • 2021-02-04
    • 1970-01-01
    • 2019-03-19
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-01-18
    • 1970-01-01
    相关资源
    最近更新 更多