GEKKO:数组大小作为模型变量
GEKKO: Array size as a model variable
我对 Gekko 很陌生。作为优化的一部分,是否可以改变模型数组的大小?我是 运行 一个简单的问题,其中各种数量的扭转 spring 以不同的角度啮合,我想让模型改变啮合角度的数量。每个 spring 都有几个组件变量,我也试图将其定义为变量数组。但是,下面数组 theta_engage 的大小定义没有接受 int(n_engage.value)。我收到以下错误:
TypeError: int() argument must be a string, a bytes-like object or a number, not 'GK_Value'
相关代码:
n_engage = m.Var(2, lb=1, ub=10, integer=True)
theta_engage = m.Array(m.Var, (int(n_engage.value)))
theta_engage[0].value = 0.0
theta_engage[0].lower = 0.0
theta_engage[0].upper = 85.0
theta_engage[1].value = 15.0
theta_engage[1].lower = 0.0
theta_engage[1].upper = 85.0
如果我尝试仅通过 n_engage.value 定义 theta_engage 的大小,我会收到此错误:
TypeError: expected sequence object with len >= 0 or a single integer
我想我可以将数组定义为我愿意接受的最大大小,并允许 spring 的数量下限为 0,但我必须强制执行最小数量总计 springs 以某种方式在约束中。如果 Gekko 能够以这种方式改变数组的大小,那么在我看来这是更优雅的解决方案。
非常感谢任何帮助。
无法逐次更改问题结构。但是,定义一个二进制变量 b
很容易,它可以激活或停用模型中应该包含或排除的那些部分。
from gekko import GEKKO
import numpy as np
m = GEKKO()
# number of springs
n = 10
# number of engaged springs (1-10)
nb = m.Var(2, lb=1, ub=n, integer=True)
# engaged springs (binary, 0-1)
b = m.Array(m.Var,n,lb=0,ub=1,integer=True)
# angle of engaged springs
θ = m.Array(m.Param,n,lb=0,ub=85)
# initialize values
t0 = [0,15,20,25,30,15,30,25,10,50]
for i,ti in enumerate(t0):
θ[i].value = ti
# contributing spring forces
F = [m.Intermediate(b[i]*m.cos((np.pi/180.0)*θ[i])) \
for i in range(10)]
# force constraint
m.Equation(m.sum(F)>=3)
# engaged springs
m.Equation(nb==m.sum(b))
# minimize engaged springs
m.Minimize(nb)
# optimize with APOPT solver
m.options.SOLVER=1
m.solve()
# print solution
print(b)
这在 0.079 秒内给出了解决方案,弹簧 1、3、9 和 10 应该接合。它选择最小数量的弹簧 (4) 来达到所需的力,相当于 0 角度的 3 个弹簧。
Successful solution
---------------------------------------------------
Solver : APOPT (v1.0)
Solution time : 7.959999999729916E-002 sec
Objective : 4.00000000000000
Successful solution
---------------------------------------------------
[[1.0] [0.0] [1.0] [0.0] [0.0] [0.0] [0.0] [0.0] [1.0] [1.0]]
我对 Gekko 很陌生。作为优化的一部分,是否可以改变模型数组的大小?我是 运行 一个简单的问题,其中各种数量的扭转 spring 以不同的角度啮合,我想让模型改变啮合角度的数量。每个 spring 都有几个组件变量,我也试图将其定义为变量数组。但是,下面数组 theta_engage 的大小定义没有接受 int(n_engage.value)。我收到以下错误:
TypeError: int() argument must be a string, a bytes-like object or a number, not 'GK_Value'
相关代码:
n_engage = m.Var(2, lb=1, ub=10, integer=True)
theta_engage = m.Array(m.Var, (int(n_engage.value)))
theta_engage[0].value = 0.0
theta_engage[0].lower = 0.0
theta_engage[0].upper = 85.0
theta_engage[1].value = 15.0
theta_engage[1].lower = 0.0
theta_engage[1].upper = 85.0
如果我尝试仅通过 n_engage.value 定义 theta_engage 的大小,我会收到此错误:
TypeError: expected sequence object with len >= 0 or a single integer
我想我可以将数组定义为我愿意接受的最大大小,并允许 spring 的数量下限为 0,但我必须强制执行最小数量总计 springs 以某种方式在约束中。如果 Gekko 能够以这种方式改变数组的大小,那么在我看来这是更优雅的解决方案。
非常感谢任何帮助。
无法逐次更改问题结构。但是,定义一个二进制变量 b
很容易,它可以激活或停用模型中应该包含或排除的那些部分。
from gekko import GEKKO
import numpy as np
m = GEKKO()
# number of springs
n = 10
# number of engaged springs (1-10)
nb = m.Var(2, lb=1, ub=n, integer=True)
# engaged springs (binary, 0-1)
b = m.Array(m.Var,n,lb=0,ub=1,integer=True)
# angle of engaged springs
θ = m.Array(m.Param,n,lb=0,ub=85)
# initialize values
t0 = [0,15,20,25,30,15,30,25,10,50]
for i,ti in enumerate(t0):
θ[i].value = ti
# contributing spring forces
F = [m.Intermediate(b[i]*m.cos((np.pi/180.0)*θ[i])) \
for i in range(10)]
# force constraint
m.Equation(m.sum(F)>=3)
# engaged springs
m.Equation(nb==m.sum(b))
# minimize engaged springs
m.Minimize(nb)
# optimize with APOPT solver
m.options.SOLVER=1
m.solve()
# print solution
print(b)
这在 0.079 秒内给出了解决方案,弹簧 1、3、9 和 10 应该接合。它选择最小数量的弹簧 (4) 来达到所需的力,相当于 0 角度的 3 个弹簧。
Successful solution
---------------------------------------------------
Solver : APOPT (v1.0)
Solution time : 7.959999999729916E-002 sec
Objective : 4.00000000000000
Successful solution
---------------------------------------------------
[[1.0] [0.0] [1.0] [0.0] [0.0] [0.0] [0.0] [0.0] [1.0] [1.0]]