From 06ee4ee6da5fb4e7568085ceaf6bd1d62fd95162 Mon Sep 17 00:00:00 2001 From: Laurent Perron Date: Tue, 22 Apr 2025 20:16:32 +0200 Subject: [PATCH] [CP-SAT] one more presolve rule --- ortools/flatzinc/fz.cc | 2 +- ortools/sat/cp_model_presolve.cc | 33 ++++++++++++++++++++++++++++++++ 2 files changed, 34 insertions(+), 1 deletion(-) diff --git a/ortools/flatzinc/fz.cc b/ortools/flatzinc/fz.cc index 686f46fd8b..c17cb247bb 100644 --- a/ortools/flatzinc/fz.cc +++ b/ortools/flatzinc/fz.cc @@ -28,7 +28,7 @@ #include "absl/flags/flag.h" #include "absl/log/check.h" - +#include "absl/log/flags.h" #include "absl/log/initialize.h" #include "absl/log/log.h" #include "absl/strings/match.h" diff --git a/ortools/sat/cp_model_presolve.cc b/ortools/sat/cp_model_presolve.cc index 1b7f5092ca..44e4022dfa 100644 --- a/ortools/sat/cp_model_presolve.cc +++ b/ortools/sat/cp_model_presolve.cc @@ -5909,6 +5909,39 @@ bool CpModelPresolver::PresolveNoOverlap(ConstraintProto* ct) { } } + { + // Special case for "all-diff" encoded as no-overlap. + int num_size_zero_or_one = 0; + for (const int index : proto->intervals()) { + const IntervalConstraintProto& interval = + context_->working_model->constraints(index).interval(); + const LinearExpressionProto& size = interval.size(); + if (size.vars().empty() && size.offset() >= 0 && size.offset() <= 1) { + ++num_size_zero_or_one; + } else { + break; // early abort + } + } + const int initial_num_intervals = proto->intervals().size(); + if (num_size_zero_or_one == initial_num_intervals) { + // If there is only size one, we can remove the size zero as there is + // no constraint on them. + int new_size = 0; + for (const int index : proto->intervals()) { + const IntervalConstraintProto& interval = + context_->working_model->constraints(index).interval(); + if (interval.size().offset() == 0) continue; + proto->set_intervals(new_size++, index); + } + if (new_size < initial_num_intervals) { + proto->mutable_intervals()->Truncate(new_size); + changed = true; + context_->UpdateRuleStats("no_overlap: removed size 0 from all diff."); + } + context_->UpdateRuleStats("TODO no_overlap: only size one !"); + } + } + if (proto->intervals_size() == 1) { context_->UpdateRuleStats("no_overlap: only one interval"); return RemoveConstraint(ct);