From d7db07736ff18fa4570fa2c21154794f8bcbeef8 Mon Sep 17 00:00:00 2001 From: Laurent Perron Date: Mon, 14 Nov 2022 20:35:24 +0100 Subject: [PATCH] fix infeasible LNS, was a bug in cumulative presolve --- ortools/sat/cp_model_presolve.cc | 23 ++++++++++++++--------- 1 file changed, 14 insertions(+), 9 deletions(-) diff --git a/ortools/sat/cp_model_presolve.cc b/ortools/sat/cp_model_presolve.cc index 4519fe4bc6..e0f81bae19 100644 --- a/ortools/sat/cp_model_presolve.cc +++ b/ortools/sat/cp_model_presolve.cc @@ -4860,7 +4860,7 @@ bool CpModelPresolver::PresolveCumulative(ConstraintProto* ct) { int new_size = 0; int num_zero_demand_removed = 0; int num_zero_size_removed = 0; - int num_incompatible_demands = 0; + int num_incompatible_intervals = 0; for (int i = 0; i < proto->intervals_size(); ++i) { if (context_->ConstraintIsInactive(proto->intervals(i))) continue; @@ -4871,22 +4871,27 @@ bool CpModelPresolver::PresolveCumulative(ConstraintProto* ct) { continue; } - if (context_->SizeMax(proto->intervals(i)) == 0) { + const int interval_index = proto->intervals(i); + if (context_->SizeMax(interval_index) == 0) { // Size 0 intervals cannot contribute to a cumulative. num_zero_size_removed++; continue; } - if (context_->MinOf(demand_expr) > capacity_max) { - if (context_->ConstraintIsOptional(proto->intervals(i))) { + const int64_t start_min = context_->StartMin(interval_index); + const int64_t end_max = context_->EndMax(interval_index); + if (start_min > end_max || + (context_->SizeMin(interval_index) > 0 && + context_->MinOf(demand_expr) > capacity_max)) { + if (context_->ConstraintIsOptional(interval_index)) { ConstraintProto* interval_ct = - context_->working_model->mutable_constraints(proto->intervals(i)); + context_->working_model->mutable_constraints(interval_index); DCHECK_EQ(interval_ct->enforcement_literal_size(), 1); const int literal = interval_ct->enforcement_literal(0); if (!context_->SetLiteralToFalse(literal)) { return true; } - num_incompatible_demands++; + num_incompatible_intervals++; continue; } else { // Interval is performed. return context_->NotifyThatModelIsUnsat( @@ -4894,7 +4899,7 @@ bool CpModelPresolver::PresolveCumulative(ConstraintProto* ct) { } } - proto->set_intervals(new_size, proto->intervals(i)); + proto->set_intervals(new_size, interval_index); *proto->mutable_demands(new_size) = proto->demands(i); new_size++; } @@ -4915,9 +4920,9 @@ bool CpModelPresolver::PresolveCumulative(ConstraintProto* ct) { context_->UpdateRuleStats( "cumulative: removed intervals with a size of zero"); } - if (num_incompatible_demands > 0) { + if (num_incompatible_intervals > 0) { context_->UpdateRuleStats( - "cumulative: removed intervals demands greater than the capacity"); + "cumulative: removed intervals that can't be performed"); } }