微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

ORTools CP-Sat 求解器通道约束依赖于 x

如何解决ORTools CP-Sat 求解器通道约束依赖于 x

我尝试将以下约束添加到我的模型中。我的问题:函数 g() 期望 x 作为二进制 numpy 数组。所以结果 arr_a 取决于优化的每一步中 x 的当前值! 之后,我希望这个数组乘以 x 的最大值小于 50。

如何动态添加此约束,以便在每次迭代时始终使用 x 的值正确计算 arr_a ,同时告诉模型保持约束 arr_a * x

#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,x)
   return  (3 * arr_b * x + 2 * arr_c * x).sum()

编辑

我的问题发生了一些变化,我设法让它正常工作。尽管如此,我体验到约束实际上从未得到满足!自定义函数一个高度非线性的函数,它期望索引 where x==1 和 where x == 0 并返回一个 numpy 数组。也无法使用 sat.solver 的预定义函数重新构建它。

#Init model
model = cp_model.CpModel()

# Declare the variables
x = [model.NewIntvar(0,"x[%i]" % (i)) for i in range(66)]
# add hints
[model.AddHint(x[i],np.random.choice(2,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)

解决方法

我不确定我是否完全理解这个问题,但一般来说,如果您想优化函数 g(x),则必须使用求解器的原语 (docs) 来实现它。

当您的计算与现有求解器函数一致时,这样做会更容易,例如:如果您正在尝试计算线性表达式;但是在尝试计算更复杂的东西时可能会变得更难。但是,我相信这是唯一的方法。

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。