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