关于or-Tools OnlyEnforceIf,AddBool和问题

问题描述

我有一个布尔数组,我希望其中一些出现在这样的特定位置: [1,1,0]或[0,1],在这里我希望出现四个在阵列的头或尾上仅两个位置,我该怎么办?

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

shifts = {}
ones={}
sequence = []
for i in range(10):
        shifts[(i)] = model.NewIntvar(0,10,"shifts(%i)" % i)
        ones[(i)] = model.NewBoolVar( '%i' % i)
        
for i in range(10):
    model.Add(shifts[(i)] ==8).OnlyEnforceIf(ones[(i)])
    model.Add(shifts[(i)] == 0).OnlyEnforceIf(ones[(i)].Not()) 

#I want the four 8s in the array to only appear in two positions at the head or tail of the array,and not in other positions.
model.AddBoolAnd([ones[(0)],ones[(1)],ones[(2)],ones[(3)]])# appear in head
#model.AddBoolAnd([ones[(6)],ones[(7)],ones[(8)],ones[(9)]]) #appear in tauk ,error!

model.Add(sum(ones[(i)] for i in range(10)) == 4)
status = solver.solve(model)
print("status:",status)

res=[]
for i in range(10):
        res.append(solver.Value(shifts[(i)]))
print(res)

粗体 斜体

报价

解决方法

尝试AddAllowedAsignments

model = cp_model.CpModel()
ones = [model.NewBoolVar("") for _ in range(10)]
model.AddAllowedAssignments(
    ones,[[1,1,0],[0,1]]
)

编辑:@Laurent的建议

model = cp_model.CpModel()
ones = [model.NewBoolVar("") for _ in range(10)]
head = model.NewBoolVar("head")

# HEAD
model.AddImplication(head,ones[0])
model.AddImplication(head,ones[1])
model.AddImplication(head,ones[2])
model.AddImplication(head,ones[3])
model.AddImplication(head,ones[4].Not())
model.AddImplication(head,ones[5].Not())
...

# TAIL
model.AddImplication(head.Not(),ones[0].Not())
model.AddImplication(head.Not(),ones[1].Not())
....
model.AddImplication(head.Not(),ones[6])
model.AddImplication(head.Not(),ones[7])
model.AddImplication(head.Not(),ones[8])
model.AddImplication(head.Not(),ones[9])