OR-Tools  8.1
integer_search.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 
15 
16 #include <cmath>
17 #include <functional>
18 #include <vector>
19 
22 #include "ortools/sat/integer.h"
24 #include "ortools/sat/probing.h"
26 #include "ortools/sat/rins.h"
27 #include "ortools/sat/sat_base.h"
32 #include "ortools/sat/util.h"
33 
34 namespace operations_research {
35 namespace sat {
36 
37 IntegerLiteral AtMinValue(IntegerVariable var, IntegerTrail* integer_trail) {
38  DCHECK(!integer_trail->IsCurrentlyIgnored(var));
39  const IntegerValue lb = integer_trail->LowerBound(var);
40  DCHECK_LE(lb, integer_trail->UpperBound(var));
41  if (lb == integer_trail->UpperBound(var)) return IntegerLiteral();
43 }
44 
46  const auto& variables =
47  model->GetOrCreate<ObjectiveDefinition>()->objective_impacting_variables;
48  auto* integer_trail = model->GetOrCreate<IntegerTrail>();
49  if (variables.contains(var)) {
50  return AtMinValue(var, integer_trail);
51  } else if (variables.contains(NegationOf(var))) {
52  return AtMinValue(NegationOf(var), integer_trail);
53  }
54  return IntegerLiteral();
55 }
56 
58  IntegerTrail* integer_trail) {
59  const IntegerValue var_lb = integer_trail->LowerBound(var);
60  const IntegerValue var_ub = integer_trail->UpperBound(var);
61  CHECK_LT(var_lb, var_ub);
62 
63  const IntegerValue chosen_value =
64  var_lb + std::max(IntegerValue(1), (var_ub - var_lb) / IntegerValue(2));
65  return IntegerLiteral::GreaterOrEqual(var, chosen_value);
66 }
67 
68 IntegerLiteral SplitAroundGivenValue(IntegerVariable var, IntegerValue value,
69  Model* model) {
70  auto* integer_trail = model->GetOrCreate<IntegerTrail>();
71  const IntegerValue lb = integer_trail->LowerBound(var);
72  const IntegerValue ub = integer_trail->UpperBound(var);
73 
74  const absl::flat_hash_set<IntegerVariable>& variables =
75  model->GetOrCreate<ObjectiveDefinition>()->objective_impacting_variables;
76 
77  // Heuristic: Prefer the objective direction first. Reference: Conflict-Driven
78  // Heuristics for Mixed Integer Programming (2019) by Jakob Witzig and Ambros
79  // Gleixner.
80  // NOTE: The value might be out of bounds. In that case we return
81  // kNoLiteralIndex.
82  const bool branch_down_feasible = value >= lb && value < ub;
83  const bool branch_up_feasible = value > lb && value <= ub;
84  if (variables.contains(var) && branch_down_feasible) {
86  } else if (variables.contains(NegationOf(var)) && branch_up_feasible) {
88  } else if (branch_down_feasible) {
90  } else if (branch_up_feasible) {
92  }
93  return IntegerLiteral();
94 }
95 
97  auto* parameters = model->GetOrCreate<SatParameters>();
98  auto* integer_trail = model->GetOrCreate<IntegerTrail>();
99  auto* lp_dispatcher = model->GetOrCreate<LinearProgrammingDispatcher>();
100  DCHECK(!integer_trail->IsCurrentlyIgnored(var));
101 
102  const IntegerVariable positive_var = PositiveVariable(var);
103  const LinearProgrammingConstraint* lp =
104  gtl::FindWithDefault(*lp_dispatcher, positive_var, nullptr);
105 
106  // We only use this if the sub-lp has a solution, and depending on the value
107  // of exploit_all_lp_solution() if it is a pure-integer solution.
108  if (lp == nullptr || !lp->HasSolution()) return IntegerLiteral();
109  if (!parameters->exploit_all_lp_solution() && !lp->SolutionIsInteger()) {
110  return IntegerLiteral();
111  }
112 
113  const IntegerValue value = IntegerValue(
114  static_cast<int64>(std::round(lp->GetSolutionValue(positive_var))));
115 
116  // Because our lp solution might be from higher up in the tree, it
117  // is possible that value is now outside the domain of positive_var.
118  // In this case, this function will return an invalid literal.
119  return SplitAroundGivenValue(positive_var, value, model);
120 }
121 
123  IntegerVariable var, const SharedSolutionRepository<int64>& solution_repo,
124  Model* model) {
125  if (solution_repo.NumSolutions() == 0) {
126  return IntegerLiteral();
127  }
128 
129  const IntegerVariable positive_var = PositiveVariable(var);
130  const int proto_var =
131  model->Get<CpModelMapping>()->GetProtoVariableFromIntegerVariable(
132  positive_var);
133 
134  if (proto_var < 0) {
135  return IntegerLiteral();
136  }
137 
138  VLOG(2) << "Using solution value for branching.";
139  const IntegerValue value(solution_repo.GetVariableValueInSolution(
140  proto_var, /*solution_index=*/0));
141  return SplitAroundGivenValue(positive_var, value, model);
142 }
143 
144 // TODO(user): the complexity caused by the linear scan in this heuristic and
145 // the one below is ok when search_branching is set to SAT_SEARCH because it is
146 // not executed often, but otherwise it is done for each search decision,
147 // which seems expensive. Improve.
149  const std::vector<IntegerVariable>& vars, Model* model) {
150  auto* integer_trail = model->GetOrCreate<IntegerTrail>();
151  return [/*copy*/ vars, integer_trail]() {
152  for (const IntegerVariable var : vars) {
153  // Note that there is no point trying to fix a currently ignored variable.
154  if (integer_trail->IsCurrentlyIgnored(var)) continue;
155  const IntegerLiteral decision = AtMinValue(var, integer_trail);
156  if (decision.IsValid()) return BooleanOrIntegerLiteral(decision);
157  }
158  return BooleanOrIntegerLiteral();
159  };
160 }
161 
162 std::function<BooleanOrIntegerLiteral()>
164  const std::vector<IntegerVariable>& vars, Model* model) {
165  auto* integer_trail = model->GetOrCreate<IntegerTrail>();
166  return [/*copy */ vars, integer_trail]() {
167  IntegerVariable candidate = kNoIntegerVariable;
168  IntegerValue candidate_lb;
169  for (const IntegerVariable var : vars) {
170  if (integer_trail->IsCurrentlyIgnored(var)) continue;
171  const IntegerValue lb = integer_trail->LowerBound(var);
172  if (lb < integer_trail->UpperBound(var) &&
173  (candidate == kNoIntegerVariable || lb < candidate_lb)) {
174  candidate = var;
175  candidate_lb = lb;
176  }
177  }
178  if (candidate == kNoIntegerVariable) return BooleanOrIntegerLiteral();
179  return BooleanOrIntegerLiteral(AtMinValue(candidate, integer_trail));
180  };
181 }
182 
184  std::vector<std::function<BooleanOrIntegerLiteral()>> heuristics) {
185  return [heuristics]() {
186  for (const auto& h : heuristics) {
187  const BooleanOrIntegerLiteral decision = h();
188  if (decision.HasValue()) return decision;
189  }
190  return BooleanOrIntegerLiteral();
191  };
192 }
193 
195  std::vector<std::function<IntegerLiteral(IntegerVariable)>>
196  value_selection_heuristics,
197  std::function<BooleanOrIntegerLiteral()> var_selection_heuristic,
198  Model* model) {
199  auto* encoder = model->GetOrCreate<IntegerEncoder>();
200  auto* integer_trail = model->GetOrCreate<IntegerTrail>();
201  return [=]() {
202  // Get the current decision.
203  const BooleanOrIntegerLiteral current_decision = var_selection_heuristic();
204  if (!current_decision.HasValue()) return current_decision;
205 
206  // IntegerLiteral case.
207  if (current_decision.boolean_literal_index == kNoLiteralIndex) {
208  for (const auto& value_heuristic : value_selection_heuristics) {
209  const IntegerLiteral decision =
210  value_heuristic(current_decision.integer_literal.var);
211  if (decision.IsValid()) return BooleanOrIntegerLiteral(decision);
212  }
213  return current_decision;
214  }
215 
216  // Boolean case. We try to decode the Boolean decision to see if it is
217  // associated with an integer variable.
218  for (const IntegerLiteral l : encoder->GetAllIntegerLiterals(
219  Literal(current_decision.boolean_literal_index))) {
220  if (integer_trail->IsCurrentlyIgnored(l.var)) continue;
221 
222  // Sequentially try the value selection heuristics.
223  for (const auto& value_heuristic : value_selection_heuristics) {
224  const IntegerLiteral decision = value_heuristic(l.var);
225  if (decision.IsValid()) return BooleanOrIntegerLiteral(decision);
226  }
227  }
228 
229  VLOG(2) << "Value selection: using default decision.";
230  return current_decision;
231  };
232 }
233 
235  auto* lp_constraints =
237  int num_lp_variables = 0;
238  for (LinearProgrammingConstraint* lp : *lp_constraints) {
239  num_lp_variables += lp->NumVariables();
240  }
241  const int num_integer_variables =
242  model->GetOrCreate<IntegerTrail>()->NumIntegerVariables().value() / 2;
243  return (num_integer_variables <= 2 * num_lp_variables);
244 }
245 
246 // TODO(user): Experiment more with value selection heuristics.
248  std::function<BooleanOrIntegerLiteral()> var_selection_heuristic,
249  Model* model) {
250  const SatParameters& parameters = *(model->GetOrCreate<SatParameters>());
251  std::vector<std::function<IntegerLiteral(IntegerVariable)>>
252  value_selection_heuristics;
253 
254  // LP based value.
255  //
256  // Note that we only do this if a big enough percentage of the problem
257  // variables appear in the LP relaxation.
259  (parameters.exploit_integer_lp_solution() ||
260  parameters.exploit_all_lp_solution())) {
261  VLOG(1) << "Using LP value selection heuristic.";
262  value_selection_heuristics.push_back([model](IntegerVariable var) {
264  });
265  }
266 
267  // Solution based value.
268  if (parameters.exploit_best_solution()) {
269  auto* response_manager = model->Get<SharedResponseManager>();
270  if (response_manager != nullptr) {
271  VLOG(1) << "Using best solution value selection heuristic.";
272  value_selection_heuristics.push_back(
273  [model, response_manager](IntegerVariable var) {
275  var, response_manager->SolutionsRepository(), model);
276  });
277  }
278  }
279 
280  // Relaxation Solution based value.
281  if (parameters.exploit_relaxation_solution()) {
282  auto* relaxation_solutions =
284  if (relaxation_solutions != nullptr) {
285  value_selection_heuristics.push_back(
286  [model, relaxation_solutions](IntegerVariable var) {
287  VLOG(1) << "Using relaxation solution value selection heuristic.";
290  });
291  }
292  }
293 
294  // Objective based value.
295  if (parameters.exploit_objective()) {
296  VLOG(1) << "Using objective value selection heuristic.";
297  value_selection_heuristics.push_back([model](IntegerVariable var) {
299  });
300  }
301 
302  return SequentialValueSelection(value_selection_heuristics,
303  var_selection_heuristic, model);
304 }
305 
307  SatSolver* sat_solver = model->GetOrCreate<SatSolver>();
308  Trail* trail = model->GetOrCreate<Trail>();
309  SatDecisionPolicy* decision_policy = model->GetOrCreate<SatDecisionPolicy>();
310  return [sat_solver, trail, decision_policy] {
311  const bool all_assigned = trail->Index() == sat_solver->NumVariables();
312  if (all_assigned) return BooleanOrIntegerLiteral();
313  const Literal result = decision_policy->NextBranch();
314  CHECK(!sat_solver->Assignment().LiteralIsAssigned(result));
315  return BooleanOrIntegerLiteral(result.Index());
316  };
317 }
318 
320  auto* objective = model->Get<ObjectiveDefinition>();
321  const bool has_objective =
322  objective != nullptr && objective->objective_var != kNoIntegerVariable;
323  if (!has_objective) {
324  return []() { return BooleanOrIntegerLiteral(); };
325  }
326 
327  auto* pseudo_costs = model->GetOrCreate<PseudoCosts>();
328  auto* integer_trail = model->GetOrCreate<IntegerTrail>();
329  return [pseudo_costs, integer_trail]() {
330  const IntegerVariable chosen_var = pseudo_costs->GetBestDecisionVar();
331  if (chosen_var == kNoIntegerVariable) return BooleanOrIntegerLiteral();
333  GreaterOrEqualToMiddleValue(chosen_var, integer_trail));
334  };
335 }
336 
338  Model* model) {
339  SatSolver* sat_solver = model->GetOrCreate<SatSolver>();
340  SatDecisionPolicy* decision_policy = model->GetOrCreate<SatDecisionPolicy>();
341 
342  // TODO(user): Add other policy and perform more experiments.
343  std::function<BooleanOrIntegerLiteral()> sat_policy =
345  std::vector<std::function<BooleanOrIntegerLiteral()>> policies{
346  sat_policy, SequentialSearch({PseudoCost(model), sat_policy})};
347  // The higher weight for the sat policy is because this policy actually
348  // contains a lot of variation as we randomize the sat parameters.
349  // TODO(user,user): Do more experiments to find better distribution.
350  std::discrete_distribution<int> var_dist{3 /*sat_policy*/, 1 /*Pseudo cost*/};
351 
352  // Value selection.
353  std::vector<std::function<IntegerLiteral(IntegerVariable)>>
354  value_selection_heuristics;
355  std::vector<int> value_selection_weight;
356 
357  // LP Based value.
358  value_selection_heuristics.push_back([model](IntegerVariable var) {
360  });
361  value_selection_weight.push_back(8);
362 
363  // Solution based value.
364  auto* response_manager = model->Get<SharedResponseManager>();
365  if (response_manager != nullptr) {
366  value_selection_heuristics.push_back(
367  [model, response_manager](IntegerVariable var) {
369  var, response_manager->SolutionsRepository(), model);
370  });
371  value_selection_weight.push_back(5);
372  }
373 
374  // Relaxation solution based value.
376  if (relaxation_solutions != nullptr) {
377  value_selection_heuristics.push_back(
378  [model, relaxation_solutions](IntegerVariable var) {
381  });
382  value_selection_weight.push_back(3);
383  }
384 
385  // Middle value.
386  auto* integer_trail = model->GetOrCreate<IntegerTrail>();
387  value_selection_heuristics.push_back([integer_trail](IntegerVariable var) {
388  return GreaterOrEqualToMiddleValue(var, integer_trail);
389  });
390  value_selection_weight.push_back(1);
391 
392  // Min value.
393  value_selection_heuristics.push_back([integer_trail](IntegerVariable var) {
394  return AtMinValue(var, integer_trail);
395  });
396  value_selection_weight.push_back(1);
397 
398  // Special case: Don't change the decision value.
399  value_selection_weight.push_back(10);
400 
401  // TODO(user): These distribution values are just guessed values. They need
402  // to be tuned.
403  std::discrete_distribution<int> val_dist(value_selection_weight.begin(),
404  value_selection_weight.end());
405 
406  int policy_index = 0;
407  int val_policy_index = 0;
408  auto* encoder = model->GetOrCreate<IntegerEncoder>();
409  return [=]() mutable {
410  if (sat_solver->CurrentDecisionLevel() == 0) {
411  auto* random = model->GetOrCreate<ModelRandomGenerator>();
412  RandomizeDecisionHeuristic(random, model->GetOrCreate<SatParameters>());
413  decision_policy->ResetDecisionHeuristic();
414 
415  // Select the variable selection heuristic.
416  policy_index = var_dist(*(random));
417 
418  // Select the value selection heuristic.
419  val_policy_index = val_dist(*(random));
420  }
421 
422  // Get the current decision.
423  const BooleanOrIntegerLiteral current_decision = policies[policy_index]();
424  if (!current_decision.HasValue()) return current_decision;
425 
426  // Special case: Don't override the decision value.
427  if (val_policy_index >= value_selection_heuristics.size()) {
428  return current_decision;
429  }
430 
431  if (current_decision.boolean_literal_index == kNoLiteralIndex) {
432  const IntegerLiteral new_decision =
433  value_selection_heuristics[val_policy_index](
434  current_decision.integer_literal.var);
435  if (new_decision.IsValid()) return BooleanOrIntegerLiteral(new_decision);
436  return current_decision;
437  }
438 
439  // Decode the decision and get the variable.
440  for (const IntegerLiteral l : encoder->GetAllIntegerLiterals(
441  Literal(current_decision.boolean_literal_index))) {
442  if (integer_trail->IsCurrentlyIgnored(l.var)) continue;
443 
444  // Try the selected policy.
445  const IntegerLiteral new_decision =
446  value_selection_heuristics[val_policy_index](l.var);
447  if (new_decision.IsValid()) return BooleanOrIntegerLiteral(new_decision);
448  }
449 
450  // Selected policy failed. Revert back to original decision.
451  return current_decision;
452  };
453 }
454 
455 // TODO(user): Avoid the quadratic algorithm!!
457  const std::vector<BooleanOrIntegerVariable>& vars,
458  const std::vector<IntegerValue>& values, Model* model) {
459  const Trail* trail = model->GetOrCreate<Trail>();
460  const IntegerTrail* integer_trail = model->GetOrCreate<IntegerTrail>();
461  return [=] { // copy
462  for (int i = 0; i < vars.size(); ++i) {
463  const IntegerValue value = values[i];
464  if (vars[i].bool_var != kNoBooleanVariable) {
465  if (trail->Assignment().VariableIsAssigned(vars[i].bool_var)) continue;
467  Literal(vars[i].bool_var, value == 1).Index());
468  } else {
469  const IntegerVariable integer_var = vars[i].int_var;
470  if (integer_trail->IsCurrentlyIgnored(integer_var)) continue;
471  if (integer_trail->IsFixed(integer_var)) continue;
472 
473  const IntegerVariable positive_var = PositiveVariable(integer_var);
474  const IntegerLiteral decision = SplitAroundGivenValue(
475  positive_var, positive_var != integer_var ? -value : value, model);
476  if (decision.IsValid()) return BooleanOrIntegerLiteral(decision);
477 
478  // If the value is outside the current possible domain, we skip it.
479  continue;
480  }
481  }
482  return BooleanOrIntegerLiteral();
483  };
484 }
485 
486 std::function<bool()> RestartEveryKFailures(int k, SatSolver* solver) {
487  bool reset_at_next_call = true;
488  int next_num_failures = 0;
489  return [=]() mutable {
490  if (reset_at_next_call) {
491  next_num_failures = solver->num_failures() + k;
492  reset_at_next_call = false;
493  } else if (solver->num_failures() >= next_num_failures) {
494  reset_at_next_call = true;
495  }
496  return reset_at_next_call;
497  };
498 }
499 
500 std::function<bool()> SatSolverRestartPolicy(Model* model) {
501  auto policy = model->GetOrCreate<RestartPolicy>();
502  return [policy]() { return policy->ShouldRestart(); };
503 }
504 
505 namespace {
506 
507 std::function<BooleanOrIntegerLiteral()> WrapIntegerLiteralHeuristic(
508  std::function<IntegerLiteral()> f) {
509  return [f]() { return BooleanOrIntegerLiteral(f()); };
510 }
511 
512 } // namespace
513 
515  SearchHeuristics& heuristics = *model->GetOrCreate<SearchHeuristics>();
516  CHECK(heuristics.fixed_search != nullptr);
517  heuristics.policy_index = 0;
518  heuristics.decision_policies.clear();
519  heuristics.restart_policies.clear();
520 
521  const SatParameters& parameters = *(model->GetOrCreate<SatParameters>());
522  switch (parameters.search_branching()) {
523  case SatParameters::AUTOMATIC_SEARCH: {
524  std::function<BooleanOrIntegerLiteral()> decision_policy;
525  if (parameters.randomize_search()) {
526  decision_policy = RandomizeOnRestartHeuristic(model);
527  } else {
528  decision_policy = SatSolverHeuristic(model);
529  }
530  decision_policy =
531  SequentialSearch({decision_policy, heuristics.fixed_search});
532  decision_policy = IntegerValueSelectionHeuristic(decision_policy, model);
533  heuristics.decision_policies = {decision_policy};
535  return;
536  }
537  case SatParameters::FIXED_SEARCH: {
538  // Not all Boolean might appear in fixed_search(), so once there is no
539  // decision left, we fix all Booleans that are still undecided.
540  heuristics.decision_policies = {SequentialSearch(
541  {heuristics.fixed_search, SatSolverHeuristic(model)})};
542 
543  if (parameters.randomize_search()) {
545  return;
546  }
547 
548  // TODO(user): We might want to restart if external info is available.
549  // Code a custom restart for this?
550  auto no_restart = []() { return false; };
551  heuristics.restart_policies = {no_restart};
552  return;
553  }
554  case SatParameters::HINT_SEARCH: {
555  CHECK(heuristics.hint_search != nullptr);
556  heuristics.decision_policies = {
558  heuristics.fixed_search})};
559  auto no_restart = []() { return false; };
560  heuristics.restart_policies = {no_restart};
561  return;
562  }
563  case SatParameters::PORTFOLIO_SEARCH: {
564  // TODO(user): This is not used in any of our default config. remove?
565  // It make also no sense to choose a value in the LP heuristic and then
566  // override it with IntegerValueSelectionHeuristic(), clean that up.
567  std::vector<std::function<BooleanOrIntegerLiteral()>> base_heuristics;
568  base_heuristics.push_back(heuristics.fixed_search);
569  for (const auto& ct :
570  *(model->GetOrCreate<LinearProgrammingConstraintCollection>())) {
571  base_heuristics.push_back(WrapIntegerLiteralHeuristic(
572  ct->HeuristicLpReducedCostBinary(model)));
573  base_heuristics.push_back(WrapIntegerLiteralHeuristic(
574  ct->HeuristicLpMostInfeasibleBinary(model)));
575  }
577  base_heuristics, SequentialSearch({SatSolverHeuristic(model),
578  heuristics.fixed_search}));
579  for (auto& ref : heuristics.decision_policies) {
581  }
582  heuristics.restart_policies.assign(heuristics.decision_policies.size(),
584  return;
585  }
586  case SatParameters::LP_SEARCH: {
587  std::vector<std::function<BooleanOrIntegerLiteral()>> lp_heuristics;
588  for (const auto& ct :
589  *(model->GetOrCreate<LinearProgrammingConstraintCollection>())) {
590  lp_heuristics.push_back(WrapIntegerLiteralHeuristic(
591  ct->HeuristicLpReducedCostAverageBranching()));
592  }
593  if (lp_heuristics.empty()) { // Revert to fixed search.
594  heuristics.decision_policies = {SequentialSearch(
595  {heuristics.fixed_search, SatSolverHeuristic(model)})},
597  return;
598  }
600  lp_heuristics, SequentialSearch({SatSolverHeuristic(model),
601  heuristics.fixed_search}));
602  heuristics.restart_policies.assign(heuristics.decision_policies.size(),
604  return;
605  }
606  case SatParameters::PSEUDO_COST_SEARCH: {
607  std::function<BooleanOrIntegerLiteral()> search =
609  heuristics.fixed_search});
610  heuristics.decision_policies = {
613  return;
614  }
615  case SatParameters::PORTFOLIO_WITH_QUICK_RESTART_SEARCH: {
616  std::function<BooleanOrIntegerLiteral()> search = SequentialSearch(
618  heuristics.decision_policies = {search};
619  heuristics.restart_policies = {
620  RestartEveryKFailures(10, model->GetOrCreate<SatSolver>())};
621  return;
622  }
623  }
624 }
625 
626 std::vector<std::function<BooleanOrIntegerLiteral()>> CompleteHeuristics(
627  const std::vector<std::function<BooleanOrIntegerLiteral()>>&
628  incomplete_heuristics,
629  const std::function<BooleanOrIntegerLiteral()>& completion_heuristic) {
630  std::vector<std::function<BooleanOrIntegerLiteral()>> complete_heuristics;
631  complete_heuristics.reserve(incomplete_heuristics.size());
632  for (const auto& incomplete : incomplete_heuristics) {
633  complete_heuristics.push_back(
634  SequentialSearch({incomplete, completion_heuristic}));
635  }
636  return complete_heuristics;
637 }
638 
640  TimeLimit* time_limit = model->GetOrCreate<TimeLimit>();
641  if (time_limit->LimitReached()) return SatSolver::LIMIT_REACHED;
642 
643  SearchHeuristics& heuristics = *model->GetOrCreate<SearchHeuristics>();
644  const int num_policies = heuristics.decision_policies.size();
645  CHECK_NE(num_policies, 0);
646  CHECK_EQ(num_policies, heuristics.restart_policies.size());
647 
648  // This is needed for recording the pseudo-costs.
649  IntegerVariable objective_var = kNoIntegerVariable;
650  {
651  const ObjectiveDefinition* objective = model->Get<ObjectiveDefinition>();
652  if (objective != nullptr) objective_var = objective->objective_var;
653  }
654 
655  // Note that it is important to do the level-zero propagation if it wasn't
656  // already done because EnqueueDecisionAndBackjumpOnConflict() assumes that
657  // the solver is in a "propagated" state.
658  SatSolver* const sat_solver = model->GetOrCreate<SatSolver>();
659 
660  // TODO(user): We have the issue that at level zero. calling the propagation
661  // loop more than once can propagate more! This is because we call the LP
662  // again and again on each level zero propagation. This is causing some
663  // CHECKs() to fail in multithread (rarely) because when we associate new
664  // literals to integer ones, Propagate() is indirectly called. Not sure yet
665  // how to fix.
666  if (!sat_solver->FinishPropagation()) return sat_solver->UnsatStatus();
667 
668  // Create and initialize pseudo costs.
669  // TODO(user): If this ever shows up in a cpu profile, find a way to not
670  // execute the code when pseudo costs are not needed.
671  PseudoCosts* pseudo_costs = model->GetOrCreate<PseudoCosts>();
672 
673  auto* integer_trail = model->GetOrCreate<IntegerTrail>();
674  auto* encoder = model->GetOrCreate<IntegerEncoder>();
675  auto* implied_bounds = model->GetOrCreate<ImpliedBounds>();
676 
677  const SatParameters& sat_parameters = *(model->GetOrCreate<SatParameters>());
678 
679  // Main search loop.
680  const int64 old_num_conflicts = sat_solver->num_failures();
681  const int64 conflict_limit = sat_parameters.max_number_of_conflicts();
682  int64 num_decisions_since_last_lp_record_ = 0;
683  int64 num_decisions_without_probing = 0;
684  while (!time_limit->LimitReached() &&
685  (sat_solver->num_failures() - old_num_conflicts < conflict_limit)) {
686  // If needed, restart and switch decision_policy.
687  if (heuristics.restart_policies[heuristics.policy_index]()) {
688  if (!sat_solver->RestoreSolverToAssumptionLevel()) {
689  return sat_solver->UnsatStatus();
690  }
691  heuristics.policy_index = (heuristics.policy_index + 1) % num_policies;
692  }
693 
694  // If we pushed root level deductions, we restart to incorporate them.
695  if (integer_trail->HasPendingRootLevelDeduction()) {
696  if (!sat_solver->RestoreSolverToAssumptionLevel()) {
697  return sat_solver->UnsatStatus();
698  }
699  }
700 
701  if (sat_solver->CurrentDecisionLevel() == 0) {
702  if (!implied_bounds->EnqueueNewDeductions()) {
703  return SatSolver::INFEASIBLE;
704  }
705 
706  auto* level_zero_callbacks =
707  model->GetOrCreate<LevelZeroCallbackHelper>();
708  for (const auto& cb : level_zero_callbacks->callbacks) {
709  if (!cb()) {
710  return SatSolver::INFEASIBLE;
711  }
712  }
713 
714  if (sat_parameters.use_sat_inprocessing() &&
715  !model->GetOrCreate<Inprocessing>()->InprocessingRound()) {
716  return SatSolver::INFEASIBLE;
717  }
718  }
719 
720  LiteralIndex decision = kNoLiteralIndex;
721  while (true) {
722  BooleanOrIntegerLiteral new_decision;
723  if (integer_trail->InPropagationLoop()) {
724  const IntegerVariable var =
725  integer_trail->NextVariableToBranchOnInPropagationLoop();
726  if (var != kNoIntegerVariable) {
727  new_decision.integer_literal =
728  GreaterOrEqualToMiddleValue(var, integer_trail);
729  }
730  }
731  if (!new_decision.HasValue()) {
732  new_decision = heuristics.decision_policies[heuristics.policy_index]();
733  }
734  if (!new_decision.HasValue() &&
735  integer_trail->CurrentBranchHadAnIncompletePropagation()) {
736  const IntegerVariable var = integer_trail->FirstUnassignedVariable();
737  if (var != kNoIntegerVariable) {
738  new_decision.integer_literal = AtMinValue(var, integer_trail);
739  }
740  }
741  if (!new_decision.HasValue()) break;
742 
743  // Convert integer decision to literal one if needed.
744  //
745  // TODO(user): Ideally it would be cool to delay the creation even more
746  // until we have a conflict with these decisions, but it is currrently
747  // hard to do so.
748  if (new_decision.boolean_literal_index != kNoLiteralIndex) {
749  decision = new_decision.boolean_literal_index;
750  } else {
751  decision =
752  encoder->GetOrCreateAssociatedLiteral(new_decision.integer_literal)
753  .Index();
754  }
755 
756  if (sat_solver->Assignment().LiteralIsAssigned(Literal(decision))) {
757  // TODO(user): It would be nicer if this can never happen. For now, it
758  // does because of the Propagate() not reaching the fixed point as
759  // mentionned in a TODO above. As a work-around, we display a message
760  // but do not crash and recall the decision heuristic.
761  VLOG(1) << "Trying to take a decision that is already assigned!"
762  << " Fix this. Continuing for now...";
763  continue;
764  }
765 
766  // Probing.
767  if (sat_solver->CurrentDecisionLevel() == 0 &&
768  sat_parameters.probing_period_at_root() > 0 &&
769  ++num_decisions_without_probing >=
770  sat_parameters.probing_period_at_root()) {
771  num_decisions_without_probing = 0;
772  // TODO(user): Be smarter about what variables we probe, we can also
773  // do more than one.
774 
775  if (!ProbeBooleanVariables(0.1, {Literal(decision).Variable()},
776  model)) {
777  return SatSolver::INFEASIBLE;
778  }
779  DCHECK_EQ(sat_solver->CurrentDecisionLevel(), 0);
780 
781  // We need to check after the probing that the literal is not fixed,
782  // otherwise we just go to the next decision.
783  if (sat_solver->Assignment().LiteralIsAssigned(Literal(decision))) {
784  continue;
785  }
786  }
787  break;
788  }
789 
790  // No decision means that we reached a leave of the search tree and that
791  // we have a feasible solution.
792  if (decision == kNoLiteralIndex) {
793  // Save the current polarity of all Booleans in the solution. It will be
794  // followed for the next SAT decisions. This is known to be a good policy
795  // for optimization problem. Note that for decision problem we don't care
796  // since we are just done as soon as a solution is found.
797  //
798  // This idea is kind of "well known", see for instance the "LinSBPS"
799  // submission to the maxSAT 2018 competition by Emir Demirovic and Peter
800  // Stuckey where they show it is a good idea and provide more references.
801  if (model->GetOrCreate<SatParameters>()->use_optimization_hints()) {
802  auto* sat_decision = model->GetOrCreate<SatDecisionPolicy>();
803  const auto& trail = *model->GetOrCreate<Trail>();
804  for (int i = 0; i < trail.Index(); ++i) {
805  sat_decision->SetAssignmentPreference(trail[i], 0.0);
806  }
807  }
808  return SatSolver::FEASIBLE;
809  }
810 
811  // Record the changelist and objective bounds for updating pseudo costs.
812  const std::vector<PseudoCosts::VariableBoundChange> bound_changes =
813  GetBoundChanges(decision, model);
814  IntegerValue old_obj_lb = kMinIntegerValue;
815  IntegerValue old_obj_ub = kMaxIntegerValue;
816  if (objective_var != kNoIntegerVariable) {
817  old_obj_lb = integer_trail->LowerBound(objective_var);
818  old_obj_ub = integer_trail->UpperBound(objective_var);
819  }
820  const int old_level = sat_solver->CurrentDecisionLevel();
821 
822  // TODO(user): on some problems, this function can be quite long. Expand
823  // so that we can check the time limit at each step?
824  sat_solver->EnqueueDecisionAndBackjumpOnConflict(Literal(decision));
825 
826  // Update the implied bounds each time we enqueue a literal at level zero.
827  // This is "almost free", so we might as well do it.
828  if (old_level == 0 && sat_solver->CurrentDecisionLevel() == 1) {
829  implied_bounds->ProcessIntegerTrail(Literal(decision));
830  }
831 
832  // Update the pseudo costs.
833  if (sat_solver->CurrentDecisionLevel() > old_level &&
834  objective_var != kNoIntegerVariable) {
835  const IntegerValue new_obj_lb = integer_trail->LowerBound(objective_var);
836  const IntegerValue new_obj_ub = integer_trail->UpperBound(objective_var);
837  const IntegerValue objective_bound_change =
838  (new_obj_lb - old_obj_lb) + (old_obj_ub - new_obj_ub);
839  pseudo_costs->UpdateCost(bound_changes, objective_bound_change);
840  }
841 
843  if (!sat_solver->ReapplyAssumptionsIfNeeded()) {
844  return sat_solver->UnsatStatus();
845  }
846 
847  // TODO(user): Experiment more around dynamically changing the
848  // threshold for storing LP solutions in the pool. Alternatively expose
849  // this as parameter so this can be tuned later.
850  //
851  // TODO(user): Avoid adding the same solution many time if the LP didn't
852  // change. Avoid adding solution that are too deep in the tree (most
853  // variable fixed). Also use a callback rather than having this here, we
854  // don't want this file to depend on cp_model.proto.
855  if (model->Get<SharedLPSolutionRepository>() != nullptr) {
856  num_decisions_since_last_lp_record_++;
857  if (num_decisions_since_last_lp_record_ >= 100) {
858  // NOTE: We can actually record LP solutions more frequently. However
859  // this process is time consuming and workers waste a lot of time doing
860  // this. To avoid this we don't record solutions after each decision.
862  num_decisions_since_last_lp_record_ = 0;
863  }
864  }
865  }
866  return SatSolver::Status::LIMIT_REACHED;
867 }
868 
870  const std::vector<Literal>& assumptions, Model* model) {
871  SatSolver* const solver = model->GetOrCreate<SatSolver>();
872 
873  // Sync the bound first.
874  if (!solver->ResetToLevelZero()) return solver->UnsatStatus();
875  auto* level_zero_callbacks = model->GetOrCreate<LevelZeroCallbackHelper>();
876  for (const auto& cb : level_zero_callbacks->callbacks) {
877  if (!cb()) return SatSolver::INFEASIBLE;
878  }
879 
880  // Add the assumptions if any and solve.
881  if (!solver->ResetWithGivenAssumptions(assumptions)) {
882  return solver->UnsatStatus();
883  }
884  return SolveIntegerProblem(model);
885 }
886 
888  const IntegerVariable num_vars =
889  model->GetOrCreate<IntegerTrail>()->NumIntegerVariables();
890  std::vector<IntegerVariable> all_variables;
891  for (IntegerVariable var(0); var < num_vars; ++var) {
892  all_variables.push_back(var);
893  }
894 
895  SearchHeuristics& heuristics = *model->GetOrCreate<SearchHeuristics>();
896  heuristics.policy_index = 0;
897  heuristics.decision_policies = {SequentialSearch(
899  FirstUnassignedVarAtItsMinHeuristic(all_variables, model)})};
901  return ResetAndSolveIntegerProblem(/*assumptions=*/{}, model);
902 }
903 
904 } // namespace sat
905 } // namespace operations_research
operations_research::sat::GreaterOrEqualToMiddleValue
IntegerLiteral GreaterOrEqualToMiddleValue(IntegerVariable var, IntegerTrail *integer_trail)
Definition: integer_search.cc:57
synchronization.h
var
IntVar * var
Definition: expr_array.cc:1858
operations_research::sat::RestartPolicy::ShouldRestart
bool ShouldRestart()
Definition: restart.cc:81
operations_research::sat::LinearProgrammingConstraint::GetSolutionValue
double GetSolutionValue(IntegerVariable variable) const
Definition: linear_programming_constraint.cc:626
operations_research::sat::Literal::Variable
BooleanVariable Variable() const
Definition: sat_base.h:80
operations_research::sat::SatSolver::Status
Status
Definition: sat_solver.h:181
operations_research::sat::RestartEveryKFailures
std::function< bool()> RestartEveryKFailures(int k, SatSolver *solver)
Definition: integer_search.cc:486
operations_research::sat::SatSolver::UnsatStatus
Status UnsatStatus() const
Definition: sat_solver.h:310
operations_research::sat::ObjectiveDefinition
Definition: cp_model_loader.h:38
operations_research::sat::IntegerTrail
Definition: integer.h:518
operations_research::sat::BooleanOrIntegerLiteral
Definition: integer_search.h:39
VLOG
#define VLOG(verboselevel)
Definition: base/logging.h:978
sat_inprocessing.h
operations_research::sat::kNoIntegerVariable
const IntegerVariable kNoIntegerVariable(-1)
operations_research::sat::LinearProgrammingConstraint::HasSolution
bool HasSolution() const
Definition: linear_programming_constraint.h:154
operations_research::sat::ChooseBestObjectiveValue
IntegerLiteral ChooseBestObjectiveValue(IntegerVariable var, Model *model)
Definition: integer_search.cc:45
operations_research::sat::RestartPolicy
Definition: restart.h:29
operations_research::sat::RandomizeOnRestartHeuristic
std::function< BooleanOrIntegerLiteral()> RandomizeOnRestartHeuristic(Model *model)
Definition: integer_search.cc:337
max
int64 max
Definition: alldiff_cst.cc:139
operations_research::sat::SearchHeuristics::policy_index
int policy_index
Definition: integer_search.h:68
operations_research::sat::SatSolver::Assignment
const VariablesAssignment & Assignment() const
Definition: sat_solver.h:363
operations_research::sat::kNoLiteralIndex
const LiteralIndex kNoLiteralIndex(-1)
operations_research::sat::SharedSolutionRepository< int64 >
rins.h
pseudo_costs.h
operations_research::sat::SatSolver::EnqueueDecisionAndBackjumpOnConflict
int EnqueueDecisionAndBackjumpOnConflict(Literal true_literal)
Definition: sat_solver.cc:499
operations_research::sat::SatSolver
Definition: sat_solver.h:58
operations_research::sat::ModelRandomGenerator
Definition: sat/util.h:33
operations_research::sat::SearchHeuristics::hint_search
std::function< BooleanOrIntegerLiteral()> hint_search
Definition: integer_search.h:73
value
int64 value
Definition: demon_profiler.cc:43
operations_research::sat::SplitUsingBestSolutionValueInRepository
IntegerLiteral SplitUsingBestSolutionValueInRepository(IntegerVariable var, const SharedSolutionRepository< int64 > &solution_repo, Model *model)
Definition: integer_search.cc:122
operations_research::sat::SolveIntegerProblem
SatSolver::Status SolveIntegerProblem(Model *model)
Definition: integer_search.cc:639
CHECK_LT
#define CHECK_LT(val1, val2)
Definition: base/logging.h:700
operations_research::sat::FollowHint
std::function< BooleanOrIntegerLiteral()> FollowHint(const std::vector< BooleanOrIntegerVariable > &vars, const std::vector< IntegerValue > &values, Model *model)
Definition: integer_search.cc:456
operations_research::sat::SatSolver::RestoreSolverToAssumptionLevel
bool RestoreSolverToAssumptionLevel()
Definition: sat_solver.cc:511
operations_research::sat::SequentialValueSelection
std::function< BooleanOrIntegerLiteral()> SequentialValueSelection(std::vector< std::function< IntegerLiteral(IntegerVariable)>> value_selection_heuristics, std::function< BooleanOrIntegerLiteral()> var_selection_heuristic, Model *model)
Definition: integer_search.cc:194
gtl::FindWithDefault
const Collection::value_type::second_type & FindWithDefault(const Collection &collection, const typename Collection::value_type::first_type &key, const typename Collection::value_type::second_type &value)
Definition: map_util.h:26
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
sat_decision.h
operations_research::sat::SatSolver::FEASIBLE
@ FEASIBLE
Definition: sat_solver.h:184
operations_research::sat::NegationOf
std::vector< IntegerVariable > NegationOf(const std::vector< IntegerVariable > &vars)
Definition: integer.cc:42
operations_research::sat::IntegerLiteral::GreaterOrEqual
static IntegerLiteral GreaterOrEqual(IntegerVariable i, IntegerValue bound)
Definition: integer.h:1216
operations_research::sat::SearchHeuristics::restart_policies
std::vector< std::function< bool()> > restart_policies
Definition: integer_search.h:65
operations_research::sat::CompleteHeuristics
std::vector< std::function< BooleanOrIntegerLiteral()> > CompleteHeuristics(const std::vector< std::function< BooleanOrIntegerLiteral()>> &incomplete_heuristics, const std::function< BooleanOrIntegerLiteral()> &completion_heuristic)
Definition: integer_search.cc:626
operations_research::sat::PositiveVariable
IntegerVariable PositiveVariable(IntegerVariable i)
Definition: integer.h:134
int64
int64_t int64
Definition: integral_types.h:34
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
relaxation_solutions
SharedRelaxationSolutionRepository * relaxation_solutions
Definition: cp_model_solver.cc:2086
operations_research::sat::SatSolver::INFEASIBLE
@ INFEASIBLE
Definition: sat_solver.h:183
sat_base.h
operations_research::sat::SatSolver::AdvanceDeterministicTime
void AdvanceDeterministicTime(TimeLimit *limit)
Definition: sat_solver.h:423
operations_research::sat::SharedResponseManager
Definition: synchronization.h:166
operations_research::sat::SharedSolutionRepository::GetVariableValueInSolution
ValueType GetVariableValueInSolution(int var_index, int solution_index) const
Definition: synchronization.h:394
operations_research::sat::SharedRelaxationSolutionRepository
Definition: synchronization.h:127
probing.h
operations_research::sat::IntegerLiteral::var
IntegerVariable var
Definition: integer.h:189
operations_research::sat::SatSolver::CurrentDecisionLevel
int CurrentDecisionLevel() const
Definition: sat_solver.h:361
operations_research::sat::ResetAndSolveIntegerProblem
SatSolver::Status ResetAndSolveIntegerProblem(const std::vector< Literal > &assumptions, Model *model)
Definition: integer_search.cc:869
operations_research::sat::GetBoundChanges
std::vector< PseudoCosts::VariableBoundChange > GetBoundChanges(LiteralIndex decision, Model *model)
Definition: pseudo_costs.cc:120
operations_research::sat::UnassignedVarWithLowestMinAtItsMinHeuristic
std::function< BooleanOrIntegerLiteral()> UnassignedVarWithLowestMinAtItsMinHeuristic(const std::vector< IntegerVariable > &vars, Model *model)
Definition: integer_search.cc:163
sat_parameters.pb.h
time_limit
SharedTimeLimit * time_limit
Definition: cp_model_solver.cc:2083
operations_research::sat::IntegerValueSelectionHeuristic
std::function< BooleanOrIntegerLiteral()> IntegerValueSelectionHeuristic(std::function< BooleanOrIntegerLiteral()> var_selection_heuristic, Model *model)
Definition: integer_search.cc:247
operations_research::sat::IntegerTrail::UpperBound
IntegerValue UpperBound(IntegerVariable i) const
Definition: integer.h:1240
operations_research::sat::SatSolverHeuristic
std::function< BooleanOrIntegerLiteral()> SatSolverHeuristic(Model *model)
Definition: integer_search.cc:306
operations_research::sat::PseudoCosts::UpdateCost
void UpdateCost(const std::vector< VariableBoundChange > &bound_changes, IntegerValue obj_bound_improvement)
Definition: pseudo_costs.cc:53
operations_research::sat::BooleanOrIntegerLiteral::boolean_literal_index
LiteralIndex boolean_literal_index
Definition: integer_search.h:51
operations_research::sat::ProbeBooleanVariables
bool ProbeBooleanVariables(const double deterministic_time_limit, Model *model, bool log_info)
Definition: probing.cc:30
operations_research::sat::SatSolverRestartPolicy
std::function< bool()> SatSolverRestartPolicy(Model *model)
Definition: integer_search.cc:500
operations_research::sat::kMaxIntegerValue
constexpr IntegerValue kMaxIntegerValue(std::numeric_limits< IntegerValue::ValueType >::max() - 1)
operations_research::sat::Trail::Assignment
const VariablesAssignment & Assignment() const
Definition: sat_base.h:380
CHECK_EQ
#define CHECK_EQ(val1, val2)
Definition: base/logging.h:697
operations_research::sat::SatSolver::ReapplyAssumptionsIfNeeded
bool ReapplyAssumptionsIfNeeded()
Definition: sat_solver.cc:554
operations_research::sat::FirstUnassignedVarAtItsMinHeuristic
std::function< BooleanOrIntegerLiteral()> FirstUnassignedVarAtItsMinHeuristic(const std::vector< IntegerVariable > &vars, Model *model)
Definition: integer_search.cc:148
operations_research::sat::Literal::Index
LiteralIndex Index() const
Definition: sat_base.h:84
operations_research::sat::Model
Class that owns everything related to a particular optimization model.
Definition: sat/model.h:38
ct
const Constraint * ct
Definition: demon_profiler.cc:42
operations_research::sat::IntegerLiteral
Definition: integer.h:153
operations_research::sat::LinearProgrammingConstraintCollection
Definition: linear_programming_constraint.h:532
operations_research::sat::kNoBooleanVariable
const BooleanVariable kNoBooleanVariable(-1)
operations_research::sat::SatDecisionPolicy
Definition: sat_decision.h:34
operations_research::sat::ImpliedBounds
Definition: implied_bounds.h:77
DCHECK
#define DCHECK(condition)
Definition: base/logging.h:884
operations_research::sat::BooleanOrIntegerLiteral::integer_literal
IntegerLiteral integer_literal
Definition: integer_search.h:52
operations_research::sat::LinearProgrammingConstraint::SolutionIsInteger
bool SolutionIsInteger() const
Definition: linear_programming_constraint.h:158
operations_research::sat::IntegerLiteral::LowerOrEqual
static IntegerLiteral LowerOrEqual(IntegerVariable i, IntegerValue bound)
Definition: integer.h:1222
implied_bounds.h
operations_research::sat::AtMinValue
IntegerLiteral AtMinValue(IntegerVariable var, IntegerTrail *integer_trail)
Definition: integer_search.cc:37
operations_research::sat::SatSolver::num_failures
int64 num_failures() const
Definition: sat_solver.cc:84
operations_research::sat::IntegerTrail::Index
int Index() const
Definition: integer.h:805
model
GRBmodel * model
Definition: gurobi_interface.cc:269
operations_research::sat::SatSolver::ResetWithGivenAssumptions
bool ResetWithGivenAssumptions(const std::vector< Literal > &assumptions)
Definition: sat_solver.cc:536
operations_research::sat::Literal
Definition: sat_base.h:64
operations_research::sat::ObjectiveDefinition::objective_var
IntegerVariable objective_var
Definition: cp_model_loader.h:41
operations_research::sat::LinearProgrammingConstraint
Definition: linear_programming_constraint.h:128
operations_research::sat::SharedSolutionRepository::NumSolutions
int NumSolutions() const
Definition: synchronization.h:381
operations_research::sat::SearchHeuristics
Definition: integer_search.h:60
operations_research::sat::Inprocessing
Definition: sat_inprocessing.h:86
operations_research::sat::kMinIntegerValue
constexpr IntegerValue kMinIntegerValue(-kMaxIntegerValue)
util.h
operations_research::sat::SequentialSearch
std::function< BooleanOrIntegerLiteral()> SequentialSearch(std::vector< std::function< BooleanOrIntegerLiteral()>> heuristics)
Definition: integer_search.cc:183
operations_research::sat::LevelZeroCallbackHelper
Definition: integer_search.h:84
operations_research::sat::SatSolver::FinishPropagation
bool FinishPropagation()
Definition: sat_solver.cc:521
operations_research::sat::UpperBound
std::function< int64(const Model &)> UpperBound(IntegerVariable v)
Definition: integer.h:1400
DCHECK_EQ
#define DCHECK_EQ(val1, val2)
Definition: base/logging.h:885
operations_research::sat::SplitAroundGivenValue
IntegerLiteral SplitAroundGivenValue(IntegerVariable var, IntegerValue value, Model *model)
Definition: integer_search.cc:68
operations_research::sat::PseudoCosts
Definition: pseudo_costs.h:27
operations_research::sat::LinearizedPartIsLarge
bool LinearizedPartIsLarge(Model *model)
Definition: integer_search.cc:234
cp_model_loader.h
operations_research::sat::LinearProgrammingDispatcher
Definition: linear_programming_constraint.h:525
operations_research::sat::VariablesAssignment::VariableIsAssigned
bool VariableIsAssigned(BooleanVariable var) const
Definition: sat_base.h:158
operations_research::sat::IntegerTrail::LowerBound
IntegerValue LowerBound(IntegerVariable i) const
Definition: integer.h:1236
operations_research::sat::SplitAroundLpValue
IntegerLiteral SplitAroundLpValue(IntegerVariable var, Model *model)
Definition: integer_search.cc:96
integer_search.h
operations_research::glop::Index
int32 Index
Definition: lp_types.h:37
CHECK_NE
#define CHECK_NE(val1, val2)
Definition: base/logging.h:698
operations_research::sat::IntegerTrail::IsCurrentlyIgnored
bool IsCurrentlyIgnored(IntegerVariable i) const
Definition: integer.h:603
operations_research::sat::CpModelMapping
Definition: cp_model_loader.h:63
operations_research::sat::SatSolver::ResetToLevelZero
bool ResetToLevelZero()
Definition: sat_solver.cc:529
operations_research::sat::SearchHeuristics::decision_policies
std::vector< std::function< BooleanOrIntegerLiteral()> > decision_policies
Definition: integer_search.h:64
DCHECK_LE
#define DCHECK_LE(val1, val2)
Definition: base/logging.h:887
operations_research::sat::SharedLPSolutionRepository
Definition: synchronization.h:135
operations_research::sat::RandomizeDecisionHeuristic
void RandomizeDecisionHeuristic(URBG *random, SatParameters *parameters)
Definition: sat/util.h:76
operations_research::sat::ConfigureSearchHeuristics
void ConfigureSearchHeuristics(Model *model)
Definition: integer_search.cc:514
operations_research::sat::SatSolver::LIMIT_REACHED
@ LIMIT_REACHED
Definition: sat_solver.h:185
CHECK
#define CHECK(condition)
Definition: base/logging.h:495
parameters
SatParameters parameters
Definition: cp_model_fz_solver.cc:107
operations_research::sat::IntegerEncoder
Definition: integer.h:262
operations_research::sat::PseudoCost
std::function< BooleanOrIntegerLiteral()> PseudoCost(Model *model)
Definition: integer_search.cc:319
operations_research::sat::IntegerLiteral::IsValid
bool IsValid() const
Definition: integer.h:170
operations_research::sat::VariablesAssignment::LiteralIsAssigned
bool LiteralIsAssigned(Literal literal) const
Definition: sat_base.h:153
integer.h
operations_research::sat::SolveIntegerProblemWithLazyEncoding
SatSolver::Status SolveIntegerProblemWithLazyEncoding(Model *model)
Definition: integer_search.cc:887
operations_research::sat::SearchHeuristics::fixed_search
std::function< BooleanOrIntegerLiteral()> fixed_search
Definition: integer_search.h:72
operations_research::sat::BooleanOrIntegerLiteral::HasValue
bool HasValue() const
Definition: integer_search.h:46
operations_research::sat::Trail
Definition: sat_base.h:233
linear_programming_constraint.h
operations_research::sat::RecordLPRelaxationValues
void RecordLPRelaxationValues(Model *model)
Definition: rins.cc:25