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/strings/escaping.h"
39#include "absl/strings/str_cat.h"
40#include "absl/strings/string_view.h"
41#include "absl/time/time.h"
42#include "absl/types/span.h"
43#include "google/protobuf/arena.h"
50#include "ortools/sat/cp_model.pb.h"
75#include "ortools/sat/sat_parameters.pb.h"
83#if !defined(__PORTABLE_PLATFORM__)
91 "DEBUG ONLY. When set to true, SolveCpModel() will dump its model "
92 "protos (original model, presolved model, mapping model) in text "
93 "format to 'FLAGS_cp_model_dump_prefix'{model|presolved_model|"
94 "mapping_model}.pb.txt.");
97ABSL_FLAG(std::string, cp_model_dump_prefix,
".\\",
98 "Prefix filename for all dumped files");
101 "Prefix filename for all dumped files");
105 "DEBUG ONLY. When set to true, solve will dump all "
106 "lns or objective_shaving submodels proto in text format to "
107 "'FLAGS_cp_model_dump_prefix'xxx.pb.txt.");
110 std::string, cp_model_load_debug_solution,
"",
111 "DEBUG ONLY. When this is set to a non-empty file name, "
112 "we will interpret this as an internal solution which can be used for "
113 "debugging. For instance we use it to identify wrong cuts/reasons.");
122#if !defined(__PORTABLE_PLATFORM__)
123 if (absl::GetFlag(FLAGS_cp_model_load_debug_solution).empty())
return;
125 CpSolverResponse response;
127 "Reading debug solution from '",
128 absl::GetFlag(FLAGS_cp_model_load_debug_solution),
"'.");
134 CHECK_EQ(response.solution().size(), model_proto.variables().size());
136 response.solution());
144 if (shared_response ==
nullptr)
return;
145 if (shared_response->DebugSolution().empty())
return;
149 debug_sol.
proto_values = shared_response->DebugSolution();
152 const int num_integers =
157 std::vector<Literal> boolean_solution;
161 if (mapping.IsBoolean(
i)) {
166 boolean_solution.push_back(l);
169 if (!mapping.IsInteger(
i))
continue;
170 const IntegerVariable var = mapping.Integer(
i);
180 if (boolean_solution.size() == debug_sol.
proto_values.size() &&
181 !model_proto.has_objective()) {
182 LOG(INFO) <<
"Loaded pure Boolean debugging solution.";
189 if (objective_def !=
nullptr) {
190 const IntegerVariable objective_var = objective_def->objective_var;
191 const int64_t objective_value =
195 debug_sol.
ivar_values[objective_var] = objective_value;
201 const auto checker = [mapping, encoder, debug_sol, model](
202 absl::Span<const Literal> clause,
203 absl::Span<const IntegerLiteral> integers) {
204 bool is_satisfied =
false;
207 std::vector<std::tuple<Literal, IntegerLiteral, int>> to_print;
208 for (
const Literal l : clause) {
211 const int proto_var =
212 mapping.GetProtoVariableFromBooleanVariable(l.Variable());
213 if (proto_var != -1) {
215 if (debug_sol.
proto_values[proto_var] == (l.IsPositive() ? 1 : 0)) {
226 bool all_true =
true;
227 for (
const IntegerLiteral associated : encoder->GetIntegerLiterals(l)) {
228 const int proto_var = mapping.GetProtoVariableFromIntegerVariable(
230 if (proto_var == -1)
break;
232 to_print.push_back({l, associated, proto_var});
235 if (value < associated.bound) {
247 const int proto_var = mapping.GetProtoVariableFromIntegerVariable(
249 if (proto_var == -1) {
260 if (value >= i_lit.bound) {
266 LOG(INFO) <<
"Reason clause is not satisfied by loaded solution:";
267 LOG(INFO) <<
"Worker '" << model->
Name() <<
"', level="
269 LOG(INFO) <<
"literals (neg): " << clause;
270 LOG(INFO) <<
"integer literals: " << integers;
271 for (
const auto [l, i_lit, proto_var] : to_print) {
272 LOG(INFO) << l <<
" " << i_lit <<
" var=" << proto_var
273 <<
" value_in_sol=" << debug_sol.
proto_values[proto_var];
278 const auto lit_checker = [checker](absl::Span<const Literal> clause) {
279 return checker(clause, {});
287 const Model& model) {
292 for (
int i = 0;
i < model_proto.variables_size(); ++
i) {
293 if (mapping->IsInteger(
i)) {
294 const IntegerVariable var = mapping->Integer(
i);
300 DCHECK(mapping->IsBoolean(
i));
302 if (trail->Assignment().LiteralIsAssigned(literal)) {
315IntegerVariable GetOrCreateVariableWithTightBound(
316 absl::Span<
const std::pair<IntegerVariable, int64_t>> terms,
Model* model) {
318 if (terms.size() == 1 && terms.front().second == 1) {
319 return terms.front().first;
321 if (terms.size() == 1 && terms.front().second == -1) {
327 for (
const std::pair<IntegerVariable, int64_t>& var_coeff : terms) {
328 const int64_t min_domain = model->Get(
LowerBound(var_coeff.first));
329 const int64_t max_domain = model->Get(
UpperBound(var_coeff.first));
330 const int64_t coeff = var_coeff.second;
331 const int64_t prod1 = min_domain * coeff;
332 const int64_t prod2 = max_domain * coeff;
333 sum_min += std::min(prod1, prod2);
334 sum_max += std::max(prod1, prod2);
339IntegerVariable GetOrCreateVariableLinkedToSumOf(
340 absl::Span<
const std::pair<IntegerVariable, int64_t>> terms,
341 bool lb_required,
bool ub_required,
Model* model) {
343 if (terms.size() == 1 && terms.front().second == 1) {
344 return terms.front().first;
346 if (terms.size() == 1 && terms.front().second == -1) {
350 const IntegerVariable new_var =
351 GetOrCreateVariableWithTightBound(terms, model);
354 std::vector<IntegerVariable> vars;
355 std::vector<int64_t> coeffs;
356 for (
const auto [var, coeff] : terms) {
358 coeffs.push_back(coeff);
360 vars.push_back(new_var);
361 coeffs.push_back(-1);
364 if (vars.size() > model->GetOrCreate<SatParameters>()->linear_split_size()) {
385void InitializeLinearConstraintSymmetrizerIfRequested(
388 if (!model_proto.has_symmetry())
return;
390 auto* params = m->GetOrCreate<SatParameters>();
391 if (params->linearization_level() < 2)
return;
392 if (!params->use_symmetry_in_lp())
return;
404 int num_constraints_with_non_proto_variables = 0;
405 for (
const auto& lp_constraint : linear_relaxation.linear_constraints) {
406 bool has_non_proto_variable =
false;
407 for (
const IntegerVariable var : lp_constraint.VarsAsSpan()) {
408 if (mapping->GetProtoVariableFromIntegerVariable(var) == -1) {
409 has_non_proto_variable =
true;
413 if (has_non_proto_variable) {
414 ++num_constraints_with_non_proto_variables;
417 if (num_constraints_with_non_proto_variables > 0) {
420 auto* logger = m->GetOrCreate<SolverLogger>();
421 SOLVER_LOG(logger, num_constraints_with_non_proto_variables,
422 " LP constraints uses new variables not appearing in the "
423 "presolved model. ");
432 const int num_vars = model_proto.variables().size();
433 std::vector<std::unique_ptr<SparsePermutation>> generators;
434 for (
const SparsePermutationProto& perm :
435 model_proto.symmetry().permutations()) {
440 const std::vector<int> var_to_orbit_index =
GetOrbits(num_vars, generators);
441 std::vector<bool> orbit_is_ok;
442 std::vector<std::vector<IntegerVariable>> orbits;
443 for (
int proto_var = 0; proto_var < num_vars; ++proto_var) {
444 const int orbit_index = var_to_orbit_index[proto_var];
445 if (orbit_index == -1)
continue;
446 if (orbit_index >= orbits.size()) {
447 orbits.resize(orbit_index + 1);
448 orbit_is_ok.resize(orbit_index + 1,
true);
453 const IntegerVariable var = mapping->Integer(proto_var);
455 orbits[orbit_index].push_back(var);
460 std::vector<std::pair<IntegerVariable, int64_t>> terms;
461 for (
const std::vector<IntegerVariable>& orbit : orbits) {
463 for (
const IntegerVariable var : orbit) {
464 terms.push_back({var, 1});
466 const IntegerVariable sum_var =
467 GetOrCreateVariableLinkedToSumOf(terms,
true,
true, m);
468 symmetrizer->AddSymmetryOrbit(sum_var, orbit);
473IntegerVariable AddLPConstraints(
bool objective_need_to_be_tight,
474 const CpModelProto& model_proto,
Model* m) {
480 InitializeLinearConstraintSymmetrizerIfRequested(model_proto, relaxation, m);
488 const int num_lp_constraints =
489 static_cast<int>(relaxation.linear_constraints.size());
490 const int num_lp_cut_generators =
491 static_cast<int>(relaxation.cut_generators.size());
492 const int num_integer_variables =
493 m->GetOrCreate<
IntegerTrail>()->NumIntegerVariables().value();
495 DenseConnectedComponentsFinder components;
497 num_integer_variables);
498 auto get_constraint_index = [](
int ct_index) {
return ct_index; };
499 auto get_cut_generator_index = [num_lp_constraints](
int cut_index) {
500 return num_lp_constraints + cut_index;
502 auto get_var_index = [num_lp_constraints,
503 num_lp_cut_generators](IntegerVariable var) {
504 return num_lp_constraints + num_lp_cut_generators +
507 for (
int i = 0;
i < num_lp_constraints;
i++) {
508 for (
const IntegerVariable var :
509 relaxation.linear_constraints[
i].VarsAsSpan()) {
510 components.
AddEdge(get_constraint_index(
i), get_var_index(var));
513 for (
int i = 0;
i < num_lp_cut_generators; ++
i) {
514 for (
const IntegerVariable var : relaxation.cut_generators[
i].vars) {
515 components.
AddEdge(get_cut_generator_index(
i), get_var_index(var));
521 for (
int i = 0;
i < symmetrizer->NumOrbits(); ++
i) {
522 const int representative = get_var_index(symmetrizer->OrbitSumVar(
i));
523 for (
const IntegerVariable var : symmetrizer->Orbit(
i)) {
524 components.
AddEdge(representative, get_var_index(var));
529 std::vector<int> component_sizes(num_components, 0);
530 const std::vector<int> index_to_component = components.
GetComponentIds();
531 for (
int i = 0;
i < num_lp_constraints;
i++) {
532 ++component_sizes[index_to_component[get_constraint_index(
i)]];
534 for (
int i = 0;
i < num_lp_cut_generators;
i++) {
535 ++component_sizes[index_to_component[get_cut_generator_index(
i)]];
539 std::vector<std::vector<IntegerVariable>> component_to_var(num_components);
540 for (IntegerVariable var(0); var < num_integer_variables; var += 2) {
542 component_to_var[index_to_component[get_var_index(var)]].push_back(var);
551 for (
int i = 0;
i < model_proto.objective().coeffs_size(); ++
i) {
552 const IntegerVariable var =
553 mapping->Integer(model_proto.objective().vars(
i));
554 ++component_sizes[index_to_component[get_var_index(var)]];
558 std::vector<LinearProgrammingConstraint*> lp_constraints(num_components,
560 for (
int i = 0;
i < num_lp_constraints;
i++) {
561 const int c = index_to_component[get_constraint_index(
i)];
562 if (component_sizes[c] <= 1)
continue;
563 if (lp_constraints[c] ==
nullptr) {
566 m->TakeOwnership(lp_constraints[c]);
569 if (!lp_constraints[c]->AddLinearConstraint(
570 std::move(relaxation.linear_constraints[
i]))) {
571 m->GetOrCreate<
SatSolver>()->NotifyThatModelIsUnsat();
577 for (
int i = 0;
i < num_lp_cut_generators;
i++) {
578 const int c = index_to_component[get_cut_generator_index(
i)];
579 if (lp_constraints[c] ==
nullptr) {
582 m->TakeOwnership(lp_constraints[c]);
584 lp_constraints[
c]->AddCutGenerator(std::move(relaxation.cut_generators[
i]));
589 auto* params = m->GetOrCreate<SatParameters>();
590 if (params->linearization_level() > 1 && params->add_clique_cuts() &&
591 params->cut_level() > 0) {
593 if (lp ==
nullptr)
continue;
599 std::vector<std::vector<std::pair<IntegerVariable, int64_t>>>
600 component_to_cp_terms(num_components);
601 std::vector<std::pair<IntegerVariable, int64_t>> top_level_cp_terms;
602 int num_components_containing_objective = 0;
603 if (model_proto.has_objective()) {
607 std::vector<std::pair<IntegerVariable, int64_t>> objective;
608 const int num_orbits = symmetrizer->NumOrbits();
609 if (num_orbits > 0) {
611 std::vector<int64_t> orbit_obj_coeff(num_orbits, 0);
612 for (
int i = 0;
i < model_proto.objective().coeffs_size(); ++
i) {
613 const IntegerVariable var =
614 mapping->Integer(model_proto.objective().vars(
i));
615 const int64_t coeff = model_proto.objective().coeffs(
i);
616 const int orbit_index = symmetrizer->OrbitIndex(var);
617 if (orbit_index != -1) {
618 if (orbit_obj_coeff[orbit_index] == 0) {
619 orbit_obj_coeff[orbit_index] = coeff;
621 CHECK_EQ(orbit_obj_coeff[orbit_index], coeff);
625 objective.push_back({var, coeff});
627 for (
int i = 0;
i < num_orbits; ++
i) {
628 if (orbit_obj_coeff[
i] == 0)
continue;
629 objective.push_back({symmetrizer->OrbitSumVar(
i), orbit_obj_coeff[
i]});
632 for (
int i = 0;
i < model_proto.objective().coeffs_size(); ++
i) {
633 const IntegerVariable var =
634 mapping->Integer(model_proto.objective().vars(
i));
635 const int64_t coeff = model_proto.objective().coeffs(
i);
636 objective.push_back({var, coeff});
642 for (
const auto [var, coeff] : objective) {
643 const int c = index_to_component[get_var_index(var)];
644 if (lp_constraints[c] !=
nullptr) {
645 lp_constraints[
c]->SetObjectiveCoefficient(var, IntegerValue(coeff));
646 component_to_cp_terms[
c].push_back(std::make_pair(var, coeff));
649 top_level_cp_terms.push_back(std::make_pair(var, coeff));
653 for (
int c = 0;
c < num_components; ++
c) {
654 if (component_to_cp_terms[c].empty())
continue;
655 const IntegerVariable sub_obj_var = GetOrCreateVariableLinkedToSumOf(
656 component_to_cp_terms[c], objective_need_to_be_tight,
true, m);
657 top_level_cp_terms.push_back(std::make_pair(sub_obj_var, 1));
658 lp_constraints[
c]->SetMainObjectiveVariable(sub_obj_var);
659 num_components_containing_objective++;
663 const IntegerVariable main_objective_var =
664 model_proto.has_objective()
665 ? GetOrCreateVariableLinkedToSumOf(
666 top_level_cp_terms, objective_need_to_be_tight,
true, m)
672 if (lp_constraint ==
nullptr)
continue;
673 lp_constraint->RegisterWith(m);
674 VLOG(3) <<
"LP constraint: " << lp_constraint->DimensionString() <<
".";
677 VLOG(3) << top_level_cp_terms.size()
678 <<
" terms in the main objective linear equation ("
679 << num_components_containing_objective <<
" from LP constraints).";
680 return main_objective_var;
688 const CpModelProto& ,
690 CHECK(shared_bounds_manager !=
nullptr);
696 int saved_trail_index = 0;
697 std::vector<int> model_variables;
698 std::vector<int64_t> new_lower_bounds;
699 std::vector<int64_t> new_upper_bounds;
700 absl::flat_hash_set<int> visited_variables;
701 const std::string name = model->
Name();
703 auto broadcast_level_zero_bounds =
704 [=](absl::Span<const IntegerVariable> modified_vars)
mutable {
706 for (
const IntegerVariable& var : modified_vars) {
708 const int model_var =
709 mapping->GetProtoVariableFromIntegerVariable(positive_var);
711 if (model_var == -1)
continue;
712 const auto [_, inserted] = visited_variables.insert(model_var);
713 if (!inserted)
continue;
715 const int64_t new_lb =
716 integer_trail->LevelZeroLowerBound(positive_var).value();
717 const int64_t new_ub =
718 integer_trail->LevelZeroUpperBound(positive_var).value();
722 model_variables.push_back(model_var);
723 new_lower_bounds.push_back(new_lb);
724 new_upper_bounds.push_back(new_ub);
728 for (; saved_trail_index < trail->Index(); ++saved_trail_index) {
729 const Literal fixed_literal = (*trail)[saved_trail_index];
730 const int model_var = mapping->GetProtoVariableFromBooleanVariable(
733 if (model_var == -1)
continue;
734 const auto [_, inserted] = visited_variables.insert(model_var);
735 if (!inserted)
continue;
737 model_variables.push_back(model_var);
739 new_lower_bounds.push_back(1);
740 new_upper_bounds.push_back(1);
742 new_lower_bounds.push_back(0);
743 new_upper_bounds.push_back(0);
747 if (!model_variables.empty()) {
749 model->
Name(), model_variables, new_lower_bounds,
753 model_variables.clear();
754 new_lower_bounds.clear();
755 new_upper_bounds.clear();
756 visited_variables.clear();
759 if (!model->
Get<SatParameters>()->interleave_search()) {
772 const IntegerVariable num_vars =
774 std::vector<IntegerVariable> all_variables;
775 all_variables.reserve(num_vars.value());
776 for (IntegerVariable var(0); var < num_vars; ++var) {
777 all_variables.push_back(var);
779 broadcast_level_zero_bounds(all_variables);
782 ->RegisterLevelZeroModifiedVariablesCallback(broadcast_level_zero_bounds);
791 CHECK(shared_bounds_manager !=
nullptr);
792 const std::string name = model->
Name();
799 const auto& import_level_zero_bounds = [&model_proto, shared_bounds_manager,
800 name, sat_solver, integer_trail,
801 trail, id, mapping]() {
802 std::vector<int> model_variables;
803 std::vector<int64_t> new_lower_bounds;
804 std::vector<int64_t> new_upper_bounds;
806 id, &model_variables, &new_lower_bounds, &new_upper_bounds);
807 for (
int i = 0;
i < model_variables.size(); ++
i) {
808 const int model_var = model_variables[
i];
813 if (mapping->IsBoolean(model_var)) {
814 Literal lit = mapping->Literal(model_var);
815 if (new_upper_bounds[
i] == 0) lit = lit.
Negated();
816 if (trail->Assignment().LiteralIsTrue(lit))
continue;
817 if (trail->Assignment().LiteralIsFalse(lit)) {
818 sat_solver->NotifyThatModelIsUnsat();
821 trail->EnqueueWithUnitReason(lit);
826 if (!mapping->IsInteger(model_var))
continue;
827 const IntegerVariable var = mapping->Integer(model_var);
828 const IntegerValue new_lb(new_lower_bounds[
i]);
829 const IntegerValue new_ub(new_upper_bounds[
i]);
830 const IntegerValue old_lb = integer_trail->LowerBound(var);
831 const IntegerValue old_ub = integer_trail->UpperBound(var);
832 const bool changed_lb = new_lb > old_lb;
833 const bool changed_ub = new_ub < old_ub;
834 if (!changed_lb && !changed_ub)
continue;
837 const IntegerVariableProto& var_proto =
838 model_proto.variables(model_var);
839 const std::string& var_name =
840 var_proto.name().empty()
841 ? absl::StrCat(
"anonymous_var(", model_var,
")")
843 LOG(INFO) <<
" '" << name <<
"' imports new bounds for " << var_name
844 <<
": from [" << old_lb <<
", " << old_ub <<
"] to ["
845 << new_lb <<
", " << new_ub <<
"]";
865 import_level_zero_bounds);
871 IntegerVariable objective_var,
874 const auto broadcast_objective_lower_bound =
875 [objective_var, integer_trail, shared_response_manager, model,
878 const IntegerValue objective_lb =
879 integer_trail->LevelZeroLowerBound(objective_var);
880 if (objective_lb > best_obj_lb) {
881 best_obj_lb = objective_lb;
883 model->
Name(), objective_lb,
884 integer_trail->LevelZeroUpperBound(objective_var));
886 if (!model->
Get<SatParameters>()->interleave_search()) {
892 ->RegisterLevelZeroModifiedVariablesCallback(
893 broadcast_objective_lower_bound);
904 const std::string name = model->
Name();
905 const auto import_objective_bounds = [name, solver, integer_trail, objective,
906 shared_response_manager]() {
907 if (solver->AssumptionLevel() != 0)
return true;
908 bool tighter_bounds =
false;
910 const IntegerValue external_lb =
912 const IntegerValue current_lb =
913 integer_trail->LowerBound(objective->objective_var);
914 if (external_lb > current_lb) {
916 objective->objective_var, external_lb),
920 tighter_bounds =
true;
923 const IntegerValue external_ub =
925 const IntegerValue current_ub =
926 integer_trail->UpperBound(objective->objective_var);
927 if (external_ub < current_ub) {
929 objective->objective_var, external_ub),
933 tighter_bounds =
true;
938 if (tighter_bounds) {
939 VLOG(3) <<
"'" << name <<
"' imports objective bounds: external ["
940 << objective->ScaleIntegerObjective(external_lb) <<
", "
941 << objective->ScaleIntegerObjective(external_ub) <<
"], current ["
942 << objective->ScaleIntegerObjective(current_lb) <<
", "
943 << objective->ScaleIntegerObjective(current_ub) <<
"]";
950 import_objective_bounds);
957 const auto& share_binary_clause = [mapping, id, shared_clauses_manager](
960 mapping->GetProtoVariableFromBooleanVariable(l1.Variable());
961 if (var1 == -1)
return;
963 mapping->GetProtoVariableFromBooleanVariable(l2.Variable());
964 if (var2 == -1)
return;
965 const int lit1 = l1.IsPositive() ? var1 :
NegatedRef(var1);
966 const int lit2 = l2.IsPositive() ? var2 :
NegatedRef(var2);
970 share_binary_clause);
971 if (!model->
GetOrCreate<SatParameters>()->share_glue_clauses()) {
976 model->
GetOrCreate<SatParameters>()->clause_cleanup_lbd_bound();
980 auto share_clause = [mapping, clause_stream, max_lbd,
981 clause = std::vector<int>()](
982 int lbd, absl::Span<const Literal> literals)
mutable {
983 if (lbd <= 0 || lbd > max_lbd ||
984 !clause_stream->CanAccept(literals.size(), lbd)) {
988 for (
const Literal& lit : literals) {
990 mapping->GetProtoVariableFromBooleanVariable(lit.Variable());
991 if (var == -1)
return;
992 clause.push_back(lit.IsPositive() ? var :
NegatedRef(var));
994 clause_stream->Add(clause);
997 std::move(share_clause));
1009 CHECK(shared_clauses_manager !=
nullptr);
1013 const bool share_glue_clauses =
1014 model->
GetOrCreate<SatParameters>()->share_glue_clauses();
1015 const bool minimize_shared_clauses =
1016 model->
GetOrCreate<SatParameters>()->minimize_shared_clauses();
1017 auto* clause_stream = share_glue_clauses
1021 const auto& import_level_zero_clauses = [shared_clauses_manager, id, mapping,
1022 sat_solver, implications,
1023 clause_stream, clause_manager,
1024 minimize_shared_clauses]() {
1025 std::vector<std::pair<int, int>> new_binary_clauses;
1027 implications->EnableSharing(
false);
1028 for (
const auto& [ref1, ref2] : new_binary_clauses) {
1031 if (!sat_solver->AddProblemClause({l1, l2})) {
1035 implications->EnableSharing(
true);
1036 if (clause_stream ==
nullptr)
return true;
1038 int new_clauses = 0;
1039 std::array<Literal, UniqueClauseStream::kMaxClauseSize> local_clause;
1040 sat_solver->EnsureNewClauseIndexInitialized();
1043 auto callback = clause_manager->TakeAddClauseCallback();
1044 for (
const absl::Span<const int> shared_clause :
1051 if (clause_stream->Delete(shared_clause))
continue;
1052 for (
int i = 0;
i < shared_clause.size(); ++
i) {
1053 local_clause[
i] = mapping->
Literal(shared_clause[
i]);
1055 if (!sat_solver->AddProblemClause(
1056 absl::MakeSpan(local_clause).subspan(0, shared_clause.size()))) {
1061 clause_manager->SetAddClauseCallback(std::move(callback));
1062 clause_stream->RemoveWorstClauses();
1063 if (minimize_shared_clauses && new_clauses > 0) {
1069 return sat_solver->MinimizeByPropagation(
1075 import_level_zero_clauses);
1081 CHECK(shared_response_manager !=
nullptr);
1085 const auto unsat = [shared_response_manager, sat_solver, model] {
1086 sat_solver->NotifyThatModelIsUnsat();
1087 shared_response_manager->NotifyThatImprovingProblemIsInfeasible(
1088 absl::StrCat(model->
Name(),
" [loading]"));
1095 const SatParameters& parameters = *(model->
GetOrCreate<SatParameters>());
1096 const bool view_all_booleans_as_integers =
1097 (parameters.linearization_level() >= 2) ||
1098 (parameters.search_branching() == SatParameters::FIXED_SEARCH &&
1099 model_proto.search_strategy().empty()) ||
1100 parameters.optimize_with_max_hs();
1101 LoadVariables(model_proto, view_all_booleans_as_integers, model);
1113 if (!parameters.optimize_with_core() && parameters.symmetry_level() > 1 &&
1114 !parameters.enumerate_all_solutions() &&
1115 parameters.linearization_level() == 0) {
1123 if (sat_solver->ModelIsUnsat())
return unsat();
1127 if (sat_solver->ModelIsUnsat())
return unsat();
1134 int num_ignored_constraints = 0;
1135 absl::flat_hash_set<ConstraintProto::ConstraintCase> unsupported_types;
1136 for (
const ConstraintProto& ct : model_proto.constraints()) {
1137 if (mapping->ConstraintIsAlreadyLoaded(&ct)) {
1138 ++num_ignored_constraints;
1143 unsupported_types.insert(ct.constraint_case());
1153 if (sat_solver->FinishPropagation()) {
1155 const int old_num_fixed = trail->
Index();
1156 if (trail->
Index() > old_num_fixed) {
1157 VLOG(3) <<
"Constraint fixed " << trail->
Index() - old_num_fixed
1162 if (sat_solver->ModelIsUnsat()) {
1163 VLOG(2) <<
"UNSAT during extraction (after adding '"
1169 if (num_ignored_constraints > 0) {
1170 VLOG(3) << num_ignored_constraints <<
" constraints were skipped.";
1172 if (!unsupported_types.empty()) {
1175 "There is unsupported constraints types in this model: ");
1176 std::vector<absl::string_view> names;
1177 for (
const ConstraintProto::ConstraintCase type : unsupported_types) {
1180 std::sort(names.begin(), names.end());
1181 for (
const absl::string_view name : names) {
1187 SOLVER_LOG(logger,
"BUG: We will wrongly report INFEASIBLE now.");
1192 ->AddAllImplicationsBetweenAssociatedLiterals();
1193 if (!sat_solver->FinishPropagation())
return unsat();
1206 const SatParameters& parameters = *(model->
GetOrCreate<SatParameters>());
1207 if (parameters.linearization_level() == 0)
return;
1214 const int num_lp_constraints =
1216 if (num_lp_constraints == 0)
return;
1218 for (
int i = 0;
i < num_lp_constraints;
i++) {
1222 if (model_proto.has_objective()) {
1223 for (
int i = 0;
i < model_proto.objective().coeffs_size(); ++
i) {
1224 const IntegerVariable var =
1225 mapping->Integer(model_proto.objective().vars(
i));
1226 const int64_t coeff = model_proto.objective().coeffs(
i);
1227 feasibility_pump->SetObjectiveCoefficient(var, IntegerValue(coeff));
1245 const auto unsat = [shared_response_manager, sat_solver, model] {
1246 sat_solver->NotifyThatModelIsUnsat();
1247 shared_response_manager->NotifyThatImprovingProblemIsInfeasible(
1248 absl::StrCat(model->
Name(),
" [loading]"));
1252 const SatParameters& parameters = *(model->
GetOrCreate<SatParameters>());
1258 if (parameters.auto_detect_greater_than_at_least_one_of()) {
1260 ->AddGreaterThanAtLeastOneOfConstraints(model);
1261 if (!sat_solver->FinishPropagation())
return unsat();
1271 if (parameters.cp_model_probing_level() > 1) {
1281 if (sat_solver->ModelIsUnsat())
return unsat();
1288 if (repository !=
nullptr) {
1294 bool objective_need_to_be_tight =
false;
1295 if (model_proto.has_objective() &&
1296 !model_proto.objective().domain().empty()) {
1297 int64_t min_value = 0;
1298 int64_t max_value = 0;
1300 const CpObjectiveProto& obj = model_proto.objective();
1301 for (
int i = 0;
i < obj.vars_size(); ++
i) {
1302 const int64_t coeff = obj.coeffs(
i);
1303 const IntegerVariable var = mapping->Integer(obj.vars(
i));
1305 min_value += coeff * integer_trail->LowerBound(var).value();
1306 max_value += coeff * integer_trail->UpperBound(var).value();
1308 min_value += coeff * integer_trail->UpperBound(var).value();
1309 max_value += coeff * integer_trail->LowerBound(var).value();
1313 const Domain automatic_domain =
Domain(min_value, max_value);
1314 objective_need_to_be_tight = !automatic_domain.
IsIncludedIn(user_domain);
1320 if (parameters.linearization_level() > 0) {
1323 AddLPConstraints(objective_need_to_be_tight, model_proto, model);
1324 if (sat_solver->ModelIsUnsat())
return unsat();
1325 }
else if (model_proto.has_objective()) {
1326 const CpObjectiveProto& obj = model_proto.objective();
1327 std::vector<std::pair<IntegerVariable, int64_t>> terms;
1328 terms.reserve(obj.vars_size());
1329 for (
int i = 0;
i < obj.vars_size(); ++
i) {
1331 std::make_pair(mapping->Integer(obj.vars(
i)), obj.coeffs(
i)));
1333 if (parameters.optimize_with_core()) {
1334 if (objective_need_to_be_tight) {
1344 GetOrCreateVariableLinkedToSumOf(terms,
true,
false, model);
1346 objective_var = GetOrCreateVariableWithTightBound(terms, model);
1349 objective_var = GetOrCreateVariableLinkedToSumOf(
1350 terms, objective_need_to_be_tight,
true, model);
1357 const CpObjectiveProto& objective_proto = model_proto.objective();
1360 objective_definition->
scaling_factor = objective_proto.scaling_factor();
1361 if (objective_definition->scaling_factor == 0.0) {
1362 objective_definition->scaling_factor = 1.0;
1364 objective_definition->offset = objective_proto.offset();
1365 objective_definition->objective_var = objective_var;
1367 const int size = objective_proto.vars_size();
1368 objective_definition->vars.resize(size);
1369 objective_definition->coeffs.resize(size);
1370 for (
int i = 0;
i < objective_proto.vars_size(); ++
i) {
1373 objective_definition->vars[
i] = mapping->Integer(objective_proto.vars(
i));
1374 objective_definition->coeffs[
i] = IntegerValue(objective_proto.coeffs(
i));
1377 const int ref = objective_proto.vars(
i);
1378 if (mapping->IsInteger(ref)) {
1379 const IntegerVariable var = mapping->Integer(objective_proto.vars(
i));
1380 objective_definition->objective_impacting_variables.insert(
1381 objective_proto.coeffs(
i) > 0 ? var :
NegationOf(var));
1388 objective_definition->coeffs, model));
1392 if (!model_proto.objective().domain().empty()) {
1395 const Domain automatic_domain =
1396 integer_trail->InitialVariableDomain(objective_var);
1397 VLOG(3) <<
"Objective offset:" << model_proto.objective().offset()
1398 <<
" scaling_factor:" << model_proto.objective().scaling_factor();
1399 VLOG(3) <<
"Automatic internal objective domain: " << automatic_domain;
1400 VLOG(3) <<
"User specified internal objective domain: " << user_domain;
1402 if (!integer_trail->UpdateInitialDomain(objective_var, user_domain)) {
1403 VLOG(2) <<
"UNSAT due to the objective domain.";
1411 "Initial num_bool: ", sat_solver->NumVariables());
1412 if (!sat_solver->FinishPropagation())
return unsat();
1414 if (model_proto.has_objective()) {
1417 shared_response_manager->UpdateInnerObjectiveBounds(
1418 absl::StrCat(model->
Name(),
" (initial_propagation)"),
1419 integer_trail->LowerBound(objective_var),
1420 integer_trail->UpperBound(objective_var));
1429 if (model->
GetOrCreate<SatParameters>()->share_objective_bounds()) {
1438 search_heuristics->heuristic_search =
1440 search_heuristics->integer_completion_search =
1442 objective_var, model);
1444 search_heuristics->user_search, search_heuristics->heuristic_search,
1445 search_heuristics->integer_completion_search);
1446 if (VLOG_IS_ON(3)) {
1447 search_heuristics->fixed_search =
1449 search_heuristics->fixed_search, model);
1451 search_heuristics->hint_search =
1455 if (parameters.optimize_with_core()) {
1458 const auto solution_observer = [&model_proto, model,
1459 shared_response_manager,
1461 const std::vector<int64_t>
solution =
1463 const IntegerValue obj_ub =
1465 if (obj_ub < best_obj_ub) {
1466 best_obj_ub = obj_ub;
1467 shared_response_manager->NewSolution(
solution, model->Name(), model);
1472 if (parameters.optimize_with_max_hs()) {
1474 model_proto, objective, solution_observer, model);
1476 model->TakeOwnership(max_hs);
1480 objective.coeffs, solution_observer, model);
1482 model->TakeOwnership(core);
1497 if (shared_response_manager->ProblemIsSolved())
return;
1499 const SatParameters& parameters = *model->
GetOrCreate<SatParameters>();
1500 if (parameters.stop_after_root_propagation())
return;
1502 auto solution_observer = [&model_proto, model, shared_response_manager,
1504 const std::vector<int64_t>
solution =
1506 if (model_proto.has_objective()) {
1507 const IntegerValue obj_ub =
1509 if (obj_ub < best_obj_ub) {
1510 best_obj_ub = obj_ub;
1511 shared_response_manager->NewSolution(
solution, model->
Name(), model);
1514 shared_response_manager->NewSolution(
solution, model->
Name(), model);
1520 shared_response_manager->NotifyThatImprovingProblemIsInfeasible(
1531 if (parameters.use_probing_search()) {
1534 status = prober.
Probe();
1536 shared_response_manager->NotifyThatImprovingProblemIsInfeasible(
1541 solution_observer();
1546 }
else if (!model_proto.has_objective()) {
1548 if (parameters.use_shared_tree_search()) {
1550 status = subtree_worker->
Search(solution_observer);
1553 mapping.Literals(model_proto.assumptions()), model);
1556 solution_observer();
1557 if (!parameters.enumerate_all_solutions())
break;
1561 shared_response_manager->NotifyThatImprovingProblemIsInfeasible(
1565 shared_response_manager->NotifyThatImprovingProblemIsInfeasible(
1571 std::vector<Literal> core = sat_solver->GetLastIncompatibleDecisions();
1573 std::vector<int> core_in_proto_format;
1574 for (
const Literal l : core) {
1575 core_in_proto_format.push_back(
1576 mapping.GetProtoVariableFromBooleanVariable(l.Variable()));
1577 if (!l.IsPositive()) {
1578 core_in_proto_format.back() =
NegatedRef(core_in_proto_format.back());
1581 shared_response_manager->AddUnsatCore(core_in_proto_format);
1586 const IntegerVariable objective_var = objective.
objective_var;
1589 if (parameters.optimize_with_lb_tree_search()) {
1591 status = search->
Search(solution_observer);
1592 }
else if (parameters.optimize_with_core()) {
1595 if (parameters.optimize_with_max_hs()) {
1600 }
else if (parameters.use_shared_tree_search()) {
1602 status = subtree_worker->
Search(solution_observer);
1606 if (parameters.binary_search_num_conflicts() >= 0) {
1608 solution_observer, model);
1611 objective_var, solution_observer, model);
1619 shared_response_manager->NotifyThatImprovingProblemIsInfeasible(
1628 if (!model_proto.has_solution_hint())
return;
1631 if (shared_response_manager->ProblemIsSolved())
return;
1634 auto* parameters = model->
GetOrCreate<SatParameters>();
1642 if (parameters->optimize_with_core())
return;
1644 const SatParameters saved_params = *parameters;
1645 parameters->set_max_number_of_conflicts(parameters->hint_conflict_limit());
1646 parameters->set_search_branching(SatParameters::HINT_SEARCH);
1647 parameters->set_optimize_with_core(
false);
1648 parameters->set_use_sat_inprocessing(
false);
1649 auto cleanup = ::absl::MakeCleanup(
1650 [parameters, saved_params]() { *parameters = saved_params; });
1656 mapping.Literals(model_proto.assumptions()), model);
1658 const std::string& solution_info = model->
Name();
1660 const std::vector<int64_t>
solution =
1662 shared_response_manager->NewSolution(
1663 solution, absl::StrCat(solution_info,
" [hint]"), model);
1665 if (!model_proto.has_objective()) {
1666 if (parameters->enumerate_all_solutions()) {
1671 const IntegerVariable objective_var =
1678 shared_response_manager->GetInnerObjectiveUpperBound()),
1680 shared_response_manager->NotifyThatImprovingProblemIsInfeasible(
1681 absl::StrCat(solution_info,
" [hint]"));
1693 if (parameters->debug_crash_on_bad_hint() &&
1694 shared_response_manager->SolutionsRepository().NumSolutions() == 0 &&
1697 LOG(FATAL) <<
"QuickSolveWithHint() didn't find a feasible solution."
1698 <<
" The model name is '" << model_proto.name() <<
"'."
1699 <<
" Status: " << status <<
".";
1703 shared_response_manager->NotifyThatImprovingProblemIsInfeasible(
1704 absl::StrCat(solution_info,
" [hint]"));
1720 if (!model_proto.has_solution_hint())
return;
1723 if (shared_response_manager->ProblemIsSolved())
return;
1725 auto* parameters = local_model.
GetOrCreate<SatParameters>();
1729 if (parameters->enumerate_all_solutions())
return;
1732 const SatParameters saved_params = *model->
GetOrCreate<SatParameters>();
1733 *parameters = saved_params;
1734 parameters->set_max_number_of_conflicts(parameters->hint_conflict_limit());
1735 parameters->set_optimize_with_core(
false);
1738 CpModelProto updated_model_proto = model_proto;
1739 updated_model_proto.clear_objective();
1742 for (
int i = 0;
i < model_proto.solution_hint().vars_size(); ++
i) {
1743 const int var = model_proto.solution_hint().vars(
i);
1744 const int64_t value = model_proto.solution_hint().values(
i);
1747 const int new_var_index = updated_model_proto.variables_size();
1748 IntegerVariableProto* var_proto = updated_model_proto.add_variables();
1749 const int64_t min_domain = model_proto.variables(var).domain(0) - value;
1750 const int64_t max_domain =
1751 model_proto.variables(var).domain(
1752 model_proto.variables(var).domain_size() - 1) -
1754 var_proto->add_domain(min_domain);
1755 var_proto->add_domain(max_domain);
1758 ConstraintProto*
const linear_constraint_proto =
1759 updated_model_proto.add_constraints();
1760 LinearConstraintProto* linear = linear_constraint_proto->mutable_linear();
1761 linear->add_vars(new_var_index);
1762 linear->add_coeffs(1);
1763 linear->add_vars(var);
1764 linear->add_coeffs(-1);
1765 linear->add_domain(-value);
1766 linear->add_domain(-value);
1769 const int abs_var_index = updated_model_proto.variables_size();
1770 IntegerVariableProto* abs_var_proto = updated_model_proto.add_variables();
1771 const int64_t abs_min_domain = 0;
1772 const int64_t abs_max_domain =
1773 std::max(std::abs(min_domain), std::abs(max_domain));
1774 abs_var_proto->add_domain(abs_min_domain);
1775 abs_var_proto->add_domain(abs_max_domain);
1776 auto* abs_ct = updated_model_proto.add_constraints()->mutable_lin_max();
1777 abs_ct->mutable_target()->add_vars(abs_var_index);
1778 abs_ct->mutable_target()->add_coeffs(1);
1779 LinearExpressionProto* left = abs_ct->add_exprs();
1780 left->add_vars(new_var_index);
1781 left->add_coeffs(1);
1782 LinearExpressionProto* right = abs_ct->add_exprs();
1783 right->add_vars(new_var_index);
1784 right->add_coeffs(-1);
1786 updated_model_proto.mutable_objective()->add_vars(abs_var_index);
1787 updated_model_proto.mutable_objective()->add_coeffs(1);
1790 auto* local_response_manager =
1800 mapping.Literals(updated_model_proto.assumptions()), &local_model);
1802 const std::string& solution_info = model->
Name();
1804 const std::vector<int64_t>
solution =
1807 const std::vector<int64_t> updated_solution =
1809 LOG(INFO) <<
"Found solution with repaired hint penalty = "
1813 shared_response_manager->NewSolution(
1814 solution, absl::StrCat(solution_info,
" [repaired]"), &local_model);
1823 CpModelProto mapping_proto,
1824 absl::Span<const int> postsolve_mapping,
1831 auto* var_proto = mapping_proto.mutable_variables(postsolve_mapping[
i]);
1832 var_proto->clear_domain();
1840 Model postsolve_model;
1843 SatParameters& params = *postsolve_model.
GetOrCreate<SatParameters>();
1844 params.set_linearization_level(0);
1845 params.set_cp_model_probing_level(0);
1853 const CpSolverResponse postsolve_response = response_manager->GetResponse();
1854 CHECK(postsolve_response.status() == CpSolverStatus::FEASIBLE ||
1855 postsolve_response.status() == CpSolverStatus::OPTIMAL)
1856 << postsolve_response.status();
1859 CHECK_LE(num_variables_in_original_model,
1860 postsolve_response.solution().size());
1862 postsolve_response.solution().begin(),
1863 postsolve_response.solution().begin() + num_variables_in_original_model);
1867 int num_variable_in_original_model,
1868 const CpModelProto& mapping_proto,
1869 absl::Span<const int> postsolve_mapping,
1871 if (params.debug_postsolve_with_full_solver()) {
1873 mapping_proto, postsolve_mapping,
solution);
1881 auto* params = model->
GetOrCreate<SatParameters>();
1885 if (params->num_workers() == 0) {
1886 params->set_num_workers(params->num_search_workers());
1889 if (params->enumerate_all_solutions()) {
1890 if (params->num_workers() >= 1) {
1892 "Forcing sequential search as enumerating all solutions is "
1893 "not supported in multi-thread.");
1895 params->set_num_workers(1);
1900 if (!params->keep_all_feasible_solutions_in_presolve()) {
1902 "Forcing presolve to keep all feasible solution given that "
1903 "enumerate_all_solutions is true");
1905 params->set_keep_all_feasible_solutions_in_presolve(
true);
1908 if (!model_proto.assumptions().empty()) {
1909 if (params->num_workers() >= 1) {
1911 "Forcing sequential search as assumptions are not supported "
1912 "in multi-thread.");
1914 if (!params->keep_all_feasible_solutions_in_presolve()) {
1916 "Forcing presolve to keep all feasible solutions in the "
1917 "presence of assumptions.");
1918 params->set_keep_all_feasible_solutions_in_presolve(
true);
1920 params->set_num_workers(1);
1923 if (params->num_workers() == 0) {
1925#if !defined(__PORTABLE_PLATFORM__)
1927 const int num_cores = std::max<int>(std::thread::hardware_concurrency(), 1);
1929 const int num_cores = 1;
1931 SOLVER_LOG(logger,
"Setting number of workers to ", num_cores);
1932 params->set_num_workers(num_cores);
1935 if (params->shared_tree_num_workers() == -1) {
1936 int num_shared_tree_workers = 0;
1937 if (params->num_workers() >= 16) {
1938 if (model_proto.has_objective() ||
1939 model_proto.has_floating_point_objective()) {
1940 num_shared_tree_workers = (params->num_workers() - 8) / 2;
1942 num_shared_tree_workers = (params->num_workers() - 8) * 3 / 4;
1945 SOLVER_LOG(logger,
"Setting number of shared tree workers to ",
1946 num_shared_tree_workers);
1947 params->set_shared_tree_num_workers(num_shared_tree_workers);
1955 if (params->interleave_search() || params->num_workers() == 1 ||
1956 !params->use_lns()) {
1957 params->set_use_rins_lns(
false);
1958 params->set_use_feasibility_pump(
false);
1962 if (params->linearization_level() == 0) {
1963 params->set_use_feasibility_pump(
false);
1968 if (!params->fill_tightened_domains_in_response() &&
1969 params->num_workers() == 1) {
1970 params->set_share_level_zero_bounds(
false);
1984 const SatParameters& params = *global_model->
GetOrCreate<SatParameters>();
1986 if (params.share_level_zero_bounds()) {
1987 bounds = std::make_unique<SharedBoundsManager>(*proto);
1988 bounds->set_dump_prefix(absl::GetFlag(FLAGS_cp_model_dump_prefix));
1989 bounds->LoadDebugSolution(response->DebugSolution());
1998 if (params.use_rins_lns() || params.use_feasibility_pump()) {
1999 lp_solutions = std::make_unique<SharedLPSolutionRepository>(
2001 global_model->Register<SharedLPSolutionRepository>(lp_solutions.get());
2003 incomplete_solutions = std::make_unique<SharedIncompleteSolutionManager>();
2004 global_model->Register<SharedIncompleteSolutionManager>(
2005 incomplete_solutions.get());
2009 const bool always_synchronize =
2010 !params.interleave_search() || params.num_workers() <= 1;
2011 response->SetSynchronizationMode(always_synchronize);
2012 if (params.share_binary_clauses() && params.num_workers() > 1) {
2013 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
bool ComputeTransitiveReduction(bool log_info=false)
SatSolver::Status Probe()
sat::Literal Literal(int ref) const
IntegerVariable NumIntegerVariables() const
ABSL_MUST_USE_RESULT bool Enqueue(IntegerLiteral i_lit)
void InitAllDecomposedEnergies()
Calls InitDecomposedEnergies on all SchedulingDemandHelper created.
SatSolver::Status Search(const std::function< void()> &feasible_solution_observer)
Explores the search space.
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)
bool ProbeBooleanVariables(double deterministic_time_limit)
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)
UniqueClauseStream * GetClauseStream(int id)
void GetUnseenBinaryClauses(int id, std::vector< std::pair< int, int > > *new_clauses)
std::vector< absl::Span< const 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)
void assign(size_type n, const value_type &val)
ABSL_FLAG(bool, cp_model_dump_models, false, "DEBUG ONLY. When set to true, SolveCpModel() will dump its model " "protos (original model, presolved model, mapping model) in text " "format to 'FLAGS_cp_model_dump_prefix'{model|presolved_model|" "mapping_model}.pb.txt.")
absl::Status GetTextProto(absl::string_view filename, google::protobuf::Message *proto, Options options)
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)
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,...)