我尝试将以下约束添加到我的模型中。我的问题:函数 g() 期望 x 作为二进制 numpy 数组。所以结果 arr_a 取决于优化的每一步中 x 的当前值!之后,我希望这个数组乘以 x 的最大值小于 50。
如何动态添加此约束,以便在每次迭代时始终使用 x 的值正确计算 arr_a ,同时告诉模型保持约束 arr_a * x <= 50 ?目前我在向模型添加约束时遇到错误,因为 g() 期望 x 作为 numpy 数组来计算 arr_a、arr_b、arr_c ( g 在其计算中使用 np.where(x == 1) )。
#Init model
from ortools.sat.python import cp_model
model = cp_model.CpModel()
# Declare the variables
x = []
for i in range(self.ds.n_banks):
x.append(model.NewIntVar(0, 1, "x[%i]" % (i)))
#add bool vars
a = model.NewBoolVar('a')
arr_a, arr_b, arr_c = g(df1,df2,df3,x)
model.Add((arr_a.astype('int32') * x).max() <= 50).OnlyEnforceIf(a)
model.Add((arr_a.astype('int32') * x).max() > 50).OnlyEnforceIf(a.Not())
之后我添加了自然也依赖于 x 的目标函数。
model.Minimize(target(x))
def target(x):
arr_a, arr_b, arr_c = g(df1,df2,df3,x)
return (3 * arr_b * x + 2 * arr_c * x).sum()
编辑:
我的问题发生了一些变化,我设法让它毫无问题地工作。然而,我体验到约束从未真正得到满足!自定义函数是一个高度非线性函数,它需要 x==1 和 x == 0 的索引,并返回一个 numpy 数组。此外,无法使用 sat.solver 的预定义函数重新构建它。
#Init model
model = cp_model.CpModel()
# Declare the variables
x = [model.NewIntVar(0, 1, "x[%i]" % (i)) for i in range(66)]
# add hints
[model.AddHint(x[i],np.random.choice(2, 1, p=[0.4, 0.6])[0]) for i in range(66)]
open_elements = [model.NewBoolVar("open_elements[%i]" % (i)) for i in range(66)]
closed_elements = [model.NewBoolVar("closed_elements[%i]" % (i)) for i in range(6)]
# open indices as bool vars
for i in range(66):
model.Add(x[i] == 1).OnlyEnforceIf(open_elements[i])
model.Add(x[i] != 1).OnlyEnforceIf(open_elements[i].Not())
model.Add(x[i] != 1).OnlyEnforceIf(closed_elements[i])
model.Add(x[i] == 1).OnlyEnforceIf(closed_elements[i].Not())
model.Add((self-defined-function(np.where(open_elements), np.where(closed_elements), some_array).astype('int32') * x - some_vector).all() <= 0)
即使我应用了更简单的功能,它也无法正常工作。
model.Add((self-defined-function(x, some_array).astype('int32') * x - some_vector).all() <= 0)
我还尝试了以下方法:
arr_indices_open = []
arr_indices_closed = []
for i in range(66):
if open_elements[i] == True:
arr_indices_open.append(i)
else:
arr_indices_closed.append(i)
# final Constraint
arr_ = self-defined-function(arr_indices_open, arr_indices_closed, some_array)[0].astype('int32')
for i in range(66):
model.Add(arr_[i] * x[i] <= some_other_vector[i])
自定义函数的一些最小示例,我只是尝试说 n_closed 应小于 10。即使求解器不满足该条件:
def self_defined_function(arr_indices_closed)
return len(arr_indices_closed)
arr_ = self-defined-function(arr_indices_closed)
for i in range(66):
model.Add(arr_ < 10)