I tried to use Assumptions in CP-SAT in python. I assumed that SufficientAssumptionsForInfeasibility will give the SMALLEST list of assumptions that make the model infeasible, but the list I got is not always the smallest possible.
from ortools.sat.python import cp_model
import random
n = 5
upper_bound = 100
model = cp_model.CpModel()
start_vars = [model.NewIntVar(0, upper_bound, f"start_{i}") for i in range(n)]
end_vars = [model.NewIntVar(0, upper_bound, f"end_{i}") for i in range(n)]
duration_vars = [model.NewIntVar(0, upper_bound , f"duration_{i}") for i in range(n)]
#durations = [random.randint(1, 50) for i in range(n)]
durations = [19, 30, 32, 49, 28]
for i in range(n):
model.Add(duration_vars[i] == durations[i])
is_present_vars = [model.NewBoolVar(f"is_present_{i}") for i in range(n)]
interval_vars = [model.NewOptionalIntervalVar(start_vars[i], duration_vars[i], end_vars[i], is_present_vars[i], f"interval_{i}") for i in range(n)]
model.AddNoOverlap(interval_vars)
model.AddAssumptions(is_present_vars)
obj_var = model.NewIntVar(0, n, 'obj')
model.Add(obj_var == sum(is_present_vars))
#model.Maximize(obj_var)
solver = cp_model.CpSolver()
print(f"DURATIONS: {durations}")
status = solver.Solve(model)
status_name = solver.StatusName(status)
print(f"STATUS: {status_name}")
infeasibles = solver.SufficientAssumptionsForInfeasibility()
print("Infeasible variables:")
for i in infeasibles:
print(model.GetBoolVarFromProtoIndex(i))
if status_name != 'INFEASIBLE':
print("Intervals:")
for i in range(n):
print(solver.Value(start_vars[i]), solver.Value(end_vars[i]) )
If I try to add an objective (uncomment #model.Maximize(obj_var) lime) then the ALL assumptions are in the list:
If I remove the assumptions but leave the objective to maximize the number of intervals then I got the correct result: