gekko - 如何在 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
解决方案
您可以尝试的一件事是使用 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 变量、参数或表达式x1
andx2
: 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
,特别是如果存在干扰if2
MPCC 的竞争目标。
推荐阅读
- powershell - 在Powershell中将字符串与数字进行比较
- config - nuxt.config.js:为开发或生产加载不同的配置
- node.js - 如何正确处理 context.sendActivity?
- systemd - systemd-udev 规则多次应用(在我的情况下是两次)
- java - Java:如何解析 Oracle DB 表中的 XML 类型列数据?
- ios - FBAudienceNetwork for iOS 静态还是动态?
- curl - 正方形 INVALID_REQUEST_ERROR
- svg - 如果我现在使用文本,如何在 svg 中显示分数
- python - BeautfilSoup Python,获取两个标签之间的所有文本
- c++ - 打开与 Qt/C++ 的数据库连接