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
25namespace operations_research {
26namespace 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
34int CpModelView::NumVariables() const { return mapping_.NumProtoVariables(); }
35
36bool 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
51int64_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
61int64_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 {
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 {
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.
131struct VarValue {
132 int ref;
133 int64_t value;
134};
135
136namespace {
137
138// TODO(user): Save this somewhere instead of recomputing it.
139bool 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 }
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
394std::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
int64_t max
Definition: alldiff_cst.cc:140
#define CHECK(condition)
Definition: base/logging.h:491
#define CHECK_NE(val1, val2)
Definition: base/logging.h:699
#define LOG(severity)
Definition: base/logging.h:416
#define DCHECK(condition)
Definition: base/logging.h:885
An Assignment is a variable -> domains mapping, used to report solutions to the user.
IntegerVariable Integer(int ref) const
sat::Literal Literal(int ref) const
const ::operations_research::sat::CpObjectiveProto & objective() const
const ::operations_research::sat::IntegerVariableProto & variables(int index) const
const ::operations_research::sat::DecisionStrategyProto & search_strategy(int index) const
const ::operations_research::sat::ConstraintProto & constraints(int index) const
BooleanOrIntegerLiteral GreaterOrEqual(int var, int64_t value) const
BooleanOrIntegerLiteral MedianValue(int var) const
BooleanOrIntegerLiteral LowerOrEqual(int var, int64_t value) const
static constexpr DomainReductionStrategy SELECT_MIN_VALUE
Definition: cp_model.pb.h:5250
static constexpr DomainReductionStrategy SELECT_MAX_VALUE
Definition: cp_model.pb.h:5252
static constexpr VariableSelectionStrategy CHOOSE_MAX_DOMAIN_SIZE
Definition: cp_model.pb.h:5222
static constexpr VariableSelectionStrategy CHOOSE_LOWEST_MIN
Definition: cp_model.pb.h:5216
static constexpr DomainReductionStrategy SELECT_MEDIAN_VALUE
Definition: cp_model.pb.h:5258
static constexpr DomainReductionStrategy SELECT_LOWER_HALF
Definition: cp_model.pb.h:5254
static constexpr VariableSelectionStrategy CHOOSE_MIN_DOMAIN_SIZE
Definition: cp_model.pb.h:5220
static constexpr VariableSelectionStrategy CHOOSE_HIGHEST_MAX
Definition: cp_model.pb.h:5218
static constexpr VariableSelectionStrategy CHOOSE_FIRST
Definition: cp_model.pb.h:5214
static constexpr DomainReductionStrategy SELECT_UPPER_HALF
Definition: cp_model.pb.h:5256
const InlinedIntegerLiteralVector & GetAllIntegerLiterals(Literal lit) const
Definition: integer.h:434
bool VariableIsFullyEncoded(IntegerVariable var) const
Definition: integer.cc:97
std::vector< ValueLiteralPair > RawDomainEncoding(IntegerVariable var) const
Definition: integer.cc:168
bool IsCurrentlyIgnored(IntegerVariable i) const
Definition: integer.h:659
bool IsFixed(IntegerVariable i) const
Definition: integer.h:1353
IntegerValue UpperBound(IntegerVariable i) const
Definition: integer.h:1349
IntegerValue LowerBound(IntegerVariable i) const
Definition: integer.h:1345
LiteralIndex NegatedIndex() const
Definition: sat_base.h:86
LiteralIndex Index() const
Definition: sat_base.h:85
BooleanVariable Variable() const
Definition: sat_base.h:81
Class that owns everything related to a particular optimization model.
Definition: sat/model.h:38
void set_search_branching(::operations_research::sat::SatParameters_SearchBranching value)
static constexpr SearchBranching PSEUDO_COST_SEARCH
void set_boolean_encoding_level(::PROTOBUF_NAMESPACE_ID::int32 value)
static constexpr SearchBranching PORTFOLIO_WITH_QUICK_RESTART_SEARCH
void set_name(ArgT0 &&arg0, ArgT... args)
void set_search_randomization_tolerance(::PROTOBUF_NAMESPACE_ID::int64 value)
void set_linearization_level(::PROTOBUF_NAMESPACE_ID::int32 value)
void set_random_seed(::PROTOBUF_NAMESPACE_ID::int32 value)
static constexpr SearchBranching LP_SEARCH
static constexpr SearchBranching AUTOMATIC_SEARCH
::PROTOBUF_NAMESPACE_ID::int64 search_randomization_tolerance() const
static constexpr SearchBranching FIXED_SEARCH
bool LiteralIsAssigned(Literal literal) const
Definition: sat_base.h:154
bool VariableIsAssigned(BooleanVariable var) const
Definition: sat_base.h:159
bool LiteralIsTrue(Literal literal) const
Definition: sat_base.h:151
bool LiteralIsFalse(Literal literal) const
Definition: sat_base.h:148
SatParameters parameters
CpModelProto proto
const std::string name
const Constraint * ct
int64_t value
IntVar * var
Definition: expr_array.cc:1874
GRBmodel * model
const int INFO
Definition: log_severity.h:31
const int FATAL
Definition: log_severity.h:32
const std::function< BooleanOrIntegerLiteral()> ConstructSearchStrategyInternal(const std::vector< DecisionStrategyProto > &strategies, Model *model)
std::function< BooleanOrIntegerLiteral()> FirstUnassignedVarAtItsMinHeuristic(const std::vector< IntegerVariable > &vars, Model *model)
bool RefIsPositive(int ref)
std::function< BooleanOrIntegerLiteral()> SequentialSearch(std::vector< std::function< BooleanOrIntegerLiteral()> > heuristics)
const LiteralIndex kNoLiteralIndex(-1)
const IntegerVariable kNoIntegerVariable(-1)
std::function< BooleanOrIntegerLiteral()> SchedulingSearchHeuristic(Model *model)
std::vector< IntegerVariable > NegationOf(const std::vector< IntegerVariable > &vars)
Definition: integer.cc:29
std::vector< SatParameters > GetDiverseSetOfParameters(const SatParameters &base_params, const CpModelProto &cp_model, const int num_workers)
std::function< BooleanOrIntegerLiteral()> ConstructSearchStrategy(const CpModelProto &cp_model_proto, const std::vector< IntegerVariable > &variable_mapping, IntegerVariable objective_var, Model *model)
std::function< BooleanOrIntegerLiteral()> InstrumentSearchStrategy(const CpModelProto &cp_model_proto, const std::vector< IntegerVariable > &variable_mapping, const std::function< BooleanOrIntegerLiteral()> &instrumented_strategy, Model *model)
Collection of objects used to extend the Constraint Solver library.
int index
Definition: pack.cc:509
static IntegerLiteral LowerOrEqual(IntegerVariable i, IntegerValue bound)
Definition: integer.h:1315
static IntegerLiteral GreaterOrEqual(IntegerVariable i, IntegerValue bound)
Definition: integer.h:1309