diff --git a/ortools/sat/linear_programming_constraint.cc b/ortools/sat/linear_programming_constraint.cc index f366596e75..77e403c7ed 100644 --- a/ortools/sat/linear_programming_constraint.cc +++ b/ortools/sat/linear_programming_constraint.cc @@ -1192,13 +1192,16 @@ bool LinearProgrammingConstraint::Propagate() { if (!SolveLp()) return true; // Add new constraints to the LP and resolve? - // - // TODO(user): We might want to do that more than once. Currently we rely on - // this beeing called again on the next IncrementalPropagate() call, but that - // might not always happen at level zero. - if (simplex_.GetProblemStatus() == glop::ProblemStatus::OPTIMAL) { + const int max_cuts_rounds = + trail_->CurrentDecisionLevel() == 0 + ? sat_parameters_.max_cut_rounds_at_level_zero() + : 1; + int cuts_round = 0; + while (simplex_.GetProblemStatus() == glop::ProblemStatus::OPTIMAL && + cuts_round < max_cuts_rounds) { // We wait for the first batch of problem constraints to be added before we // begin to generate cuts. + cuts_round++; if (!integer_lp_.empty() && constraint_manager_.num_cuts() < sat_parameters_.max_num_cuts()) { // The "generic" cuts are currently part of this class as they are using @@ -1238,6 +1241,7 @@ bool LinearProgrammingConstraint::Propagate() { if (trail_->CurrentDecisionLevel() == 0) { lp_at_level_zero_is_final_ = true; } + break; } } diff --git a/ortools/sat/sat_parameters.proto b/ortools/sat/sat_parameters.proto index afdc4e33be..d85af1dc79 100644 --- a/ortools/sat/sat_parameters.proto +++ b/ortools/sat/sat_parameters.proto @@ -21,7 +21,7 @@ option java_multiple_files = true; // Contains the definitions for all the sat algorithm parameters and their // default values. // -// NEXT TAG: 154 +// NEXT TAG: 155 message SatParameters { // ========================================================================== // Branching and polarity @@ -597,6 +597,9 @@ message SatParameters { // feature. optional double min_orthogonality_for_lp_constraints = 115 [default = 0.0]; + // Max number of time we perform cut generation and resolve the LP at level 0. + optional int32 max_cut_rounds_at_level_zero = 154 [default = 1]; + // If a constraint/cut in LP is not active for that many consecutive OPTIMAL // solves, remove it from the LP. Note that it might be added again later if // it become violated by the current LP solution.