diff --git a/ortools/sat/cp_model.cc b/ortools/sat/cp_model.cc index 8e5ee45cfe..025e8f088e 100644 --- a/ortools/sat/cp_model.cc +++ b/ortools/sat/cp_model.cc @@ -169,7 +169,7 @@ LinearExpr LinearExpr::Term(IntVar var, int64_t coefficient) { LinearExpr LinearExpr::BooleanSum(absl::Span vars) { LinearExpr result; - for (const IntVar& var : vars) { + for (const BoolVar& var : vars) { result.AddVar(var); } return result; @@ -190,9 +190,12 @@ LinearExpr& LinearExpr::AddConstant(int64_t value) { return *this; } -void LinearExpr::AddVar(IntVar var) { AddTerm(var, 1); } +LinearExpr& LinearExpr::AddVar(IntVar var) { + AddTerm(var, 1); + return *this; +} -void LinearExpr::AddTerm(IntVar var, int64_t coeff) { +LinearExpr& LinearExpr::AddTerm(IntVar var, int64_t coeff) { const int index = var.index_; if (RefIsPositive(index)) { variables_.push_back(var); @@ -202,6 +205,7 @@ void LinearExpr::AddTerm(IntVar var, int64_t coeff) { coefficients_.push_back(-coeff); constant_ += coeff; } + return *this; } Constraint::Constraint(ConstraintProto* proto) : proto_(proto) {} diff --git a/ortools/sat/cp_model.h b/ortools/sat/cp_model.h index 15ff90b053..86aa8fbcc5 100644 --- a/ortools/sat/cp_model.h +++ b/ortools/sat/cp_model.h @@ -268,10 +268,10 @@ class LinearExpr { LinearExpr& AddConstant(int64_t value); /// Adds a single integer variable to the linear expression. - void AddVar(IntVar var); + LinearExpr& AddVar(IntVar var); /// Adds a term (var * coeff) to the linear expression. - void AddTerm(IntVar var, int64_t coeff); + LinearExpr& AddTerm(IntVar var, int64_t coeff); /// Constructs the sum of a list of variables. static LinearExpr Sum(absl::Span vars); @@ -286,7 +286,7 @@ class LinearExpr { /// Constructs the scalar product of Booleans and coefficients. static LinearExpr BooleanScalProd(absl::Span vars, absl::Span coeffs); - /// Construncts var * coefficient. + /// Constructs var * coefficient. static LinearExpr Term(IntVar var, int64_t coefficient); /// Returns the vector of variables. diff --git a/ortools/sat/cp_model.proto b/ortools/sat/cp_model.proto index 595e93b08a..535c910e59 100644 --- a/ortools/sat/cp_model.proto +++ b/ortools/sat/cp_model.proto @@ -22,6 +22,7 @@ option java_package = "com.google.ortools.sat"; option java_multiple_files = true; option java_outer_classname = "CpModelProtobuf"; + // An integer variable. // // It will be referred to by an int32 corresponding to its index in a diff --git a/ortools/sat/cp_model_presolve.cc b/ortools/sat/cp_model_presolve.cc index a8c066acdf..75b73e6756 100644 --- a/ortools/sat/cp_model_presolve.cc +++ b/ortools/sat/cp_model_presolve.cc @@ -3028,41 +3028,32 @@ bool CpModelPresolver::PresolveNoOverlap(ConstraintProto* ct) { } // Split constraints in disjoint sets. - { - if (proto->intervals_size() > 1) { - std::vector indexed_intervals; - for (int i = 0; i < proto->intervals().size(); ++i) { - const int index = proto->intervals(i); - indexed_intervals.push_back({index, - IntegerValue(context_->StartMin(index)), - IntegerValue(context_->EndMax(index))}); - } - std::vector> components; - ConstructNonOverlappingSets(false, &indexed_intervals, &components); + if (proto->intervals_size() > 1) { + std::vector indexed_intervals; + for (int i = 0; i < proto->intervals().size(); ++i) { + const int index = proto->intervals(i); + indexed_intervals.push_back({index, + IntegerValue(context_->StartMin(index)), + IntegerValue(context_->EndMax(index))}); + } + std::vector> components; + GetOverlappingIntervalComponents(&indexed_intervals, &components); - if (components.size() > 1) { - NoOverlapConstraintProto* dest = proto; - dest->clear_intervals(); - for (const std::vector& intervals : components) { - if (components.size() <= 1) continue; + if (components.size() > 1) { + for (const std::vector& intervals : components) { + if (intervals.size() <= 1) continue; - // Create a new no_overlap constraint after the first iteration. - if (dest == nullptr) { - dest = context_->working_model->add_constraints() - ->mutable_no_overlap(); - } - // Fill in the intervals. Unfortunately, the Assign() method does not - // compile in or-tools. - for (const int i : intervals) { - dest->add_intervals(i); - } - // Zero the ptr, so than we can create a new no_overlap constraint - // at the next iteration. - dest = nullptr; + NoOverlapConstraintProto* new_no_overlap = + context_->working_model->add_constraints()->mutable_no_overlap(); + // Fill in the intervals. Unfortunately, the Assign() method does not + // compile in or-tools. + for (const int i : intervals) { + new_no_overlap->add_intervals(i); } - changed = true; - context_->UpdateNewConstraintsVariableUsage(); } + context_->UpdateNewConstraintsVariableUsage(); + context_->UpdateRuleStats("no_overlap: split into disjoint components"); + return RemoveConstraint(ct); } } diff --git a/ortools/sat/csharp/IntegerExpressions.cs b/ortools/sat/csharp/IntegerExpressions.cs index 825c2fae58..0ad50dd943 100644 --- a/ortools/sat/csharp/IntegerExpressions.cs +++ b/ortools/sat/csharp/IntegerExpressions.cs @@ -73,6 +73,18 @@ namespace Google.OrTools.Sat return Prod(var, coeff); } + public static LinearExpr Affine(IntVar var, long coeff, long offset) + { + if (offset == 0) + { + return Prod(var, coeff); + } + else + { + return new SumArray(Prod(var, coeff), offset); + } + } + public int Index { get { diff --git a/ortools/sat/diffn_util.cc b/ortools/sat/diffn_util.cc index c859e82e6b..67ee08a470 100644 --- a/ortools/sat/diffn_util.cc +++ b/ortools/sat/diffn_util.cc @@ -389,9 +389,8 @@ void ConstructOverlappingSets(bool already_sorted, } } -void ConstructNonOverlappingSets(bool already_sorted, - std::vector* intervals, - std::vector>* result) { +void GetOverlappingIntervalComponents(std::vector* intervals, + std::vector>* result) { result->clear(); if (intervals->empty()) return; if (intervals->size() == 1) { @@ -399,29 +398,21 @@ void ConstructNonOverlappingSets(bool already_sorted, return; } - if (already_sorted) { - DCHECK( - std::is_sorted(intervals->begin(), intervals->end(), - [](const IndexedInterval& a, const IndexedInterval& b) { - return a.start < b.start; - })); - } else { - std::sort(intervals->begin(), intervals->end(), - [](const IndexedInterval& a, const IndexedInterval& b) { - return a.start < b.start; - }); - } + std::sort(intervals->begin(), intervals->end(), + [](const IndexedInterval& a, const IndexedInterval& b) { + return a.start < b.start; + }); IntegerValue end_max_so_far = (*intervals)[0].end; result->push_back({(*intervals)[0].index}); for (int i = 1; i < intervals->size(); ++i) { - const IndexedInterval& j = (*intervals)[i]; - if (j.start >= end_max_so_far) { - result->push_back({j.index}); + const IndexedInterval& interval = (*intervals)[i]; + if (interval.start >= end_max_so_far) { + result->push_back({interval.index}); } else { - result->back().push_back(j.index); + result->back().push_back(interval.index); } - end_max_so_far = std::max(end_max_so_far, j.end); + end_max_so_far = std::max(end_max_so_far, interval.end); } } diff --git a/ortools/sat/diffn_util.h b/ortools/sat/diffn_util.h index 943014e27e..f12324c562 100644 --- a/ortools/sat/diffn_util.h +++ b/ortools/sat/diffn_util.h @@ -122,9 +122,8 @@ void ConstructOverlappingSets(bool already_sorted, // Given n intervals, returns the set of connected components (using the overlap // relation between 2 intervals). -void ConstructNonOverlappingSets(bool already_sorted, - std::vector* intervals, - std::vector>* result); +void GetOverlappingIntervalComponents(std::vector* intervals, + std::vector>* result); } // namespace sat } // namespace operations_research diff --git a/ortools/sat/sat_parameters.proto b/ortools/sat/sat_parameters.proto index 2d7458944e..dc7167ceb1 100644 --- a/ortools/sat/sat_parameters.proto +++ b/ortools/sat/sat_parameters.proto @@ -18,6 +18,7 @@ package operations_research.sat; option java_package = "com.google.ortools.sat"; option java_multiple_files = true; + // Contains the definitions for all the sat algorithm parameters and their // default values. //