31#if !defined(__PORTABLE_PLATFORM__)
35#include "absl/algorithm/container.h"
36#include "absl/cleanup/cleanup.h"
37#include "absl/container/flat_hash_set.h"
38#include "absl/flags/flag.h"
39#include "absl/log/check.h"
40#include "absl/log/log.h"
41#include "absl/log/vlog_is_on.h"
42#include "absl/strings/escaping.h"
43#include "absl/strings/str_cat.h"
44#include "absl/strings/string_view.h"
45#include "absl/types/span.h"
46#include "google/protobuf/arena.h"
89#if !defined(__PORTABLE_PLATFORM__)
97 std::string, cp_model_load_debug_solution,
"",
98 "DEBUG ONLY. When this is set to a non-empty file name, "
99 "we will interpret this as an internal solution which can be used for "
100 "debugging. For instance we use it to identify wrong cuts/reasons.");
109#if !defined(__PORTABLE_PLATFORM__)
110 if (absl::GetFlag(FLAGS_cp_model_load_debug_solution).empty())
return;
114 "Reading debug solution from '",
115 absl::GetFlag(FLAGS_cp_model_load_debug_solution),
"'.");
131 if (shared_response ==
nullptr)
return;
132 if (shared_response->DebugSolution().empty())
return;
137 "Debug solution is not feasible.");
144 debug_sol.
proto_values = shared_response->DebugSolution();
147 const int num_integers =
152 std::vector<Literal> boolean_solution;
156 if (mapping.IsBoolean(
i)) {
161 boolean_solution.push_back(l);
164 if (!mapping.IsInteger(
i))
continue;
165 const IntegerVariable var = mapping.Integer(
i);
175 if (boolean_solution.size() == debug_sol.
proto_values.size() &&
178 "Loaded pure Boolean debugging solution.");
185 if (objective_def !=
nullptr &&
187 if (absl::c_all_of(objective_def->vars, [&debug_sol](IntegerVariable var) {
188 return var < debug_sol.ivar_has_value.end_index() &&
189 debug_sol.ivar_has_value[var];
191 const IntegerVariable objective_var = objective_def->objective_var;
196 IntegerValue objective_value = 0;
197 for (
int i = 0;
i < objective_def->vars.size(); ++
i) {
198 objective_value += objective_def->coeffs[
i] *
203 absl::StrCat(
"Debug solution objective value: ",
204 objective_def->ScaleIntegerObjective(objective_value)));
207 debug_sol.
ivar_values[objective_var] = objective_value;
215 const auto checker = [mapping = &mapping, encoder, model](
216 absl::Span<const Literal> clause,
217 absl::Span<const IntegerLiteral> integers) {
219 if (!debug_sol || debug_sol->
proto_values.empty())
return true;
221 bool is_satisfied =
false;
222 std::vector<std::tuple<Literal, IntegerLiteral, IntegerValue>> to_print;
223 for (
const Literal l : clause) {
226 const int proto_var =
227 mapping->GetProtoVariableFromBooleanVariable(l.Variable());
228 if (proto_var != -1) {
232 if (debug_sol->
proto_values[proto_var] == (l.IsPositive() ? 1 : 0)) {
242 bool all_true =
true;
243 for (
const IntegerLiteral associated : encoder->GetIntegerLiterals(l)) {
248 const IntegerValue value = debug_sol->
ivar_values[associated.var];
249 to_print.push_back({l, associated, value});
251 if (value < associated.bound) {
262 DCHECK(!i_lit.IsAlwaysFalse());
263 if (i_lit.IsAlwaysTrue())
continue;
270 const IntegerValue value = debug_sol->
ivar_values[i_lit.var];
276 if (value < i_lit.bound) {
282 LOG(INFO) <<
"Reason clause is not satisfied by loaded solution:";
283 LOG(INFO) <<
"Worker '" << model->
Name() <<
"', level="
285 LOG(INFO) <<
"literals (neg): " << clause;
286 LOG(INFO) <<
"integer literals: " << integers;
287 for (
const auto [l, i_lit, solution_value] : to_print) {
288 if (i_lit.IsAlwaysTrue()) {
289 const int proto_var =
290 mapping->GetProtoVariableFromBooleanVariable(l.Variable());
291 LOG(INFO) << l <<
" (bool in model) proto_var=" << proto_var
292 <<
" value_in_sol=" << solution_value;
294 const int proto_var = mapping->GetProtoVariableFromIntegerVariable(
296 LOG(INFO) << l <<
" " << i_lit <<
" proto_var="
297 << (proto_var == -1 ?
"none" : absl::StrCat(proto_var))
299 <<
" value_in_sol=" << solution_value;
305 const auto lit_checker = [checker =
306 checker](absl::Span<const Literal> clause) {
307 return checker(clause, {});
315 const Model& model) {
321 if (mapping->IsInteger(
i)) {
322 const IntegerVariable var = mapping->Integer(
i);
328 DCHECK(mapping->IsBoolean(
i));
330 if (trail->Assignment().LiteralIsAssigned(literal)) {
343IntegerVariable GetOrCreateVariableWithTightBound(
344 absl::Span<
const std::pair<IntegerVariable, int64_t>> terms,
Model* model) {
346 if (terms.size() == 1 && terms.front().second == 1) {
347 return terms.front().first;
349 if (terms.size() == 1 && terms.front().second == -1) {
355 for (
const std::pair<IntegerVariable, int64_t>& var_coeff : terms) {
356 const int64_t min_domain = model->Get(
LowerBound(var_coeff.first));
357 const int64_t max_domain = model->Get(
UpperBound(var_coeff.first));
358 const int64_t coeff = var_coeff.second;
359 const int64_t prod1 = min_domain * coeff;
360 const int64_t prod2 = max_domain * coeff;
361 sum_min += std::min(prod1, prod2);
362 sum_max += std::max(prod1, prod2);
367IntegerVariable GetOrCreateVariableLinkedToSumOf(
368 absl::Span<
const std::pair<IntegerVariable, int64_t>> terms,
369 bool lb_required,
bool ub_required,
Model* model) {
371 if (terms.size() == 1 && terms.front().second == 1) {
372 return terms.front().first;
374 if (terms.size() == 1 && terms.front().second == -1) {
378 const IntegerVariable new_var =
379 GetOrCreateVariableWithTightBound(terms, model);
382 std::vector<IntegerVariable> vars;
383 std::vector<IntegerValue> coeffs;
384 for (
const auto [var, coeff] : terms) {
386 coeffs.push_back(IntegerValue(coeff));
388 vars.push_back(new_var);
389 coeffs.push_back(IntegerValue(-1));
413void InitializeLinearConstraintSymmetrizerIfRequested(
416 if (!model_proto.has_symmetry())
return;
419 if (params->linearization_level() < 2)
return;
420 if (!params->use_symmetry_in_lp())
return;
432 int num_constraints_with_non_proto_variables = 0;
433 for (
const auto& lp_constraint : linear_relaxation.linear_constraints) {
434 bool has_non_proto_variable =
false;
435 for (
const IntegerVariable var : lp_constraint.VarsAsSpan()) {
436 if (mapping->GetProtoVariableFromIntegerVariable(var) == -1) {
437 has_non_proto_variable =
true;
441 if (has_non_proto_variable) {
442 ++num_constraints_with_non_proto_variables;
445 if (num_constraints_with_non_proto_variables > 0) {
448 auto* logger = m->GetOrCreate<SolverLogger>();
449 SOLVER_LOG(logger, num_constraints_with_non_proto_variables,
450 " LP constraints uses new variables not appearing in the "
451 "presolved model. ");
460 const int num_vars = model_proto.variables().size();
461 std::vector<std::unique_ptr<SparsePermutation>> generators;
463 model_proto.symmetry().permutations()) {
468 const std::vector<int> var_to_orbit_index =
GetOrbits(num_vars, generators);
469 std::vector<bool> orbit_is_ok;
470 std::vector<std::vector<IntegerVariable>> orbits;
471 for (
int proto_var = 0; proto_var < num_vars; ++proto_var) {
472 const int orbit_index = var_to_orbit_index[proto_var];
473 if (orbit_index == -1)
continue;
474 if (orbit_index >= orbits.size()) {
475 orbits.resize(orbit_index + 1);
476 orbit_is_ok.resize(orbit_index + 1,
true);
481 const IntegerVariable var = mapping->Integer(proto_var);
483 orbits[orbit_index].push_back(var);
488 std::vector<std::pair<IntegerVariable, int64_t>> terms;
489 for (
const std::vector<IntegerVariable>& orbit : orbits) {
491 for (
const IntegerVariable var : orbit) {
492 terms.push_back({var, 1});
494 const IntegerVariable sum_var =
495 GetOrCreateVariableLinkedToSumOf(terms,
true,
true, m);
496 symmetrizer->AddSymmetryOrbit(sum_var, orbit);
501IntegerVariable AddLPConstraints(
bool objective_need_to_be_tight,
508 InitializeLinearConstraintSymmetrizerIfRequested(model_proto, relaxation, m);
516 const int num_lp_constraints =
517 static_cast<int>(relaxation.linear_constraints.size());
518 const int num_lp_cut_generators =
519 static_cast<int>(relaxation.cut_generators.size());
520 const int num_integer_variables =
521 m->GetOrCreate<
IntegerTrail>()->NumIntegerVariables().value();
523 DenseConnectedComponentsFinder components;
525 num_integer_variables);
526 auto get_constraint_index = [](
int ct_index) {
return ct_index; };
527 auto get_cut_generator_index = [num_lp_constraints](
int cut_index) {
528 return num_lp_constraints + cut_index;
530 auto get_var_index = [num_lp_constraints,
531 num_lp_cut_generators](IntegerVariable var) {
532 return num_lp_constraints + num_lp_cut_generators +
535 for (
int i = 0;
i < num_lp_constraints;
i++) {
536 for (
const IntegerVariable var :
537 relaxation.linear_constraints[
i].VarsAsSpan()) {
538 components.
AddEdge(get_constraint_index(
i), get_var_index(var));
541 for (
int i = 0;
i < num_lp_cut_generators; ++
i) {
542 for (
const IntegerVariable var : relaxation.cut_generators[
i].vars) {
543 components.
AddEdge(get_cut_generator_index(
i), get_var_index(var));
549 for (
int i = 0;
i < symmetrizer->NumOrbits(); ++
i) {
550 const int representative = get_var_index(symmetrizer->OrbitSumVar(
i));
551 for (
const IntegerVariable var : symmetrizer->Orbit(
i)) {
552 components.
AddEdge(representative, get_var_index(var));
557 std::vector<int> component_sizes(num_components, 0);
558 const std::vector<int> index_to_component = components.
GetComponentIds();
559 for (
int i = 0;
i < num_lp_constraints;
i++) {
560 ++component_sizes[index_to_component[get_constraint_index(
i)]];
562 for (
int i = 0;
i < num_lp_cut_generators;
i++) {
563 ++component_sizes[index_to_component[get_cut_generator_index(
i)]];
567 std::vector<std::vector<IntegerVariable>> component_to_var(num_components);
568 for (IntegerVariable var(0); var < num_integer_variables; var += 2) {
570 component_to_var[index_to_component[get_var_index(var)]].push_back(var);
579 for (
int i = 0;
i < model_proto.objective().coeffs_size(); ++
i) {
580 const IntegerVariable var =
581 mapping->Integer(model_proto.objective().vars(
i));
582 ++component_sizes[index_to_component[get_var_index(var)]];
586 std::vector<LinearProgrammingConstraint*> lp_constraints(num_components,
588 for (
int i = 0;
i < num_lp_constraints;
i++) {
589 const int c = index_to_component[get_constraint_index(
i)];
590 if (component_sizes[c] <= 1)
continue;
591 if (lp_constraints[c] ==
nullptr) {
594 m->TakeOwnership(lp_constraints[c]);
597 if (!lp_constraints[c]->AddLinearConstraint(
598 std::move(relaxation.linear_constraints[
i]))) {
599 m->GetOrCreate<
SatSolver>()->NotifyThatModelIsUnsat();
605 for (
int i = 0;
i < num_lp_cut_generators;
i++) {
606 const int c = index_to_component[get_cut_generator_index(
i)];
607 if (lp_constraints[c] ==
nullptr) {
610 m->TakeOwnership(lp_constraints[c]);
612 lp_constraints[
c]->AddCutGenerator(std::move(relaxation.cut_generators[
i]));
618 if (params->linearization_level() > 1 && params->add_clique_cuts() &&
619 params->cut_level() > 0) {
621 if (lp ==
nullptr)
continue;
627 std::vector<std::vector<std::pair<IntegerVariable, int64_t>>>
628 component_to_cp_terms(num_components);
629 std::vector<std::pair<IntegerVariable, int64_t>> top_level_cp_terms;
630 int num_components_containing_objective = 0;
631 if (model_proto.has_objective()) {
635 std::vector<std::pair<IntegerVariable, int64_t>> objective;
636 const int num_orbits = symmetrizer->NumOrbits();
637 if (num_orbits > 0) {
639 std::vector<int64_t> orbit_obj_coeff(num_orbits, 0);
640 for (
int i = 0;
i < model_proto.objective().coeffs_size(); ++
i) {
641 const IntegerVariable var =
642 mapping->Integer(model_proto.objective().vars(
i));
643 const int64_t coeff = model_proto.objective().coeffs(
i);
644 const int orbit_index = symmetrizer->OrbitIndex(var);
645 if (orbit_index != -1) {
646 if (orbit_obj_coeff[orbit_index] == 0) {
647 orbit_obj_coeff[orbit_index] = coeff;
649 CHECK_EQ(orbit_obj_coeff[orbit_index], coeff);
653 objective.push_back({var, coeff});
655 for (
int i = 0;
i < num_orbits; ++
i) {
656 if (orbit_obj_coeff[
i] == 0)
continue;
657 objective.push_back({symmetrizer->OrbitSumVar(
i), orbit_obj_coeff[
i]});
660 for (
int i = 0;
i < model_proto.objective().coeffs_size(); ++
i) {
661 const IntegerVariable var =
662 mapping->Integer(model_proto.objective().vars(
i));
663 const int64_t coeff = model_proto.objective().coeffs(
i);
664 objective.push_back({var, coeff});
670 for (
const auto [var, coeff] : objective) {
671 const int c = index_to_component[get_var_index(var)];
672 if (lp_constraints[c] !=
nullptr) {
673 lp_constraints[
c]->SetObjectiveCoefficient(var, IntegerValue(coeff));
674 component_to_cp_terms[
c].push_back(std::make_pair(var, coeff));
677 top_level_cp_terms.push_back(std::make_pair(var, coeff));
681 for (
int c = 0;
c < num_components; ++
c) {
682 if (component_to_cp_terms[c].empty())
continue;
683 const IntegerVariable sub_obj_var = GetOrCreateVariableLinkedToSumOf(
684 component_to_cp_terms[c], objective_need_to_be_tight,
true, m);
685 top_level_cp_terms.push_back(std::make_pair(sub_obj_var, 1));
686 lp_constraints[
c]->SetMainObjectiveVariable(sub_obj_var);
687 num_components_containing_objective++;
691 const IntegerVariable main_objective_var =
692 model_proto.has_objective()
693 ? GetOrCreateVariableLinkedToSumOf(
694 top_level_cp_terms, objective_need_to_be_tight,
true, m)
700 if (lp_constraint ==
nullptr)
continue;
701 lp_constraint->RegisterWith(m);
702 VLOG(3) <<
"LP constraint: " << lp_constraint->DimensionString() <<
".";
705 VLOG(3) << top_level_cp_terms.size()
706 <<
" terms in the main objective linear equation ("
707 << num_components_containing_objective <<
" from LP constraints).";
708 return main_objective_var;
718 CHECK(shared_bounds_manager !=
nullptr);
724 int saved_trail_index = 0;
725 std::vector<int> model_variables;
726 std::vector<int64_t> new_lower_bounds;
727 std::vector<int64_t> new_upper_bounds;
728 absl::flat_hash_set<int> visited_variables;
729 const std::string name = model->
Name();
731 auto broadcast_level_zero_bounds =
732 [=](absl::Span<const IntegerVariable> modified_vars)
mutable {
734 for (
const IntegerVariable& var : modified_vars) {
736 const int model_var =
737 mapping->GetProtoVariableFromIntegerVariable(positive_var);
739 if (model_var == -1)
continue;
740 const auto [_, inserted] = visited_variables.insert(model_var);
741 if (!inserted)
continue;
743 const int64_t new_lb =
744 integer_trail->LevelZeroLowerBound(positive_var).value();
745 const int64_t new_ub =
746 integer_trail->LevelZeroUpperBound(positive_var).value();
750 model_variables.push_back(model_var);
751 new_lower_bounds.push_back(new_lb);
752 new_upper_bounds.push_back(new_ub);
756 for (; saved_trail_index < trail->Index(); ++saved_trail_index) {
757 const Literal fixed_literal = (*trail)[saved_trail_index];
758 const int model_var = mapping->GetProtoVariableFromBooleanVariable(
761 if (model_var == -1)
continue;
762 const auto [_, inserted] = visited_variables.insert(model_var);
763 if (!inserted)
continue;
765 model_variables.push_back(model_var);
767 new_lower_bounds.push_back(1);
768 new_upper_bounds.push_back(1);
770 new_lower_bounds.push_back(0);
771 new_upper_bounds.push_back(0);
775 if (!model_variables.empty()) {
777 model->
Name(), model_variables, new_lower_bounds,
781 model_variables.clear();
782 new_lower_bounds.clear();
783 new_upper_bounds.clear();
784 visited_variables.clear();
800 const IntegerVariable num_vars =
802 std::vector<IntegerVariable> all_variables;
803 all_variables.reserve(num_vars.value());
804 for (IntegerVariable var(0); var < num_vars; ++var) {
805 all_variables.push_back(var);
807 broadcast_level_zero_bounds(all_variables);
810 ->RegisterLevelZeroModifiedVariablesCallback(broadcast_level_zero_bounds);
819 CHECK(shared_bounds_manager !=
nullptr);
820 const std::string name = model->
Name();
829 const auto& import_level_zero_bounds =
830 [&model_proto, shared_bounds_manager, name = name, sat_solver,
831 integer_trail, trail, lrat_proof_handler, clause_id_generator, id,
833 std::vector<int> model_variables;
834 std::vector<int64_t> new_lower_bounds;
835 std::vector<int64_t> new_upper_bounds;
837 id, &model_variables, &new_lower_bounds, &new_upper_bounds);
838 for (
int i = 0;
i < model_variables.size(); ++
i) {
839 const int model_var = model_variables[
i];
844 if (mapping->IsBoolean(model_var)) {
845 Literal lit = mapping->Literal(model_var);
846 if (new_upper_bounds[
i] == 0) lit = lit.
Negated();
847 if (trail->Assignment().LiteralIsTrue(lit))
continue;
849 if (lrat_proof_handler !=
nullptr) {
850 clause_id = clause_id_generator->GetNextId();
851 lrat_proof_handler->AddImportedClause(clause_id, {lit});
853 if (trail->Assignment().LiteralIsFalse(lit)) {
854 if (lrat_proof_handler !=
nullptr) {
856 lrat_proof_handler->AddInferredClause(
857 clause_id_generator->GetNextId(), {},
858 {clause_id, trail->GetUnitClauseId(lit.Variable())});
860 sat_solver->NotifyThatModelIsUnsat();
863 trail->EnqueueWithUnitReason(clause_id, lit);
868 if (!mapping->IsInteger(model_var))
continue;
869 const IntegerVariable var = mapping->Integer(model_var);
870 const IntegerValue new_lb(new_lower_bounds[
i]);
871 const IntegerValue new_ub(new_upper_bounds[
i]);
872 const IntegerValue old_lb = integer_trail->LowerBound(var);
873 const IntegerValue old_ub = integer_trail->UpperBound(var);
874 const bool changed_lb = new_lb > old_lb;
875 const bool changed_ub = new_ub < old_ub;
876 if (!changed_lb && !changed_ub)
continue;
881 const std::string& var_name =
882 var_proto.
name().empty()
883 ? absl::StrCat(
"anonymous_var(", model_var,
")")
885 LOG(INFO) <<
" '" << name <<
"' imports new bounds for "
886 << var_name <<
": from [" << old_lb <<
", " << old_ub
887 <<
"] to [" << new_lb <<
", " << new_ub <<
"]";
891 !integer_trail->Enqueue(
907 import_level_zero_bounds);
912 CHECK(shared_linear2_bounds !=
nullptr);
916 const int import_id =
918 const auto& import_function = [import_id, shared_linear2_bounds, root_linear2,
919 cp_model_mapping, sat_solver, model]() {
920 const auto new_bounds =
922 int num_imported = 0;
923 for (
const auto& [proto_expr, bounds] : new_bounds) {
926 if (!cp_model_mapping->IsInteger(proto_expr.vars[0]) ||
927 !cp_model_mapping->IsInteger(proto_expr.vars[1])) {
930 for (
const int i : {0, 1}) {
931 expr.
vars[
i] = cp_model_mapping->Integer(proto_expr.vars[
i]);
932 expr.
coeffs[
i] = proto_expr.coeffs[
i];
934 const auto [lb, ub] = bounds;
935 const auto [lb_added, ub_added] = root_linear2->Add(expr, lb, ub);
936 if (!lb_added && !ub_added)
continue;
944 const std::vector<IntegerValue> coeffs = {expr.
coeffs[0].value(),
949 if (sat_solver->ModelIsUnsat())
return false;
954 if (sat_solver->ModelIsUnsat())
return false;
967 IntegerVariable objective_var,
970 const auto broadcast_objective_lower_bound =
971 [objective_var, integer_trail, shared_response_manager, model,
974 const IntegerValue objective_lb =
975 integer_trail->LevelZeroLowerBound(objective_var);
976 if (objective_lb > best_obj_lb) {
977 best_obj_lb = objective_lb;
979 model->
Name(), objective_lb,
980 integer_trail->LevelZeroUpperBound(objective_var));
988 ->RegisterLevelZeroModifiedVariablesCallback(
989 broadcast_objective_lower_bound);
1000 const std::string name = model->
Name();
1002 const auto import_objective_bounds = [name = name, solver, integer_trail,
1003 objective, shared_response_manager,
1005 if (solver->AssumptionLevel() != 0)
return true;
1006 bool tighter_bounds =
false;
1008 const IntegerValue external_lb =
1010 const IntegerValue current_lb =
1011 integer_trail->LowerBound(objective->objective_var);
1012 if (external_lb > current_lb) {
1014 objective->objective_var, external_lb),
1018 tighter_bounds =
true;
1021 const IntegerValue external_ub =
1023 const IntegerValue current_ub =
1024 integer_trail->UpperBound(objective->objective_var);
1025 if (external_ub < current_ub) {
1030 if (debug_sol && external_ub <= debug_sol->inner_objective_value) {
1035 objective->objective_var, external_ub),
1039 tighter_bounds =
true;
1044 if (tighter_bounds) {
1045 VLOG(3) <<
"'" << name <<
"' imports objective bounds: external ["
1046 << objective->ScaleIntegerObjective(external_lb) <<
", "
1047 << objective->ScaleIntegerObjective(external_ub) <<
"], current ["
1048 << objective->ScaleIntegerObjective(current_lb) <<
", "
1049 << objective->ScaleIntegerObjective(current_ub) <<
"]";
1056 import_objective_bounds);
1063 const auto& share_binary_clause = [mapping, id, shared_clauses_manager](
1066 mapping->GetProtoVariableFromBooleanVariable(l1.Variable());
1067 if (var1 == -1)
return;
1069 mapping->GetProtoVariableFromBooleanVariable(l2.Variable());
1070 if (var2 == -1)
return;
1071 const int lit1 = l1.IsPositive() ? var1 :
NegatedRef(var1);
1072 const int lit2 = l2.IsPositive() ? var2 :
NegatedRef(var2);
1076 share_binary_clause);
1080 const double share_interval =
1085 auto share_clause = [mapping, clause_stream, time_limit, lrat_proof_handler,
1086 id, shared_clauses_manager, share_interval,
1087 next_batch_dtime = -1.0, clause = std::vector<int>()](
1088 int lbd, ClauseId clause_id,
1089 absl::Span<const Literal> literals)
mutable {
1093 for (
const Literal& lit : literals) {
1095 mapping->GetProtoVariableFromBooleanVariable(lit.Variable());
1096 if (var == -1)
return;
1097 clause.push_back(lit.IsPositive() ? var :
NegatedRef(var));
1099 if (clause_stream->Add(clause, lbd) && lrat_proof_handler !=
nullptr) {
1100 lrat_proof_handler->ExportClause(clause_id, literals);
1103 const double elapsed_dtime = time_limit->GetElapsedDeterministicTime();
1104 if (next_batch_dtime < 0) next_batch_dtime = elapsed_dtime + share_interval;
1105 if (elapsed_dtime >= next_batch_dtime) {
1106 shared_clauses_manager->
AddBatch(
id, clause_stream->NextBatch());
1107 next_batch_dtime = elapsed_dtime + share_interval;
1111 std::move(share_clause));
1123 CHECK(shared_clauses_manager !=
nullptr);
1128 const bool share_glue_clauses =
1130 auto* clause_stream =
1132 const bool minimize_shared_clauses =
1135 const auto& import_level_zero_clauses = [shared_clauses_manager, id, mapping,
1136 sat_solver, vivifier, implications,
1137 minimize_shared_clauses,
1139 clause_manager]()
mutable {
1140 std::vector<std::pair<int, int>> new_binary_clauses;
1142 implications->EnableSharing(
false);
1143 for (
const auto& [ref1, ref2] : new_binary_clauses) {
1146 if (!sat_solver->AddProblemClause({l1, l2},
true)) {
1150 implications->EnableSharing(
true);
1151 if (clause_stream ==
nullptr)
return true;
1153 int new_clauses = 0;
1154 std::array<Literal, UniqueClauseStream::kMaxClauseSize> local_clause;
1155 sat_solver->EnsureNewClauseIndexInitialized();
1157 auto callback = clause_manager->TakeAddClauseCallback();
1160 if (batch.empty())
break;
1161 for (
int clause_index = 0; clause_index < batch.size(); ++clause_index) {
1162 const absl::Span<const int>& shared_clause = batch[clause_index];
1164 if (!clause_stream->BlockClause(shared_clause))
continue;
1166 for (
int i = 0;
i < shared_clause.size(); ++
i) {
1167 local_clause[
i] = mapping->
Literal(shared_clause[
i]);
1169 if (!sat_solver->AddProblemClause(
1170 absl::MakeSpan(local_clause).subspan(0, shared_clause.size()),
1176 clause_manager->SetAddClauseCallback(std::move(callback));
1177 if (new_clauses > 0) {
1181 if (new_clauses > 0 && !sat_solver->FinishPropagation())
return false;
1182 if (minimize_shared_clauses && new_clauses > 0) {
1196 import_level_zero_clauses);
1207void FillConditionalLinear2Bounds(
const CpModelProto& model_proto,
1209 auto* integer_trail = model->GetOrCreate<IntegerTrail>();
1210 auto* encoder = model->GetOrCreate<IntegerEncoder>();
1211 auto* mapping = model->GetOrCreate<CpModelMapping>();
1212 auto* repository = model->GetOrCreate<ConditionalLinear2Bounds>();
1213 auto* root_level_lin2_bounds = model->GetOrCreate<RootLevelLinear2Bounds>();
1214 auto* reified_lin2_bounds = model->GetOrCreate<ReifiedLinear2Bounds>();
1216 for (
const ConstraintProto& ct : model_proto.constraints()) {
1221 if (ct.enforcement_literal().size() == 2 && ct.linear().vars_size() == 1) {
1224 auto process = [&](Literal enforcement_literal, IntegerVariable var1,
1225 const Domain& var1_domain, Literal lit2,
1226 int64_t implied_lb) {
1227 const int64_t delta = implied_lb - var1_domain.Min();
1228 if (delta <= 0)
return;
1229 const IntegerVariable var2 = encoder->GetLiteralView(lit2);
1230 const IntegerVariable negated_var2 =
1231 encoder->GetLiteralView(lit2.Negated());
1236 repository->Add(enforcement_literal,
1237 LinearExpression2(var1, var2, 1, -delta),
1238 var1_domain.Min(), var1_domain.Max());
1243 repository->Add(enforcement_literal,
1245 var1_domain.Min() + delta, var1_domain.Max() + delta);
1248 const IntegerVariable var = mapping->Integer(ct.linear().vars(0));
1250 model_proto.variables(ct.linear().vars(0));
1252 const Domain implied_var_domain =
1255 for (
int i = 0;
i < 2; ++
i) {
1258 process(lit1, var, var_domain, lit2, implied_var_domain.
Min());
1259 process(lit1,
NegationOf(var), var_domain.Negation(), lit2,
1260 -implied_var_domain.
Max());
1263 }
else if (ct.enforcement_literal().size() > 1 ||
1264 ct.linear().vars_size() > 2) {
1267 const std::vector<IntegerVariable> vars =
1268 mapping->Integers(ct.linear().vars());
1269 absl::Span<const int64_t> coeffs = ct.linear().coeffs();
1271 const auto [min_sum, max_sum] =
1272 mapping->ComputeMinMaxActivity(ct.linear(), integer_trail);
1274 const int64_t rhs_min = std::max(ct.linear().domain(0), min_sum);
1275 const int64_t rhs_max =
1276 std::min(ct.linear().domain(ct.linear().domain().size() - 1), max_sum);
1278 if (ct.enforcement_literal().empty()) {
1279 if (vars.size() == 2) {
1281 root_level_lin2_bounds->Add(expr, rhs_min, rhs_max);
1282 }
else if (vars.size() == 3 && rhs_min == rhs_max) {
1283 reified_lin2_bounds->AddLinear3(vars, coeffs, rhs_min);
1286 if (vars.size() == 2) {
1294 repository->Build();
1301 CHECK(shared_response_manager !=
nullptr);
1305 const auto unsat = [shared_response_manager, sat_solver, model] {
1306 sat_solver->NotifyThatModelIsUnsat();
1307 shared_response_manager->NotifyThatImprovingProblemIsInfeasible(
1308 absl::StrCat(model->
Name(),
" [loading]"));
1316 const bool view_all_booleans_as_integers =
1317 (parameters.linearization_level() >= 2) ||
1321 LoadVariables(model_proto, view_all_booleans_as_integers, model);
1333 if (!parameters.optimize_with_core() && parameters.symmetry_level() > 1 &&
1334 !parameters.enumerate_all_solutions() &&
1335 parameters.linearization_level() == 0) {
1347 if (sat_solver->ModelIsUnsat())
return unsat();
1351 if (sat_solver->ModelIsUnsat())
return unsat();
1353 FillConditionalLinear2Bounds(model_proto, model);
1358 int num_ignored_constraints = 0;
1361 absl::flat_hash_set<ConstraintProto::ConstraintCase> unsupported_types;
1363 if (mapping->ConstraintIsAlreadyLoaded(&ct)) {
1364 ++num_ignored_constraints;
1369 unsupported_types.insert(ct.constraint_case());
1381 if (sat_solver->FinishPropagation()) {
1383 const int old_num_fixed = trail->
Index();
1384 if (trail->
Index() > old_num_fixed) {
1385 VLOG(3) <<
"Constraint fixed " << trail->
Index() - old_num_fixed
1390 if (sat_solver->ModelIsUnsat()) {
1391 VLOG(2) <<
"UNSAT during extraction (after adding '"
1397 if (num_ignored_constraints > 0) {
1398 VLOG(3) << num_ignored_constraints <<
" constraints were skipped.";
1400 if (!unsupported_types.empty()) {
1403 "There is unsupported constraints types in this model: ");
1404 std::vector<absl::string_view> names;
1408 std::sort(names.begin(), names.end());
1409 for (
const absl::string_view name : names) {
1415 SOLVER_LOG(logger,
"BUG: We will wrongly report INFEASIBLE now.");
1423 ->AddAllImplicationsBetweenAssociatedLiterals();
1424 if (!sat_solver->FinishPropagation())
return unsat();
1438 if (parameters.linearization_level() == 0)
return;
1445 const int num_lp_constraints =
1447 if (num_lp_constraints == 0)
return;
1449 for (
int i = 0;
i < num_lp_constraints;
i++) {
1454 for (
int i = 0;
i < model_proto.
objective().coeffs_size(); ++
i) {
1455 const IntegerVariable var =
1458 feasibility_pump->SetObjectiveCoefficient(var, IntegerValue(coeff));
1478 const auto unsat = [shared_response_manager, sat_solver, model] {
1479 sat_solver->NotifyThatModelIsUnsat();
1480 shared_response_manager->NotifyThatImprovingProblemIsInfeasible(
1481 absl::StrCat(model->
Name(),
" [loading]"));
1491 ->AddGreaterThanAtLeastOneOfConstraints(model);
1492 if (!sat_solver->FinishPropagation())
return unsat();
1517 if (sat_solver->ModelIsUnsat())
return unsat();
1524 if (repository !=
nullptr) {
1530 bool objective_need_to_be_tight =
false;
1534 int64_t min_value = 0;
1535 int64_t max_value = 0;
1538 for (
int i = 0;
i < obj.vars_size(); ++
i) {
1539 const int64_t coeff = obj.coeffs(
i);
1540 const IntegerVariable var = mapping->Integer(obj.vars(
i));
1542 min_value += coeff * integer_trail->LowerBound(var).value();
1543 max_value += coeff * integer_trail->UpperBound(var).value();
1545 min_value += coeff * integer_trail->UpperBound(var).value();
1546 max_value += coeff * integer_trail->LowerBound(var).value();
1550 const Domain automatic_domain =
Domain(min_value, max_value);
1551 objective_need_to_be_tight = !automatic_domain.
IsIncludedIn(user_domain);
1560 AddLPConstraints(objective_need_to_be_tight, model_proto, model);
1561 if (sat_solver->ModelIsUnsat())
return unsat();
1564 std::vector<std::pair<IntegerVariable, int64_t>> terms;
1568 std::make_pair(mapping->Integer(obj.
vars(
i)), obj.
coeffs(
i)));
1571 if (objective_need_to_be_tight) {
1581 GetOrCreateVariableLinkedToSumOf(terms,
true,
false, model);
1583 objective_var = GetOrCreateVariableWithTightBound(terms, model);
1586 objective_var = GetOrCreateVariableLinkedToSumOf(
1587 terms, objective_need_to_be_tight,
true, model);
1598 if (objective_definition->scaling_factor == 0.0) {
1599 objective_definition->scaling_factor = 1.0;
1601 objective_definition->offset = objective_proto.
offset();
1602 objective_definition->objective_var = objective_var;
1604 const int size = objective_proto.
vars_size();
1605 objective_definition->vars.resize(size);
1606 objective_definition->coeffs.resize(size);
1607 for (
int i = 0;
i < objective_proto.
vars_size(); ++
i) {
1610 objective_definition->vars[
i] = mapping->Integer(objective_proto.
vars(
i));
1611 objective_definition->coeffs[
i] = IntegerValue(objective_proto.
coeffs(
i));
1614 const int ref = objective_proto.
vars(
i);
1615 if (mapping->IsInteger(ref)) {
1616 const IntegerVariable var = mapping->Integer(objective_proto.
vars(
i));
1617 objective_definition->objective_impacting_variables.insert(
1625 objective_definition->coeffs, model));
1632 const Domain automatic_domain =
1633 integer_trail->InitialVariableDomain(objective_var);
1636 VLOG(3) <<
"Automatic internal objective domain: " << automatic_domain;
1637 VLOG(3) <<
"User specified internal objective domain: " << user_domain;
1639 if (!integer_trail->UpdateInitialDomain(objective_var, user_domain)) {
1640 VLOG(2) <<
"UNSAT due to the objective domain.";
1648 "Initial num_bool: ", sat_solver->NumVariables());
1649 if (!sat_solver->FinishPropagation())
return unsat();
1654 shared_response_manager->UpdateInnerObjectiveBounds(
1655 absl::StrCat(model->
Name(),
" (initial_propagation)"),
1656 integer_trail->LowerBound(objective_var),
1657 integer_trail->UpperBound(objective_var));
1675 search_heuristics->heuristic_search =
1677 search_heuristics->integer_completion_search =
1679 objective_var, model);
1681 if (VLOG_IS_ON(3)) {
1682 search_heuristics->fixed_search =
1684 search_heuristics->fixed_search, model);
1686 search_heuristics->hint_search =
1693 const auto solution_observer = [&model_proto, model,
1694 shared_response_manager,
1696 const std::vector<int64_t>
solution =
1698 const IntegerValue obj_ub =
1700 if (obj_ub < best_obj_ub) {
1701 best_obj_ub = obj_ub;
1702 shared_response_manager->NewSolution(
solution, model->Name(), model);
1709 model_proto, objective, solution_observer, model);
1711 model->TakeOwnership(max_hs);
1715 objective.coeffs, solution_observer, model);
1717 model->TakeOwnership(core);
1732 if (shared_response_manager->ProblemIsSolved())
return;
1747 auto solution_observer = [&model_proto, model, shared_response_manager,
1749 const std::vector<int64_t>
solution =
1752 const IntegerValue obj_ub =
1754 if (obj_ub < best_obj_ub) {
1755 best_obj_ub = obj_ub;
1756 shared_response_manager->NewSolution(
solution, model->
Name(), model);
1759 shared_response_manager->NewSolution(
solution, model->
Name(), model);
1765 shared_response_manager->NotifyThatImprovingProblemIsInfeasible(
1779 status = prober.
Probe();
1781 shared_response_manager->NotifyThatImprovingProblemIsInfeasible(
1786 solution_observer();
1795 status = subtree_worker->
Search(solution_observer);
1798 mapping.Literals(model_proto.
assumptions()), model);
1801 solution_observer();
1806 shared_response_manager->NotifyThatImprovingProblemIsInfeasible(
1810 shared_response_manager->NotifyThatImprovingProblemIsInfeasible(
1816 std::vector<Literal> core = sat_solver->GetLastIncompatibleDecisions();
1818 std::vector<int> core_in_proto_format;
1819 for (
const Literal l : core) {
1820 core_in_proto_format.push_back(
1821 mapping.GetProtoVariableFromBooleanVariable(l.Variable()));
1822 if (!l.IsPositive()) {
1823 core_in_proto_format.back() =
NegatedRef(core_in_proto_format.back());
1826 shared_response_manager->AddUnsatCore(core_in_proto_format);
1831 const IntegerVariable objective_var = objective.
objective_var;
1836 status = search->
Search(solution_observer);
1847 status = subtree_worker->
Search(solution_observer);
1853 solution_observer, model);
1856 objective_var, solution_observer, model);
1864 shared_response_manager->NotifyThatImprovingProblemIsInfeasible(
1878 if (shared_response_manager->ProblemIsSolved())
return;
1889 if (parameters->optimize_with_core())
return;
1894 parameters->set_optimize_with_core(
false);
1895 parameters->set_use_sat_inprocessing(
false);
1897 ::absl::MakeCleanup([parameters, saved_params = saved_params]() {
1898 *parameters = saved_params;
1905 mapping.Literals(model_proto.
assumptions()), model);
1907 const std::string& solution_info = model->
Name();
1909 const std::vector<int64_t>
solution =
1911 shared_response_manager->NewSolution(
1912 solution, absl::StrCat(solution_info,
" [hint]"), model);
1915 if (parameters->enumerate_all_solutions()) {
1920 const IntegerVariable objective_var =
1929 shared_response_manager->GetInnerObjectiveUpperBound() <=
1935 if (!integer_trail->Enqueue(
1938 shared_response_manager->GetInnerObjectiveUpperBound()),
1940 shared_response_manager->NotifyThatImprovingProblemIsInfeasible(
1941 absl::StrCat(solution_info,
" [hint]"));
1953 if (parameters->debug_crash_on_bad_hint() &&
1954 shared_response_manager->HasFeasibleSolution() &&
1957 LOG(FATAL) <<
"QuickSolveWithHint() didn't find a feasible solution."
1958 <<
" The model name is '" << model_proto.
name() <<
"'."
1959 <<
" Status: " << status <<
".";
1963 shared_response_manager->NotifyThatImprovingProblemIsInfeasible(
1964 absl::StrCat(solution_info,
" [hint]"));
1982 if (shared_response_manager->ProblemIsSolved())
return;
1988 if (parameters->enumerate_all_solutions())
return;
1992 *parameters = saved_params;
2008 const int64_t min_domain = model_proto.
variables(var).
domain(0) - value;
2009 const int64_t max_domain =
2030 const int64_t abs_min_domain = 0;
2031 const int64_t abs_max_domain =
2032 std::max(std::abs(min_domain), std::abs(max_domain));
2037 abs_ct->mutable_target()->add_coeffs(1);
2049 auto* local_response_manager =
2065 mapping.Literals(updated_model_proto.
assumptions()), &local_model);
2067 const std::string& solution_info = model->
Name();
2069 const std::vector<int64_t>
solution =
2072 const std::vector<int64_t> updated_solution =
2074 LOG(INFO) <<
"Found solution with repaired hint penalty = "
2078 shared_response_manager->NewSolution(
2079 solution, absl::StrCat(solution_info,
" [repaired]"), &local_model);
2093 absl::Span<const int> postsolve_mapping,
2109 Model postsolve_model;
2122 const CpSolverResponse postsolve_response = response_manager->GetResponse();
2125 << postsolve_response.
status();
2128 CHECK_LE(num_variables_in_original_model,
2129 postsolve_response.
solution().size());
2131 postsolve_response.
solution().begin(),
2132 postsolve_response.
solution().begin() + num_variables_in_original_model);
2136 int num_variable_in_original_model,
2138 absl::Span<const int> postsolve_mapping,
2142 mapping_proto, postsolve_mapping,
solution);
2154 if (params->num_workers() == 0) {
2155 params->set_num_workers(params->num_search_workers());
2158 if (params->enumerate_all_solutions()) {
2159 if (params->num_workers() == 0) {
2161 "Setting num_workers to 1 since it is not specified and "
2162 "enumerate_all_solutions is true.");
2163 params->set_num_workers(1);
2164 }
else if (params->num_workers() > 1) {
2167 "WARNING: enumerating all solutions in multi-thread works but might "
2168 "lead to the same solution being found up to num_workers times.");
2171 if (!params->has_keep_all_feasible_solutions_in_presolve()) {
2173 "Forcing presolve to keep all feasible solution given that "
2174 "enumerate_all_solutions is true and that option is unset.");
2175 params->set_keep_all_feasible_solutions_in_presolve(
true);
2180 if (params->num_workers() >= 1) {
2182 "Forcing sequential search as assumptions are not supported "
2183 "in multi-thread.");
2185 if (!params->keep_all_feasible_solutions_in_presolve()) {
2187 "Forcing presolve to keep all feasible solutions in the "
2188 "presence of assumptions.");
2189 params->set_keep_all_feasible_solutions_in_presolve(
true);
2191 params->set_num_workers(1);
2194 if (params->num_workers() == 0) {
2196#if !defined(__PORTABLE_PLATFORM__)
2198 const int num_cores = std::max<int>(std::thread::hardware_concurrency(), 1);
2200 const int num_cores = 1;
2202 SOLVER_LOG(logger,
"Setting number of workers to ", num_cores);
2203 params->set_num_workers(num_cores);
2206 if (params->shared_tree_num_workers() == -1) {
2207 int num_shared_tree_workers = 0;
2210 num_shared_tree_workers = (params->num_workers() - 16) / 2;
2212 num_shared_tree_workers = (params->num_workers() - 8) * 3 / 4;
2214 if (num_shared_tree_workers > 4) {
2215 SOLVER_LOG(logger,
"Setting number of shared tree workers to ",
2216 num_shared_tree_workers);
2217 params->set_shared_tree_num_workers(num_shared_tree_workers);
2226 if (params->interleave_search() || params->num_workers() == 1 ||
2227 !params->use_lns()) {
2228 params->set_use_rins_lns(
false);
2229 params->set_use_feasibility_pump(
false);
2233 if (params->linearization_level() == 0) {
2234 params->set_use_feasibility_pump(
false);
2239 if (!params->fill_tightened_domains_in_response() &&
2240 params->num_workers() == 1) {
2241 params->set_share_level_zero_bounds(
false);
2260 bounds = std::make_unique<SharedBoundsManager>(*proto);
2261 bounds->set_dump_prefix(absl::GetFlag(FLAGS_cp_model_dump_prefix));
2262 bounds->LoadDebugSolution(response->DebugSolution());
2266 linear2_bounds = std::make_unique<SharedLinear2Bounds>();
2276 lp_solutions = std::make_unique<SharedLPSolutionRepository>(
2278 global_model->Register<SharedLPSolutionRepository>(lp_solutions.get());
2280 incomplete_solutions = std::make_unique<SharedIncompleteSolutionManager>();
2281 global_model->Register<SharedIncompleteSolutionManager>(
2282 incomplete_solutions.get());
2286 const bool always_synchronize =
2288 response->SetSynchronizationMode(always_synchronize);
2290 clauses = std::make_unique<SharedClausesManager>(always_synchronize);
2334 if (!
logger->LoggingIsEnabled())
return;
2336 logger->FlushPendingThrottledLogs(
true);
2342 std::vector<std::vector<std::string>> table;
2343 table.push_back({
"Solution repositories",
"Added",
"Queried",
"Synchro"});
2344 response->SolutionPool().AddTableStats(&table);
2345 table.push_back(
ls_hints->TableLineStats());
bool AddEdge(int node1, int node2)
void SetNumberOfNodes(int num_nodes)
int GetNumberOfComponents() const
std::vector< int > GetComponentIds()
bool IsIncludedIn(const Domain &domain) const
Domain InverseMultiplicationBy(int64_t coeff) const
double GetElapsedDeterministicTime() 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
bool has_floating_point_objective() const
const ::operations_research::sat::IntegerVariableProto & variables(int index) const
const ::operations_research::sat::ConstraintProto & constraints(int index) const
bool has_objective() const
const ::operations_research::sat::DecisionStrategyProto & search_strategy(int index) const
::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
::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
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
const ::std::string & name() const
void add_domain(::int64_t value)
::int64_t domain(int index) const
void InitAllDecomposedEnergies()
SatSolver::Status Search(const std::function< void()> &feasible_solution_observer)
::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)
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
::int32_t linearization_level() 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)
bool share_linear2_bounds() const
bool auto_detect_greater_than_at_least_one_of() const
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 use_new_integer_conflict_resolution() const
bool share_binary_clauses() const
static constexpr SearchBranching HINT_SEARCH
::int32_t cp_model_probing_level() const
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 MinimizeByPropagation(double dtime, bool minimize_new_clauses_only=false)
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)
void NotifyNumImported(int id, int64_t num_imported)
int RegisterNewImportId(std::string name)
std::vector< std::pair< Key, std::pair< IntegerValue, IntegerValue > > > NewlyUpdatedBounds(int import_id)
void NotifyNumImported(int import_id, int num)
IntegerValue GetInnerObjectiveLowerBound()
void InitializeObjective(const CpModelProto &cp_model)
IntegerValue GetInnerObjectiveUpperBound()
void UpdateInnerObjectiveBounds(const std::string &update_info, IntegerValue lb, IntegerValue ub)
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)
IntType end_index() const
void resize(size_type new_size)
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)
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 AddWeightedSumLowerOrEqual(absl::Span< const Literal > enforcement_literals, absl::Span< const IntegerVariable > vars, absl::Span< const IntegerValue > coefficients, int64_t upper_bound, Model *model)
const LiteralIndex kNoLiteralIndex(-1)
void DetectOptionalVariables(const CpModelProto &model_proto, Model *m)
bool SolutionIsFeasible(const CpModelProto &model, absl::Span< const int64_t > variable_values, const CpModelProto *mapping_proto, const std::vector< int > *postsolve_mapping)
LinearRelaxation ComputeLinearRelaxation(const CpModelProto &model_proto, Model *m)
void AddWeightedSumGreaterOrEqual(absl::Span< const Literal > enforcement_literals, absl::Span< const IntegerVariable > vars, absl::Span< const IntegerValue > coefficients, int64_t lower_bound, Model *model)
std::function< int64_t(const Model &)> LowerBound(IntegerVariable v)
std::function< BooleanOrIntegerLiteral()> ConstructIntegerCompletionSearchStrategy(absl::Span< const IntegerVariable > variable_mapping, IntegerVariable objective_var, Model *model)
std::vector< IntegerVariable > NegationOf(absl::Span< const IntegerVariable > vars)
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)
constexpr IntegerValue kMinIntegerValue(-kMaxIntegerValue.value())
std::function< BooleanOrIntegerLiteral()> ConstructHintSearchStrategy(const CpModelProto &cp_model_proto, CpModelMapping *mapping, Model *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)
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)
void LoadFeasibilityPump(const CpModelProto &model_proto, Model *model)
void ExtractElementEncoding(const CpModelProto &model_proto, Model *m)
constexpr ClauseId kNoClauseId(0)
std::function< int64_t(const Model &)> Value(IntegerVariable v)
void ConstructFixedSearchStrategy(SearchHeuristics *h, Model *model)
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)
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)
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)
SatSolver::Status ResetAndSolveIntegerProblem(const std::vector< Literal > &assumptions, Model *model)
bool VariableIsPositive(IntegerVariable i)
void RegisterObjectiveBestBoundExport(IntegerVariable objective_var, SharedResponseManager *shared_response_manager, Model *model)
std::function< void(Model *)> ExcludeCurrentSolutionAndBacktrack()
void RegisterLinear2BoundsImport(SharedLinear2Bounds *shared_linear2_bounds, Model *model)
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)
std::string FormatTable(std::vector< std::vector< std::string > > &table, int spacing)
void ExtractEncoding(const CpModelProto &model_proto, Model *m)
void SplitAndLoadIntermediateConstraints(bool lb_required, bool ub_required, std::vector< IntegerVariable > *vars, std::vector< IntegerValue > *coeffs, Model *m)
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)
IntegerValue inner_objective_value
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
void RegisterSharedClassesInLocalModel(Model *local_model)
SolverLogger *const logger
SharedLratProofStatus *const lrat_proof_status
const CpModelProto & model_proto
SharedLsSolutionRepository *const ls_hints
SolverProgressLogger *const progress_logger
std::unique_ptr< SharedIncompleteSolutionManager > incomplete_solutions
std::unique_ptr< SharedClausesManager > clauses
void LogFinalStatistics()
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
std::unique_ptr< SharedLinear2Bounds > linear2_bounds
WallTimer *const wall_timer
std::unique_ptr< SharedBoundsManager > bounds
#define SOLVER_LOG(logger,...)