30#if !defined(__PORTABLE_PLATFORM__)
34#include "absl/cleanup/cleanup.h"
35#include "absl/container/flat_hash_set.h"
36#include "absl/flags/flag.h"
37#include "absl/log/check.h"
38#include "absl/log/log.h"
39#include "absl/log/vlog_is_on.h"
40#include "absl/strings/escaping.h"
41#include "absl/strings/str_cat.h"
42#include "absl/strings/string_view.h"
43#include "absl/time/time.h"
44#include "absl/types/span.h"
45#include "google/protobuf/arena.h"
84#if !defined(__PORTABLE_PLATFORM__)
92 std::string, cp_model_load_debug_solution,
"",
93 "DEBUG ONLY. When this is set to a non-empty file name, "
94 "we will interpret this as an internal solution which can be used for "
95 "debugging. For instance we use it to identify wrong cuts/reasons.");
104#if !defined(__PORTABLE_PLATFORM__)
105 if (absl::GetFlag(FLAGS_cp_model_load_debug_solution).empty())
return;
109 "Reading debug solution from '",
110 absl::GetFlag(FLAGS_cp_model_load_debug_solution),
"'.");
126 if (shared_response ==
nullptr)
return;
127 if (shared_response->DebugSolution().empty())
return;
131 debug_sol.
proto_values = shared_response->DebugSolution();
134 const int num_integers =
139 std::vector<Literal> boolean_solution;
143 if (mapping.IsBoolean(
i)) {
148 boolean_solution.push_back(l);
151 if (!mapping.IsInteger(
i))
continue;
152 const IntegerVariable var = mapping.Integer(
i);
162 if (boolean_solution.size() == debug_sol.
proto_values.size() &&
164 LOG(INFO) <<
"Loaded pure Boolean debugging solution.";
171 if (objective_def !=
nullptr) {
172 const IntegerVariable objective_var = objective_def->objective_var;
173 const int64_t objective_value =
177 debug_sol.
ivar_values[objective_var] = objective_value;
183 const auto checker = [mapping, encoder, debug_sol, model](
184 absl::Span<const Literal> clause,
185 absl::Span<const IntegerLiteral> integers) {
186 bool is_satisfied =
false;
189 std::vector<std::tuple<Literal, IntegerLiteral, int>> to_print;
190 for (
const Literal l : clause) {
193 const int proto_var =
194 mapping.GetProtoVariableFromBooleanVariable(l.Variable());
195 if (proto_var != -1) {
197 if (debug_sol.
proto_values[proto_var] == (l.IsPositive() ? 1 : 0)) {
208 bool all_true =
true;
209 for (
const IntegerLiteral associated : encoder->GetIntegerLiterals(l)) {
210 const int proto_var = mapping.GetProtoVariableFromIntegerVariable(
212 if (proto_var == -1)
break;
214 to_print.push_back({l, associated, proto_var});
217 if (value < associated.bound) {
229 const int proto_var = mapping.GetProtoVariableFromIntegerVariable(
231 if (proto_var == -1) {
242 if (value >= i_lit.bound) {
248 LOG(INFO) <<
"Reason clause is not satisfied by loaded solution:";
249 LOG(INFO) <<
"Worker '" << model->
Name() <<
"', level="
251 LOG(INFO) <<
"literals (neg): " << clause;
252 LOG(INFO) <<
"integer literals: " << integers;
253 for (
const auto [l, i_lit, proto_var] : to_print) {
254 LOG(INFO) << l <<
" " << i_lit <<
" var=" << proto_var
255 <<
" value_in_sol=" << debug_sol.
proto_values[proto_var];
260 const auto lit_checker = [checker](absl::Span<const Literal> clause) {
261 return checker(clause, {});
269 const Model& model) {
275 if (mapping->IsInteger(
i)) {
276 const IntegerVariable var = mapping->Integer(
i);
282 DCHECK(mapping->IsBoolean(
i));
284 if (trail->Assignment().LiteralIsAssigned(literal)) {
297IntegerVariable GetOrCreateVariableWithTightBound(
298 absl::Span<
const std::pair<IntegerVariable, int64_t>> terms,
Model* model) {
300 if (terms.size() == 1 && terms.front().second == 1) {
301 return terms.front().first;
303 if (terms.size() == 1 && terms.front().second == -1) {
309 for (
const std::pair<IntegerVariable, int64_t>& var_coeff : terms) {
310 const int64_t min_domain = model->Get(
LowerBound(var_coeff.first));
311 const int64_t max_domain = model->Get(
UpperBound(var_coeff.first));
312 const int64_t coeff = var_coeff.second;
313 const int64_t prod1 = min_domain * coeff;
314 const int64_t prod2 = max_domain * coeff;
315 sum_min += std::min(prod1, prod2);
316 sum_max += std::max(prod1, prod2);
321IntegerVariable GetOrCreateVariableLinkedToSumOf(
322 absl::Span<
const std::pair<IntegerVariable, int64_t>> terms,
323 bool lb_required,
bool ub_required,
Model* model) {
325 if (terms.size() == 1 && terms.front().second == 1) {
326 return terms.front().first;
328 if (terms.size() == 1 && terms.front().second == -1) {
332 const IntegerVariable new_var =
333 GetOrCreateVariableWithTightBound(terms, model);
336 std::vector<IntegerVariable> vars;
337 std::vector<int64_t> coeffs;
338 for (
const auto [var, coeff] : terms) {
340 coeffs.push_back(coeff);
342 vars.push_back(new_var);
343 coeffs.push_back(-1);
367void InitializeLinearConstraintSymmetrizerIfRequested(
370 if (!model_proto.has_symmetry())
return;
373 if (params->linearization_level() < 2)
return;
374 if (!params->use_symmetry_in_lp())
return;
386 int num_constraints_with_non_proto_variables = 0;
387 for (
const auto& lp_constraint : linear_relaxation.linear_constraints) {
388 bool has_non_proto_variable =
false;
389 for (
const IntegerVariable var : lp_constraint.VarsAsSpan()) {
390 if (mapping->GetProtoVariableFromIntegerVariable(var) == -1) {
391 has_non_proto_variable =
true;
395 if (has_non_proto_variable) {
396 ++num_constraints_with_non_proto_variables;
399 if (num_constraints_with_non_proto_variables > 0) {
402 auto* logger = m->GetOrCreate<SolverLogger>();
403 SOLVER_LOG(logger, num_constraints_with_non_proto_variables,
404 " LP constraints uses new variables not appearing in the "
405 "presolved model. ");
414 const int num_vars = model_proto.variables().size();
415 std::vector<std::unique_ptr<SparsePermutation>> generators;
417 model_proto.symmetry().permutations()) {
422 const std::vector<int> var_to_orbit_index =
GetOrbits(num_vars, generators);
423 std::vector<bool> orbit_is_ok;
424 std::vector<std::vector<IntegerVariable>> orbits;
425 for (
int proto_var = 0; proto_var < num_vars; ++proto_var) {
426 const int orbit_index = var_to_orbit_index[proto_var];
427 if (orbit_index == -1)
continue;
428 if (orbit_index >= orbits.size()) {
429 orbits.resize(orbit_index + 1);
430 orbit_is_ok.resize(orbit_index + 1,
true);
435 const IntegerVariable var = mapping->Integer(proto_var);
437 orbits[orbit_index].push_back(var);
442 std::vector<std::pair<IntegerVariable, int64_t>> terms;
443 for (
const std::vector<IntegerVariable>& orbit : orbits) {
445 for (
const IntegerVariable var : orbit) {
446 terms.push_back({var, 1});
448 const IntegerVariable sum_var =
449 GetOrCreateVariableLinkedToSumOf(terms,
true,
true, m);
450 symmetrizer->AddSymmetryOrbit(sum_var, orbit);
455IntegerVariable AddLPConstraints(
bool objective_need_to_be_tight,
462 InitializeLinearConstraintSymmetrizerIfRequested(model_proto, relaxation, m);
470 const int num_lp_constraints =
471 static_cast<int>(relaxation.linear_constraints.size());
472 const int num_lp_cut_generators =
473 static_cast<int>(relaxation.cut_generators.size());
474 const int num_integer_variables =
475 m->GetOrCreate<
IntegerTrail>()->NumIntegerVariables().value();
477 DenseConnectedComponentsFinder components;
479 num_integer_variables);
480 auto get_constraint_index = [](
int ct_index) {
return ct_index; };
481 auto get_cut_generator_index = [num_lp_constraints](
int cut_index) {
482 return num_lp_constraints + cut_index;
484 auto get_var_index = [num_lp_constraints,
485 num_lp_cut_generators](IntegerVariable var) {
486 return num_lp_constraints + num_lp_cut_generators +
489 for (
int i = 0;
i < num_lp_constraints;
i++) {
490 for (
const IntegerVariable var :
491 relaxation.linear_constraints[
i].VarsAsSpan()) {
492 components.
AddEdge(get_constraint_index(
i), get_var_index(var));
495 for (
int i = 0;
i < num_lp_cut_generators; ++
i) {
496 for (
const IntegerVariable var : relaxation.cut_generators[
i].vars) {
497 components.
AddEdge(get_cut_generator_index(
i), get_var_index(var));
503 for (
int i = 0;
i < symmetrizer->NumOrbits(); ++
i) {
504 const int representative = get_var_index(symmetrizer->OrbitSumVar(
i));
505 for (
const IntegerVariable var : symmetrizer->Orbit(
i)) {
506 components.
AddEdge(representative, get_var_index(var));
511 std::vector<int> component_sizes(num_components, 0);
512 const std::vector<int> index_to_component = components.
GetComponentIds();
513 for (
int i = 0;
i < num_lp_constraints;
i++) {
514 ++component_sizes[index_to_component[get_constraint_index(
i)]];
516 for (
int i = 0;
i < num_lp_cut_generators;
i++) {
517 ++component_sizes[index_to_component[get_cut_generator_index(
i)]];
521 std::vector<std::vector<IntegerVariable>> component_to_var(num_components);
522 for (IntegerVariable var(0); var < num_integer_variables; var += 2) {
524 component_to_var[index_to_component[get_var_index(var)]].push_back(var);
533 for (
int i = 0;
i < model_proto.objective().coeffs_size(); ++
i) {
534 const IntegerVariable var =
535 mapping->Integer(model_proto.objective().vars(
i));
536 ++component_sizes[index_to_component[get_var_index(var)]];
540 std::vector<LinearProgrammingConstraint*> lp_constraints(num_components,
542 for (
int i = 0;
i < num_lp_constraints;
i++) {
543 const int c = index_to_component[get_constraint_index(
i)];
544 if (component_sizes[c] <= 1)
continue;
545 if (lp_constraints[c] ==
nullptr) {
548 m->TakeOwnership(lp_constraints[c]);
551 if (!lp_constraints[c]->AddLinearConstraint(
552 std::move(relaxation.linear_constraints[
i]))) {
553 m->GetOrCreate<
SatSolver>()->NotifyThatModelIsUnsat();
559 for (
int i = 0;
i < num_lp_cut_generators;
i++) {
560 const int c = index_to_component[get_cut_generator_index(
i)];
561 if (lp_constraints[c] ==
nullptr) {
564 m->TakeOwnership(lp_constraints[c]);
566 lp_constraints[
c]->AddCutGenerator(std::move(relaxation.cut_generators[
i]));
572 if (params->linearization_level() > 1 && params->add_clique_cuts() &&
573 params->cut_level() > 0) {
575 if (lp ==
nullptr)
continue;
581 std::vector<std::vector<std::pair<IntegerVariable, int64_t>>>
582 component_to_cp_terms(num_components);
583 std::vector<std::pair<IntegerVariable, int64_t>> top_level_cp_terms;
584 int num_components_containing_objective = 0;
585 if (model_proto.has_objective()) {
589 std::vector<std::pair<IntegerVariable, int64_t>> objective;
590 const int num_orbits = symmetrizer->NumOrbits();
591 if (num_orbits > 0) {
593 std::vector<int64_t> orbit_obj_coeff(num_orbits, 0);
594 for (
int i = 0;
i < model_proto.objective().coeffs_size(); ++
i) {
595 const IntegerVariable var =
596 mapping->Integer(model_proto.objective().vars(
i));
597 const int64_t coeff = model_proto.objective().coeffs(
i);
598 const int orbit_index = symmetrizer->OrbitIndex(var);
599 if (orbit_index != -1) {
600 if (orbit_obj_coeff[orbit_index] == 0) {
601 orbit_obj_coeff[orbit_index] = coeff;
603 CHECK_EQ(orbit_obj_coeff[orbit_index], coeff);
607 objective.push_back({var, coeff});
609 for (
int i = 0;
i < num_orbits; ++
i) {
610 if (orbit_obj_coeff[
i] == 0)
continue;
611 objective.push_back({symmetrizer->OrbitSumVar(
i), orbit_obj_coeff[
i]});
614 for (
int i = 0;
i < model_proto.objective().coeffs_size(); ++
i) {
615 const IntegerVariable var =
616 mapping->Integer(model_proto.objective().vars(
i));
617 const int64_t coeff = model_proto.objective().coeffs(
i);
618 objective.push_back({var, coeff});
624 for (
const auto [var, coeff] : objective) {
625 const int c = index_to_component[get_var_index(var)];
626 if (lp_constraints[c] !=
nullptr) {
627 lp_constraints[
c]->SetObjectiveCoefficient(var, IntegerValue(coeff));
628 component_to_cp_terms[
c].push_back(std::make_pair(var, coeff));
631 top_level_cp_terms.push_back(std::make_pair(var, coeff));
635 for (
int c = 0;
c < num_components; ++
c) {
636 if (component_to_cp_terms[c].empty())
continue;
637 const IntegerVariable sub_obj_var = GetOrCreateVariableLinkedToSumOf(
638 component_to_cp_terms[c], objective_need_to_be_tight,
true, m);
639 top_level_cp_terms.push_back(std::make_pair(sub_obj_var, 1));
640 lp_constraints[
c]->SetMainObjectiveVariable(sub_obj_var);
641 num_components_containing_objective++;
645 const IntegerVariable main_objective_var =
646 model_proto.has_objective()
647 ? GetOrCreateVariableLinkedToSumOf(
648 top_level_cp_terms, objective_need_to_be_tight,
true, m)
654 if (lp_constraint ==
nullptr)
continue;
655 lp_constraint->RegisterWith(m);
656 VLOG(3) <<
"LP constraint: " << lp_constraint->DimensionString() <<
".";
659 VLOG(3) << top_level_cp_terms.size()
660 <<
" terms in the main objective linear equation ("
661 << num_components_containing_objective <<
" from LP constraints).";
662 return main_objective_var;
672 CHECK(shared_bounds_manager !=
nullptr);
678 int saved_trail_index = 0;
679 std::vector<int> model_variables;
680 std::vector<int64_t> new_lower_bounds;
681 std::vector<int64_t> new_upper_bounds;
682 absl::flat_hash_set<int> visited_variables;
683 const std::string name = model->
Name();
685 auto broadcast_level_zero_bounds =
686 [=](absl::Span<const IntegerVariable> modified_vars)
mutable {
688 for (
const IntegerVariable& var : modified_vars) {
690 const int model_var =
691 mapping->GetProtoVariableFromIntegerVariable(positive_var);
693 if (model_var == -1)
continue;
694 const auto [_, inserted] = visited_variables.insert(model_var);
695 if (!inserted)
continue;
697 const int64_t new_lb =
698 integer_trail->LevelZeroLowerBound(positive_var).value();
699 const int64_t new_ub =
700 integer_trail->LevelZeroUpperBound(positive_var).value();
704 model_variables.push_back(model_var);
705 new_lower_bounds.push_back(new_lb);
706 new_upper_bounds.push_back(new_ub);
710 for (; saved_trail_index < trail->Index(); ++saved_trail_index) {
711 const Literal fixed_literal = (*trail)[saved_trail_index];
712 const int model_var = mapping->GetProtoVariableFromBooleanVariable(
715 if (model_var == -1)
continue;
716 const auto [_, inserted] = visited_variables.insert(model_var);
717 if (!inserted)
continue;
719 model_variables.push_back(model_var);
721 new_lower_bounds.push_back(1);
722 new_upper_bounds.push_back(1);
724 new_lower_bounds.push_back(0);
725 new_upper_bounds.push_back(0);
729 if (!model_variables.empty()) {
731 model->
Name(), model_variables, new_lower_bounds,
735 model_variables.clear();
736 new_lower_bounds.clear();
737 new_upper_bounds.clear();
738 visited_variables.clear();
754 const IntegerVariable num_vars =
756 std::vector<IntegerVariable> all_variables;
757 all_variables.reserve(num_vars.value());
758 for (IntegerVariable var(0); var < num_vars; ++var) {
759 all_variables.push_back(var);
761 broadcast_level_zero_bounds(all_variables);
764 ->RegisterLevelZeroModifiedVariablesCallback(broadcast_level_zero_bounds);
773 CHECK(shared_bounds_manager !=
nullptr);
774 const std::string name = model->
Name();
781 const auto& import_level_zero_bounds = [&model_proto, shared_bounds_manager,
782 name, sat_solver, integer_trail,
783 trail, id, mapping]() {
784 std::vector<int> model_variables;
785 std::vector<int64_t> new_lower_bounds;
786 std::vector<int64_t> new_upper_bounds;
788 id, &model_variables, &new_lower_bounds, &new_upper_bounds);
789 for (
int i = 0;
i < model_variables.size(); ++
i) {
790 const int model_var = model_variables[
i];
795 if (mapping->IsBoolean(model_var)) {
796 Literal lit = mapping->Literal(model_var);
797 if (new_upper_bounds[
i] == 0) lit = lit.
Negated();
798 if (trail->Assignment().LiteralIsTrue(lit))
continue;
799 if (trail->Assignment().LiteralIsFalse(lit)) {
800 sat_solver->NotifyThatModelIsUnsat();
803 trail->EnqueueWithUnitReason(lit);
808 if (!mapping->IsInteger(model_var))
continue;
809 const IntegerVariable var = mapping->Integer(model_var);
810 const IntegerValue new_lb(new_lower_bounds[
i]);
811 const IntegerValue new_ub(new_upper_bounds[
i]);
812 const IntegerValue old_lb = integer_trail->LowerBound(var);
813 const IntegerValue old_ub = integer_trail->UpperBound(var);
814 const bool changed_lb = new_lb > old_lb;
815 const bool changed_ub = new_ub < old_ub;
816 if (!changed_lb && !changed_ub)
continue;
821 const std::string& var_name =
822 var_proto.
name().empty()
823 ? absl::StrCat(
"anonymous_var(", model_var,
")")
825 LOG(INFO) <<
" '" << name <<
"' imports new bounds for " << var_name
826 <<
": from [" << old_lb <<
", " << old_ub <<
"] to ["
827 << new_lb <<
", " << new_ub <<
"]";
847 import_level_zero_bounds);
853 IntegerVariable objective_var,
856 const auto broadcast_objective_lower_bound =
857 [objective_var, integer_trail, shared_response_manager, model,
860 const IntegerValue objective_lb =
861 integer_trail->LevelZeroLowerBound(objective_var);
862 if (objective_lb > best_obj_lb) {
863 best_obj_lb = objective_lb;
865 model->
Name(), objective_lb,
866 integer_trail->LevelZeroUpperBound(objective_var));
874 ->RegisterLevelZeroModifiedVariablesCallback(
875 broadcast_objective_lower_bound);
886 const std::string name = model->
Name();
887 const auto import_objective_bounds = [name, solver, integer_trail, objective,
888 shared_response_manager]() {
889 if (solver->AssumptionLevel() != 0)
return true;
890 bool tighter_bounds =
false;
892 const IntegerValue external_lb =
894 const IntegerValue current_lb =
895 integer_trail->LowerBound(objective->objective_var);
896 if (external_lb > current_lb) {
898 objective->objective_var, external_lb),
902 tighter_bounds =
true;
905 const IntegerValue external_ub =
907 const IntegerValue current_ub =
908 integer_trail->UpperBound(objective->objective_var);
909 if (external_ub < current_ub) {
911 objective->objective_var, external_ub),
915 tighter_bounds =
true;
920 if (tighter_bounds) {
921 VLOG(3) <<
"'" << name <<
"' imports objective bounds: external ["
922 << objective->ScaleIntegerObjective(external_lb) <<
", "
923 << objective->ScaleIntegerObjective(external_ub) <<
"], current ["
924 << objective->ScaleIntegerObjective(current_lb) <<
", "
925 << objective->ScaleIntegerObjective(current_ub) <<
"]";
932 import_objective_bounds);
939 const auto& share_binary_clause = [mapping, id, shared_clauses_manager](
942 mapping->GetProtoVariableFromBooleanVariable(l1.Variable());
943 if (var1 == -1)
return;
945 mapping->GetProtoVariableFromBooleanVariable(l2.Variable());
946 if (var2 == -1)
return;
947 const int lit1 = l1.IsPositive() ? var1 :
NegatedRef(var1);
948 const int lit2 = l2.IsPositive() ? var2 :
NegatedRef(var2);
952 share_binary_clause);
956 const double share_interval =
960 auto share_clause = [mapping, clause_stream,
time_limit, id,
961 shared_clauses_manager, share_interval,
962 next_batch_dtime = -1.0, clause = std::vector<int>()](
963 int lbd, absl::Span<const Literal> literals)
mutable {
967 for (
const Literal& lit : literals) {
969 mapping->GetProtoVariableFromBooleanVariable(lit.Variable());
970 if (var == -1)
return;
971 clause.push_back(lit.IsPositive() ? var :
NegatedRef(var));
973 clause_stream->Add(clause, lbd);
975 const double elapsed_dtime =
time_limit->GetElapsedDeterministicTime();
976 if (next_batch_dtime < 0) next_batch_dtime = elapsed_dtime + share_interval;
977 if (elapsed_dtime >= next_batch_dtime) {
978 shared_clauses_manager->
AddBatch(
id, clause_stream->NextBatch());
979 next_batch_dtime = elapsed_dtime + share_interval;
983 std::move(share_clause));
995 CHECK(shared_clauses_manager !=
nullptr);
999 const bool share_glue_clauses =
1001 auto* clause_stream =
1003 const bool minimize_shared_clauses =
1006 const auto& import_level_zero_clauses = [shared_clauses_manager, id, mapping,
1007 sat_solver, implications,
1008 minimize_shared_clauses,
1010 clause_manager]()
mutable {
1011 std::vector<std::pair<int, int>> new_binary_clauses;
1013 implications->EnableSharing(
false);
1014 for (
const auto& [ref1, ref2] : new_binary_clauses) {
1017 if (!sat_solver->AddProblemClause({l1, l2})) {
1021 implications->EnableSharing(
true);
1022 if (clause_stream ==
nullptr)
return true;
1024 int new_clauses = 0;
1025 std::array<Literal, UniqueClauseStream::kMaxClauseSize> local_clause;
1026 sat_solver->EnsureNewClauseIndexInitialized();
1028 auto callback = clause_manager->TakeAddClauseCallback();
1031 if (batch.empty())
break;
1032 for (
int clause_index = 0; clause_index < batch.size(); ++clause_index) {
1033 const absl::Span<const int>& shared_clause = batch[clause_index];
1035 if (!clause_stream->BlockClause(shared_clause))
continue;
1037 for (
int i = 0;
i < shared_clause.size(); ++
i) {
1038 local_clause[
i] = mapping->
Literal(shared_clause[
i]);
1040 if (!sat_solver->AddProblemClause(
1041 absl::MakeSpan(local_clause)
1042 .subspan(0, shared_clause.size()))) {
1047 clause_manager->SetAddClauseCallback(std::move(callback));
1048 if (minimize_shared_clauses && new_clauses > 0) {
1054 return sat_solver->MinimizeByPropagation(
1060 import_level_zero_clauses);
1070void FillBinaryRelationRepository(
const CpModelProto& model_proto,
1072 auto* integer_trail = model->GetOrCreate<IntegerTrail>();
1073 auto* encoder = model->GetOrCreate<IntegerEncoder>();
1074 auto* mapping = model->GetOrCreate<CpModelMapping>();
1075 auto* repository = model->GetOrCreate<BinaryRelationRepository>();
1076 auto* relations_maps = model->GetOrCreate<BinaryRelationsMaps>();
1078 for (
const ConstraintProto& ct : model_proto.constraints()) {
1083 if (ct.enforcement_literal().size() == 2 && ct.linear().vars_size() == 1) {
1086 auto process = [&](Literal enforcement_literal, IntegerVariable var1,
1087 const Domain& var1_domain, Literal lit2,
1088 int64_t implied_lb) {
1089 const int64_t delta = implied_lb - var1_domain.Min();
1090 if (delta <= 0)
return;
1091 const IntegerVariable var2 = encoder->GetLiteralView(lit2);
1092 const IntegerVariable negated_var2 =
1093 encoder->GetLiteralView(lit2.Negated());
1098 repository->Add(enforcement_literal, {var1, 1}, {var2, -delta},
1099 var1_domain.Min(), var1_domain.Max());
1104 repository->Add(enforcement_literal, {var1, 1}, {negated_var2, delta},
1105 var1_domain.Min() + delta, var1_domain.Max() + delta);
1108 const IntegerVariable var = mapping->Integer(ct.linear().vars(0));
1110 model_proto.variables(ct.linear().vars(0));
1112 const Domain implied_var_domain =
1115 for (
int i = 0;
i < 2; ++
i) {
1118 process(lit1, var, var_domain, lit2, implied_var_domain.
Min());
1119 process(lit1,
NegationOf(var), var_domain.Negation(), lit2,
1120 -implied_var_domain.
Max());
1123 }
else if (ct.enforcement_literal().size() > 1 ||
1124 ct.linear().vars_size() > 2) {
1127 const std::vector<IntegerVariable> vars =
1128 mapping->Integers(ct.linear().vars());
1129 absl::Span<const int64_t> coeffs = ct.linear().coeffs();
1131 const auto [min_sum, max_sum] =
1132 mapping->ComputeMinMaxActivity(ct.linear(), integer_trail);
1134 const int64_t rhs_min = std::max(ct.linear().domain(0), min_sum);
1135 const int64_t rhs_max =
1136 std::min(ct.linear().domain(ct.linear().domain().size() - 1), max_sum);
1138 if (ct.enforcement_literal().empty()) {
1139 if (vars.size() == 2) {
1141 {vars[1], coeffs[1]}, rhs_min, rhs_max);
1144 expr.
vars[0] = vars[0];
1145 expr.vars[1] = vars[1];
1146 expr.coeffs[0] = coeffs[0];
1147 expr.coeffs[1] = coeffs[1];
1148 relations_maps->AddRelationBounds(expr, rhs_min, rhs_max);
1152 if (vars.size() == 1) {
1153 repository->Add(lit, {vars[0], coeffs[0]}, {}, rhs_min, rhs_max);
1154 }
else if (vars.size() == 2) {
1155 repository->Add(lit, {vars[0], coeffs[0]}, {vars[1], coeffs[1]},
1160 repository->Build();
1167 CHECK(shared_response_manager !=
nullptr);
1171 const auto unsat = [shared_response_manager, sat_solver, model] {
1172 sat_solver->NotifyThatModelIsUnsat();
1173 shared_response_manager->NotifyThatImprovingProblemIsInfeasible(
1174 absl::StrCat(model->
Name(),
" [loading]"));
1182 const bool view_all_booleans_as_integers =
1183 (parameters.linearization_level() >= 2) ||
1187 LoadVariables(model_proto, view_all_booleans_as_integers, model);
1199 if (!parameters.optimize_with_core() && parameters.symmetry_level() > 1 &&
1200 !parameters.enumerate_all_solutions() &&
1201 parameters.linearization_level() == 0) {
1213 if (sat_solver->ModelIsUnsat())
return unsat();
1217 if (sat_solver->ModelIsUnsat())
return unsat();
1223 FillBinaryRelationRepository(model_proto, model);
1228 int num_ignored_constraints = 0;
1231 absl::flat_hash_set<ConstraintProto::ConstraintCase> unsupported_types;
1233 if (mapping->ConstraintIsAlreadyLoaded(&ct)) {
1234 ++num_ignored_constraints;
1239 unsupported_types.insert(ct.constraint_case());
1251 if (sat_solver->FinishPropagation()) {
1253 const int old_num_fixed = trail->
Index();
1254 if (trail->
Index() > old_num_fixed) {
1255 VLOG(3) <<
"Constraint fixed " << trail->
Index() - old_num_fixed
1260 if (sat_solver->ModelIsUnsat()) {
1261 VLOG(2) <<
"UNSAT during extraction (after adding '"
1267 if (num_ignored_constraints > 0) {
1268 VLOG(3) << num_ignored_constraints <<
" constraints were skipped.";
1270 if (!unsupported_types.empty()) {
1273 "There is unsupported constraints types in this model: ");
1274 std::vector<absl::string_view> names;
1278 std::sort(names.begin(), names.end());
1279 for (
const absl::string_view name : names) {
1285 SOLVER_LOG(logger,
"BUG: We will wrongly report INFEASIBLE now.");
1290 ->AddAllImplicationsBetweenAssociatedLiterals();
1291 if (!sat_solver->FinishPropagation())
return unsat();
1305 if (parameters.linearization_level() == 0)
return;
1312 const int num_lp_constraints =
1314 if (num_lp_constraints == 0)
return;
1316 for (
int i = 0;
i < num_lp_constraints;
i++) {
1321 for (
int i = 0;
i < model_proto.
objective().coeffs_size(); ++
i) {
1322 const IntegerVariable var =
1325 feasibility_pump->SetObjectiveCoefficient(var, IntegerValue(coeff));
1345 const auto unsat = [shared_response_manager, sat_solver, model] {
1346 sat_solver->NotifyThatModelIsUnsat();
1347 shared_response_manager->NotifyThatImprovingProblemIsInfeasible(
1348 absl::StrCat(model->
Name(),
" [loading]"));
1358 if (parameters.auto_detect_greater_than_at_least_one_of()) {
1360 ->AddGreaterThanAtLeastOneOfConstraints(model);
1361 if (!sat_solver->FinishPropagation())
return unsat();
1371 if (parameters.cp_model_probing_level() > 1) {
1381 if (sat_solver->ModelIsUnsat())
return unsat();
1388 if (repository !=
nullptr) {
1394 bool objective_need_to_be_tight =
false;
1397 int64_t min_value = 0;
1398 int64_t max_value = 0;
1401 for (
int i = 0;
i < obj.vars_size(); ++
i) {
1402 const int64_t coeff = obj.coeffs(
i);
1403 const IntegerVariable var = mapping->Integer(obj.vars(
i));
1405 min_value += coeff * integer_trail->LowerBound(var).value();
1406 max_value += coeff * integer_trail->UpperBound(var).value();
1408 min_value += coeff * integer_trail->UpperBound(var).value();
1409 max_value += coeff * integer_trail->LowerBound(var).value();
1413 const Domain automatic_domain =
Domain(min_value, max_value);
1414 objective_need_to_be_tight = !automatic_domain.
IsIncludedIn(user_domain);
1420 if (parameters.linearization_level() > 0) {
1423 AddLPConstraints(objective_need_to_be_tight, model_proto, model);
1424 if (sat_solver->ModelIsUnsat())
return unsat();
1427 std::vector<std::pair<IntegerVariable, int64_t>> terms;
1431 std::make_pair(mapping->Integer(obj.
vars(
i)), obj.
coeffs(
i)));
1433 if (parameters.optimize_with_core()) {
1434 if (objective_need_to_be_tight) {
1444 GetOrCreateVariableLinkedToSumOf(terms,
true,
false, model);
1446 objective_var = GetOrCreateVariableWithTightBound(terms, model);
1449 objective_var = GetOrCreateVariableLinkedToSumOf(
1450 terms, objective_need_to_be_tight,
true, model);
1461 if (objective_definition->scaling_factor == 0.0) {
1462 objective_definition->scaling_factor = 1.0;
1464 objective_definition->offset = objective_proto.
offset();
1465 objective_definition->objective_var = objective_var;
1467 const int size = objective_proto.
vars_size();
1468 objective_definition->vars.resize(size);
1469 objective_definition->coeffs.resize(size);
1470 for (
int i = 0;
i < objective_proto.
vars_size(); ++
i) {
1473 objective_definition->vars[
i] = mapping->Integer(objective_proto.
vars(
i));
1474 objective_definition->coeffs[
i] = IntegerValue(objective_proto.
coeffs(
i));
1477 const int ref = objective_proto.
vars(
i);
1478 if (mapping->IsInteger(ref)) {
1479 const IntegerVariable var = mapping->Integer(objective_proto.
vars(
i));
1480 objective_definition->objective_impacting_variables.insert(
1488 objective_definition->coeffs, model));
1495 const Domain automatic_domain =
1496 integer_trail->InitialVariableDomain(objective_var);
1499 VLOG(3) <<
"Automatic internal objective domain: " << automatic_domain;
1500 VLOG(3) <<
"User specified internal objective domain: " << user_domain;
1502 if (!integer_trail->UpdateInitialDomain(objective_var, user_domain)) {
1503 VLOG(2) <<
"UNSAT due to the objective domain.";
1511 "Initial num_bool: ", sat_solver->NumVariables());
1512 if (!sat_solver->FinishPropagation())
return unsat();
1517 shared_response_manager->UpdateInnerObjectiveBounds(
1518 absl::StrCat(model->
Name(),
" (initial_propagation)"),
1519 integer_trail->LowerBound(objective_var),
1520 integer_trail->UpperBound(objective_var));
1538 search_heuristics->heuristic_search =
1540 search_heuristics->integer_completion_search =
1542 objective_var, model);
1544 search_heuristics->user_search, search_heuristics->heuristic_search,
1545 search_heuristics->integer_completion_search);
1546 if (VLOG_IS_ON(3)) {
1547 search_heuristics->fixed_search =
1549 search_heuristics->fixed_search, model);
1551 search_heuristics->hint_search =
1555 if (parameters.optimize_with_core()) {
1558 const auto solution_observer = [&model_proto, model,
1559 shared_response_manager,
1561 const std::vector<int64_t>
solution =
1563 const IntegerValue obj_ub =
1565 if (obj_ub < best_obj_ub) {
1566 best_obj_ub = obj_ub;
1567 shared_response_manager->NewSolution(
solution, model->Name(), model);
1572 if (parameters.optimize_with_max_hs()) {
1574 model_proto, objective, solution_observer, model);
1576 model->TakeOwnership(max_hs);
1580 objective.coeffs, solution_observer, model);
1582 model->TakeOwnership(core);
1597 if (shared_response_manager->ProblemIsSolved())
return;
1603 auto solution_observer = [&model_proto, model, shared_response_manager,
1605 const std::vector<int64_t>
solution =
1608 const IntegerValue obj_ub =
1610 if (obj_ub < best_obj_ub) {
1611 best_obj_ub = obj_ub;
1612 shared_response_manager->NewSolution(
solution, model->
Name(), model);
1615 shared_response_manager->NewSolution(
solution, model->
Name(), model);
1621 shared_response_manager->NotifyThatImprovingProblemIsInfeasible(
1635 status = prober.
Probe();
1637 shared_response_manager->NotifyThatImprovingProblemIsInfeasible(
1642 solution_observer();
1651 status = subtree_worker->
Search(solution_observer);
1654 mapping.Literals(model_proto.
assumptions()), model);
1657 solution_observer();
1662 shared_response_manager->NotifyThatImprovingProblemIsInfeasible(
1666 shared_response_manager->NotifyThatImprovingProblemIsInfeasible(
1672 std::vector<Literal> core = sat_solver->GetLastIncompatibleDecisions();
1674 std::vector<int> core_in_proto_format;
1675 for (
const Literal l : core) {
1676 core_in_proto_format.push_back(
1677 mapping.GetProtoVariableFromBooleanVariable(l.Variable()));
1678 if (!l.IsPositive()) {
1679 core_in_proto_format.back() =
NegatedRef(core_in_proto_format.back());
1682 shared_response_manager->AddUnsatCore(core_in_proto_format);
1687 const IntegerVariable objective_var = objective.
objective_var;
1692 status = search->
Search(solution_observer);
1703 status = subtree_worker->
Search(solution_observer);
1709 solution_observer, model);
1712 objective_var, solution_observer, model);
1720 shared_response_manager->NotifyThatImprovingProblemIsInfeasible(
1734 if (shared_response_manager->ProblemIsSolved())
return;
1745 if (parameters->optimize_with_core())
return;
1750 parameters->set_optimize_with_core(
false);
1751 parameters->set_use_sat_inprocessing(
false);
1752 auto cleanup = ::absl::MakeCleanup(
1753 [parameters, saved_params]() { *parameters = saved_params; });
1759 mapping.Literals(model_proto.
assumptions()), model);
1761 const std::string& solution_info = model->
Name();
1763 const std::vector<int64_t>
solution =
1765 shared_response_manager->NewSolution(
1766 solution, absl::StrCat(solution_info,
" [hint]"), model);
1769 if (parameters->enumerate_all_solutions()) {
1774 const IntegerVariable objective_var =
1781 shared_response_manager->GetInnerObjectiveUpperBound()),
1783 shared_response_manager->NotifyThatImprovingProblemIsInfeasible(
1784 absl::StrCat(solution_info,
" [hint]"));
1796 if (parameters->debug_crash_on_bad_hint() &&
1797 shared_response_manager->SolutionsRepository().NumSolutions() == 0 &&
1800 LOG(FATAL) <<
"QuickSolveWithHint() didn't find a feasible solution."
1801 <<
" The model name is '" << model_proto.
name() <<
"'."
1802 <<
" Status: " << status <<
".";
1806 shared_response_manager->NotifyThatImprovingProblemIsInfeasible(
1807 absl::StrCat(solution_info,
" [hint]"));
1826 if (shared_response_manager->ProblemIsSolved())
return;
1832 if (parameters->enumerate_all_solutions())
return;
1836 *parameters = saved_params;
1852 const int64_t min_domain = model_proto.
variables(var).
domain(0) - value;
1853 const int64_t max_domain =
1874 const int64_t abs_min_domain = 0;
1875 const int64_t abs_max_domain =
1876 std::max(std::abs(min_domain), std::abs(max_domain));
1881 abs_ct->mutable_target()->add_coeffs(1);
1893 auto* local_response_manager =
1903 mapping.Literals(updated_model_proto.
assumptions()), &local_model);
1905 const std::string& solution_info = model->
Name();
1907 const std::vector<int64_t>
solution =
1910 const std::vector<int64_t> updated_solution =
1912 LOG(INFO) <<
"Found solution with repaired hint penalty = "
1916 shared_response_manager->NewSolution(
1917 solution, absl::StrCat(solution_info,
" [repaired]"), &local_model);
1927 absl::Span<const int> postsolve_mapping,
1943 Model postsolve_model;
1956 const CpSolverResponse postsolve_response = response_manager->GetResponse();
1959 << postsolve_response.
status();
1962 CHECK_LE(num_variables_in_original_model,
1963 postsolve_response.
solution().size());
1965 postsolve_response.
solution().begin(),
1966 postsolve_response.
solution().begin() + num_variables_in_original_model);
1970 int num_variable_in_original_model,
1972 absl::Span<const int> postsolve_mapping,
1976 mapping_proto, postsolve_mapping,
solution);
1988 if (params->num_workers() == 0) {
1989 params->set_num_workers(params->num_search_workers());
1992 if (params->enumerate_all_solutions()) {
1993 if (params->num_workers() >= 1) {
1995 "Forcing sequential search as enumerating all solutions is "
1996 "not supported in multi-thread.");
1998 params->set_num_workers(1);
2003 if (!params->keep_all_feasible_solutions_in_presolve()) {
2005 "Forcing presolve to keep all feasible solution given that "
2006 "enumerate_all_solutions is true");
2008 params->set_keep_all_feasible_solutions_in_presolve(
true);
2012 if (params->num_workers() >= 1) {
2014 "Forcing sequential search as assumptions are not supported "
2015 "in multi-thread.");
2017 if (!params->keep_all_feasible_solutions_in_presolve()) {
2019 "Forcing presolve to keep all feasible solutions in the "
2020 "presence of assumptions.");
2021 params->set_keep_all_feasible_solutions_in_presolve(
true);
2023 params->set_num_workers(1);
2026 if (params->num_workers() == 0) {
2028#if !defined(__PORTABLE_PLATFORM__)
2030 const int num_cores = std::max<int>(std::thread::hardware_concurrency(), 1);
2032 const int num_cores = 1;
2034 SOLVER_LOG(logger,
"Setting number of workers to ", num_cores);
2035 params->set_num_workers(num_cores);
2038 if (params->shared_tree_num_workers() == -1) {
2039 int num_shared_tree_workers = 0;
2040 if (params->num_workers() >= 16) {
2043 num_shared_tree_workers = (params->num_workers() - 8) / 2;
2045 num_shared_tree_workers = (params->num_workers() - 8) * 3 / 4;
2048 SOLVER_LOG(logger,
"Setting number of shared tree workers to ",
2049 num_shared_tree_workers);
2050 params->set_shared_tree_num_workers(num_shared_tree_workers);
2058 if (params->interleave_search() || params->num_workers() == 1 ||
2059 !params->use_lns()) {
2060 params->set_use_rins_lns(
false);
2061 params->set_use_feasibility_pump(
false);
2065 if (params->linearization_level() == 0) {
2066 params->set_use_feasibility_pump(
false);
2071 if (!params->fill_tightened_domains_in_response() &&
2072 params->num_workers() == 1) {
2073 params->set_share_level_zero_bounds(
false);
2090 bounds = std::make_unique<SharedBoundsManager>(*proto);
2091 bounds->set_dump_prefix(absl::GetFlag(FLAGS_cp_model_dump_prefix));
2092 bounds->LoadDebugSolution(response->DebugSolution());
2102 lp_solutions = std::make_unique<SharedLPSolutionRepository>(
2104 global_model->Register<SharedLPSolutionRepository>(lp_solutions.get());
2106 incomplete_solutions = std::make_unique<SharedIncompleteSolutionManager>();
2107 global_model->Register<SharedIncompleteSolutionManager>(
2108 incomplete_solutions.get());
2112 const bool always_synchronize =
2114 response->SetSynchronizationMode(always_synchronize);
2116 clauses = std::make_unique<SharedClausesManager>(always_synchronize);
bool AddEdge(int node1, int node2)
void SetNumberOfNodes(int num_nodes)
int GetNumberOfComponents() const
std::vector< int > GetComponentIds()
Returns the same as GetConnectedComponents().
void Start()
When Start() is called multiple times, only the most recent is used.
bool IsIncludedIn(const Domain &domain) const
Domain InverseMultiplicationBy(int64_t coeff) const
bool ComputeTransitiveReduction(bool log_info=false)
::operations_research::sat::LinearArgumentProto *PROTOBUF_NONNULL mutable_lin_max()
::operations_research::sat::LinearConstraintProto *PROTOBUF_NONNULL mutable_linear()
SatSolver::Status Probe()
sat::Literal Literal(int ref) const
bool has_solution_hint() const
.operations_research.sat.PartialVariableAssignment solution_hint = 6;
bool has_floating_point_objective() const
.operations_research.sat.FloatObjectiveProto floating_point_objective = 9;
const ::operations_research::sat::IntegerVariableProto & variables(int index) const
const ::operations_research::sat::ConstraintProto & constraints(int index) const
bool has_objective() const
.operations_research.sat.CpObjectiveProto objective = 4;
const ::operations_research::sat::DecisionStrategyProto & search_strategy(int index) const
::int32_t assumptions(int index) const
::operations_research::sat::IntegerVariableProto *PROTOBUF_NONNULL add_variables()
::operations_research::sat::ConstraintProto *PROTOBUF_NONNULL add_constraints()
int variables_size() const
repeated .operations_research.sat.IntegerVariableProto variables = 2;
::operations_research::sat::CpObjectiveProto *PROTOBUF_NONNULL mutable_objective()
::operations_research::sat::IntegerVariableProto *PROTOBUF_NONNULL mutable_variables(int index)
const ::std::string & name() const
const ::operations_research::sat::PartialVariableAssignment & solution_hint() const
const ::operations_research::sat::CpObjectiveProto & objective() const
::int64_t domain(int index) const
double scaling_factor() const
int vars_size() const
repeated int32 vars = 1;
void add_coeffs(::int64_t value)
::int32_t vars(int index) const
void add_vars(::int32_t value)
::int64_t coeffs(int index) const
::operations_research::sat::CpSolverStatus status() const
::int64_t solution(int index) const
IntegerVariable NumIntegerVariables() const
ABSL_MUST_USE_RESULT bool Enqueue(IntegerLiteral i_lit)
int domain_size() const
repeated int64 domain = 2;
const ::std::string & name() const
void add_domain(::int64_t value)
::int64_t domain(int index) const
void InitAllDecomposedEnergies()
Calls InitDecomposedEnergies on all SchedulingDemandHelper created.
SatSolver::Status Search(const std::function< void()> &feasible_solution_observer)
Explores the search space.
::operations_research::sat::LinearExpressionProto *PROTOBUF_NONNULL mutable_target()
void add_vars(::int32_t value)
void add_domain(::int64_t value)
void add_coeffs(::int64_t value)
void add_coeffs(::int64_t value)
void add_vars(::int32_t value)
BooleanVariable Variable() const
Literal(int signed_value)
The model "singleton" shared time limit.
T Add(std::function< T(Model *)> f)
T Get(std::function< T(const Model &)> f) const
Similar to Add() but this is const.
const std::string & Name() const
void Register(T *non_owned_class)
::int64_t values(int index) const
::int32_t vars(int index) const
bool ProbeBooleanVariables(double deterministic_time_limit)
bool use_probing_search() const
bool use_feasibility_pump() const
::int32_t linear_split_size() const
bool share_glue_clauses() const
bool debug_postsolve_with_full_solver() const
::int32_t hint_conflict_limit() const
bool enumerate_all_solutions() const
bool share_objective_bounds() const
bool optimize_with_lb_tree_search() const
bool use_rins_lns() const
bool stop_after_root_propagation() const
void set_max_number_of_conflicts(::int64_t value)
void set_linearization_level(::int32_t value)
::int32_t binary_search_num_conflicts() const
static constexpr SearchBranching FIXED_SEARCH
bool optimize_with_core() const
bool use_shared_tree_search() const
void set_optimize_with_core(bool value)
bool share_binary_clauses() const
static constexpr SearchBranching HINT_SEARCH
bool share_level_zero_bounds() const
::int32_t num_workers() const
void set_cp_model_probing_level(::int32_t value)
bool optimize_with_max_hs() const
bool interleave_search() const
bool ModelIsUnsat() const
ABSL_MUST_USE_RESULT bool ResetToLevelZero()
void ReportPotentialNewBounds(const std::string &worker_name, absl::Span< const int > variables, absl::Span< const int64_t > new_lower_bounds, absl::Span< const int64_t > new_upper_bounds)
void GetChangedBounds(int id, std::vector< int > *variables, std::vector< int64_t > *new_lower_bounds, std::vector< int64_t > *new_upper_bounds)
void AddBinaryClause(int id, int lit1, int lit2)
void AddBatch(int id, CompactVectorVector< int > batch)
void GetUnseenBinaryClauses(int id, std::vector< std::pair< int, int > > *new_clauses)
const CompactVectorVector< int > & GetUnseenClauses(int id)
Solutions coming from the LP.
IntegerValue GetInnerObjectiveLowerBound()
void InitializeObjective(const CpModelProto &cp_model)
IntegerValue GetInnerObjectiveUpperBound()
void UpdateInnerObjectiveBounds(const std::string &update_info, IntegerValue lb, IntegerValue ub)
Updates the inner objective bounds.
Contains the table we display after the solver is done.
Simple class to add statistics by name and print them at the end.
SatSolver::Status Search(const std::function< void()> &feasible_solution_observer)
static constexpr int kMaxClauseSize
static constexpr int kMinClauseSize
void assign(size_type n, const value_type &val)
ABSL_FLAG(std::string, cp_model_load_debug_solution, "", "DEBUG ONLY. When this is set to a non-empty file name, " "we will interpret this as an internal solution which can be used for " "debugging. For instance we use it to identify wrong cuts/reasons.")
absl::Status GetTextProto(absl::string_view file_name, google::protobuf::Message *proto, Options options)
-— Protobuf API -—
void ConfigureSearchHeuristics(Model *model)
std::vector< int64_t > GetSolutionValues(const CpModelProto &model_proto, const Model &model)
void SolveLoadedCpModel(const CpModelProto &model_proto, Model *model)
constexpr IntegerValue kMaxIntegerValue(std::numeric_limits< IntegerValue::ValueType >::max() - 1)
void LoadBaseModel(const CpModelProto &model_proto, Model *model)
int64_t ComputeInnerObjective(const CpObjectiveProto &objective, absl::Span< const int64_t > solution)
void SplitAndLoadIntermediateConstraints(bool lb_required, bool ub_required, std::vector< IntegerVariable > *vars, std::vector< int64_t > *coeffs, Model *m)
std::function< void(Model *)> WeightedSumGreaterOrEqual(absl::Span< const IntegerVariable > vars, const VectorInt &coefficients, int64_t lower_bound)
Weighted sum >= constant.
const LiteralIndex kNoLiteralIndex(-1)
void DetectOptionalVariables(const CpModelProto &model_proto, Model *m)
Automatically detect optional variables.
LinearRelaxation ComputeLinearRelaxation(const CpModelProto &model_proto, Model *m)
Builds the linear relaxation of a CpModelProto.
std::function< int64_t(const Model &)> LowerBound(IntegerVariable v)
std::function< BooleanOrIntegerLiteral()> ConstructIntegerCompletionSearchStrategy(absl::Span< const IntegerVariable > variable_mapping, IntegerVariable objective_var, Model *model)
Constructs an integer completion search strategy.
std::vector< IntegerVariable > NegationOf(absl::Span< const IntegerVariable > vars)
Returns the vector of the negated variables.
void LoadVariables(const CpModelProto &model_proto, bool view_all_booleans_as_integers, Model *m)
void MinimizeCoreWithPropagation(TimeLimit *limit, SatSolver *solver, std::vector< Literal > *core)
void RegisterObjectiveBoundsImport(SharedResponseManager *shared_response_manager, Model *model)
std::function< BooleanOrIntegerLiteral()> ConstructFixedSearchStrategy(std::function< BooleanOrIntegerLiteral()> user_search, std::function< BooleanOrIntegerLiteral()> heuristic_search, std::function< BooleanOrIntegerLiteral()> integer_completion)
constexpr IntegerValue kMinIntegerValue(-kMaxIntegerValue.value())
std::function< BooleanOrIntegerLiteral()> ConstructHintSearchStrategy(const CpModelProto &cp_model_proto, CpModelMapping *mapping, Model *model)
Constructs a search strategy that follow the hint from the model.
void InitializeDebugSolution(const CpModelProto &model_proto, Model *model)
const IntegerVariable kNoIntegerVariable(-1)
void PostsolveResponseWithFullSolver(int num_variables_in_original_model, CpModelProto mapping_proto, absl::Span< const int > postsolve_mapping, std::vector< int64_t > *solution)
void RegisterClausesExport(int id, SharedClausesManager *shared_clauses_manager, Model *model)
Registers a callback that will export good clauses discovered during search.
void MinimizeL1DistanceWithHint(const CpModelProto &model_proto, Model *model)
std::function< IntegerVariable(Model *)> ConstantIntegerVariable(int64_t value)
void LoadBooleanSymmetries(const CpModelProto &model_proto, Model *m)
void AddFullEncodingFromSearchBranching(const CpModelProto &model_proto, Model *m)
CutGenerator CreateCliqueCutGenerator(absl::Span< const IntegerVariable > base_variables, Model *model)
IntegerVariable PositiveVariable(IntegerVariable i)
std::function< BooleanOrIntegerLiteral()> ConstructHeuristicSearchStrategy(const CpModelProto &cp_model_proto, Model *model)
Constructs a search strategy tailored for the current model.
void LoadFeasibilityPump(const CpModelProto &model_proto, Model *model)
void ExtractElementEncoding(const CpModelProto &model_proto, Model *m)
std::function< int64_t(const Model &)> Value(IntegerVariable v)
This checks that the variable is fixed.
void AdaptGlobalParameters(const CpModelProto &model_proto, Model *model)
std::function< int64_t(const Model &)> UpperBound(IntegerVariable v)
std::vector< int > GetOrbits(int n, absl::Span< const std::unique_ptr< SparsePermutation > > generators)
Domain ReadDomainFromProto(const ProtoWithDomain &proto)
Reads a Domain from the domain field of a proto.
std::function< IntegerVariable(Model *)> NewIntegerVariable(int64_t lb, int64_t ub)
SatSolver::Status MinimizeIntegerVariableWithLinearScanAndLazyEncoding(IntegerVariable objective_var, const std::function< void()> &feasible_solution_observer, Model *model)
void QuickSolveWithHint(const CpModelProto &model_proto, Model *model)
std::function< BooleanOrIntegerLiteral()> ConstructUserSearchStrategy(const CpModelProto &cp_model_proto, Model *model)
Constructs the search strategy specified in the given CpModelProto.
absl::string_view ConstraintCaseName(ConstraintProto::ConstraintCase constraint_case)
void PostsolveResponse(const int64_t num_variables_in_original_model, const CpModelProto &mapping_proto, absl::Span< const int > postsolve_mapping, std::vector< int64_t > *solution)
void LoadDebugSolution(const CpModelProto &model_proto, Model *model)
bool LoadConstraint(const ConstraintProto &ct, Model *m)
void RegisterVariableBoundsLevelZeroExport(const CpModelProto &, SharedBoundsManager *shared_bounds_manager, Model *model)
void PropagateEncodingFromEquivalenceRelations(const CpModelProto &model_proto, Model *m)
void PostsolveResponseWrapper(const SatParameters ¶ms, int num_variable_in_original_model, const CpModelProto &mapping_proto, absl::Span< const int > postsolve_mapping, std::vector< int64_t > *solution)
void RegisterVariableBoundsLevelZeroImport(const CpModelProto &model_proto, SharedBoundsManager *shared_bounds_manager, Model *model)
void LoadCpModel(const CpModelProto &model_proto, Model *model)
std::unique_ptr< SparsePermutation > CreateSparsePermutationFromProto(int n, const SparsePermutationProto &proto)
Creates a SparsePermutation on [0, n) from its proto representation.
SatSolver::Status ResetAndSolveIntegerProblem(const std::vector< Literal > &assumptions, Model *model)
int NegatedRef(int ref)
Small utility functions to deal with negative variable/literal references.
bool VariableIsPositive(IntegerVariable i)
void RegisterObjectiveBestBoundExport(IntegerVariable objective_var, SharedResponseManager *shared_response_manager, Model *model)
std::function< void(Model *)> ExcludeCurrentSolutionAndBacktrack()
int RegisterClausesLevelZeroImport(int id, SharedClausesManager *shared_clauses_manager, Model *model)
void RestrictObjectiveDomainWithBinarySearch(IntegerVariable objective_var, const std::function< void()> &feasible_solution_observer, Model *model)
std::function< BooleanOrIntegerLiteral()> InstrumentSearchStrategy(const CpModelProto &cp_model_proto, absl::Span< const IntegerVariable > variable_mapping, std::function< BooleanOrIntegerLiteral()> instrumented_strategy, Model *model)
void ExtractEncoding(const CpModelProto &model_proto, Model *m)
std::function< void(Model *)> WeightedSumLowerOrEqual(absl::Span< const IntegerVariable > vars, const VectorInt &coefficients, int64_t upper_bound)
Weighted sum <= constant.
In SWIG mode, we don't want anything besides these top-level includes.
Select next search node to expand Select next item_i to add this new search node to the search Generate a new search node where item_i is not in the knapsack Check validity of this new partial solution(using propagators) - If valid
std::string ProtobufDebugString(const P &message)
int64_t Max() const
Returns the max of the domain.
int64_t Min() const
Returns the min of the domain.
std::vector< int64_t > proto_values
util_intops::StrongVector< IntegerVariable, bool > ivar_has_value
util_intops::StrongVector< IntegerVariable, IntegerValue > ivar_values
static IntegerLiteral GreaterOrEqual(IntegerVariable i, IntegerValue bound)
static IntegerLiteral LowerOrEqual(IntegerVariable i, IntegerValue bound)
std::vector< LinearConstraint > linear_constraints
IntegerVariable objective_var
std::function< BooleanOrIntegerLiteral()> user_search
Contains the search specified by the user in CpModelProto.
void RegisterSharedClassesInLocalModel(Model *local_model)
SolverLogger *const logger
const CpModelProto & model_proto
These are never nullptr.
SharedLsSolutionRepository *const ls_hints
std::unique_ptr< SharedIncompleteSolutionManager > incomplete_solutions
std::unique_ptr< SharedClausesManager > clauses
ModelSharedTimeLimit *const time_limit
SharedTreeManager *const shared_tree_manager
SharedResponseManager *const response
SharedClasses(const CpModelProto *proto, Model *global_model)
SharedStatTables *const stat_tables
SharedStatistics *const stats
std::unique_ptr< SharedLPSolutionRepository > lp_solutions
WallTimer *const wall_timer
std::unique_ptr< SharedBoundsManager > bounds
These can be nullptr depending on the options.
#define SOLVER_LOG(logger,...)