Edit: As @Laurent Perron says, it is probably better to model your problem using booleans.
model = cp_model.CpModel()
solver = cp_model.CpSolver()
shifts = {}
values = range(3+1)
for i in range(5):
for j in values:
shifts[i, j] = model.NewBoolVar(f"{i} == {j}")
# for each shift only 1 value is true
model.Add(sum(shifts[i, j] for j in values) == 1)
# number of booleans where value is 1 == 3
model.Add(sum(shifts[i, 1] for i in range(5)) == 3)
solver = cp_model.CpSolver()
status = solver.Solve(model)
for i in range(5):
for j in values:
if solver.Value(shifts[i, j]):
print(i, "==", j)
Original answer:
You can't sum constraints, create one boolvar per position, link the variables using model.Add(shifts[i]==1).OnlyEnforceIf(ones[i])
and constraint sum(ones)
instead.
from ortools.sat.python import cp_model
model = cp_model.CpModel()
solver = cp_model.CpSolver()
shifts = {}
ones = {}
for i in range(5):
shifts[i] = model.NewIntVar(0, 3, "shifts(%i)" % i)
ones[i] = model.NewBoolVar("")
model.Add(shifts[i] == 1).OnlyEnforceIf(ones[i])
model.Add(shifts[i] != 1).OnlyEnforceIf(ones[i].Not())
model.Add(sum(ones.values()) == 3)
solver = cp_model.CpSolver()
status = solver.Solve(model)
for i in range(5):
print(solver.Value(shifts[(i)]))