如何解决使用二进制选择器的边界优化求和函数 - GEKKO
我正在尝试优化求和函数。从类似的 question 中,我找到了我问题的一半答案(我已经使我的目标函数类似于该问题中的目标函数)。
问题:
尝试:
from gekko import GEKKO
import numpy as np
from scipy.special import factorial
m = GEKKO(remote=False)
x = m.sos1([1,2,3])
yb = m.Array(m.Var,3,lb=0,ub=1,integer=True)
m.Equation(m.sum(yb)==1)
y = m.sum([yb[i]*(i+1) for i in range(3)])
m.Equation(m.sum([yb[i]*(i+1) for i in range(3)])<2)
yf = factorial(np.linspace(0,len(yb),len(yb)+1))
obj = m.exp(x)
for j in range(0,len(yb)):
obj += x**j/yf[j]
m.Maximize(obj*yb[j])
m.solve()
print('x='+str(x.value[0]))
print('y='+str(y.value[0]))
print('Objective='+str(-m.options.objfcnval))
这有效,但仅当我在 for 循环中添加 m.Maximize
时才有效。在循环内没有 m.Maximize
的情况下运行相同的结果会产生错误的结果(如下所示)。问题在于二元选择器 yb
。当 yb = [0,1,0]
=> y=2
时,求和界限将为 i=0 到 2。但我无法获得此行为。我无法使用 range(y)
运行 for 循环,因为它是一个 GKVariable 并且它会随着变量值的变化而改变方程的大小。
obj = m.exp(x) + x**0/yf[0]
for j in range(1,len(yb)+1):
obj += x**j/yf[j]*yb[j-1] # It non-zero only when yb[j-1]=1 and misses the values before that.
#Without it I'm computing the entire bound everytime and changing yb has no impact.
m.Maximize(obj)
在工作解决方案中,Gekko 如何给我正确的结果?当函数是如下约束时(即在 for 循环中不使用 m.maximize
),如何重现这种行为?谢谢。
编辑:
(修改了上面的python代码)。下图说明了这个问题。考虑yb=[0,0]
=> y=2
。所以求和应该停在 i=0 to 1
如果 x
和 yb
是普通列表,我可以轻松做到这一点,然后我可以从下面得到预期的结果。
import numpy as np
from scipy.special import factorial
x = 3
yb = [0,0]
y = np.sum([yb[i]*(i+1) for i in range(3)])
yf = factorial(np.linspace(0,len(yb)+1))
obj = np.exp(x)
for j in range(0,y):
obj += x**j/yf[j]
print(obj)
如果我不希望最终方程大小随变量变化,我可以执行以下操作。
x = 3
yb = [0,len(yb)+1))
obj = np.exp(x)
for i in range(0,y):
yb[i] = 1
for j in range(0,len(yb)):
obj += (x**j/yf[j]) * yb[j]
print(obj)
我不能用 Gekko 做这两个选项,因为 x
和 yb
是 GKVariable(设计变量)并且不能被解释为整数(即)range(y)
不起作用。有什么解决方法吗?谢谢。
解决方法
由于没有任何回复,我正在分享我想出的解决方法。这可能不是一种有效的方法,但它确实有效。
m = GEKKO(remote=False)
x = m.sos1([1,2,3])
yb = m.Array(m.Var,3,lb=0,ub=1,integer=True)
m.Equation(m.sum(yb)==1)
y = m.sum([yb[i]*(i+1) for i in range(3)])
#m.Equation(m.sum([yb[i]*(i+1) for i in range(3)])<2)
yf = factorial(np.linspace(0,len(yb),len(yb)+1))
obj = m.exp(x) + x**0/yf[0]
obj_temp=[]
for j in range(1,len(yb)+1):
obj_temp.append(x**j/yf[j])
for k in range(j):
obj+= obj_temp[k] * yb[j-1]
m.Maximize(obj)
m.solve()
print('x='+str(x.value[0]))
print('y='+str(y.value[0]))
print('Objective='+str(-m.options.objfcnval))
然而,我不知道 Gekko 如何在内部复制这个额外的 for loop
以及为什么它只在求和函数是目标(m.Maximze
)时才有效,而在它是约束时失败({{ 1}}).
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。