20 #include "absl/container/flat_hash_map.h" 21 #include "absl/strings/str_format.h" 72 int64_t
value)
const {
88 int64_t
value)
const {
109 const IntegerVariable variable = mapping_.
Integer(
var);
112 std::vector<IntegerEncoder::ValueLiteralPair> encoding =
114 std::sort(encoding.begin(), encoding.end());
115 std::vector<Literal> unassigned_sorted_literals;
116 for (
const auto& p : encoding) {
118 unassigned_sorted_literals.push_back(p.literal);
124 const int target = (unassigned_sorted_literals.size() + 1) / 2 - 1;
139 bool ModelHasSchedulingConstraints(
const CpModelProto& cp_model_proto) {
150 const std::vector<DecisionStrategyProto>& strategies,
Model*
model) {
157 return [&view, &
parameters, random, strategies]() {
166 std::vector<VarValue> active_refs;
169 for (
int i = 0; i < strategy.variables().size(); ++i) {
170 const int ref = strategy.variables(i);
172 if (view.IsFixed(
var) || view.IsCurrentlyFree(
var))
continue;
176 while (t_index < strategy.transformations().size() &&
177 strategy.transformations(t_index).index() < i) {
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();
191 int64_t lb = view.Min(
var);
192 int64_t ub = view.Max(
var);
197 switch (strategy.variable_selection_strategy()) {
201 value = coeff * lb + offset;
204 value = -(coeff * ub + offset);
207 value = coeff * (ub - lb + 1);
210 value = -coeff * (ub - lb + 1);
213 LOG(
FATAL) <<
"Unknown VariableSelectionStrategy " 214 << strategy.variable_selection_strategy();
216 if (
value < candidate_value) {
218 candidate_value =
value;
220 if (strategy.variable_selection_strategy() ==
227 active_refs.push_back({ref,
value});
234 CHECK(!active_refs.empty());
235 const IntegerValue threshold(
237 auto is_above_tolerance = [threshold](
const VarValue& entry) {
238 return entry.value > threshold;
241 active_refs.erase(std::remove_if(active_refs.begin(), active_refs.end(),
244 const int winner = absl::Uniform<int>(*random, 0, active_refs.size());
245 candidate = active_refs[winner].ref;
249 strategy.domain_reduction_strategy();
270 const int64_t lb = view.Min(
var);
271 const int64_t ub = view.Max(
var);
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);
284 LOG(
FATAL) <<
"Unknown DomainReductionStrategy " 285 << strategy.domain_reduction_strategy();
294 const std::vector<IntegerVariable>& variable_mapping,
295 IntegerVariable objective_var,
Model*
model) {
300 std::vector<DecisionStrategyProto> strategies;
303 strategies.push_back(
proto);
310 if (ModelHasSchedulingConstraints(cp_model_proto)) {
316 std::vector<IntegerVariable> decisions;
317 for (
const IntegerVariable
var : variable_mapping) {
322 decisions.push_back(objective_var);
324 decisions.push_back(
var);
335 const std::vector<IntegerVariable>& variable_mapping,
338 std::vector<int> ref_to_display;
342 ref_to_display.push_back(i);
344 std::sort(ref_to_display.begin(), ref_to_display.end(), [&](
int i,
int j) {
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 {
353 if (!decision.
HasValue())
return decision;
357 LOG(
INFO) <<
"Boolean decision " << l;
360 LOG(
INFO) <<
" - associated with " << i_lit;
365 const int level =
model->Get<
Trail>()->CurrentDecisionLevel();
366 std::string to_display =
367 absl::StrCat(
"Diff since last call, level=", level,
"\n");
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(
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,
379 old_domains[ref] = new_domain;
396 const int num_workers) {
399 std::map<std::string, SatParameters> strategies;
405 strategies[
"no_lp"] = new_params;
407 strategies[
"default_lp"] = new_params;
410 strategies[
"max_lp"] = new_params;
424 strategies[
"core"] = new_params;
433 strategies[
"core_default_lp"] = new_params;
441 strategies[
"core_max_lp"] = new_params;
448 strategies[
"lb_tree_search"] = new_params;
455 strategies[
"probing"] = new_params;
462 strategies[
"auto"] = new_params;
465 strategies[
"fixed"] = new_params;
469 strategies[
"quick_restart"] = new_params;
474 strategies[
"quick_restart_no_lp"] = new_params;
479 strategies[
"reduced_costs"] = new_params;
485 strategies[
"pseudo_costs"] = new_params;
492 strategies[
"less_encoding"] = new_params;
502 ModelHasSchedulingConstraints(cp_model);
508 std::vector<std::string> names;
513 names.push_back(
"default_lp");
514 names.push_back(use_fixed_strategy ?
"fixed" :
"pseudo_costs");
516 names.push_back(
"max_lp");
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");
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");
530 names.push_back(
"reduced_costs");
532 names.push_back(
"pseudo_costs");
533 names.push_back(
"no_lp");
534 names.push_back(
"max_lp");
541 names.push_back(
"quick_restart");
543 if (num_workers > 10) {
544 names.push_back(
"quick_restart_no_lp");
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");
557 if (num_workers > 12) {
558 names.push_back(
"probing");
559 names.push_back(
"lb_tree_search");
564 std::vector<SatParameters> result;
565 for (
const std::string&
name : names) {
569 result.push_back(new_params);
575 int target = num_workers;
582 target =
std::max(1, num_workers - 1);
586 while (result.size() < target) {
594 result.push_back(new_params);
604 result.resize(num_workers);
const std::string & name() const
void set_randomize_search(bool value)
static constexpr DomainReductionStrategy SELECT_MIN_VALUE
static constexpr SearchBranching LP_SEARCH
Class that owns everything related to a particular optimization model.
DecisionStrategyProto_DomainReductionStrategy
static constexpr DomainReductionStrategy SELECT_MEDIAN_VALUE
static constexpr VariableSelectionStrategy CHOOSE_LOWEST_MIN
bool VariableIsFullyEncoded(IntegerVariable var) const
void set_linearization_level(::PROTOBUF_NAMESPACE_ID::int32 value)
static IntegerLiteral LowerOrEqual(IntegerVariable i, IntegerValue bound)
CpModelView(Model *model)
IntegerValue LowerBound(IntegerVariable i) const
bool LiteralIsFalse(Literal literal) const
bool LiteralIsTrue(Literal literal) const
LiteralIndex Index() const
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
int variables_size() const
bool use_relaxation_lns() const
bool IsInteger(int ref) const
sat::Literal Literal(int ref) const
static constexpr VariableSelectionStrategy CHOOSE_FIRST
void set_exploit_best_solution(bool value)
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)
LiteralIndex NegatedIndex() const
static constexpr VariableSelectionStrategy CHOOSE_MAX_DOMAIN_SIZE
const ::operations_research::sat::IntegerVariableProto & variables(int index) const
BooleanVariable Variable() const
LiteralIndex boolean_literal_index
void set_search_randomization_tolerance(::PROTOBUF_NAMESPACE_ID::int64 value)
int NumProtoVariables() const
bool VariableIsAssigned(BooleanVariable var) const
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
An Assignment is a variable -> domains mapping, used to report solutions to the user.
static constexpr DomainReductionStrategy SELECT_MAX_VALUE
static constexpr SearchBranching AUTOMATIC_SEARCH
BooleanOrIntegerLiteral MedianValue(int var) const
bool use_feasibility_pump() const
std::function< BooleanOrIntegerLiteral()> SchedulingSearchHeuristic(Model *model)
bool interleave_search() const
bool has_objective() const
static constexpr DomainReductionStrategy SELECT_UPPER_HALF
void set_optimize_with_lb_tree_search(bool value)
std::vector< IntegerVariable > NegationOf(const std::vector< IntegerVariable > &vars)
#define DCHECK(condition)
bool IsBoolean(int ref) const
static constexpr VariableSelectionStrategy CHOOSE_MIN_DOMAIN_SIZE
bool IsCurrentlyIgnored(IntegerVariable i) const
bool IsCurrentlyFree(int var) const
BooleanOrIntegerLiteral GreaterOrEqual(int var, int64_t value) const
bool use_rins_lns() const
int64_t Max(int var) const
const ::operations_research::sat::DecisionStrategyProto & search_strategy(int index) const
IntegerLiteral integer_literal
const InlinedIntegerLiteralVector & GetAllIntegerLiterals(Literal lit) const
void set_add_lp_constraints_lazily(bool value)
IntegerValue UpperBound(IntegerVariable i) const
bool instantiate_all_variables() const
static constexpr SearchBranching FIXED_SEARCH
std::vector< ValueLiteralPair > RawDomainEncoding(IntegerVariable var) const
Collection of objects used to extend the Constraint Solver library.
const IntegerVariable kNoIntegerVariable(-1)
void set_use_probing_search(bool value)
static IntegerLiteral GreaterOrEqual(IntegerVariable i, IntegerValue bound)
bool reduce_memory_usage_in_interleave_mode() const
bool RefIsPositive(int ref)
const LiteralIndex kNoLiteralIndex(-1)
void set_search_branching(::operations_research::sat::SatParameters_SearchBranching value)
BooleanOrIntegerLiteral LowerOrEqual(int var, int64_t value) const
int64_t Min(int var) const
void set_optimize_with_core(bool value)
static constexpr DomainReductionStrategy SELECT_LOWER_HALF
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)
bool randomize_search() const
IntegerVariable Integer(int ref) const
std::function< BooleanOrIntegerLiteral()> FirstUnassignedVarAtItsMinHeuristic(const std::vector< IntegerVariable > &vars, Model *model)
bool IsFixed(int var) const
#define CHECK_NE(val1, val2)
bool IsFixed(IntegerVariable i) const
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)