OR-Tools  8.1
bop_fs.cc
Go to the documentation of this file.
1 // Copyright 2010-2018 Google LLC
2 // Licensed under the Apache License, Version 2.0 (the "License");
3 // you may not use this file except in compliance with the License.
4 // You may obtain a copy of the License at
5 //
6 // http://www.apache.org/licenses/LICENSE-2.0
7 //
8 // Unless required by applicable law or agreed to in writing, software
9 // distributed under the License is distributed on an "AS IS" BASIS,
10 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
11 // See the License for the specific language governing permissions and
12 // limitations under the License.
13 
14 #include "ortools/bop/bop_fs.h"
15 
16 #include <string>
17 #include <vector>
18 
19 #include "absl/memory/memory.h"
20 #include "absl/strings/str_format.h"
21 #include "google/protobuf/text_format.h"
24 #include "ortools/base/stl_util.h"
25 #include "ortools/glop/lp_solver.h"
28 #include "ortools/sat/lp_utils.h"
29 #include "ortools/sat/sat_solver.h"
30 #include "ortools/sat/symmetry.h"
31 #include "ortools/sat/util.h"
32 #include "ortools/util/bitset.h"
33 
34 namespace operations_research {
35 namespace bop {
36 namespace {
37 
38 using ::operations_research::glop::ColIndex;
40 using ::operations_research::glop::GlopParameters;
41 using ::operations_research::glop::RowIndex;
42 
43 BopOptimizerBase::Status SolutionStatus(const BopSolution& solution,
44  int64 lower_bound) {
45  // The lower bound might be greater that the cost of a feasible solution due
46  // to rounding errors in the problem scaling and Glop.
47  return solution.IsFeasible() ? (solution.GetCost() <= lower_bound
51 }
52 
53 bool AllIntegralValues(const DenseRow& values, double tolerance) {
54  for (const glop::Fractional value : values) {
55  // Note that this test is correct because in this part of the code, Bop
56  // only deals with boolean variables.
57  if (value >= tolerance && value + tolerance < 1.0) {
58  return false;
59  }
60  }
61  return true;
62 }
63 
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())]));
69  }
70 }
71 } // anonymous namespace
72 
73 //------------------------------------------------------------------------------
74 // GuidedSatFirstSolutionGenerator
75 //------------------------------------------------------------------------------
76 
78  const std::string& name, Policy policy)
80  policy_(policy),
81  abort_(false),
82  state_update_stamp_(ProblemState::kInitialStampValue),
83  sat_solver_() {}
84 
86 
87 BopOptimizerBase::Status GuidedSatFirstSolutionGenerator::SynchronizeIfNeeded(
88  const ProblemState& problem_state) {
89  if (state_update_stamp_ == problem_state.update_stamp()) {
91  }
92  state_update_stamp_ = problem_state.update_stamp();
93 
94  // Create the sat_solver if not already done.
95  if (!sat_solver_) {
96  sat_solver_ = absl::make_unique<sat::SatSolver>();
97 
98  // Add in symmetries.
99  if (problem_state.GetParameters()
100  .exploit_symmetry_in_sat_first_solution()) {
101  std::vector<std::unique_ptr<SparsePermutation>> generators;
103  &generators);
104  std::unique_ptr<sat::SymmetryPropagator> propagator(
106  for (int i = 0; i < generators.size(); ++i) {
107  propagator->AddSymmetry(std::move(generators[i]));
108  }
109  sat_solver_->AddPropagator(propagator.get());
110  sat_solver_->TakePropagatorOwnership(std::move(propagator));
111  }
112  }
113 
114  const BopOptimizerBase::Status load_status =
115  LoadStateProblemToSatSolver(problem_state, sat_solver_.get());
116  if (load_status != BopOptimizerBase::CONTINUE) return load_status;
117 
118  switch (policy_) {
119  case Policy::kNotGuided:
120  break;
121  case Policy::kLpGuided:
122  for (ColIndex col(0); col < problem_state.lp_values().size(); ++col) {
123  const double value = problem_state.lp_values()[col];
124  sat_solver_->SetAssignmentPreference(
125  sat::Literal(sat::BooleanVariable(col.value()), round(value) == 1),
126  1 - fabs(value - round(value)));
127  }
128  break;
131  sat_solver_.get());
132  break;
133  case Policy::kUserGuided:
134  for (int i = 0; i < problem_state.assignment_preference().size(); ++i) {
135  sat_solver_->SetAssignmentPreference(
136  sat::Literal(sat::BooleanVariable(i),
137  problem_state.assignment_preference()[i]),
138  1.0);
139  }
140  break;
141  }
143 }
144 
146  const ProblemState& problem_state) const {
147  if (abort_) return false;
148  if (policy_ == Policy::kLpGuided && problem_state.lp_values().empty()) {
149  return false;
150  }
151  if (policy_ == Policy::kUserGuided &&
152  problem_state.assignment_preference().empty()) {
153  return false;
154  }
155  return true;
156 }
157 
159  const BopParameters& parameters, const ProblemState& problem_state,
160  LearnedInfo* learned_info, TimeLimit* time_limit) {
161  CHECK(learned_info != nullptr);
162  CHECK(time_limit != nullptr);
163  learned_info->Clear();
164 
165  const BopOptimizerBase::Status sync_status =
166  SynchronizeIfNeeded(problem_state);
167  if (sync_status != BopOptimizerBase::CONTINUE) return sync_status;
168 
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());
173 
174  // We use a relatively small conflict limit so that other optimizer get a
175  // chance to run if this one is slow. Note that if this limit is reached, we
176  // will return BopOptimizerBase::CONTINUE so that Optimize() will be called
177  // again later to resume the current work.
178  sat_params.set_max_number_of_conflicts(
179  parameters.guided_sat_conflicts_chunk());
180  sat_solver_->SetParameters(sat_params);
181 
182  const double initial_deterministic_time = sat_solver_->deterministic_time();
183  const sat::SatSolver::Status sat_status = sat_solver_->Solve();
184  time_limit->AdvanceDeterministicTime(sat_solver_->deterministic_time() -
185  initial_deterministic_time);
186 
187  if (sat_status == sat::SatSolver::INFEASIBLE) {
188  if (policy_ != Policy::kNotGuided) abort_ = true;
189  if (problem_state.upper_bound() != kint64max) {
190  // As the solution in the state problem is feasible, it is proved optimal.
191  learned_info->lower_bound = problem_state.upper_bound();
193  }
194  // The problem is proved infeasible
196  }
197 
198  ExtractLearnedInfoFromSatSolver(sat_solver_.get(), learned_info);
199  if (sat_status == sat::SatSolver::FEASIBLE) {
200  SatAssignmentToBopSolution(sat_solver_->Assignment(),
201  &learned_info->solution);
202  return SolutionStatus(learned_info->solution, problem_state.lower_bound());
203  }
204 
206 }
207 
208 //------------------------------------------------------------------------------
209 // BopRandomFirstSolutionGenerator
210 //------------------------------------------------------------------------------
212  const std::string& name, const BopParameters& parameters,
213  sat::SatSolver* sat_propagator, MTRandom* random)
215  random_(random),
216  sat_propagator_(sat_propagator) {}
217 
219 
220 // Only run the RandomFirstSolution when there is an objective to minimize.
222  const ProblemState& problem_state) const {
223  return problem_state.original_problem().objective().literals_size() > 0;
224 }
225 
227  const BopParameters& parameters, const ProblemState& problem_state,
228  LearnedInfo* learned_info, TimeLimit* time_limit) {
229  CHECK(learned_info != nullptr);
230  CHECK(time_limit != nullptr);
231  learned_info->Clear();
232 
233  // Save the current solver heuristics.
234  const sat::SatParameters saved_params = sat_propagator_->parameters();
235  const std::vector<std::pair<sat::Literal, double>> saved_prefs =
236  sat_propagator_->AllPreferences();
237 
238  const int kMaxNumConflicts = 10;
239  int64 best_cost = problem_state.solution().IsFeasible()
240  ? problem_state.solution().GetCost()
241  : kint64max;
242  int64 remaining_num_conflicts =
243  parameters.max_number_of_conflicts_in_random_solution_generation();
244  int64 old_num_failures = 0;
245 
246  // Optimization: Since each Solve() is really fast, we want to limit as
247  // much as possible the work around one.
248  bool objective_need_to_be_overconstrained = (best_cost != kint64max);
249 
250  bool solution_found = false;
251  while (remaining_num_conflicts > 0 && !time_limit->LimitReached()) {
252  sat_propagator_->Backtrack(0);
253  old_num_failures = sat_propagator_->num_failures();
254 
255  sat::SatParameters sat_params = saved_params;
256  sat::RandomizeDecisionHeuristic(random_, &sat_params);
257  sat_params.set_max_number_of_conflicts(kMaxNumConflicts);
258  sat_propagator_->SetParameters(sat_params);
259  sat_propagator_->ResetDecisionHeuristic();
260 
261  if (objective_need_to_be_overconstrained) {
263  problem_state.original_problem(), false, sat::Coefficient(0),
264  true, sat::Coefficient(best_cost) - 1, sat_propagator_)) {
265  // The solution is proved optimal (if any).
266  learned_info->lower_bound = best_cost;
267  return best_cost == kint64max
270  }
271  objective_need_to_be_overconstrained = false;
272  }
273 
274  // Special assignment preference parameters.
275  const int preference = random_->Uniform(4);
276  if (preference == 0) {
278  sat_propagator_);
279  } else if (preference == 1 && !problem_state.lp_values().empty()) {
280  // Assign SAT assignment preference based on the LP solution.
281  for (ColIndex col(0); col < problem_state.lp_values().size(); ++col) {
282  const double value = problem_state.lp_values()[col];
283  sat_propagator_->SetAssignmentPreference(
284  sat::Literal(sat::BooleanVariable(col.value()), round(value) == 1),
285  1 - fabs(value - round(value)));
286  }
287  }
288 
289  const sat::SatSolver::Status sat_status =
290  sat_propagator_->SolveWithTimeLimit(time_limit);
291  if (sat_status == sat::SatSolver::FEASIBLE) {
292  objective_need_to_be_overconstrained = true;
293  solution_found = true;
294  SatAssignmentToBopSolution(sat_propagator_->Assignment(),
295  &learned_info->solution);
296  CHECK_LT(learned_info->solution.GetCost(), best_cost);
297  best_cost = learned_info->solution.GetCost();
298  } else if (sat_status == sat::SatSolver::INFEASIBLE) {
299  // The solution is proved optimal (if any).
300  learned_info->lower_bound = best_cost;
301  return best_cost == kint64max ? BopOptimizerBase::INFEASIBLE
303  }
304 
305  // The number of failure is a good approximation of the number of conflicts.
306  // Note that the number of failures of the SAT solver is not reinitialized.
307  remaining_num_conflicts -=
308  sat_propagator_->num_failures() - old_num_failures;
309  }
310 
311  // Restore sat_propagator_ to its original state.
312  // Note that if the function is aborted before that, it means we solved the
313  // problem to optimality (or proven it to be infeasible), so we don't need
314  // to do any extra work in these cases since the sat_propagator_ will not be
315  // used anymore.
316  CHECK_EQ(0, sat_propagator_->AssumptionLevel());
317  sat_propagator_->RestoreSolverToAssumptionLevel();
318  sat_propagator_->SetParameters(saved_params);
319  sat_propagator_->ResetDecisionHeuristicAndSetAllPreferences(saved_prefs);
320 
321  // This can be proved during the call to RestoreSolverToAssumptionLevel().
322  if (sat_propagator_->IsModelUnsat()) {
323  // The solution is proved optimal (if any).
324  learned_info->lower_bound = best_cost;
325  return best_cost == kint64max ? BopOptimizerBase::INFEASIBLE
327  }
328 
329  ExtractLearnedInfoFromSatSolver(sat_propagator_, learned_info);
330 
331  return solution_found ? BopOptimizerBase::SOLUTION_FOUND
333 }
334 
335 //------------------------------------------------------------------------------
336 // LinearRelaxation
337 //------------------------------------------------------------------------------
339  const std::string& name)
341  parameters_(parameters),
342  state_update_stamp_(ProblemState::kInitialStampValue),
343  lp_model_loaded_(false),
344  num_full_solves_(0),
345  lp_model_(),
346  lp_solver_(),
347  scaling_(1),
348  offset_(0),
349  num_fixed_variables_(-1),
350  problem_already_solved_(false),
351  scaled_solution_cost_(glop::kInfinity) {}
352 
354 
355 BopOptimizerBase::Status LinearRelaxation::SynchronizeIfNeeded(
356  const ProblemState& problem_state) {
357  if (state_update_stamp_ == problem_state.update_stamp()) {
359  }
360  state_update_stamp_ = problem_state.update_stamp();
361 
362  // If this is a pure feasibility problem, obey
363  // `BopParameters.max_lp_solve_for_feasibility_problems`.
364  if (problem_state.original_problem().objective().literals_size() == 0 &&
365  parameters_.max_lp_solve_for_feasibility_problems() >= 0 &&
366  num_full_solves_ >= parameters_.max_lp_solve_for_feasibility_problems()) {
368  }
369 
370  // Check if the number of fixed variables is greater than last time.
371  // TODO(user): Consider checking changes in number of conflicts too.
372  int num_fixed_variables = 0;
373  for (const bool is_fixed : problem_state.is_fixed()) {
374  if (is_fixed) {
375  ++num_fixed_variables;
376  }
377  }
378  problem_already_solved_ =
379  problem_already_solved_ && num_fixed_variables_ >= num_fixed_variables;
380  if (problem_already_solved_) return BopOptimizerBase::ABORT;
381 
382  // Create the LP model based on the current problem state.
383  num_fixed_variables_ = num_fixed_variables;
384  if (!lp_model_loaded_) {
385  lp_model_.Clear();
387  &lp_model_);
388  lp_model_loaded_ = true;
389  }
390  for (VariableIndex var(0); var < problem_state.is_fixed().size(); ++var) {
391  if (problem_state.IsVariableFixed(var)) {
392  const glop::Fractional value =
393  problem_state.GetVariableFixedValue(var) ? 1.0 : 0.0;
394  lp_model_.SetVariableBounds(ColIndex(var.value()), value, value);
395  }
396  }
397 
398  // Add learned binary clauses.
399  if (parameters_.use_learned_binary_clauses_in_lp()) {
400  for (const sat::BinaryClause& clause :
401  problem_state.NewlyAddedBinaryClauses()) {
402  const RowIndex constraint_index = lp_model_.CreateNewConstraint();
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());
409  const std::string name_a = lp_model_.GetVariableName(col_a);
410  const std::string name_b = lp_model_.GetVariableName(col_b);
411 
412  lp_model_.SetConstraintName(
413  constraint_index,
414  (clause.a.IsPositive() ? name_a : "not(" + name_a + ")") + " or " +
415  (clause.b.IsPositive() ? name_b : "not(" + name_b + ")"));
416  lp_model_.SetCoefficient(constraint_index, col_a, coefficient_a);
417  lp_model_.SetCoefficient(constraint_index, col_b, coefficient_b);
418  lp_model_.SetConstraintBounds(constraint_index, rhs, glop::kInfinity);
419  }
420  }
421 
422  scaling_ = problem_state.original_problem().objective().scaling_factor();
423  offset_ = problem_state.original_problem().objective().offset();
424  scaled_solution_cost_ =
425  problem_state.solution().IsFeasible()
426  ? problem_state.solution().GetScaledCost()
427  : (lp_model_.IsMaximizationProblem() ? -glop::kInfinity
428  : glop::kInfinity);
430 }
431 
432 // Always let the LP solver run if there is an objective. If there isn't, only
433 // let the LP solver run if the user asked for it by setting
434 // `BopParameters.max_lp_solve_for_feasibility_problems` to a non-zero value
435 // (a negative value means no limit).
436 // TODO(user): also deal with problem_already_solved_
437 bool LinearRelaxation::ShouldBeRun(const ProblemState& problem_state) const {
438  return problem_state.original_problem().objective().literals_size() > 0 ||
439  parameters_.max_lp_solve_for_feasibility_problems() != 0;
440 }
441 
443  const BopParameters& parameters, const ProblemState& problem_state,
444  LearnedInfo* learned_info, TimeLimit* time_limit) {
445  CHECK(learned_info != nullptr);
446  CHECK(time_limit != nullptr);
447  learned_info->Clear();
448 
449  const BopOptimizerBase::Status sync_status =
450  SynchronizeIfNeeded(problem_state);
451  if (sync_status != BopOptimizerBase::CONTINUE) {
452  return sync_status;
453  }
454 
455  const glop::ProblemStatus lp_status = Solve(false, time_limit);
456  VLOG(1) << " LP: "
457  << absl::StrFormat("%.6f", lp_solver_.GetObjectiveValue())
458  << " status: " << GetProblemStatusString(lp_status);
459 
460  if (lp_status == glop::ProblemStatus::OPTIMAL ||
461  lp_status == glop::ProblemStatus::IMPRECISE) {
462  ++num_full_solves_;
463  problem_already_solved_ = true;
464  }
465 
466  if (lp_status == glop::ProblemStatus::INIT) {
468  }
469  if (lp_status != glop::ProblemStatus::OPTIMAL &&
470  lp_status != glop::ProblemStatus::IMPRECISE &&
471  lp_status != glop::ProblemStatus::PRIMAL_FEASIBLE) {
473  }
474  learned_info->lp_values = lp_solver_.variable_values();
475 
476  if (lp_status == glop::ProblemStatus::OPTIMAL) {
477  // The lp returns the objective with the offset and scaled, so we need to
478  // unscale it and then remove the offset.
479  double lower_bound = lp_solver_.GetObjectiveValue();
480  if (parameters_.use_lp_strong_branching()) {
481  lower_bound =
482  ComputeLowerBoundUsingStrongBranching(learned_info, time_limit);
483  VLOG(1) << " LP: "
484  << absl::StrFormat("%.6f", lower_bound)
485  << " using strong branching.";
486  }
487 
488  const int tolerance_sign = scaling_ < 0 ? 1 : -1;
489  const double unscaled_cost =
490  (lower_bound +
491  tolerance_sign *
492  lp_solver_.GetParameters().solution_feasibility_tolerance()) /
493  scaling_ -
494  offset_;
495  learned_info->lower_bound = static_cast<int64>(ceil(unscaled_cost));
496 
497  if (AllIntegralValues(
498  learned_info->lp_values,
499  lp_solver_.GetParameters().primal_feasibility_tolerance())) {
500  DenseRowToBopSolution(learned_info->lp_values, &learned_info->solution);
501  CHECK(learned_info->solution.IsFeasible());
503  }
504  }
505 
507 }
508 
509 // TODO(user): It is possible to stop the search earlier using the glop
510 // parameter objective_lower_limit / objective_upper_limit. That
511 // can be used when a feasible solution is known, or when the false
512 // best bound is computed.
513 glop::ProblemStatus LinearRelaxation::Solve(bool incremental_solve,
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);
520  lp_solver_.SetParameters(glop_params);
521  }
522  NestedTimeLimit nested_time_limit(time_limit, time_limit->GetTimeLeft(),
523  parameters_.lp_max_deterministic_time());
524  const glop::ProblemStatus lp_status = lp_solver_.SolveWithTimeLimit(
525  lp_model_, nested_time_limit.GetTimeLimit());
526  return lp_status;
527 }
528 
529 double LinearRelaxation::ComputeLowerBoundUsingStrongBranching(
530  LearnedInfo* learned_info, TimeLimit* time_limit) {
531  const glop::DenseRow initial_lp_values = lp_solver_.variable_values();
532  const double tolerance =
533  lp_solver_.GetParameters().primal_feasibility_tolerance();
534  double best_lp_objective = lp_solver_.GetObjectiveValue();
535  for (glop::ColIndex col(0); col < initial_lp_values.size(); ++col) {
536  // TODO(user): Order the variables by some meaningful quantity (probably
537  // the cost variation when we snap it to one of its bound) so
538  // we can try the one that seems the most promising first.
539  // That way we can stop the strong branching earlier.
540  if (time_limit->LimitReached()) break;
541 
542  // Skip fixed variables.
543  if (lp_model_.variable_lower_bounds()[col] ==
544  lp_model_.variable_upper_bounds()[col]) {
545  continue;
546  }
547  CHECK_EQ(0.0, lp_model_.variable_lower_bounds()[col]);
548  CHECK_EQ(1.0, lp_model_.variable_upper_bounds()[col]);
549 
550  // Note(user): Experiments show that iterating on all variables can be
551  // costly and doesn't lead to better solutions when a SAT optimizer is used
552  // afterward, e.g. BopSatLpFirstSolutionGenerator, and no feasible solutions
553  // are available.
554  // No variables are skipped when a feasible solution is know as the best
555  // bound / cost comparison can be used to deduce fixed variables, and be
556  // useful for other optimizers.
557  if ((scaled_solution_cost_ == glop::kInfinity ||
558  scaled_solution_cost_ == -glop::kInfinity) &&
559  (initial_lp_values[col] < tolerance ||
560  initial_lp_values[col] + tolerance > 1)) {
561  continue;
562  }
563 
564  double objective_true = best_lp_objective;
565  double objective_false = best_lp_objective;
566 
567  // Set to true.
568  lp_model_.SetVariableBounds(col, 1.0, 1.0);
569  const glop::ProblemStatus status_true = Solve(true, time_limit);
570  // TODO(user): Deal with PRIMAL_INFEASIBLE, DUAL_INFEASIBLE and
571  // INFEASIBLE_OR_UNBOUNDED statuses. In all cases, if the
572  // original lp was feasible, this means that the variable can
573  // be fixed to the other bound.
574  if (status_true == glop::ProblemStatus::OPTIMAL ||
575  status_true == glop::ProblemStatus::DUAL_FEASIBLE) {
576  objective_true = lp_solver_.GetObjectiveValue();
577 
578  // Set to false.
579  lp_model_.SetVariableBounds(col, 0.0, 0.0);
580  const glop::ProblemStatus status_false = Solve(true, time_limit);
581  if (status_false == glop::ProblemStatus::OPTIMAL ||
582  status_false == glop::ProblemStatus::DUAL_FEASIBLE) {
583  objective_false = lp_solver_.GetObjectiveValue();
584 
585  // Compute the new min.
586  best_lp_objective =
587  lp_model_.IsMaximizationProblem()
588  ? std::min(best_lp_objective,
589  std::max(objective_true, objective_false))
590  : std::max(best_lp_objective,
591  std::min(objective_true, objective_false));
592  }
593  }
594 
595  if (CostIsWorseThanSolution(objective_true, tolerance)) {
596  // Having variable col set to true can't possibly lead to and better
597  // solution than the current one. Set the variable to false.
598  lp_model_.SetVariableBounds(col, 0.0, 0.0);
599  learned_info->fixed_literals.push_back(
600  sat::Literal(sat::BooleanVariable(col.value()), false));
601  } else if (CostIsWorseThanSolution(objective_false, tolerance)) {
602  // Having variable col set to false can't possibly lead to and better
603  // solution than the current one. Set the variable to true.
604  lp_model_.SetVariableBounds(col, 1.0, 1.0);
605  learned_info->fixed_literals.push_back(
606  sat::Literal(sat::BooleanVariable(col.value()), true));
607  } else {
608  // Unset. This is safe to use 0.0 and 1.0 as the variable is not fixed.
609  lp_model_.SetVariableBounds(col, 0.0, 1.0);
610  }
611  }
612  return best_lp_objective;
613 }
614 
615 bool LinearRelaxation::CostIsWorseThanSolution(double scaled_cost,
616  double tolerance) const {
617  return lp_model_.IsMaximizationProblem()
618  ? scaled_cost + tolerance < scaled_solution_cost_
619  : scaled_cost > scaled_solution_cost_ + tolerance;
620 }
621 
622 } // namespace bop
623 } // namespace operations_research
operations_research::bop::BopRandomFirstSolutionGenerator::Optimize
Status Optimize(const BopParameters &parameters, const ProblemState &problem_state, LearnedInfo *learned_info, TimeLimit *time_limit) override
Definition: bop_fs.cc:226
var
IntVar * var
Definition: expr_array.cc:1858
bop_fs.h
scaled_cost
Fractional scaled_cost
Definition: preprocessor.cc:425
operations_research::sat::SatSolver::Status
Status
Definition: sat_solver.h:181
min
int64 min
Definition: alldiff_cst.cc:138
operations_research::glop::DenseRow
StrictITIVector< ColIndex, Fractional > DenseRow
Definition: lp_types.h:299
operations_research::glop::LPSolver::GetParameters
const GlopParameters & GetParameters() const
Definition: lp_solver.cc:117
VLOG
#define VLOG(verboselevel)
Definition: base/logging.h:978
operations_research::sat::SatSolver::SetAssignmentPreference
void SetAssignmentPreference(Literal literal, double weight)
Definition: sat_solver.h:151
operations_research::sat::SatSolver::AssumptionLevel
int AssumptionLevel() const
Definition: sat_solver.h:221
operations_research::bop::BopOptimizerBase::SOLUTION_FOUND
@ SOLUTION_FOUND
Definition: bop_base.h:63
max
int64 max
Definition: alldiff_cst.cc:139
operations_research::glop::LPSolver::GetObjectiveValue
Fractional GetObjectiveValue() const
Definition: lp_solver.cc:446
operations_research::bop::ProblemState::solution
const BopSolution & solution() const
Definition: bop_base.h:193
sparse_permutation.h
operations_research::sat::SatSolver::Assignment
const VariablesAssignment & Assignment() const
Definition: sat_solver.h:363
operations_research::bop::GuidedSatFirstSolutionGenerator::Policy::kUserGuided
@ kUserGuided
operations_research::bop::ProblemState::lower_bound
int64 lower_bound() const
Definition: bop_base.h:206
operations_research::bop::ProblemState::upper_bound
int64 upper_bound() const
Definition: bop_base.h:207
operations_research::bop::LearnedInfo::Clear
void Clear()
Definition: bop_base.h:255
operations_research::glop::LinearProgram::variable_lower_bounds
const DenseRow & variable_lower_bounds() const
Definition: lp_data.h:229
operations_research::bop::LinearRelaxation::Optimize
Status Optimize(const BopParameters &parameters, const ProblemState &problem_state, LearnedInfo *learned_info, TimeLimit *time_limit) override
Definition: bop_fs.cc:442
operations_research::bop::LinearRelaxation::LinearRelaxation
LinearRelaxation(const BopParameters &parameters, const std::string &name)
Definition: bop_fs.cc:338
operations_research::ACMRandom::Uniform
uint32 Uniform(uint32 n)
Definition: random.cc:40
operations_research::bop::BopOptimizerBase::LIMIT_REACHED
@ LIMIT_REACHED
Definition: bop_base.h:65
operations_research::bop::GuidedSatFirstSolutionGenerator::ShouldBeRun
bool ShouldBeRun(const ProblemState &problem_state) const override
Definition: bop_fs.cc:145
operations_research::bop::GuidedSatFirstSolutionGenerator::Policy::kLpGuided
@ kLpGuided
symmetry.h
operations_research::sat::SatSolver
Definition: sat_solver.h:58
operations_research::bop::ProblemState::lp_values
const glop::DenseRow & lp_values() const
Definition: bop_base.h:188
operations_research::glop::LinearProgram::SetConstraintBounds
void SetConstraintBounds(RowIndex row, Fractional lower_bound, Fractional upper_bound)
Definition: lp_data.cc:307
operations_research::bop::BopRandomFirstSolutionGenerator::ShouldBeRun
bool ShouldBeRun(const ProblemState &problem_state) const override
Definition: bop_fs.cc:221
value
int64 value
Definition: demon_profiler.cc:43
CHECK_LT
#define CHECK_LT(val1, val2)
Definition: base/logging.h:700
operations_research::bop::LearnedInfo::solution
BopSolution solution
Definition: bop_base.h:266
operations_research::sat::SatSolver::RestoreSolverToAssumptionLevel
bool RestoreSolverToAssumptionLevel()
Definition: sat_solver.cc:511
operations_research
The vehicle routing library lets one model and solve generic vehicle routing problems ranging from th...
Definition: dense_doubly_linked_list.h:21
operations_research::sat::SatSolver::FEASIBLE
@ FEASIBLE
Definition: sat_solver.h:184
operations_research::bop::LoadStateProblemToSatSolver
BopOptimizerBase::Status LoadStateProblemToSatSolver(const ProblemState &problem_state, sat::SatSolver *sat_solver)
Definition: bop_util.cc:87
operations_research::bop::BopOptimizerBase::INFORMATION_FOUND
@ INFORMATION_FOUND
Definition: bop_base.h:72
operations_research::sat::FindLinearBooleanProblemSymmetries
void FindLinearBooleanProblemSymmetries(const LinearBooleanProblem &problem, std::vector< std::unique_ptr< SparsePermutation >> *generators)
Definition: boolean_problem.cc:670
operations_research::bop::BopOptimizerBase
Definition: bop_base.h:40
int64
int64_t int64
Definition: integral_types.h:34
sat_solver.h
operations_research::sat::ConvertBooleanProblemToLinearProgram
void ConvertBooleanProblemToLinearProgram(const LinearBooleanProblem &problem, glop::LinearProgram *lp)
Definition: sat/lp_utils.cc:1090
operations_research::TimeLimit
A simple class to enforce both an elapsed time limit and a deterministic time limit in the same threa...
Definition: time_limit.h:105
operations_research::bop::GuidedSatFirstSolutionGenerator::~GuidedSatFirstSolutionGenerator
~GuidedSatFirstSolutionGenerator() override
Definition: bop_fs.cc:85
operations_research::sat::SatSolver::INFEASIBLE
@ INFEASIBLE
Definition: sat_solver.h:183
offset_
const int64 offset_
Definition: interval.cc:2076
operations_research::bop::ProblemState::IsVariableFixed
bool IsVariableFixed(VariableIndex var) const
Definition: bop_base.h:172
operations_research::glop::Fractional
double Fractional
Definition: lp_types.h:77
operations_research::glop::LinearProgram::CreateNewConstraint
RowIndex CreateNewConstraint()
Definition: lp_data.cc:189
operations_research::glop::LinearProgram::Clear
void Clear()
Definition: lp_data.cc:132
operations_research::glop::kInfinity
const double kInfinity
Definition: lp_types.h:83
operations_research::sat::UseObjectiveForSatAssignmentPreference
void UseObjectiveForSatAssignmentPreference(const LinearBooleanProblem &problem, SatSolver *solver)
Definition: boolean_problem.cc:307
operations_research::MTRandom
Definition: random.h:55
operations_research::bop::SatAssignmentToBopSolution
void SatAssignmentToBopSolution(const sat::VariablesAssignment &assignment, BopSolution *solution)
Definition: bop_util.cc:121
operations_research::bop::ProblemState::is_fixed
const absl::StrongVector< VariableIndex, bool > & is_fixed() const
Definition: bop_base.h:173
operations_research::bop::BopOptimizerBase::INFEASIBLE
@ INFEASIBLE
Definition: bop_base.h:64
operations_research::NestedTimeLimit
Provides a way to nest time limits for algorithms where a certain part of the computation is bounded ...
Definition: time_limit.h:425
time_limit
SharedTimeLimit * time_limit
Definition: cp_model_solver.cc:2103
operations_research::glop::LinearProgram::SetVariableBounds
void SetVariableBounds(ColIndex col, Fractional lower_bound, Fractional upper_bound)
Definition: lp_data.cc:247
operations_research::bop::BopRandomFirstSolutionGenerator::BopRandomFirstSolutionGenerator
BopRandomFirstSolutionGenerator(const std::string &name, const BopParameters &parameters, sat::SatSolver *sat_propagator, MTRandom *random)
Definition: bop_fs.cc:211
operations_research::bop::LearnedInfo
Definition: bop_base.h:245
operations_research::sat::SatSolver::ResetDecisionHeuristicAndSetAllPreferences
void ResetDecisionHeuristicAndSetAllPreferences(const std::vector< std::pair< Literal, double >> &prefs)
Definition: sat_solver.h:160
operations_research::bop::ProblemState
Definition: bop_base.h:111
operations_research::bop::GuidedSatFirstSolutionGenerator::GuidedSatFirstSolutionGenerator
GuidedSatFirstSolutionGenerator(const std::string &name, Policy policy)
Definition: bop_fs.cc:77
operations_research::sat::SatSolver::ResetDecisionHeuristic
void ResetDecisionHeuristic()
Definition: sat_solver.h:157
CHECK_EQ
#define CHECK_EQ(val1, val2)
Definition: base/logging.h:697
operations_research::bop::LinearRelaxation::~LinearRelaxation
~LinearRelaxation() override
Definition: bop_fs.cc:353
operations_research::glop::LinearProgram::GetVariableName
std::string GetVariableName(ColIndex col) const
Definition: lp_data.cc:358
operations_research::bop::BopSolution::GetScaledCost
double GetScaledCost() const
Definition: bop_solution.h:61
operations_research::bop::ExtractLearnedInfoFromSatSolver
void ExtractLearnedInfoFromSatSolver(sat::SatSolver *solver, LearnedInfo *info)
Definition: bop_util.cc:98
operations_research::bop::ProblemState::NewlyAddedBinaryClauses
const std::vector< sat::BinaryClause > & NewlyAddedBinaryClauses() const
Definition: bop_base.cc:247
operations_research::glop::LinearProgram::SetCoefficient
void SetCoefficient(RowIndex row, ColIndex col, Fractional value)
Definition: lp_data.cc:315
operations_research::bop::ProblemState::original_problem
const sat::LinearBooleanProblem & original_problem() const
Definition: bop_base.h:198
operations_research::sat::SatSolver::AllPreferences
std::vector< std::pair< Literal, double > > AllPreferences() const
Definition: sat_solver.h:154
operations_research::bop::ProblemState::assignment_preference
const std::vector< bool > assignment_preference() const
Definition: bop_base.h:127
operations_research::glop::GetProblemStatusString
std::string GetProblemStatusString(ProblemStatus problem_status)
Definition: lp_types.cc:19
operations_research::bop::GuidedSatFirstSolutionGenerator::Policy::kObjectiveGuided
@ kObjectiveGuided
operations_research::glop::LinearProgram::SetConstraintName
void SetConstraintName(RowIndex row, absl::string_view name)
Definition: lp_data.cc:243
operations_research::bop::BopOptimizerBase::OPTIMAL_SOLUTION_FOUND
@ OPTIMAL_SOLUTION_FOUND
Definition: bop_base.h:62
operations_research::sat::SatSolver::num_failures
int64 num_failures() const
Definition: sat_solver.cc:84
operations_research::bop::LearnedInfo::lower_bound
int64 lower_bound
Definition: bop_base.h:269
operations_research::sat::Literal
Definition: sat_base.h:64
operations_research::glop::LPSolver::variable_values
const DenseRow & variable_values() const
Definition: lp_solver.h:100
operations_research::bop::GuidedSatFirstSolutionGenerator::Policy::kNotGuided
@ kNotGuided
operations_research::bop::BopRandomFirstSolutionGenerator::~BopRandomFirstSolutionGenerator
~BopRandomFirstSolutionGenerator() override
Definition: bop_fs.cc:218
operations_research::bop::GuidedSatFirstSolutionGenerator::Policy
Policy
Definition: bop_fs.h:45
lp_print_utils.h
operations_research::glop::ProblemStatus::OPTIMAL
@ OPTIMAL
operations_research::glop::LPSolver::SolveWithTimeLimit
ABSL_MUST_USE_RESULT ProblemStatus SolveWithTimeLimit(const LinearProgram &lp, TimeLimit *time_limit)
Definition: lp_solver.cc:127
operations_research::bop::LearnedInfo::lp_values
glop::DenseRow lp_values
Definition: bop_base.h:275
col
ColIndex col
Definition: markowitz.cc:176
operations_research::bop::BopSolution::IsFeasible
bool IsFeasible() const
Definition: bop_solution.h:69
util.h
operations_research::bop::ProblemState::GetParameters
const BopParameters & GetParameters() const
Definition: bop_base.h:120
operations_research::glop::ProblemStatus
ProblemStatus
Definition: lp_types.h:101
operations_research::glop::LinearProgram::IsMaximizationProblem
bool IsMaximizationProblem() const
Definition: lp_data.h:171
stl_util.h
operations_research::sat::SatSolver::Backtrack
void Backtrack(int target_level)
Definition: sat_solver.cc:888
operations_research::glop::ProblemStatus::INIT
@ INIT
lp_utils.h
boolean_problem.h
operations_research::bop::LinearRelaxation::ShouldBeRun
bool ShouldBeRun(const ProblemState &problem_state) const override
Definition: bop_fs.cc:437
operations_research::bop::GuidedSatFirstSolutionGenerator::Optimize
Status Optimize(const BopParameters &parameters, const ProblemState &problem_state, LearnedInfo *learned_info, TimeLimit *time_limit) override
Definition: bop_fs.cc:158
operations_research::glop::LPSolver::SetParameters
void SetParameters(const GlopParameters &parameters)
Definition: lp_solver.cc:113
operations_research::sat::SatSolver::SolveWithTimeLimit
Status SolveWithTimeLimit(TimeLimit *time_limit)
Definition: sat_solver.cc:968
operations_research::bop::BopOptimizerBase::CONTINUE
@ CONTINUE
Definition: bop_base.h:76
operations_research::bop::BopSolution::GetCost
int64 GetCost() const
Definition: bop_solution.h:50
operations_research::sat::SatSolver::parameters
const SatParameters & parameters() const
Definition: sat_solver.cc:110
operations_research::sat::AddObjectiveConstraint
bool AddObjectiveConstraint(const LinearBooleanProblem &problem, bool use_lower_bound, Coefficient lower_bound, bool use_upper_bound, Coefficient upper_bound, SatSolver *solver)
Definition: boolean_problem.cc:336
operations_research::bop::ProblemState::GetVariableFixedValue
bool GetVariableFixedValue(VariableIndex var) const
Definition: bop_base.h:179
operations_research::sat::RandomizeDecisionHeuristic
void RandomizeDecisionHeuristic(URBG *random, SatParameters *parameters)
Definition: sat/util.h:76
absl::StrongVector::empty
bool empty() const
Definition: strong_vector.h:156
operations_research::glop::LinearProgram::variable_upper_bounds
const DenseRow & variable_upper_bounds() const
Definition: lp_data.h:232
operations_research::bop::BopOptimizerBase::Status
Status
Definition: bop_base.h:61
CHECK
#define CHECK(condition)
Definition: base/logging.h:495
commandlineflags.h
operations_research::sat::SatSolver::IsModelUnsat
bool IsModelUnsat() const
Definition: sat_solver.h:137
parameters
SatParameters parameters
Definition: cp_model_fz_solver.cc:108
name
const std::string name
Definition: default_search.cc:808
operations_research::sat::SymmetryPropagator
Definition: symmetry.h:61
operations_research::bop::BopOptimizerBase::ABORT
@ ABORT
Definition: bop_base.h:79
bitset.h
kint64max
static const int64 kint64max
Definition: integral_types.h:62
operations_research::bop::ProblemState::update_stamp
int64 update_stamp() const
Definition: bop_base.h:153
lp_solver.h
operations_research::sat::SatSolver::SetParameters
void SetParameters(const SatParameters &parameters)
Definition: sat_solver.cc:115