25#include "absl/algorithm/container.h"
26#include "absl/container/flat_hash_map.h"
27#include "absl/container/flat_hash_set.h"
28#include "absl/log/check.h"
29#include "absl/random/distributions.h"
30#include "absl/strings/str_cat.h"
31#include "absl/strings/string_view.h"
32#include "absl/types/span.h"
60 if (mapping_.IsBoolean(var)) {
61 return boolean_assignment_.VariableIsAssigned(
62 mapping_.Literal(var).Variable());
63 }
else if (mapping_.IsInteger(var)) {
64 return integer_trail_.IsFixed(mapping_.Integer(var));
70 if (mapping_.IsBoolean(var)) {
72 return boolean_assignment_.LiteralIsTrue(l) ? 1 : 0;
73 }
else if (mapping_.IsInteger(var)) {
74 return integer_trail_.LowerBound(mapping_.Integer(var)).value();
80 if (mapping_.IsBoolean(var)) {
82 return boolean_assignment_.LiteralIsFalse(l) ? 0 : 1;
83 }
else if (mapping_.IsInteger(var)) {
84 return integer_trail_.UpperBound(mapping_.Integer(var)).value();
90 int64_t value)
const {
93 if (mapping_.IsBoolean(var)) {
94 DCHECK(value == 0 || value == 1);
98 }
else if (mapping_.IsInteger(var)) {
100 mapping_.Integer(var), IntegerValue(value));
106 int64_t value)
const {
109 if (mapping_.IsBoolean(var)) {
110 DCHECK(value == 0 || value == 1);
114 }
else if (mapping_.IsInteger(var)) {
116 IntegerValue(value));
124 if (mapping_.IsBoolean(var)) {
126 }
else if (mapping_.IsInteger(var)) {
127 const IntegerVariable variable = mapping_.Integer(var);
128 const std::vector<ValueLiteralPair> encoding =
129 integer_encoder_.FullDomainEncoding(variable);
134 const int target = (
static_cast<int>(encoding.size()) + 1) / 2 - 1;
144 if (mapping_.IsBoolean(var)) {
145 if (absl::Bernoulli(random_, 0.5)) {
150 }
else if (mapping_.IsInteger(var)) {
151 if (absl::Bernoulli(random_, 0.5)) {
153 mapping_.Integer(var), IntegerValue(lb + (ub - lb) / 2));
156 mapping_.Integer(var), IntegerValue(ub - (ub - lb) / 2));
171bool ModelHasSchedulingConstraints(
const CpModelProto& cp_model_proto) {
179void AddExtraSchedulingPropagators(SatParameters& new_params) {
180 new_params.set_exploit_all_precedences(
true);
181 new_params.set_use_hard_precedences_in_cumulative(
true);
182 new_params.set_use_overload_checker_in_cumulative(
true);
183 new_params.set_use_strong_propagation_in_disjunctive(
true);
184 new_params.set_use_timetable_edge_finding_in_cumulative(
true);
185 new_params.set_use_conservative_scale_overload_checker(
true);
186 new_params.set_max_pairs_pairwise_reasoning_in_no_overlap_2d(5000);
187 new_params.set_use_timetabling_in_no_overlap_2d(
true);
188 new_params.set_use_energetic_reasoning_in_no_overlap_2d(
true);
189 new_params.set_use_area_energetic_reasoning_in_no_overlap_2d(
true);
190 new_params.set_use_try_edge_reasoning_in_no_overlap_2d(
true);
191 new_params.set_no_overlap_2d_boolean_relations_limit(100);
199 bool operator<=(
const NoisyInteger& other)
const {
200 return value < other.value ||
201 (value == other.value && noise <= other.noise);
203 bool operator>(
const NoisyInteger& other)
const {
204 return value > other.value || (value == other.value && noise > other.noise);
214 std::vector<DecisionStrategyProto> strategies;
216 strategies.push_back(proto);
224 return [&view, ¶meters, random, strategies]() {
226 int candidate_ref = -1;
227 int64_t candidate_value = std::numeric_limits<int64_t>::max();
233 const bool randomize_decision =
234 parameters.search_random_variable_pool_size() > 1;
236 randomize_decision ? parameters.search_random_variable_pool_size()
240 const int var = expr.vars(0);
241 if (view.IsFixed(var))
continue;
243 int64_t coeff = expr.coeffs(0);
244 int64_t offset = expr.offset();
245 int64_t lb = view.Min(var);
246 int64_t ub = view.Max(var);
256 switch (strategy.variable_selection_strategy()) {
260 value = coeff * lb + offset;
263 value = -(coeff * ub + offset);
271 value = -(ub - lb + 1);
274 LOG(FATAL) <<
"Unknown VariableSelectionStrategy "
275 << strategy.variable_selection_strategy();
278 if (randomize_decision) {
281 const double noise = absl::Uniform(*random, 0., 1.0);
282 top_variables.
Add(ref, {-value, noise});
283 candidate_value = std::min(candidate_value, value);
284 }
else if (value < candidate_value) {
286 candidate_value = value;
291 if (strategy.variable_selection_strategy() ==
293 !randomize_decision) {
299 if (candidate_value == std::numeric_limits<int64_t>::max())
continue;
302 if (randomize_decision) {
304 candidate_ref = candidates[absl::Uniform(
305 *random, 0,
static_cast<int>(candidates.size()))];
309 strategy.domain_reduction_strategy();
330 const int64_t lb = view.Min(var);
331 const int64_t ub = view.Max(var);
334 return view.LowerOrEqual(var, lb);
336 return view.GreaterOrEqual(var, ub);
338 return view.LowerOrEqual(var, lb + (ub - lb) / 2);
340 return view.GreaterOrEqual(var, ub - (ub - lb) / 2);
342 return view.MedianValue(var);
344 return view.RandomSplit(var, lb, ub);
346 LOG(FATAL) <<
"Unknown DomainReductionStrategy "
347 << strategy.domain_reduction_strategy();
357 if (ModelHasSchedulingConstraints(cp_model_proto)) {
360 bool possible_new_constraints =
false;
361 if (params.use_dynamic_precedence_in_disjunctive()) {
362 possible_new_constraints =
true;
365 if (params.use_dynamic_precedence_in_cumulative()) {
366 possible_new_constraints =
true;
375 if (possible_new_constraints && params.new_linear_propagation()) {
385std::function<BooleanOrIntegerLiteral()>
387 absl::Span<const IntegerVariable> variable_mapping,
388 IntegerVariable objective_var,
Model* model) {
390 if (!params.instantiate_all_variables()) {
394 std::vector<IntegerVariable> decisions;
395 for (
const IntegerVariable var : variable_mapping) {
402 decisions.push_back(objective_var);
404 decisions.push_back(var);
413 std::vector<BooleanOrIntegerVariable> vars;
414 std::vector<IntegerValue> values;
450 absl::Span<const IntegerVariable> variable_mapping,
453 std::vector<int> ref_to_display;
457 ref_to_display.push_back(
i);
459 std::sort(ref_to_display.begin(), ref_to_display.end(), [&](
int i,
int j) {
460 return cp_model_proto.variables(i).name() <
461 cp_model_proto.variables(j).name();
464 std::vector<std::pair<int64_t, int64_t>> old_domains(variable_mapping.size());
465 return [instrumented_strategy, model, variable_mapping, &cp_model_proto,
466 old_domains, ref_to_display]()
mutable {
468 if (!decision.
HasValue())
return decision;
472 LOG(INFO) <<
"Boolean decision " << l;
474 for (
const IntegerLiteral i_lit : encoder->GetIntegerLiterals(l)) {
475 LOG(INFO) <<
" - associated with " << i_lit;
477 for (
const auto [var, value] : encoder->GetEqualityLiterals(l)) {
478 LOG(INFO) <<
" - associated with " << var <<
" == " << value;
483 const int level = model->
Get<
Trail>()->CurrentDecisionLevel();
484 std::string to_display =
485 absl::StrCat(
"Diff since last call, level=", level,
"\n");
487 for (
const int ref : ref_to_display) {
488 const IntegerVariable var = variable_mapping[ref];
489 const std::pair<int64_t, int64_t> new_domain(
492 if (new_domain != old_domains[ref]) {
493 absl::StrAppend(&to_display, cp_model_proto.variables(ref).name(),
" [",
494 old_domains[ref].first,
",", old_domains[ref].second,
495 "] -> [", new_domain.first,
",", new_domain.second,
497 old_domains[ref] = new_domain;
500 LOG(INFO) << to_display;
507 absl::flat_hash_map<std::string, SatParameters> strategies;
515 strategies[
"default"] = base_params;
521 strategies[
"no_lp"] = new_params;
523 strategies[
"default_lp"] = new_params;
526 strategies[
"max_lp"] = new_params;
528 strategies[
"max_lp_sym"] = new_params;
542 strategies[
"core"] = new_params;
551 strategies[
"core_default_lp"] = new_params;
559 strategies[
"core_max_lp"] = new_params;
567 strategies[
"max_hs"] = new_params;
578 strategies[
"lb_tree_search_no_lp"] = new_params;
582 AddExtraSchedulingPropagators(new_params);
587 strategies[
"lb_tree_search"] = new_params;
595 strategies[
"objective_lb_search_no_lp"] = new_params;
598 strategies[
"objective_lb_search"] = new_params;
601 AddExtraSchedulingPropagators(new_params);
604 strategies[
"objective_lb_search_max_lp"] = new_params;
614 AddExtraSchedulingPropagators(new_params);
617 strategies[
"objective_shaving"] = new_params;
620 strategies[
"objective_shaving_no_lp"] = new_params;
623 strategies[
"objective_shaving_max_lp"] = new_params;
635 strategies[
"variables_shaving"] = new_params;
638 strategies[
"variables_shaving_no_lp"] = new_params;
641 AddExtraSchedulingPropagators(new_params);
644 strategies[
"variables_shaving_max_lp"] = new_params;
656 AddExtraSchedulingPropagators(new_params);
658 strategies[
"probing"] = new_params;
661 strategies[
"probing_no_lp"] = new_params;
667 strategies[
"probing_max_lp"] = new_params;
674 strategies[
"auto"] = new_params;
679 strategies[
"fixed"] = new_params;
682 strategies[
"fixed_no_lp"] = new_params;
687 strategies[
"fixed_max_lp"] = new_params;
694 strategies[
"portfolio"] = new_params;
697 strategies[
"portfolio_no_lp"] = new_params;
702 strategies[
"portfolio_max_lp"] = new_params;
711 strategies[
"quick_restart"] = new_params;
714 strategies[
"quick_restart_no_lp"] = new_params;
717 strategies[
"quick_restart_max_lp"] = new_params;
725 AddExtraSchedulingPropagators(new_params);
727 strategies[
"reduced_costs"] = new_params;
736 strategies[
"pseudo_costs"] = new_params;
743 strategies[
"less_encoding"] = new_params;
765 strategies[
"shared_tree"] = new_params;
785 strategies[
"lns"] = lns_params;
789 auto it = absl::c_find_if(
791 [](
const SatParameters& params) { return params.name() ==
"lns"; });
799 strategies[
"lns_base"] = lns_params_base;
804 strategies[
"lns_stalling"] = lns_params_stalling;
811 strategies[
"lns_routing"] = lns_params_routing;
817 auto it = strategies.find(params.name());
818 if (it != strategies.end()) {
819 it->second.MergeFrom(params);
825 strategies[params.name()] = new_params;
830 for (
auto& [name, params] : strategies) {
831 params.set_name(name);
858 ModelHasSchedulingConstraints(cp_model);
861 std::vector<std::string> names;
865 names.push_back(name);
871 names.push_back(
"default_lp");
872 names.push_back(
"fixed");
873 names.push_back(
"core");
874 names.push_back(
"no_lp");
876 names.push_back(
"max_lp_sym");
880 names.push_back(
"max_lp");
882 names.push_back(
"quick_restart");
883 names.push_back(
"reduced_costs");
884 names.push_back(
"quick_restart_no_lp");
885 names.push_back(
"pseudo_costs");
886 names.push_back(
"lb_tree_search");
887 names.push_back(
"probing");
888 names.push_back(
"objective_lb_search");
889 names.push_back(
"objective_shaving_no_lp");
890 names.push_back(
"objective_shaving_max_lp");
891 names.push_back(
"probing_max_lp");
892 names.push_back(
"probing_no_lp");
893 names.push_back(
"objective_lb_search_no_lp");
894 names.push_back(
"objective_lb_search_max_lp");
896 names.push_back(
"max_lp");
899 for (
const std::string& name : base_params.
subsolvers()) {
902 if (name ==
"core_or_no_lp") {
905 names.push_back(
"no_lp");
907 names.push_back(
"core");
910 names.push_back(name);
917 for (
const std::string& name : names) {
918 if (filter->
Keep(name)) {
919 names[new_size++] = name;
922 names.resize(new_size);
925 std::vector<SatParameters> result;
926 for (
const std::string& name : names) {
930 if (!use_fixed_strategy &&
964 if (name ==
"less_encoding")
continue;
989 base_params.
random_seed(),
static_cast<int64_t
>(result.size()) + 1));
990 result.push_back(params);
1001 if (num_to_keep == 0) {
1004 const int num_available =
1005 std::max(0, base_params.
num_workers() - num_already_present);
1007 const auto heuristic_num_workers = [](
int num_workers) {
1008 DCHECK_GE(num_workers, 0);
1009 if (num_workers == 1)
return 1;
1010 if (num_workers <= 4)
return num_workers - 1;
1011 if (num_workers <= 8)
return num_workers - 2;
1012 if (num_workers <= 16)
return num_workers - (num_workers / 4 + 1);
1013 return num_workers - (num_workers / 2 - 3);
1016 num_to_keep = heuristic_num_workers(num_available);
1019 if (result.size() > num_to_keep) {
1020 result.resize(std::max(0, num_to_keep));
1021 }
else if (!result.empty() && num_to_keep >= 0) {
1025 while (result.size() < num_to_keep) {
1026 result.push_back(result[0]);
1035 std::vector<SatParameters> result;
1037 const auto get_base = [&result, &base_params](
bool fj) {
1052 result.push_back(new_params);
1056 for (
int i = 0;
i < 2; ++
i) {
1061 new_params.
set_name(
"fs_random_no_lp");
1066 result.push_back(new_params);
1074 result.push_back(new_params);
1078 for (
int i = 0;
i < 2; ++
i) {
1084 new_params.
set_name(
"fs_random_quick_restart_no_lp");
1087 new_params.
set_name(
"fs_random_quick_restart");
1089 result.push_back(new_params);
1099 result.push_back(new_params);
1106 absl::Span<const SatParameters> base_params,
int num_params_to_generate) {
1108 std::vector<SatParameters> result;
1109 result.assign(base_params.begin(), base_params.end());
1110 if (result.empty())
return result;
1111 if (result.size() >= num_params_to_generate) {
1112 result.resize(num_params_to_generate);
1118 const int base_size = result.size();
1119 while (result.size() < num_params_to_generate) {
1120 result.push_back(result[
i % base_size]);
1121 result.back().set_random_seed(
CombineSeed(result.back().random_seed(),
i));
1129 filter_patterns_.push_back(pattern);
1132 ignore_patterns_.push_back(pattern);
1137 filter_patterns_.push_back(
"ls*");
1138 filter_patterns_.push_back(
"fj*");
1143 filter_patterns_.push_back(
"fj*");
1144 filter_patterns_.push_back(
"fs*");
1145 filter_patterns_.push_back(
"*lns");
1151 if (!filter_patterns_.empty()) {
1153 for (
const absl::string_view pattern : filter_patterns_) {
1154 if (FNMatch(pattern, name)) {
1160 ignored_.emplace_back(name);
1164 for (
const absl::string_view pattern : ignore_patterns_) {
1165 if (FNMatch(pattern, name)) {
1166 ignored_.emplace_back(name);
1173bool SubsolverNameFilter::FNMatch(absl::string_view pattern,
1174 absl::string_view str) {
1175 bool in_wildcard_match =
false;
1177 if (pattern.empty()) {
1178 return in_wildcard_match || str.empty();
1181 return pattern.find_first_not_of(
'*') == pattern.npos;
1183 switch (pattern.front()) {
1185 pattern.remove_prefix(1);
1186 in_wildcard_match =
true;
1189 pattern.remove_prefix(1);
1190 str.remove_prefix(1);
1193 if (in_wildcard_match) {
1194 absl::string_view fixed_portion = pattern;
1195 const size_t end = fixed_portion.find_first_of(
"*?");
1196 if (
end != fixed_portion.npos) {
1197 fixed_portion = fixed_portion.substr(0,
end);
1199 const size_t match = str.find(fixed_portion);
1200 if (match == str.npos) {
1203 pattern.remove_prefix(fixed_portion.size());
1204 str.remove_prefix(match + fixed_portion.size());
1205 in_wildcard_match =
false;
1207 if (pattern.front() != str.front()) {
1210 pattern.remove_prefix(1);
1211 str.remove_prefix(1);
sat::Literal Literal(int ref) const
bool IsBoolean(int ref) const
IntegerVariable Integer(int ref) const
bool has_symmetry() const
const ::operations_research::sat::IntegerVariableProto & variables(int index) const
const ::operations_research::sat::ConstraintProto & constraints(int index) const
bool has_objective() const
const ::operations_research::sat::DecisionStrategyProto & search_strategy(int index) const
int variables_size() const
const ::operations_research::sat::PartialVariableAssignment & solution_hint() const
const ::operations_research::sat::CpObjectiveProto & objective() const
BooleanOrIntegerLiteral GreaterOrEqual(int var, int64_t value) const
BooleanOrIntegerLiteral LowerOrEqual(int var, int64_t value) const
BooleanOrIntegerLiteral MedianValue(int var) const
int64_t Max(int var) const
CpModelView(Model *model)
int64_t Min(int var) const
bool IsFixed(int var) const
BooleanOrIntegerLiteral RandomSplit(int var, int64_t lb, int64_t ub) const
::int32_t vars(int index) const
static constexpr DomainReductionStrategy SELECT_MAX_VALUE
static constexpr DomainReductionStrategy SELECT_MIN_VALUE
DecisionStrategyProto_DomainReductionStrategy DomainReductionStrategy
static constexpr VariableSelectionStrategy CHOOSE_HIGHEST_MAX
static constexpr VariableSelectionStrategy CHOOSE_FIRST
static constexpr DomainReductionStrategy SELECT_MEDIAN_VALUE
static constexpr DomainReductionStrategy SELECT_UPPER_HALF
static constexpr VariableSelectionStrategy CHOOSE_LOWEST_MIN
static constexpr VariableSelectionStrategy CHOOSE_MAX_DOMAIN_SIZE
static constexpr VariableSelectionStrategy CHOOSE_MIN_DOMAIN_SIZE
static constexpr DomainReductionStrategy SELECT_LOWER_HALF
static constexpr DomainReductionStrategy SELECT_RANDOM_HALF
IntegerValue LowerBound(IntegerVariable i) const
IntegerValue UpperBound(IntegerVariable i) const
const ::std::string & name() const
BooleanVariable Variable() const
Literal(int signed_value)
T Get(std::function< T(const Model &)> f) const
Similar to Add() but this is const.
::int64_t values(int index) const
::int32_t vars(int index) const
bool use_probing_search() const
const ::std::string & ignore_subsolvers(int index) const
void set_use_feasibility_jump(bool value)
void set_debug_crash_on_bad_hint(bool value)
::int32_t num_full_subsolvers() const
bool use_feasibility_jump() const
::int32_t linearization_level() const
const ::operations_research::sat::SatParameters & subsolver_params(int index) const
void set_use_probing_search(bool value)
void set_search_branching(::operations_research::sat::SatParameters_SearchBranching value)
void set_exploit_best_solution(bool value)
void set_solution_pool_size(::int32_t value)
static constexpr SearchBranching PORTFOLIO_SEARCH
bool output_lrat_proof() const
bool check_lrat_proof() const
const ::std::string & extra_subsolvers(int index) const
void set_find_clauses_that_are_exactly_one(bool value)
bool optimize_with_lb_tree_search() const
void set_boolean_encoding_level(::int32_t value)
void set_use_symmetry_in_lp(bool value)
void set_stop_after_first_solution(bool value)
bool check_drat_proof() const
void set_share_level_zero_bounds(bool value)
bool use_objective_shaving_search() const
void set_alternative_pool_size(::int32_t value)
void set_cp_model_presolve(bool value)
bool output_drat_proof() const
void set_use_sat_inprocessing(bool value)
static constexpr SearchBranching AUTOMATIC_SEARCH
static constexpr SearchBranching RANDOMIZED_SEARCH
void set_optimize_with_max_hs(bool value)
void set_use_shared_tree_search(bool value)
void set_feasibility_jump_linearization_level(::int32_t value)
void set_symmetry_level(::int32_t value)
void set_linearization_level(::int32_t value)
bool use_objective_lb_search() const
void set_optimize_with_lb_tree_search(bool value)
bool use_lns_only() const
void set_root_lp_iterations(::int32_t value)
static constexpr SearchBranching FIXED_SEARCH
bool optimize_with_core() const
void set_find_big_linear_overlap(bool value)
const ::std::string & subsolvers(int index) const
static constexpr SearchBranching PSEUDO_COST_SEARCH
bool use_dual_scheduling_heuristics() const
void set_optimize_with_core(bool value)
void set_at_most_one_max_expansion_size(::int32_t value)
void set_random_seed(::int32_t value)
void set_use_dynamic_precedence_in_cumulative(bool value)
void set_use_dynamic_precedence_in_disjunctive(bool value)
void set_use_objective_shaving_search(bool value)
void set_use_objective_lb_search(bool value)
void set_log_search_progress(bool value)
const ::std::string & filter_subsolvers(int index) const
::operations_research::sat::SatParameters_SearchBranching search_branching() const
void set_share_objective_bounds(bool value)
::int32_t random_seed() const
void set_add_lp_constraints_lazily(bool value)
void set_name(Arg_ &&arg, Args_... args)
static constexpr SearchBranching PORTFOLIO_WITH_QUICK_RESTART_SEARCH
void set_no_overlap_2d_boolean_relations_limit(::int32_t value)
void set_polarity_exploit_ls_hints(bool value)
static constexpr SearchBranching LP_SEARCH
::int32_t num_workers() const
void MergeFrom(const SatParameters &from)
void set_cp_model_probing_level(::int32_t value)
void set_search_random_variable_pool_size(::int64_t value)
void set_shaving_search_deterministic_time(double value)
bool interleave_search() const
SubsolverNameFilter(const SatParameters ¶ms)
bool Keep(absl::string_view name)
void Add(Element e, Score score)
const std::vector< Element > & UnorderedElements() const
bool RefIsPositive(int ref)
std::function< BooleanOrIntegerLiteral()> FirstUnassignedVarAtItsMinHeuristic(absl::Span< const IntegerVariable > vars, Model *model)
std::vector< SatParameters > GetFullWorkerParameters(const SatParameters &base_params, const CpModelProto &cp_model, int num_already_present, SubsolverNameFilter *filter)
const LiteralIndex kNoLiteralIndex(-1)
std::function< BooleanOrIntegerLiteral()> DisjunctivePrecedenceSearchHeuristic(Model *model)
std::function< BooleanOrIntegerLiteral()> ConstructIntegerCompletionSearchStrategy(absl::Span< const IntegerVariable > variable_mapping, IntegerVariable objective_var, Model *model)
std::vector< IntegerVariable > NegationOf(absl::Span< const IntegerVariable > vars)
int CombineSeed(int base_seed, int64_t delta)
std::function< BooleanOrIntegerLiteral()> ConstructHintSearchStrategy(const CpModelProto &cp_model_proto, CpModelMapping *mapping, Model *model)
const IntegerVariable kNoIntegerVariable(-1)
std::function< BooleanOrIntegerLiteral()> PseudoCost(Model *model)
std::function< BooleanOrIntegerLiteral()> ConstructHeuristicSearchStrategy(const CpModelProto &cp_model_proto, Model *model)
std::function< BooleanOrIntegerLiteral()> SchedulingSearchHeuristic(Model *model)
std::vector< SatParameters > GetFirstSolutionBaseParams(const SatParameters &base_params)
void ConstructFixedSearchStrategy(SearchHeuristics *h, Model *model)
std::vector< SatParameters > RepeatParameters(absl::Span< const SatParameters > base_params, int num_params_to_generate)
std::function< BooleanOrIntegerLiteral()> ConstructUserSearchStrategy(const CpModelProto &cp_model_proto, Model *model)
std::function< BooleanOrIntegerLiteral()> FollowHint(absl::Span< const BooleanOrIntegerVariable > vars, absl::Span< const IntegerValue > values, Model *model)
absl::flat_hash_map< std::string, SatParameters > GetNamedParameters(SatParameters base_params)
std::function< BooleanOrIntegerLiteral()> InstrumentSearchStrategy(const CpModelProto &cp_model_proto, absl::Span< const IntegerVariable > variable_mapping, std::function< BooleanOrIntegerLiteral()> instrumented_strategy, Model *model)
std::function< BooleanOrIntegerLiteral()> CumulativePrecedenceSearchHeuristic(Model *model)
std::function< BooleanOrIntegerLiteral()> SequentialSearch(std::vector< std::function< BooleanOrIntegerLiteral()> > heuristics)
LinearRange operator<=(const LinearExpr &lhs, const LinearExpr &rhs)
ClosedInterval::Iterator end(ClosedInterval interval)
LiteralIndex boolean_literal_index
IntegerLiteral integer_literal
static IntegerLiteral GreaterOrEqual(IntegerVariable i, IntegerValue bound)
static IntegerLiteral LowerOrEqual(IntegerVariable i, IntegerValue bound)
std::function< BooleanOrIntegerLiteral()> fixed_search
std::function< BooleanOrIntegerLiteral()> heuristic_search
std::function< BooleanOrIntegerLiteral()> user_search
std::function< BooleanOrIntegerLiteral()> integer_completion_search