如何在Google或工具中获取行索引?

问题描述

我有一个二维布尔数组,我想找到每个不为0的列元素的行索引(index + 1),如果列的所有元素都为0,则得到的行索引是0.另外,每一列最多具有1个不为0的值。我该怎么办?

enter image description here

以下代码无法处理一列全为零的情况

model = cp_model.CpModel()
solver = cp_model.cpsolver()

shifts = {}
worker_shift={}


for i in range(6):
    worker_shift[(i)]=model.NewIntvar(0,6,"worker_shift(%i)" % (i))
    for j in range(6):
        shifts[(i,j)] = model.NewBoolVar("shifts(%i,%i)" % (i,j))

for j in range(6): 
    model.Add(sum(shifts[(i,j)] for i in range(6))<=1)


for j in range(6):
    for i in range(6):
        model.Add(worker_shift[(j)]==i+1).OnlyEnforceIf(shifts[(i,j)])  

        
model.Add(shifts[(2,1)]==1)

r1= np.empty([6,6],dtype = int)
r2=np.empty([1,dtype = int)


status = solver.solve(model) 
print("status:",status) 
for i in range(6):
    r2[0,i]=solver.Value(worker_shift[(i)])
    for j in range(6):
        r1[i,j]=solver.Value(shifts[(i,j)])

print(r1)    
print("----------------------")
print(r2)   

enter image description here

解决方法

我们来看一列

[b1..bn]

如果我们创建

pi == n - bi * (n - i)

然后使用model.AddMinEquality()min([pi])计算与您的代码相同的想法。

现在让我们介绍e一个新的布尔变量。

我们想要

e <=> bool_or(pi)

我们以通常的方式进行编码

for all i,pi => e  (using model.AddImplication())
bool_or([b1,...,bn,e.Not()])  (reverse implication,if all bi are false,then e is false.

现在,我们可以使用新的IntVar pe[0..n]

使用正确的min()
model.Add(pe = e*n)
model.AddMinEquality(target,[p1,..,pn,pe])
,

感谢@Laurent Perron,@ Stradivari!

我在@Stradivari的博客(https://www.xiang.dev/cp-sat/#iff-equivalence-boolean-product)中研究了or-tools的介绍,我使用以下代码:

for j in range(6):
   model.Add(worker_shift[(j)]==0).OnlyEnforceIf([shifts[(i,j)].Not() for i in range(6) ]) 
   for i in range(6):
      model.Add(worker_shift[(j)]==i+1).OnlyEnforceIf(shifts[(i,j)]) 

似乎运作良好!

完整代码如下:

model = cp_model.CpModel()
solver = cp_model.CpSolver()
shifts = {}
worker_shift={}

for i in range(6):
   worker_shift[(i)]=model.NewIntVar(0,6,"worker_shift(%i)" % (i))
   for j in range(6):
      shifts[(i,j)] = model.NewBoolVar("shifts(%i,%i)" % (i,j))

for j in range(6): 
   model.Add(sum(shifts[(i,j)] for i in range(6))<=1)


for j in range(6):
   model.Add(worker_shift[(j)]==0).OnlyEnforceIf([shifts[(i,j)]) 

model.Add(worker_shift[(2)]==0)
model.Add(worker_shift[(0)]==0)
model.Add(worker_shift[(3)]==0)
model.Add(shifts[(2,1)]==1)
model.Add(shifts[(3,4)]==1)

r1= np.empty([6,6],dtype = int)
r2=np.empty([1,dtype = int)

status = solver.Solve(model) 
print("status:",status) 
for i in range(6):
   r2[0,i]=solver.Value(worker_shift[(i)])
   for j in range(6):
      r1[i,j]=solver.Value(shifts[(i,j)])

print(r1)    
print("----------------------")
print(r2)

enter image description here