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