OR-Tools  9.1
cp_model_search.cc
Go to the documentation of this file.
1 // Copyright 2010-2021 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 <cstdint>
17 #include <limits>
18 #include <random>
19 
20 #include "absl/container/flat_hash_map.h"
21 #include "absl/strings/str_format.h"
23 #include "ortools/sat/util.h"
24 
25 namespace operations_research {
26 namespace sat {
27 
29  : mapping_(*model->GetOrCreate<CpModelMapping>()),
30  boolean_assignment_(model->GetOrCreate<Trail>()->Assignment()),
31  integer_trail_(*model->GetOrCreate<IntegerTrail>()),
32  integer_encoder_(*model->GetOrCreate<IntegerEncoder>()) {}
33 
34 int CpModelView::NumVariables() const { return mapping_.NumProtoVariables(); }
35 
36 bool CpModelView::IsFixed(int var) const {
37  if (mapping_.IsBoolean(var)) {
38  return boolean_assignment_.VariableIsAssigned(
39  mapping_.Literal(var).Variable());
40  } else if (mapping_.IsInteger(var)) {
41  return integer_trail_.IsFixed(mapping_.Integer(var));
42  }
43  return true; // Default.
44 }
45 
47  return mapping_.IsInteger(var) &&
48  integer_trail_.IsCurrentlyIgnored(mapping_.Integer(var));
49 }
50 
51 int64_t CpModelView::Min(int var) const {
52  if (mapping_.IsBoolean(var)) {
53  const Literal l = mapping_.Literal(var);
54  return boolean_assignment_.LiteralIsTrue(l) ? 1 : 0;
55  } else if (mapping_.IsInteger(var)) {
56  return integer_trail_.LowerBound(mapping_.Integer(var)).value();
57  }
58  return 0; // Default.
59 }
60 
61 int64_t CpModelView::Max(int var) const {
62  if (mapping_.IsBoolean(var)) {
63  const Literal l = mapping_.Literal(var);
64  return boolean_assignment_.LiteralIsFalse(l) ? 0 : 1;
65  } else if (mapping_.IsInteger(var)) {
66  return integer_trail_.UpperBound(mapping_.Integer(var)).value();
67  }
68  return 0; // Default.
69 }
70 
72  int64_t value) const {
73  DCHECK(!IsFixed(var));
75  if (mapping_.IsBoolean(var)) {
76  DCHECK(value == 0 || value == 1);
77  if (value == 1) {
78  result.boolean_literal_index = mapping_.Literal(var).Index();
79  }
80  } else if (mapping_.IsInteger(var)) {
82  mapping_.Integer(var), IntegerValue(value));
83  }
84  return result;
85 }
86 
88  int64_t value) const {
89  DCHECK(!IsFixed(var));
91  if (mapping_.IsBoolean(var)) {
92  DCHECK(value == 0 || value == 1);
93  if (value == 0) {
94  result.boolean_literal_index = mapping_.Literal(var).NegatedIndex();
95  }
96  } else if (mapping_.IsInteger(var)) {
98  IntegerValue(value));
99  }
100  return result;
101 }
102 
104  DCHECK(!IsFixed(var));
106  if (mapping_.IsBoolean(var)) {
107  result.boolean_literal_index = mapping_.Literal(var).NegatedIndex();
108  } else if (mapping_.IsInteger(var)) {
109  const IntegerVariable variable = mapping_.Integer(var);
110  CHECK_NE(variable, kNoIntegerVariable);
111  CHECK(integer_encoder_.VariableIsFullyEncoded(variable));
112  std::vector<IntegerEncoder::ValueLiteralPair> encoding =
113  integer_encoder_.RawDomainEncoding(variable);
114  std::sort(encoding.begin(), encoding.end());
115  std::vector<Literal> unassigned_sorted_literals;
116  for (const auto& p : encoding) {
117  if (!boolean_assignment_.LiteralIsAssigned(p.literal)) {
118  unassigned_sorted_literals.push_back(p.literal);
119  }
120  }
121  // 5 values -> returns the second.
122  // 4 values -> returns the second too.
123  // Array is 0 based.
124  const int target = (unassigned_sorted_literals.size() + 1) / 2 - 1;
125  result.boolean_literal_index = unassigned_sorted_literals[target].Index();
126  }
127  return result;
128 }
129 
130 // Stores one variable and its strategy value.
131 struct VarValue {
132  int ref;
133  int64_t value;
134 };
135 
136 namespace {
137 
138 // TODO(user): Save this somewhere instead of recomputing it.
139 bool ModelHasSchedulingConstraints(const CpModelProto& cp_model_proto) {
140  for (const ConstraintProto& ct : cp_model_proto.constraints()) {
141  if (ct.constraint_case() == ConstraintProto::kNoOverlap) return true;
142  if (ct.constraint_case() == ConstraintProto::kCumulative) return true;
143  }
144  return false;
145 }
146 
147 } // namespace
148 
150  const std::vector<DecisionStrategyProto>& strategies, Model* model) {
151  const auto& view = *model->GetOrCreate<CpModelView>();
152  const auto& parameters = *model->GetOrCreate<SatParameters>();
153  auto* random = model->GetOrCreate<ModelRandomGenerator>();
154 
155  // Note that we copy strategies to keep the return function validity
156  // independently of the life of the passed vector.
157  return [&view, &parameters, random, strategies]() {
158  for (const DecisionStrategyProto& strategy : strategies) {
159  int candidate;
160  int64_t candidate_value = std::numeric_limits<int64_t>::max();
161 
162  // TODO(user): Improve the complexity if this becomes an issue which
163  // may be the case if we do a fixed_search.
164 
165  // To store equivalent variables in randomized search.
166  std::vector<VarValue> active_refs;
167 
168  int t_index = 0; // Index in strategy.transformations().
169  for (int i = 0; i < strategy.variables().size(); ++i) {
170  const int ref = strategy.variables(i);
171  const int var = PositiveRef(ref);
172  if (view.IsFixed(var) || view.IsCurrentlyFree(var)) continue;
173 
174  int64_t coeff(1);
175  int64_t offset(0);
176  while (t_index < strategy.transformations().size() &&
177  strategy.transformations(t_index).index() < i) {
178  ++t_index;
179  }
180  if (t_index < strategy.transformations_size() &&
181  strategy.transformations(t_index).index() == i) {
182  coeff = strategy.transformations(t_index).positive_coeff();
183  offset = strategy.transformations(t_index).offset();
184  }
185 
186  // TODO(user): deal with integer overflow in case of wrongly specified
187  // coeff? Note that if this is filled by the presolve it shouldn't
188  // happen since any feasible value in the new variable domain should be
189  // a feasible value of the original variable domain.
190  int64_t value(0);
191  int64_t lb = view.Min(var);
192  int64_t ub = view.Max(var);
193  if (!RefIsPositive(ref)) {
194  lb = -view.Max(var);
195  ub = -view.Min(var);
196  }
197  switch (strategy.variable_selection_strategy()) {
199  break;
201  value = coeff * lb + offset;
202  break;
204  value = -(coeff * ub + offset);
205  break;
207  value = coeff * (ub - lb + 1);
208  break;
210  value = -coeff * (ub - lb + 1);
211  break;
212  default:
213  LOG(FATAL) << "Unknown VariableSelectionStrategy "
214  << strategy.variable_selection_strategy();
215  }
216  if (value < candidate_value) {
217  candidate = ref;
218  candidate_value = value;
219  }
220  if (strategy.variable_selection_strategy() ==
223  break;
224  } else if (parameters.randomize_search()) {
225  if (value <=
226  candidate_value + parameters.search_randomization_tolerance()) {
227  active_refs.push_back({ref, value});
228  }
229  }
230  }
231 
232  if (candidate_value == std::numeric_limits<int64_t>::max()) continue;
234  CHECK(!active_refs.empty());
235  const IntegerValue threshold(
236  candidate_value + parameters.search_randomization_tolerance());
237  auto is_above_tolerance = [threshold](const VarValue& entry) {
238  return entry.value > threshold;
239  };
240  // Remove all values above tolerance.
241  active_refs.erase(std::remove_if(active_refs.begin(), active_refs.end(),
242  is_above_tolerance),
243  active_refs.end());
244  const int winner = absl::Uniform<int>(*random, 0, active_refs.size());
245  candidate = active_refs[winner].ref;
246  }
247 
249  strategy.domain_reduction_strategy();
250  if (!RefIsPositive(candidate)) {
251  switch (selection) {
254  break;
257  break;
260  break;
263  break;
264  default:
265  break;
266  }
267  }
268 
269  const int var = PositiveRef(candidate);
270  const int64_t lb = view.Min(var);
271  const int64_t ub = view.Max(var);
272  switch (selection) {
274  return view.LowerOrEqual(var, lb);
276  return view.GreaterOrEqual(var, ub);
278  return view.LowerOrEqual(var, lb + (ub - lb) / 2);
280  return view.GreaterOrEqual(var, ub - (ub - lb) / 2);
282  return view.MedianValue(var);
283  default:
284  LOG(FATAL) << "Unknown DomainReductionStrategy "
285  << strategy.domain_reduction_strategy();
286  }
287  }
288  return BooleanOrIntegerLiteral();
289  };
290 }
291 
293  const CpModelProto& cp_model_proto,
294  const std::vector<IntegerVariable>& variable_mapping,
295  IntegerVariable objective_var, Model* model) {
296  std::vector<std::function<BooleanOrIntegerLiteral()>> heuristics;
297 
298  // We start by the user specified heuristic.
299  {
300  std::vector<DecisionStrategyProto> strategies;
301  for (const DecisionStrategyProto& proto :
302  cp_model_proto.search_strategy()) {
303  strategies.push_back(proto);
304  }
305  heuristics.push_back(ConstructSearchStrategyInternal(strategies, model));
306  }
307 
308  // If there are some scheduling constraint, we complete with a custom
309  // "scheduling" strategy.
310  if (ModelHasSchedulingConstraints(cp_model_proto)) {
311  heuristics.push_back(SchedulingSearchHeuristic(model));
312  }
313 
314  // If needed, we finish by instantiating anything left.
315  if (model->GetOrCreate<SatParameters>()->instantiate_all_variables()) {
316  std::vector<IntegerVariable> decisions;
317  for (const IntegerVariable var : variable_mapping) {
318  if (var == kNoIntegerVariable) continue;
319 
320  // Make sure we try to fix the objective to its lowest value first.
321  if (var == NegationOf(objective_var)) {
322  decisions.push_back(objective_var);
323  } else {
324  decisions.push_back(var);
325  }
326  }
327  heuristics.push_back(FirstUnassignedVarAtItsMinHeuristic(decisions, model));
328  }
329 
330  return SequentialSearch(heuristics);
331 }
332 
334  const CpModelProto& cp_model_proto,
335  const std::vector<IntegerVariable>& variable_mapping,
336  const std::function<BooleanOrIntegerLiteral()>& instrumented_strategy,
337  Model* model) {
338  std::vector<int> ref_to_display;
339  for (int i = 0; i < cp_model_proto.variables_size(); ++i) {
340  if (variable_mapping[i] == kNoIntegerVariable) continue;
341  if (cp_model_proto.variables(i).name().empty()) continue;
342  ref_to_display.push_back(i);
343  }
344  std::sort(ref_to_display.begin(), ref_to_display.end(), [&](int i, int j) {
345  return cp_model_proto.variables(i).name() <
346  cp_model_proto.variables(j).name();
347  });
348 
349  std::vector<std::pair<int64_t, int64_t>> old_domains(variable_mapping.size());
350  return [instrumented_strategy, model, variable_mapping, cp_model_proto,
351  old_domains, ref_to_display]() mutable {
352  const BooleanOrIntegerLiteral decision = instrumented_strategy();
353  if (!decision.HasValue()) return decision;
354 
355  if (decision.boolean_literal_index != kNoLiteralIndex) {
356  const Literal l = Literal(decision.boolean_literal_index);
357  LOG(INFO) << "Boolean decision " << l;
358  for (const IntegerLiteral i_lit :
360  LOG(INFO) << " - associated with " << i_lit;
361  }
362  } else {
363  LOG(INFO) << "Integer decision " << decision.integer_literal;
364  }
365  const int level = model->Get<Trail>()->CurrentDecisionLevel();
366  std::string to_display =
367  absl::StrCat("Diff since last call, level=", level, "\n");
368  IntegerTrail* integer_trail = model->GetOrCreate<IntegerTrail>();
369  for (const int ref : ref_to_display) {
370  const IntegerVariable var = variable_mapping[ref];
371  const std::pair<int64_t, int64_t> new_domain(
372  integer_trail->LowerBound(var).value(),
373  integer_trail->UpperBound(var).value());
374  if (new_domain != old_domains[ref]) {
375  absl::StrAppend(&to_display, cp_model_proto.variables(ref).name(), " [",
376  old_domains[ref].first, ",", old_domains[ref].second,
377  "] -> [", new_domain.first, ",", new_domain.second,
378  "]\n");
379  old_domains[ref] = new_domain;
380  }
381  }
382  LOG(INFO) << to_display;
383  return decision;
384  };
385 }
386 
387 // Note: in flatzinc setting, we know we always have a fixed search defined.
388 //
389 // Things to try:
390 // - Specialize for purely boolean problems
391 // - Disable linearization_level options for non linear problems
392 // - Fast restart in randomized search
393 // - Different propatation levels for scheduling constraints
394 std::vector<SatParameters> GetDiverseSetOfParameters(
395  const SatParameters& base_params, const CpModelProto& cp_model,
396  const int num_workers) {
397  // Defines a set of named strategies so it is easier to read in one place
398  // the one that are used. See below.
399  std::map<std::string, SatParameters> strategies;
400 
401  // Lp variations only.
402  {
403  SatParameters new_params = base_params;
404  new_params.set_linearization_level(0);
405  strategies["no_lp"] = new_params;
406  new_params.set_linearization_level(1);
407  strategies["default_lp"] = new_params;
408  new_params.set_linearization_level(2);
409  new_params.set_add_lp_constraints_lazily(false);
410  strategies["max_lp"] = new_params;
411  }
412 
413  // Core. Note that we disable the lp here because it is faster on the minizinc
414  // benchmark.
415  //
416  // TODO(user): Do more experiments, the LP with core could be useful, but we
417  // probably need to incorporate the newly created integer variables from the
418  // core algorithm into the LP.
419  {
420  SatParameters new_params = base_params;
422  new_params.set_optimize_with_core(true);
423  new_params.set_linearization_level(0);
424  strategies["core"] = new_params;
425  }
426 
427  // It can be interesting to try core and lp.
428  {
429  SatParameters new_params = base_params;
431  new_params.set_optimize_with_core(true);
432  new_params.set_linearization_level(1);
433  strategies["core_default_lp"] = new_params;
434  }
435 
436  {
437  SatParameters new_params = base_params;
439  new_params.set_optimize_with_core(true);
440  new_params.set_linearization_level(2);
441  strategies["core_max_lp"] = new_params;
442  }
443 
444  {
445  SatParameters new_params = base_params;
446  new_params.set_optimize_with_lb_tree_search(true);
447  new_params.set_linearization_level(2);
448  strategies["lb_tree_search"] = new_params;
449  }
450 
451  {
452  SatParameters new_params = base_params;
454  new_params.set_use_probing_search(true);
455  strategies["probing"] = new_params;
456  }
457 
458  // Search variation.
459  {
460  SatParameters new_params = base_params;
462  strategies["auto"] = new_params;
463 
465  strategies["fixed"] = new_params;
466 
467  new_params.set_search_branching(
469  strategies["quick_restart"] = new_params;
470 
471  new_params.set_search_branching(
473  new_params.set_linearization_level(0);
474  strategies["quick_restart_no_lp"] = new_params;
475 
476  // We force the max lp here too.
477  new_params.set_linearization_level(2);
479  strategies["reduced_costs"] = new_params;
480 
481  // For this one, we force other param too.
482  new_params.set_linearization_level(2);
484  new_params.set_exploit_best_solution(true);
485  strategies["pseudo_costs"] = new_params;
486  }
487 
488  // Less encoding.
489  {
490  SatParameters new_params = base_params;
491  new_params.set_boolean_encoding_level(0);
492  strategies["less_encoding"] = new_params;
493  }
494 
495  // We only use a "fixed search" worker if some strategy is specified or
496  // if we have a scheduling model.
497  //
498  // TODO(user): For scheduling, this is important to find good first solution
499  // but afterwards it is not really great and should probably be replaced by a
500  // LNS worker.
501  const bool use_fixed_strategy = !cp_model.search_strategy().empty() ||
502  ModelHasSchedulingConstraints(cp_model);
503 
504  // Our current set of strategies
505  //
506  // TODO(user, fdid): Avoid launching two strategies if they are the same,
507  // like if there is no lp, or everything is already linearized at level 1.
508  std::vector<std::string> names;
509  if (base_params.reduce_memory_usage_in_interleave_mode() &&
510  base_params.interleave_search()) {
511  // Low memory mode for interleaved search in single thread.
512  if (cp_model.has_objective()) {
513  names.push_back("default_lp");
514  names.push_back(use_fixed_strategy ? "fixed" : "pseudo_costs");
515  names.push_back(cp_model.objective().vars_size() > 1 ? "core" : "no_lp");
516  names.push_back("max_lp");
517  } else {
518  names.push_back("default_lp");
519  names.push_back(use_fixed_strategy ? "fixed" : "no_lp");
520  names.push_back("less_encoding");
521  names.push_back("max_lp");
522  names.push_back("quick_restart");
523  }
524  } else if (cp_model.has_objective()) {
525  names.push_back("default_lp");
526  if (use_fixed_strategy) {
527  names.push_back("fixed");
528  if (num_workers > 8) names.push_back("reduced_costs");
529  } else {
530  names.push_back("reduced_costs");
531  }
532  names.push_back("pseudo_costs");
533  names.push_back("no_lp");
534  names.push_back("max_lp");
535 
536  // TODO(user): Experiment with core and LP.
537  if (cp_model.objective().vars_size() > 1) names.push_back("core");
538 
539  // Only add this strategy if we have enough worker left for LNS.
540  if (num_workers > 8 || base_params.interleave_search()) {
541  names.push_back("quick_restart");
542  }
543  if (num_workers > 10) {
544  names.push_back("quick_restart_no_lp");
545  }
546  } else {
547  names.push_back("default_lp");
548  if (use_fixed_strategy) names.push_back("fixed");
549  names.push_back("less_encoding");
550  names.push_back("no_lp");
551  names.push_back("max_lp");
552  names.push_back("quick_restart");
553  if (num_workers > 10) {
554  names.push_back("quick_restart_no_lp");
555  }
556  }
557  if (num_workers > 12) {
558  names.push_back("probing");
559  names.push_back("lb_tree_search");
560  }
561 
562  // Creates the diverse set of parameters with names and seed. We remove the
563  // last ones if needed below.
564  std::vector<SatParameters> result;
565  for (const std::string& name : names) {
566  SatParameters new_params = strategies.at(name);
567  new_params.set_name(name);
568  new_params.set_random_seed(result.size() + 1);
569  result.push_back(new_params);
570  }
571 
572  // If there is no objective, we complete with randomized fixed search.
573  // If there is an objective, the extra workers will use LNS.
574  if (!cp_model.has_objective()) {
575  int target = num_workers;
576 
577  // If strategies that do not require a full worker are present, leave one
578  // worker for them.
579  if (!base_params.interleave_search() &&
580  (base_params.use_rins_lns() || base_params.use_relaxation_lns() ||
581  base_params.use_feasibility_pump())) {
582  target = std::max(1, num_workers - 1);
583  }
584 
585  int index = 1;
586  while (result.size() < target) {
587  // TODO(user): This doesn't make sense if there is no fixed search.
588  SatParameters new_params = base_params;
590  new_params.set_randomize_search(true);
592  new_params.set_random_seed(result.size() + 1);
593  new_params.set_name(absl::StrCat("random_", index));
594  result.push_back(new_params);
595  ++index;
596  }
597  }
598 
599  // If we are not in interleave search, we cannot run more strategies than
600  // the number of worker.
601  //
602  // TODO(user): consider using LNS if we use a small number of workers.
603  if (!base_params.interleave_search() && result.size() > num_workers) {
604  result.resize(num_workers);
605  }
606 
607  return result;
608 }
609 
610 } // namespace sat
611 } // namespace operations_research
#define CHECK(condition)
Definition: base/logging.h:491
static constexpr DomainReductionStrategy SELECT_MIN_VALUE
Definition: cp_model.pb.h:5158
static constexpr SearchBranching LP_SEARCH
const int FATAL
Definition: log_severity.h:32
Class that owns everything related to a particular optimization model.
Definition: sat/model.h:38
static constexpr DomainReductionStrategy SELECT_MEDIAN_VALUE
Definition: cp_model.pb.h:5166
static constexpr VariableSelectionStrategy CHOOSE_LOWEST_MIN
Definition: cp_model.pb.h:5124
bool VariableIsFullyEncoded(IntegerVariable var) const
Definition: integer.cc:97
void set_linearization_level(::PROTOBUF_NAMESPACE_ID::int32 value)
static IntegerLiteral LowerOrEqual(IntegerVariable i, IntegerValue bound)
Definition: integer.h:1315
const std::string name
IntegerValue LowerBound(IntegerVariable i) const
Definition: integer.h:1345
bool LiteralIsFalse(Literal literal) const
Definition: sat_base.h:148
bool LiteralIsTrue(Literal literal) const
Definition: sat_base.h:151
LiteralIndex Index() const
Definition: sat_base.h:85
#define LOG(severity)
Definition: base/logging.h:416
GRBmodel * model
std::function< BooleanOrIntegerLiteral()> ConstructSearchStrategy(const CpModelProto &cp_model_proto, const std::vector< IntegerVariable > &variable_mapping, IntegerVariable objective_var, Model *model)
static constexpr VariableSelectionStrategy CHOOSE_HIGHEST_MAX
Definition: cp_model.pb.h:5126
sat::Literal Literal(int ref) const
static constexpr VariableSelectionStrategy CHOOSE_FIRST
Definition: cp_model.pb.h:5122
static constexpr SearchBranching PSEUDO_COST_SEARCH
static constexpr SearchBranching PORTFOLIO_WITH_QUICK_RESTART_SEARCH
void set_name(ArgT0 &&arg0, ArgT... args)
::PROTOBUF_NAMESPACE_ID::int64 search_randomization_tolerance() const
void set_boolean_encoding_level(::PROTOBUF_NAMESPACE_ID::int32 value)
int64_t max
Definition: alldiff_cst.cc:140
LiteralIndex NegatedIndex() const
Definition: sat_base.h:86
static constexpr VariableSelectionStrategy CHOOSE_MAX_DOMAIN_SIZE
Definition: cp_model.pb.h:5130
const ::operations_research::sat::IntegerVariableProto & variables(int index) const
CpModelProto proto
BooleanVariable Variable() const
Definition: sat_base.h:81
void set_search_randomization_tolerance(::PROTOBUF_NAMESPACE_ID::int64 value)
bool VariableIsAssigned(BooleanVariable var) const
Definition: sat_base.h:159
const std::function< BooleanOrIntegerLiteral()> ConstructSearchStrategyInternal(const std::vector< DecisionStrategyProto > &strategies, Model *model)
const ::operations_research::sat::ConstraintProto & constraints(int index) const
const ::operations_research::sat::CpObjectiveProto & objective() const
bool LiteralIsAssigned(Literal literal) const
Definition: sat_base.h:154
int index
Definition: pack.cc:509
An Assignment is a variable -> domains mapping, used to report solutions to the user.
static constexpr DomainReductionStrategy SELECT_MAX_VALUE
Definition: cp_model.pb.h:5160
static constexpr SearchBranching AUTOMATIC_SEARCH
BooleanOrIntegerLiteral MedianValue(int var) const
std::function< BooleanOrIntegerLiteral()> SchedulingSearchHeuristic(Model *model)
static constexpr DomainReductionStrategy SELECT_UPPER_HALF
Definition: cp_model.pb.h:5164
std::vector< IntegerVariable > NegationOf(const std::vector< IntegerVariable > &vars)
Definition: integer.cc:29
#define DCHECK(condition)
Definition: base/logging.h:885
static constexpr VariableSelectionStrategy CHOOSE_MIN_DOMAIN_SIZE
Definition: cp_model.pb.h:5128
bool IsCurrentlyIgnored(IntegerVariable i) const
Definition: integer.h:659
BooleanOrIntegerLiteral GreaterOrEqual(int var, int64_t value) const
const ::operations_research::sat::DecisionStrategyProto & search_strategy(int index) const
const InlinedIntegerLiteralVector & GetAllIntegerLiterals(Literal lit) const
Definition: integer.h:434
IntegerValue UpperBound(IntegerVariable i) const
Definition: integer.h:1349
static constexpr SearchBranching FIXED_SEARCH
std::vector< ValueLiteralPair > RawDomainEncoding(IntegerVariable var) const
Definition: integer.cc:168
Collection of objects used to extend the Constraint Solver library.
const IntegerVariable kNoIntegerVariable(-1)
static IntegerLiteral GreaterOrEqual(IntegerVariable i, IntegerValue bound)
Definition: integer.h:1309
SatParameters parameters
bool RefIsPositive(int ref)
const LiteralIndex kNoLiteralIndex(-1)
IntVar * var
Definition: expr_array.cc:1874
void set_search_branching(::operations_research::sat::SatParameters_SearchBranching value)
BooleanOrIntegerLiteral LowerOrEqual(int var, int64_t value) const
static constexpr DomainReductionStrategy SELECT_LOWER_HALF
Definition: cp_model.pb.h:5162
void set_random_seed(::PROTOBUF_NAMESPACE_ID::int32 value)
std::function< BooleanOrIntegerLiteral()> InstrumentSearchStrategy(const CpModelProto &cp_model_proto, const std::vector< IntegerVariable > &variable_mapping, const std::function< BooleanOrIntegerLiteral()> &instrumented_strategy, Model *model)
IntegerVariable Integer(int ref) const
std::function< BooleanOrIntegerLiteral()> FirstUnassignedVarAtItsMinHeuristic(const std::vector< IntegerVariable > &vars, Model *model)
int64_t value
#define CHECK_NE(val1, val2)
Definition: base/logging.h:699
bool IsFixed(IntegerVariable i) const
Definition: integer.h:1353
const Constraint * ct
std::function< BooleanOrIntegerLiteral()> SequentialSearch(std::vector< std::function< BooleanOrIntegerLiteral()>> heuristics)
std::vector< SatParameters > GetDiverseSetOfParameters(const SatParameters &base_params, const CpModelProto &cp_model, const int num_workers)
const int INFO
Definition: log_severity.h:31