GEKKO:计算数组中的出现次数作为条件
GEKKO: count ocurrences in array as condition
我正在为 INLP 使用 gekko,即整数非线性规划。
我有一个整数变量数组;但是,我的条件是任何值都不能出现多次,即
代码:
from gekko import GEKKO
model = GEKKO()
model.options.SOLVER = 1
x = model.Array(model.Var, 2, lb=0, ub=10, integer=True)
for m in range(11):
model.Equation(x.count(m) <= 1)
model.Obj(sum(x))
model.solve()
给出错误:
类型错误:'int' 类型的对象没有 len()
为什么我不能那样做?
Numpy count
函数不为求解器提供梯度,因此在 gekko 方程中不受支持。解决该问题的另一种方法是使用二进制变量 b
来确定在 0 和 10 之间选择哪 2 个数字。
from gekko import GEKKO
model = GEKKO()
model.options.SOLVER = 1
n = 10
b = model.Array(model.Var, 11, lb=0, ub=1, integer=True)
y = [model.Intermediate(b[i]*i) for i in range(11)]
model.Equation(model.sum(b)==2)
model.Minimize(model.sum(y))
model.solve()
print('b: ' + str(b))
print('y: ' + str(y))
解决方法是:
b: [[1.0] [1.0] [0.0] [0.0] [0.0] [0.0] [0.0] [0.0] [0.0] [0.0] [0.0]]
y: [[0.0], [1.0], [0.0], [0.0], [0.0], [0.0], [0.0], [0.0], [0.0], [0.0], [0.0]]
是正确的,因为选择了0和1来最小化求和。如果切换到 m.Maximize(model.sum(y))
,则求解器会选择 9 和 10。
b: [[0.0] [0.0] [0.0] [0.0] [0.0] [0.0] [0.0] [0.0] [0.0] [1.0] [1.0]]
y: [[0.0], [0.0], [0.0], [0.0], [0.0], [0.0], [0.0], [0.0], [0.0], [9.0], [10.0]]
这没有给出 x
的解决方案作为仅包含 2 个数字的数组。您也可以在应用程序中使用 y
。
这是一种将 y
压缩为 x
的方法:
from gekko import GEKKO
model = GEKKO()
model.options.SOLVER = 1
b = model.Array(model.Var, (11,2), lb=0, ub=1, integer=True)
x = [None]*2
for j in range(2):
x[j] = model.sum([model.Intermediate(b[i,j]*i) for i in range(11)])
model.Equations([model.sum(b[:,j])==1 for j in range(2)])
model.Equations([model.sum(b[i,:])<=1 for i in range(11)])
model.Minimize(model.sum(x))
model.solve()
print('b: ' + str(b))
print('x: ' + str(x))
这给出了解决方案:
b: [[[0.0] [1.0]]
[[1.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]]]
x: [[1.0], [0.0]]
此方法需要更多二进制变量,但求解速度仍然很快。
我正在为 INLP 使用 gekko,即整数非线性规划。 我有一个整数变量数组;但是,我的条件是任何值都不能出现多次,即
代码:
from gekko import GEKKO
model = GEKKO()
model.options.SOLVER = 1
x = model.Array(model.Var, 2, lb=0, ub=10, integer=True)
for m in range(11):
model.Equation(x.count(m) <= 1)
model.Obj(sum(x))
model.solve()
给出错误: 类型错误:'int' 类型的对象没有 len()
为什么我不能那样做?
Numpy count
函数不为求解器提供梯度,因此在 gekko 方程中不受支持。解决该问题的另一种方法是使用二进制变量 b
来确定在 0 和 10 之间选择哪 2 个数字。
from gekko import GEKKO
model = GEKKO()
model.options.SOLVER = 1
n = 10
b = model.Array(model.Var, 11, lb=0, ub=1, integer=True)
y = [model.Intermediate(b[i]*i) for i in range(11)]
model.Equation(model.sum(b)==2)
model.Minimize(model.sum(y))
model.solve()
print('b: ' + str(b))
print('y: ' + str(y))
解决方法是:
b: [[1.0] [1.0] [0.0] [0.0] [0.0] [0.0] [0.0] [0.0] [0.0] [0.0] [0.0]]
y: [[0.0], [1.0], [0.0], [0.0], [0.0], [0.0], [0.0], [0.0], [0.0], [0.0], [0.0]]
是正确的,因为选择了0和1来最小化求和。如果切换到 m.Maximize(model.sum(y))
,则求解器会选择 9 和 10。
b: [[0.0] [0.0] [0.0] [0.0] [0.0] [0.0] [0.0] [0.0] [0.0] [1.0] [1.0]]
y: [[0.0], [0.0], [0.0], [0.0], [0.0], [0.0], [0.0], [0.0], [0.0], [9.0], [10.0]]
这没有给出 x
的解决方案作为仅包含 2 个数字的数组。您也可以在应用程序中使用 y
。
这是一种将 y
压缩为 x
的方法:
from gekko import GEKKO
model = GEKKO()
model.options.SOLVER = 1
b = model.Array(model.Var, (11,2), lb=0, ub=1, integer=True)
x = [None]*2
for j in range(2):
x[j] = model.sum([model.Intermediate(b[i,j]*i) for i in range(11)])
model.Equations([model.sum(b[:,j])==1 for j in range(2)])
model.Equations([model.sum(b[i,:])<=1 for i in range(11)])
model.Minimize(model.sum(x))
model.solve()
print('b: ' + str(b))
print('x: ' + str(x))
这给出了解决方案:
b: [[[0.0] [1.0]]
[[1.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]]]
x: [[1.0], [0.0]]
此方法需要更多二进制变量,但求解速度仍然很快。