19 #include "absl/memory/memory.h"
20 #include "absl/strings/str_format.h"
21 #include "google/protobuf/text_format.h"
38 using ::operations_research::glop::ColIndex;
40 using ::operations_research::glop::GlopParameters;
41 using ::operations_research::glop::RowIndex;
47 return solution.IsFeasible() ? (solution.GetCost() <= lower_bound
53 bool AllIntegralValues(
const DenseRow& values,
double tolerance) {
57 if (
value >= tolerance &&
value + tolerance < 1.0) {
64 void DenseRowToBopSolution(
const DenseRow& values, BopSolution* solution) {
65 CHECK(solution !=
nullptr);
66 CHECK_EQ(solution->Size(), values.size());
67 for (VariableIndex
var(0);
var < solution->Size(); ++
var) {
68 solution->SetValue(
var, round(values[ColIndex(
var.value())]));
89 if (state_update_stamp_ == problem_state.
update_stamp()) {
96 sat_solver_ = absl::make_unique<sat::SatSolver>();
100 .exploit_symmetry_in_sat_first_solution()) {
101 std::vector<std::unique_ptr<SparsePermutation>> generators;
104 std::unique_ptr<sat::SymmetryPropagator> propagator(
106 for (
int i = 0; i < generators.size(); ++i) {
107 propagator->AddSymmetry(std::move(generators[i]));
109 sat_solver_->AddPropagator(propagator.get());
110 sat_solver_->TakePropagatorOwnership(std::move(propagator));
124 sat_solver_->SetAssignmentPreference(
125 sat::Literal(sat::BooleanVariable(
col.value()), round(
value) == 1),
135 sat_solver_->SetAssignmentPreference(
136 sat::Literal(sat::BooleanVariable(i),
147 if (abort_)
return false;
161 CHECK(learned_info !=
nullptr);
163 learned_info->
Clear();
166 SynchronizeIfNeeded(problem_state);
169 sat::SatParameters sat_params;
170 sat_params.set_max_time_in_seconds(
time_limit->GetTimeLeft());
171 sat_params.set_max_deterministic_time(
time_limit->GetDeterministicTimeLeft());
172 sat_params.set_random_seed(
parameters.random_seed());
178 sat_params.set_max_number_of_conflicts(
180 sat_solver_->SetParameters(sat_params);
182 const double initial_deterministic_time = sat_solver_->deterministic_time();
184 time_limit->AdvanceDeterministicTime(sat_solver_->deterministic_time() -
185 initial_deterministic_time);
216 sat_propagator_(sat_propagator) {}
229 CHECK(learned_info !=
nullptr);
231 learned_info->
Clear();
234 const sat::SatParameters saved_params = sat_propagator_->
parameters();
235 const std::vector<std::pair<sat::Literal, double>> saved_prefs =
238 const int kMaxNumConflicts = 10;
242 int64 remaining_num_conflicts =
243 parameters.max_number_of_conflicts_in_random_solution_generation();
244 int64 old_num_failures = 0;
248 bool objective_need_to_be_overconstrained = (best_cost !=
kint64max);
250 bool solution_found =
false;
251 while (remaining_num_conflicts > 0 && !
time_limit->LimitReached()) {
255 sat::SatParameters sat_params = saved_params;
257 sat_params.set_max_number_of_conflicts(kMaxNumConflicts);
261 if (objective_need_to_be_overconstrained) {
264 true, sat::Coefficient(best_cost) - 1, sat_propagator_)) {
271 objective_need_to_be_overconstrained =
false;
275 const int preference = random_->
Uniform(4);
276 if (preference == 0) {
279 }
else if (preference == 1 && !problem_state.
lp_values().
empty()) {
292 objective_need_to_be_overconstrained =
true;
293 solution_found =
true;
307 remaining_num_conflicts -=
339 const std::string&
name)
343 lp_model_loaded_(false),
349 num_fixed_variables_(-1),
350 problem_already_solved_(false),
351 scaled_solution_cost_(glop::
kInfinity) {}
357 if (state_update_stamp_ == problem_state.
update_stamp()) {
365 parameters_.max_lp_solve_for_feasibility_problems() >= 0 &&
366 num_full_solves_ >= parameters_.max_lp_solve_for_feasibility_problems()) {
372 int num_fixed_variables = 0;
373 for (
const bool is_fixed : problem_state.
is_fixed()) {
375 ++num_fixed_variables;
378 problem_already_solved_ =
379 problem_already_solved_ && num_fixed_variables_ >= num_fixed_variables;
383 num_fixed_variables_ = num_fixed_variables;
384 if (!lp_model_loaded_) {
388 lp_model_loaded_ =
true;
399 if (parameters_.use_learned_binary_clauses_in_lp()) {
400 for (
const sat::BinaryClause& clause :
403 const int64 coefficient_a = clause.a.IsPositive() ? 1 : -1;
404 const int64 coefficient_b = clause.b.IsPositive() ? 1 : -1;
405 const int64 rhs = 1 + (clause.a.IsPositive() ? 0 : -1) +
406 (clause.b.IsPositive() ? 0 : -1);
407 const ColIndex col_a(clause.a.Variable().value());
408 const ColIndex col_b(clause.b.Variable().value());
414 (clause.a.IsPositive() ? name_a :
"not(" + name_a +
")") +
" or " +
415 (clause.b.IsPositive() ? name_b :
"not(" + name_b +
")"));
424 scaled_solution_cost_ =
439 parameters_.max_lp_solve_for_feasibility_problems() != 0;
445 CHECK(learned_info !=
nullptr);
447 learned_info->
Clear();
450 SynchronizeIfNeeded(problem_state);
463 problem_already_solved_ =
true;
471 lp_status != glop::ProblemStatus::PRIMAL_FEASIBLE) {
480 if (parameters_.use_lp_strong_branching()) {
482 ComputeLowerBoundUsingStrongBranching(learned_info,
time_limit);
484 << absl::StrFormat(
"%.6f", lower_bound)
485 <<
" using strong branching.";
488 const int tolerance_sign = scaling_ < 0 ? 1 : -1;
489 const double unscaled_cost =
492 lp_solver_.
GetParameters().solution_feasibility_tolerance()) /
497 if (AllIntegralValues(
499 lp_solver_.
GetParameters().primal_feasibility_tolerance())) {
515 GlopParameters glop_params;
516 if (incremental_solve) {
517 glop_params.set_use_dual_simplex(
true);
518 glop_params.set_allow_simplex_algorithm_change(
true);
519 glop_params.set_use_preprocessing(
false);
523 parameters_.lp_max_deterministic_time());
525 lp_model_, nested_time_limit.GetTimeLimit());
529 double LinearRelaxation::ComputeLowerBoundUsingStrongBranching(
530 LearnedInfo* learned_info, TimeLimit*
time_limit) {
532 const double tolerance =
535 for (glop::ColIndex
col(0);
col < initial_lp_values.size(); ++
col) {
559 (initial_lp_values[
col] < tolerance ||
560 initial_lp_values[
col] + tolerance > 1)) {
564 double objective_true = best_lp_objective;
565 double objective_false = best_lp_objective;
575 status_true == glop::ProblemStatus::DUAL_FEASIBLE) {
582 status_false == glop::ProblemStatus::DUAL_FEASIBLE) {
589 std::max(objective_true, objective_false))
590 : std::
max(best_lp_objective,
591 std::
min(objective_true, objective_false));
595 if (CostIsWorseThanSolution(objective_true, tolerance)) {
599 learned_info->fixed_literals.push_back(
600 sat::Literal(sat::BooleanVariable(
col.value()),
false));
601 }
else if (CostIsWorseThanSolution(objective_false, tolerance)) {
605 learned_info->fixed_literals.push_back(
606 sat::Literal(sat::BooleanVariable(
col.value()),
true));
612 return best_lp_objective;
615 bool LinearRelaxation::CostIsWorseThanSolution(
double scaled_cost,
616 double tolerance)
const {