40 const Literal le = encoder->GetOrCreateAssociatedLiteral(
42 DCHECK(!trail->Assignment().VariableIsAssigned(le.Variable()));
49 const Literal ge = encoder->GetOrCreateAssociatedLiteral(
51 DCHECK(!trail->Assignment().VariableIsAssigned(ge.Variable()));
64 return result.
Index();
70 const IntegerValue var_ub = integer_trail->UpperBound(
var);
71 CHECK_LT(var_lb, var_ub);
73 const IntegerValue chosen_value =
74 var_lb +
std::max(IntegerValue(1), (var_ub - var_lb) / IntegerValue(2));
83 const IntegerValue lb = integer_trail->
LowerBound(positive_var);
84 const IntegerValue ub = integer_trail->UpperBound(positive_var);
86 const absl::flat_hash_set<IntegerVariable>& variables =
94 const bool branch_down_feasible =
value >= lb &&
value < ub;
95 const bool branch_up_feasible =
value > lb &&
value <= ub;
96 if (variables.contains(positive_var) && branch_down_feasible) {
98 }
else if (variables.contains(
NegationOf(positive_var)) &&
101 }
else if (branch_down_feasible) {
103 }
else if (branch_up_feasible) {
113 DCHECK(!integer_trail->IsCurrentlyIgnored(
var));
126 const IntegerValue
value = IntegerValue(
143 const int proto_var =
151 VLOG(2) <<
"Using solution value for branching.";
162 const std::vector<IntegerVariable>& vars,
Model*
model) {
165 return [ vars, integer_trail, integer_encoder]() {
166 for (
const IntegerVariable
var : vars) {
168 if (integer_trail->IsCurrentlyIgnored(
var))
continue;
169 const LiteralIndex decision =
178 const std::vector<IntegerVariable>& vars,
Model*
model) {
181 return [ vars, integer_trail, integer_encoder]() {
183 IntegerValue candidate_lb;
184 for (
const IntegerVariable
var : vars) {
185 if (integer_trail->IsCurrentlyIgnored(
var))
continue;
186 const IntegerValue lb = integer_trail->LowerBound(
var);
194 return AtMinValue(candidate, integer_trail, integer_encoder);
199 std::vector<std::function<LiteralIndex()>> heuristics) {
200 return [heuristics]() {
201 for (
const auto& h : heuristics) {
202 const LiteralIndex li = h();
210 std::vector<std::function<LiteralIndex(IntegerVariable)>>
211 value_selection_heuristics,
212 std::function<LiteralIndex()> var_selection_heuristic,
Model*
model) {
217 const LiteralIndex current_decision = var_selection_heuristic();
222 encoder->GetAllIntegerLiterals(
Literal(current_decision))) {
223 if (integer_trail->IsCurrentlyIgnored(l.var))
continue;
226 for (
const auto& value_heuristic : value_selection_heuristics) {
227 const LiteralIndex decision = value_heuristic(l.var);
234 VLOG(2) <<
"Value selection: using default decision.";
235 return current_decision;
241 const auto& variables =
245 if (variables.contains(
var)) {
255 std::function<LiteralIndex()> var_selection_heuristic,
Model*
model) {
256 const SatParameters&
parameters = *(
model->GetOrCreate<SatParameters>());
257 std::vector<std::function<LiteralIndex(IntegerVariable)>>
258 value_selection_heuristics;
267 VLOG(1) <<
"Using LP value selection heuristic.";
268 value_selection_heuristics.push_back([
model](IntegerVariable
var) {
276 if (response_manager !=
nullptr) {
277 VLOG(1) <<
"Using best solution value selection heuristic.";
278 value_selection_heuristics.push_back(
279 [
model, response_manager](IntegerVariable
var) {
281 var, response_manager->SolutionsRepository(),
model);
287 if (
parameters.exploit_relaxation_solution()) {
291 value_selection_heuristics.push_back(
293 VLOG(1) <<
"Using relaxation solution value selection heuristic.";
302 VLOG(1) <<
"Using objective value selection heuristic.";
303 value_selection_heuristics.push_back([
model](IntegerVariable
var) {
309 var_selection_heuristic,
model);
316 return [sat_solver, trail, decision_policy] {
317 const bool all_assigned = trail->Index() == sat_solver->NumVariables();
319 const Literal result = decision_policy->NextBranch();
320 CHECK(!sat_solver->Assignment().LiteralIsAssigned(result));
321 return result.
Index();
327 const bool has_objective =
329 if (!has_objective) {
334 return [pseudo_costs,
model]() {
349 std::vector<std::function<LiteralIndex()>> policies{
354 std::discrete_distribution<int> var_dist{3 , 1 };
357 std::vector<std::function<LiteralIndex(IntegerVariable)>>
358 value_selection_heuristics;
359 std::vector<int> value_selection_weight;
362 value_selection_heuristics.push_back([
model](IntegerVariable
var) {
365 value_selection_weight.push_back(8);
369 if (response_manager !=
nullptr) {
370 value_selection_heuristics.push_back(
371 [
model, response_manager](IntegerVariable
var) {
373 var, response_manager->SolutionsRepository(),
model);
375 value_selection_weight.push_back(5);
381 value_selection_heuristics.push_back(
386 value_selection_weight.push_back(3);
390 value_selection_heuristics.push_back([
model](IntegerVariable
var) {
393 value_selection_weight.push_back(1);
398 value_selection_heuristics.push_back(
399 [integer_trail, integer_encoder](IntegerVariable
var) {
402 value_selection_weight.push_back(1);
405 value_selection_weight.push_back(10);
409 std::discrete_distribution<int> val_dist(value_selection_weight.begin(),
410 value_selection_weight.end());
412 int policy_index = 0;
413 int val_policy_index = 0;
414 return [=]()
mutable {
418 decision_policy->ResetDecisionHeuristic();
421 policy_index = var_dist(*(random));
424 val_policy_index = val_dist(*(random));
428 const LiteralIndex current_decision = policies[policy_index]();
432 if (val_policy_index >= value_selection_heuristics.size()) {
433 return current_decision;
438 integer_encoder->GetAllIntegerLiterals(
Literal(current_decision))) {
439 if (integer_trail->IsCurrentlyIgnored(l.var))
continue;
442 const LiteralIndex new_decision =
443 value_selection_heuristics[val_policy_index](l.var);
450 return current_decision;
456 const std::vector<BooleanOrIntegerVariable>& vars,
457 const std::vector<IntegerValue>& values,
Model*
model) {
461 for (
int i = 0; i < vars.size(); ++i) {
462 const IntegerValue
value = values[i];
467 const IntegerVariable integer_var = vars[i].int_var;
468 if (integer_trail->IsCurrentlyIgnored(integer_var))
continue;
469 if (integer_trail->IsFixed(integer_var))
continue;
485 auto* lp_constraints =
487 const SatParameters&
parameters = *(
model->GetOrCreate<SatParameters>());
493 if (!lp->HasSolution() ||
494 !(
parameters.exploit_all_lp_solution() || lp->SolutionIsInteger())) {
502 auto* lp_constraints =
505 int num_lp_variables = 0;
507 num_lp_variables += lp->NumVariables();
509 const int num_integer_variables =
511 return (num_integer_variables <= 2 * num_lp_variables);
515 bool reset_at_next_call =
true;
516 int next_num_failures = 0;
517 return [=]()
mutable {
518 if (reset_at_next_call) {
520 reset_at_next_call =
false;
521 }
else if (solver->
num_failures() >= next_num_failures) {
522 reset_at_next_call =
true;
524 return reset_at_next_call;
540 const SatParameters&
parameters = *(
model->GetOrCreate<SatParameters>());
542 case SatParameters::AUTOMATIC_SEARCH: {
543 std::function<LiteralIndex()> decision_policy;
556 case SatParameters::FIXED_SEARCH: {
569 auto no_restart = []() {
return false; };
573 case SatParameters::HINT_SEARCH: {
578 auto no_restart = []() {
return false; };
582 case SatParameters::PORTFOLIO_SEARCH: {
594 case SatParameters::LP_SEARCH: {
595 std::vector<std::function<LiteralIndex()>> lp_heuristics;
596 for (
const auto&
ct :
598 lp_heuristics.push_back(
ct->LPReducedCostAverageBranching());
600 if (lp_heuristics.empty()) {
613 case SatParameters::PSEUDO_COST_SEARCH: {
614 std::function<LiteralIndex()> search =
622 case SatParameters::PORTFOLIO_WITH_QUICK_RESTART_SEARCH: {
634 const std::vector<std::function<LiteralIndex()>>& input_heuristics,
636 std::vector<std::function<LiteralIndex()>> heuristics = input_heuristics;
638 heuristics.insert(heuristics.end(), extra_heuristics->begin(),
639 extra_heuristics->end());
644 const std::vector<std::function<LiteralIndex()>>& incomplete_heuristics,
645 const std::function<LiteralIndex()>& completion_heuristic) {
646 std::vector<std::function<LiteralIndex()>> complete_heuristics;
647 complete_heuristics.reserve(incomplete_heuristics.size());
648 for (
const auto& incomplete : incomplete_heuristics) {
649 complete_heuristics.push_back(
652 return complete_heuristics;
661 CHECK_NE(num_policies, 0);
668 if (objective !=
nullptr) objective_var = objective->
objective_var;
692 const SatParameters& sat_parameters = *(
model->GetOrCreate<SatParameters>());
696 const int64 conflict_limit = sat_parameters.max_number_of_conflicts();
697 int64 num_decisions_since_last_lp_record_ = 0;
698 int64 num_decisions_without_probing = 0;
700 (sat_solver->
num_failures() - old_num_conflicts < conflict_limit)) {
710 if (!implied_bounds->EnqueueNewDeductions()) {
714 auto* level_zero_callbacks =
716 for (
const auto& cb : level_zero_callbacks->callbacks) {
722 if (sat_parameters.use_sat_inprocessing() &&
730 if (integer_trail->InPropagationLoop()) {
731 const IntegerVariable
var =
732 integer_trail->NextVariableToBranchOnInPropagationLoop();
741 integer_trail->CurrentBranchHadAnIncompletePropagation()) {
742 const IntegerVariable
var = integer_trail->FirstUnassignedVariable();
755 VLOG(1) <<
"Trying to take a decision that is already assigned!"
756 <<
" Fix this. Continuing for now...";
762 sat_parameters.probing_period_at_root() > 0 &&
763 ++num_decisions_without_probing >=
764 sat_parameters.probing_period_at_root()) {
765 num_decisions_without_probing = 0;
785 const std::vector<PseudoCosts::VariableBoundChange> bound_changes =
790 current_obj_lb = integer_trail->LowerBound(objective_var);
791 current_obj_ub = integer_trail->UpperBound(objective_var);
806 if (
model->GetOrCreate<SatParameters>()->use_optimization_hints()) {
808 const auto& trail = *
model->GetOrCreate<
Trail>();
809 for (
int i = 0; i < trail.Index(); ++i) {
810 sat_decision->SetAssignmentPreference(trail[i], 0.0);
823 implied_bounds->ProcessIntegerTrail(
Literal(decision));
829 const IntegerValue new_obj_lb = integer_trail->LowerBound(objective_var);
830 const IntegerValue new_obj_ub = integer_trail->UpperBound(objective_var);
831 const IntegerValue objective_bound_change =
832 (new_obj_lb - current_obj_lb) + (current_obj_ub - new_obj_ub);
833 pseudo_costs->
UpdateCost(bound_changes, objective_bound_change);
841 num_decisions_since_last_lp_record_++;
845 if (num_decisions_since_last_lp_record_ >= 100) {
850 num_decisions_since_last_lp_record_ = 0;
854 return SatSolver::Status::LIMIT_REACHED;
858 const std::vector<Literal>& assumptions,
Model*
model) {
864 for (
const auto& cb : level_zero_callbacks->callbacks) {
876 const IntegerVariable num_vars =
878 std::vector<IntegerVariable> all_variables;
879 for (IntegerVariable
var(0);
var < num_vars; ++
var) {
880 all_variables.push_back(
var);