22 #include <type_traits>
25 #include "absl/strings/str_format.h"
39 owned_model_.reset(model_);
48 track_binary_clauses_(false),
51 parameters_(
model->GetOrCreate<SatParameters>()),
54 clause_activity_increment_(1.0),
55 same_reason_identifier_(*trail_),
56 is_relevant_for_core_computation_(true),
57 problem_is_pure_sat_(true),
58 drat_proof_handler_(nullptr),
60 InitializePropagators();
67 CHECK_GE(num_variables, num_variables_);
69 num_variables_ = num_variables;
70 binary_implication_graph_->
Resize(num_variables);
71 clauses_propagator_->
Resize(num_variables);
72 trail_->
Resize(num_variables);
74 pb_constraints_->
Resize(num_variables);
75 same_reason_identifier_.
Resize(num_variables);
80 decisions_.resize(num_variables + 1);
123 bool SatSolver::IsMemoryLimitReached()
const {
124 const int64_t memory_usage =
126 const int64_t kMegaByte = 1024 * 1024;
127 return memory_usage > kMegaByte * parameters_->max_memory_in_mb();
130 bool SatSolver::SetModelUnsat() {
131 model_is_unsat_ =
true;
136 if (model_is_unsat_)
return false;
138 if (literals.empty())
return SetModelUnsat();
140 if (literals.size() == 2) {
145 return SetModelUnsat();
149 InitializePropagators();
152 if (!clauses_propagator_->
AddClause(literals)) {
154 return SetModelUnsat();
168 if (model_is_unsat_)
return false;
171 if (drat_proof_handler_ !=
nullptr) {
174 drat_proof_handler_->
AddClause({true_literal});
177 if (!
Propagate())
return SetModelUnsat();
183 tmp_pb_constraint_.clear();
187 true, Coefficient(1),
188 false, Coefficient(0),
189 &tmp_pb_constraint_);
194 tmp_pb_constraint_.clear();
199 true, Coefficient(1),
200 false, Coefficient(0),
201 &tmp_pb_constraint_);
210 tmp_pb_constraint_.clear();
215 true, Coefficient(1),
216 false, Coefficient(0),
217 &tmp_pb_constraint_);
220 bool SatSolver::AddProblemClauseInternal(absl::Span<const Literal> literals) {
228 if (literals.size() == 1) {
235 if (parameters_->treat_binary_clauses_separately() && literals.size() == 2) {
236 AddBinaryClauseInternal(literals[0], literals[1]);
238 if (!clauses_propagator_->
AddClause(literals, trail_)) {
239 return SetModelUnsat();
245 bool SatSolver::AddLinearConstraintInternal(
246 const std::vector<LiteralWithCoeff>& cst, Coefficient rhs,
247 Coefficient max_value) {
250 if (rhs < 0)
return SetModelUnsat();
251 if (rhs >= max_value)
return true;
258 const Coefficient min_coeff = cst.front().coefficient;
259 const Coefficient max_coeff = cst.back().coefficient;
263 if (max_value - min_coeff <= rhs) {
265 literals_scratchpad_.clear();
266 for (
const LiteralWithCoeff& term : cst) {
267 literals_scratchpad_.push_back(term.literal.Negated());
269 return AddProblemClauseInternal(literals_scratchpad_);
274 if (parameters_->treat_binary_clauses_separately() &&
275 !parameters_->use_pb_resolution() && max_coeff <= rhs &&
276 2 * min_coeff > rhs) {
277 literals_scratchpad_.clear();
278 for (
const LiteralWithCoeff& term : cst) {
279 literals_scratchpad_.push_back(term.literal);
281 if (!binary_implication_graph_->
AddAtMostOne(literals_scratchpad_)) {
282 return SetModelUnsat();
287 InitializePropagators();
291 problem_is_pure_sat_ =
false;
295 const bool result = pb_constraints_->
AddConstraint(cst, rhs, trail_);
296 InitializePropagators();
302 bool use_upper_bound,
304 std::vector<LiteralWithCoeff>* cst) {
307 if (model_is_unsat_)
return false;
310 Coefficient fixed_variable_shift(0);
319 (*cst)[
index] = term;
327 Coefficient bound_shift;
328 Coefficient max_value;
333 if (use_upper_bound) {
334 const Coefficient rhs =
336 if (!AddLinearConstraintInternal(*cst, rhs, max_value)) {
337 return SetModelUnsat();
340 if (use_lower_bound) {
342 for (
int i = 0; i < cst->size(); ++i) {
343 (*cst)[i].literal = (*cst)[i].literal.Negated();
345 const Coefficient rhs =
347 if (!AddLinearConstraintInternal(*cst, rhs, max_value)) {
348 return SetModelUnsat();
356 if (!PropagationIsDone() && !
Propagate()) {
357 return SetModelUnsat();
362 int SatSolver::AddLearnedClauseAndEnqueueUnitPropagation(
363 const std::vector<Literal>& literals,
bool is_redundant) {
366 if (literals.size() == 1) {
374 if (literals.size() == 2 && parameters_->treat_binary_clauses_separately()) {
375 if (track_binary_clauses_) {
376 CHECK(binary_clauses_.
Add(BinaryClause(literals[0], literals[1])));
381 InitializePropagators();
385 CleanClauseDatabaseIfNeeded();
389 const int lbd = ComputeLbd(literals);
390 if (is_redundant && lbd > parameters_->clause_cleanup_lbd_bound()) {
391 --num_learned_clause_before_cleanup_;
399 BumpClauseActivity(clause);
408 problem_is_pure_sat_ =
false;
410 external_propagators_.push_back(propagator);
411 InitializePropagators();
416 CHECK(last_propagator_ ==
nullptr);
417 problem_is_pure_sat_ =
false;
419 last_propagator_ = propagator;
420 InitializePropagators();
424 BooleanVariable
var)
const {
434 SatClause* SatSolver::ReasonClauseOrNull(BooleanVariable
var)
const {
436 const AssignmentInfo& info = trail_->
Info(
var);
438 return clauses_propagator_->
ReasonClause(info.trail_index);
444 debug_assignment_.
Resize(num_variables_.value());
445 for (BooleanVariable i(0); i < num_variables_; ++i) {
456 InitializePropagators();
460 bool SatSolver::ClauseIsValidUnderDebugAssignement(
461 const std::vector<Literal>& clause)
const {
462 for (Literal l : clause) {
471 bool SatSolver::PBConstraintIsValidUnderDebugAssignment(
472 const std::vector<LiteralWithCoeff>& cst,
const Coefficient rhs)
const {
473 Coefficient sum(0.0);
474 for (LiteralWithCoeff term : cst) {
479 sum += term.coefficient;
489 bool ClauseSubsumption(
const std::vector<Literal>&
a, SatClause*
b) {
490 std::vector<Literal> superset(
b->begin(),
b->end());
491 std::vector<Literal> subset(
a.begin(),
a.end());
492 std::sort(superset.begin(), superset.end());
493 std::sort(subset.begin(), subset.end());
494 return std::includes(superset.begin(), superset.end(), subset.begin(),
503 CHECK(PropagationIsDone());
504 EnqueueNewDecision(true_literal);
505 while (!PropagateAndStopAfterOneConflictResolution()) {
508 CHECK(PropagationIsDone());
509 return last_decision_or_backtrack_trail_index_;
513 if (model_is_unsat_)
return false;
523 if (model_is_unsat_)
return false;
524 while (!PropagateAndStopAfterOneConflictResolution()) {
525 if (model_is_unsat_)
return false;
531 if (model_is_unsat_)
return false;
532 assumption_level_ = 0;
538 const std::vector<Literal>& assumptions) {
547 std::min<int>(assumptions.size(), num_variables_.value() + 1);
548 for (
int i = 0; i < assumption_level_; ++i) {
549 decisions_[i].literal = assumptions[i];
556 if (model_is_unsat_)
return false;
560 const int64_t old_num_branches = counters_.num_branches;
562 ReapplyDecisionsUpTo(assumption_level_ - 1, &unused);
563 counters_.num_branches = old_num_branches;
568 bool SatSolver::PropagateAndStopAfterOneConflictResolution() {
572 ++counters_.num_failures;
573 const int conflict_trail_index = trail_->
Index();
574 const int conflict_decision_level = current_decision_level_;
577 same_reason_identifier_.
Clear();
578 const int max_trail_index = ComputeMaxTrailIndex(trail_->
FailingClause());
579 ComputeFirstUIPConflict(max_trail_index, &learned_conflict_,
580 &reason_used_to_infer_the_conflict_,
584 if (learned_conflict_.empty())
return SetModelUnsat();
585 DCHECK(IsConflictValid(learned_conflict_));
586 DCHECK(ClauseIsValidUnderDebugAssignement(learned_conflict_));
594 if (parameters_->also_bump_variables_in_conflict_reasons()) {
595 ComputeUnionOfReasons(learned_conflict_, &extra_reason_literals_);
605 BumpReasonActivities(reason_used_to_infer_the_conflict_);
609 UpdateClauseActivityIncrement();
613 const int period = parameters_->glucose_decay_increment_period();
614 const double max_decay = parameters_->glucose_max_decay();
615 if (counters_.num_failures % period == 0 &&
616 parameters_->variable_activity_decay() < max_decay) {
617 parameters_->set_variable_activity_decay(
618 parameters_->variable_activity_decay() +
619 parameters_->glucose_decay_increment());
625 bool compute_pb_conflict =
false;
626 if (parameters_->use_pb_resolution()) {
628 if (!compute_pb_conflict) {
629 for (Literal lit : reason_used_to_infer_the_conflict_) {
630 if (ReasonPbConstraintOrNull(lit.Variable()) !=
nullptr) {
631 compute_pb_conflict =
true;
640 if (compute_pb_conflict) {
642 Coefficient initial_slack(-1);
645 Coefficient num_literals(0);
650 pb_conflict_.
AddToRhs(num_literals - 1);
659 int pb_backjump_level;
660 ComputePBConflict(max_trail_index, initial_slack, &pb_conflict_,
662 if (pb_backjump_level == -1)
return SetModelUnsat();
665 std::vector<LiteralWithCoeff> cst;
667 DCHECK(PBConstraintIsValidUnderDebugAssignment(cst, pb_conflict_.
Rhs()));
671 bool conflict_is_a_clause = (pb_conflict_.
Rhs() == cst.size() - 1);
672 if (conflict_is_a_clause) {
673 for (LiteralWithCoeff term : cst) {
674 if (term.coefficient != Coefficient(1)) {
675 conflict_is_a_clause =
false;
681 if (!conflict_is_a_clause) {
690 CHECK_GT(trail_->
Index(), last_decision_or_backtrack_trail_index_);
691 counters_.num_learned_pb_literals += cst.size();
697 if (pb_backjump_level < ComputeBacktrackLevel(learned_conflict_)) {
698 subsumed_clauses_.clear();
699 learned_conflict_.clear();
703 for (LiteralWithCoeff term : cst) {
706 const int level = trail_->
Info(term.literal.Variable()).
level;
707 if (level == 0)
continue;
708 if (level > max_level) {
710 max_index = learned_conflict_.size();
712 learned_conflict_.push_back(term.literal.Negated());
716 is_marked_.
Set(term.literal.Variable());
718 CHECK(!learned_conflict_.empty());
719 std::swap(learned_conflict_.front(), learned_conflict_[max_index]);
720 DCHECK(IsConflictValid(learned_conflict_));
729 DCHECK(ClauseIsValidUnderDebugAssignement(learned_conflict_));
730 if (!binary_implication_graph_->
IsEmpty()) {
731 if (parameters_->binary_minimization_algorithm() ==
732 SatParameters::BINARY_MINIMIZATION_FIRST) {
734 *trail_, &learned_conflict_, &is_marked_);
735 }
else if (parameters_->binary_minimization_algorithm() ==
737 BINARY_MINIMIZATION_FIRST_WITH_TRANSITIVE_REDUCTION) {
739 *trail_, &learned_conflict_, &is_marked_,
742 DCHECK(IsConflictValid(learned_conflict_));
746 MinimizeConflict(&learned_conflict_, &reason_used_to_infer_the_conflict_);
749 if (!binary_implication_graph_->
IsEmpty()) {
753 switch (parameters_->binary_minimization_algorithm()) {
754 case SatParameters::NO_BINARY_MINIMIZATION:
755 ABSL_FALLTHROUGH_INTENDED;
756 case SatParameters::BINARY_MINIMIZATION_FIRST:
757 ABSL_FALLTHROUGH_INTENDED;
758 case SatParameters::BINARY_MINIMIZATION_FIRST_WITH_TRANSITIVE_REDUCTION:
760 case SatParameters::BINARY_MINIMIZATION_WITH_REACHABILITY:
764 case SatParameters::EXPERIMENTAL_BINARY_MINIMIZATION:
766 *trail_, &learned_conflict_);
769 DCHECK(IsConflictValid(learned_conflict_));
783 counters_.num_literals_learned += learned_conflict_.size();
784 Backtrack(ComputeBacktrackLevel(learned_conflict_));
785 DCHECK(ClauseIsValidUnderDebugAssignement(learned_conflict_));
791 if (drat_proof_handler_ !=
nullptr) {
792 drat_proof_handler_->
AddClause(learned_conflict_);
797 bool is_redundant =
true;
798 if (!subsumed_clauses_.empty() &&
799 parameters_->subsumption_during_conflict_analysis()) {
800 for (SatClause* clause : subsumed_clauses_) {
801 DCHECK(ClauseSubsumption(learned_conflict_, clause));
803 is_redundant =
false;
808 counters_.num_subsumed_clauses += subsumed_clauses_.size();
812 const int conflict_lbd = AddLearnedClauseAndEnqueueUnitPropagation(
813 learned_conflict_, is_redundant);
814 restart_->
OnConflict(conflict_trail_index, conflict_decision_level,
820 int max_level,
int* first_propagation_index) {
822 int decision_index = current_decision_level_;
823 while (decision_index <= max_level) {
824 DCHECK_GE(decision_index, current_decision_level_);
825 const Literal previous_decision = decisions_[decision_index].literal;
827 if (
Assignment().LiteralIsTrue(previous_decision)) {
833 if (
Assignment().LiteralIsFalse(previous_decision)) {
835 decisions_[current_decision_level_].literal = previous_decision;
840 const int old_level = current_decision_level_;
842 *first_propagation_index =
std::min(*first_propagation_index,
index);
844 if (current_decision_level_ <= old_level) {
856 decision_index = current_decision_level_;
864 CHECK(PropagationIsDone());
869 int first_propagation_index = trail_->
Index();
871 return first_propagation_index;
876 CHECK(PropagationIsDone());
880 EnqueueNewDecision(true_literal);
905 if (target_level == 0) counters_.num_restarts++;
910 int target_trail_index = 0;
911 while (current_decision_level_ > target_level) {
912 --current_decision_level_;
913 target_trail_index = decisions_[current_decision_level_].trail_index;
915 Untrail(target_trail_index);
916 last_decision_or_backtrack_trail_index_ = trail_->
Index();
925 return SetModelUnsat();
927 AddBinaryClauseInternal(c.a, c.b);
929 if (!
Propagate())
return SetModelUnsat();
949 const std::vector<Literal>& assumptions) {
952 return SolveInternal(time_limit_);
956 if (parameters_->log_search_progress()) {
957 LOG(
INFO) << RunningStatisticsString();
958 LOG(
INFO) << StatusString(status);
966 assumption_level_ = assumption_level;
975 void SatSolver::KeepAllClauseUsedToInfer(BooleanVariable variable) {
977 if (trail_->
Info(variable).
level == 0)
return;
979 std::vector<bool> is_marked(trail_index + 1,
false);
980 is_marked[trail_index] =
true;
982 for (; num > 0 && trail_index >= 0; --trail_index) {
983 if (!is_marked[trail_index])
continue;
984 is_marked[trail_index] =
false;
987 const BooleanVariable
var = (*trail_)[trail_index].Variable();
989 if (clause !=
nullptr) {
992 for (
const Literal l : trail_->
Reason(
var)) {
993 const AssignmentInfo& info = trail_->
Info(l.Variable());
994 if (info.level == 0)
continue;
995 if (!is_marked[info.trail_index]) {
996 is_marked[info.trail_index] =
true;
1006 void SatSolver::TryToMinimizeClause(SatClause* clause) {
1008 ++counters_.minimization_num_clauses;
1010 std::set<LiteralIndex> moved_last;
1011 std::vector<Literal> candidate(clause->begin(), clause->end());
1012 while (!model_is_unsat_) {
1019 if (target_level == -1)
break;
1023 const Literal
literal = candidate[level];
1025 candidate.erase(candidate.begin() + level);
1028 const int variable_level =
1030 if (variable_level == 0) {
1031 ProcessNewlyFixedVariablesForDratProof();
1032 counters_.minimization_num_true++;
1033 counters_.minimization_num_removed_literals += clause->size();
1035 clauses_propagator_->
Detach(clause);
1043 if (ReasonClauseOrNull(
literal.Variable()) != clause) {
1044 counters_.minimization_num_subsumed++;
1045 counters_.minimization_num_removed_literals += clause->size();
1048 KeepAllClauseUsedToInfer(
literal.Variable());
1050 clauses_propagator_->
Detach(clause);
1056 if (variable_level + 1 < candidate.size()) {
1057 candidate.resize(variable_level);
1063 ++counters_.minimization_num_decisions;
1065 if (!clause->IsAttached()) {
1069 if (model_is_unsat_)
return;
1072 if (candidate.empty()) {
1073 model_is_unsat_ =
true;
1076 moved_last.insert(candidate.back().Index());
1081 if (candidate.size() == clause->size())
return;
1083 if (candidate.size() == 1) {
1084 if (drat_proof_handler_ !=
nullptr) {
1085 drat_proof_handler_->
AddClause(candidate);
1087 if (!
Assignment().VariableIsAssigned(candidate[0].Variable())) {
1088 counters_.minimization_num_removed_literals += clause->size();
1095 if (parameters_->treat_binary_clauses_separately() && candidate.size() == 2) {
1096 counters_.minimization_num_removed_literals += clause->size() - 2;
1099 AddBinaryClauseInternal(candidate[0], candidate[1]);
1100 clauses_propagator_->
Detach(clause);
1109 counters_.minimization_num_removed_literals +=
1110 clause->size() - candidate.size();
1115 model_is_unsat_ =
true;
1129 if (parameters_->log_search_progress()) {
1131 LOG(
INFO) <<
"Number of variables: " << num_variables_;
1132 LOG(
INFO) <<
"Number of clauses (size > 2): "
1134 LOG(
INFO) <<
"Number of binary clauses: "
1136 LOG(
INFO) <<
"Number of linear constraints: "
1138 LOG(
INFO) <<
"Number of fixed variables: " << trail_->
Index();
1139 LOG(
INFO) <<
"Number of watched clauses: "
1145 int64_t next_minimization_num_restart =
1147 parameters_->minimize_with_propagation_restart_period();
1150 const int64_t kDisplayFrequency = 10000;
1151 int64_t next_display = parameters_->log_search_progress()
1153 : std::numeric_limits<int64_t>::
max();
1156 const int64_t kMemoryCheckFrequency = 10000;
1157 int64_t next_memory_check =
1162 const int64_t kFailureLimit =
1163 parameters_->max_number_of_conflicts() ==
1166 : counters_.
num_failures + parameters_->max_number_of_conflicts();
1174 if (parameters_->log_search_progress()) {
1175 LOG(
INFO) <<
"The time limit has been reached. Aborting.";
1181 if (parameters_->log_search_progress()) {
1182 LOG(
INFO) <<
"The conflict limit has been reached. Aborting.";
1192 if (counters_.num_failures >= next_memory_check) {
1193 next_memory_check = NextMultipleOf(
num_failures(), kMemoryCheckFrequency);
1194 if (IsMemoryLimitReached()) {
1195 if (parameters_->log_search_progress()) {
1196 LOG(
INFO) <<
"The memory limit has been reached. Aborting.";
1204 if (counters_.num_failures >= next_display) {
1205 LOG(
INFO) << RunningStatisticsString();
1206 next_display = NextMultipleOf(
num_failures(), kDisplayFrequency);
1209 if (!PropagateAndStopAfterOneConflictResolution()) {
1211 if (model_is_unsat_)
return StatusWithLog(
INFEASIBLE);
1217 if (trail_->
Index() == num_variables_.value()) {
1227 restart_->
NumRestarts() >= next_minimization_num_restart) {
1228 next_minimization_num_restart =
1230 parameters_->minimize_with_propagation_restart_period();
1232 parameters_->minimize_with_propagation_num_decisions());
1236 if (model_is_unsat_)
return StatusWithLog(
INFEASIBLE);
1237 if (trail_->
Index() == num_variables_.value()) {
1243 EnqueueNewDecision(decision_policy_->
NextBranch());
1251 block_clause_deletion_ =
true;
1253 const int64_t target_num_branches = counters_.num_branches + decisions_budget;
1254 while (counters_.num_branches < target_num_branches &&
1255 (time_limit_ ==
nullptr || !time_limit_->
LimitReached())) {
1257 if (to_minimize !=
nullptr) {
1258 TryToMinimizeClause(to_minimize);
1259 if (model_is_unsat_)
return;
1261 if (to_minimize ==
nullptr) {
1262 VLOG(1) <<
"Minimized all clauses, restarting from first one.";
1269 block_clause_deletion_ =
false;
1276 std::vector<Literal> unsat_assumptions;
1292 unsat_assumptions.push_back(decisions_[i].
literal);
1294 return unsat_assumptions;
1297 unsat_assumptions.push_back(false_assumption);
1304 int trail_index = trail_->
Info(false_assumption.
Variable()).trail_index;
1310 while (trail_index >= 0 && !is_marked_[(*trail_)[trail_index].Variable()]) {
1313 if (trail_index < limit)
break;
1314 const Literal marked_literal = (*trail_)[trail_index];
1319 unsat_assumptions.push_back(marked_literal);
1323 const BooleanVariable
var =
literal.Variable();
1324 const int level = DecisionLevel(
var);
1325 if (level > 0 && !is_marked_[
var]) is_marked_.
Set(
var);
1332 std::reverse(unsat_assumptions.begin(), unsat_assumptions.end());
1333 return unsat_assumptions;
1336 void SatSolver::BumpReasonActivities(
const std::vector<Literal>& literals) {
1339 const BooleanVariable
var =
literal.Variable();
1340 if (DecisionLevel(
var) > 0) {
1342 if (clause !=
nullptr) {
1343 BumpClauseActivity(clause);
1345 UpperBoundedLinearConstraint* pb_constraint =
1346 ReasonPbConstraintOrNull(
var);
1347 if (pb_constraint !=
nullptr) {
1357 void SatSolver::BumpClauseActivity(SatClause* clause) {
1368 const int new_lbd = ComputeLbd(*clause);
1369 if (new_lbd + 1 <= parameters_->clause_cleanup_lbd_bound()) {
1375 switch (parameters_->clause_cleanup_protection()) {
1376 case SatParameters::PROTECTION_NONE:
1378 case SatParameters::PROTECTION_ALWAYS:
1379 it->second.protected_during_next_cleanup =
true;
1381 case SatParameters::PROTECTION_LBD:
1386 if (new_lbd + 1 < it->second.lbd) {
1387 it->second.protected_during_next_cleanup =
true;
1388 it->second.lbd = new_lbd;
1393 const double activity = it->second.activity += clause_activity_increment_;
1394 if (activity > parameters_->max_clause_activity_value()) {
1395 RescaleClauseActivities(1.0 / parameters_->max_clause_activity_value());
1399 void SatSolver::RescaleClauseActivities(
double scaling_factor) {
1401 clause_activity_increment_ *= scaling_factor;
1403 entry.second.activity *= scaling_factor;
1407 void SatSolver::UpdateClauseActivityIncrement() {
1409 clause_activity_increment_ *= 1.0 / parameters_->clause_activity_decay();
1412 bool SatSolver::IsConflictValid(
const std::vector<Literal>& literals) {
1414 if (literals.empty())
return false;
1415 const int highest_level = DecisionLevel(literals[0].Variable());
1416 for (
int i = 1; i < literals.size(); ++i) {
1417 const int level = DecisionLevel(literals[i].Variable());
1418 if (level <= 0 || level >= highest_level)
return false;
1423 int SatSolver::ComputeBacktrackLevel(
const std::vector<Literal>& literals) {
1436 int backtrack_level = 0;
1437 for (
int i = 1; i < literals.size(); ++i) {
1438 const int level = DecisionLevel(literals[i].Variable());
1439 backtrack_level =
std::max(backtrack_level, level);
1441 DCHECK_LT(backtrack_level, DecisionLevel(literals[0].Variable()));
1443 return backtrack_level;
1446 template <
typename LiteralList>
1447 int SatSolver::ComputeLbd(
const LiteralList& literals) {
1450 parameters_->count_assumption_levels_in_lbd() ? 0 : assumption_level_;
1454 SatDecisionLevel(DecisionLevel(literals.begin()->Variable()) + 1));
1455 for (
const Literal
literal : literals) {
1456 const SatDecisionLevel level(DecisionLevel(
literal.Variable()));
1458 if (level > limit && !is_level_marked_[level]) {
1459 is_level_marked_.
Set(level);
1465 std::string SatSolver::StatusString(Status status)
const {
1466 const double time_in_s = timer_.
Get();
1468 absl::StrFormat(
" time: %fs\n", time_in_s) +
1471 " num failures: %d (%.0f /sec)\n", counters_.num_failures,
1472 static_cast<double>(counters_.num_failures) / time_in_s) +
1474 " num branches: %d (%.0f /sec)\n", counters_.num_branches,
1475 static_cast<double>(counters_.num_branches) / time_in_s) +
1476 absl::StrFormat(
" num propagations: %d (%.0f /sec)\n",
1479 absl::StrFormat(
" num binary propagations: %d\n",
1481 absl::StrFormat(
" num binary inspections: %d\n",
1484 " num binary redundant implications: %d\n",
1487 " num classic minimizations: %d"
1488 " (literals removed: %d)\n",
1489 counters_.num_minimizations, counters_.num_literals_removed) +
1491 " num binary minimizations: %d"
1492 " (literals removed: %d)\n",
1495 absl::StrFormat(
" num inspected clauses: %d\n",
1497 absl::StrFormat(
" num inspected clause_literals: %d\n",
1500 " num learned literals: %d (avg: %.1f /clause)\n",
1501 counters_.num_literals_learned,
1502 1.0 * counters_.num_literals_learned / counters_.num_failures) +
1504 " num learned PB literals: %d (avg: %.1f /clause)\n",
1505 counters_.num_learned_pb_literals,
1506 1.0 * counters_.num_learned_pb_literals / counters_.num_failures) +
1507 absl::StrFormat(
" num subsumed clauses: %d\n",
1508 counters_.num_subsumed_clauses) +
1509 absl::StrFormat(
" minimization_num_clauses: %d\n",
1510 counters_.minimization_num_clauses) +
1511 absl::StrFormat(
" minimization_num_decisions: %d\n",
1512 counters_.minimization_num_decisions) +
1513 absl::StrFormat(
" minimization_num_true: %d\n",
1514 counters_.minimization_num_true) +
1515 absl::StrFormat(
" minimization_num_subsumed: %d\n",
1516 counters_.minimization_num_subsumed) +
1517 absl::StrFormat(
" minimization_num_removed_literals: %d\n",
1518 counters_.minimization_num_removed_literals) +
1519 absl::StrFormat(
" pb num threshold updates: %d\n",
1521 absl::StrFormat(
" pb num constraint lookups: %d\n",
1523 absl::StrFormat(
" pb num inspected constraint literals: %d\n",
1529 std::string SatSolver::RunningStatisticsString()
const {
1530 const double time_in_s = timer_.
Get();
1531 return absl::StrFormat(
1532 "%6.2fs, mem:%s, fails:%d, depth:%d, clauses:%d, tmp:%d, bin:%u, "
1533 "restarts:%d, vars:%d",
1539 num_variables_.value() - num_processed_fixed_variables_);
1542 void SatSolver::ProcessNewlyFixedVariablesForDratProof() {
1543 if (drat_proof_handler_ ==
nullptr)
return;
1557 for (; drat_num_processed_fixed_variables_ < trail_->
Index();
1558 ++drat_num_processed_fixed_variables_) {
1559 temp = (*trail_)[drat_num_processed_fixed_variables_];
1560 drat_proof_handler_->
AddClause({&temp, 1});
1567 int num_detached_clauses = 0;
1570 ProcessNewlyFixedVariablesForDratProof();
1576 if (!clause->IsAttached())
continue;
1578 const size_t old_size = clause->size();
1579 if (clause->RemoveFixedLiteralsAndTestIfTrue(trail_->
Assignment())) {
1582 ++num_detached_clauses;
1586 const size_t new_size = clause->size();
1587 if (new_size == old_size)
continue;
1589 if (drat_proof_handler_ !=
nullptr) {
1591 drat_proof_handler_->
AddClause({clause->begin(), new_size});
1592 drat_proof_handler_->
DeleteClause({clause->begin(), old_size});
1595 if (new_size == 2 && parameters_->treat_binary_clauses_separately()) {
1599 AddBinaryClauseInternal(clause->FirstLiteral(), clause->SecondLiteral());
1608 if (num_detached_clauses > 0 || num_binary > 0) {
1609 VLOG(1) << trail_->
Index() <<
" fixed variables at level 0. "
1610 <<
"Detached " << num_detached_clauses <<
" clauses. " << num_binary
1611 <<
" converted to binary.";
1616 num_processed_fixed_variables_ = trail_->
Index();
1633 const int old_index = trail_->
Index();
1635 DCHECK(propagator->PropagatePreconditionsAreSatisfied(*trail_));
1636 if (!propagator->Propagate(trail_))
return false;
1637 if (trail_->
Index() > old_index)
break;
1639 if (trail_->
Index() == old_index)
break;
1644 void SatSolver::InitializePropagators() {
1645 propagators_.clear();
1656 if (!binary_implication_graph_->
IsEmpty()) {
1657 propagators_.push_back(binary_implication_graph_);
1659 propagators_.push_back(clauses_propagator_);
1661 propagators_.push_back(pb_constraints_);
1663 for (
int i = 0; i < external_propagators_.size(); ++i) {
1664 propagators_.push_back(external_propagators_[i]);
1666 if (last_propagator_ !=
nullptr) {
1667 propagators_.push_back(last_propagator_);
1671 bool SatSolver::PropagationIsDone()
const {
1672 for (SatPropagator* propagator : propagators_) {
1673 if (!propagator->PropagationIsDone(*trail_))
return false;
1678 bool SatSolver::ResolvePBConflict(BooleanVariable
var,
1679 MutableUpperBoundedLinearConstraint* conflict,
1680 Coefficient* slack) {
1684 DCHECK_EQ(*slack, conflict->ComputeSlackForTrailPrefix(*trail_, trail_index));
1687 UpperBoundedLinearConstraint* pb_reason = ReasonPbConstraintOrNull(
var);
1688 if (pb_reason !=
nullptr) {
1689 pb_reason->ResolvePBConflict(*trail_,
var, conflict, slack);
1694 Coefficient multiplier(1);
1697 const int algorithm = 1;
1698 switch (algorithm) {
1702 conflict->ReduceSlackTo(*trail_, trail_index, *slack, Coefficient(0));
1706 multiplier = *slack + 1;
1710 multiplier = conflict->GetCoefficient(
var);
1713 Coefficient num_literals(1);
1720 conflict->AddTerm(
literal.Negated(), multiplier);
1723 conflict->AddToRhs((num_literals - 1) * multiplier);
1727 DCHECK_EQ(*slack, conflict->ComputeSlackForTrailPrefix(*trail_, trail_index));
1731 void SatSolver::EnqueueNewDecision(Literal
literal) {
1742 const double kMinDeterministicTimeBetweenCleanups = 1.0;
1743 if (num_processed_fixed_variables_ < trail_->
Index() &&
1745 deterministic_time_of_last_fixed_variables_cleanup_ +
1746 kMinDeterministicTimeBetweenCleanups) {
1751 counters_.num_branches++;
1752 last_decision_or_backtrack_trail_index_ = trail_->
Index();
1753 decisions_[current_decision_level_] = Decision(trail_->
Index(),
literal);
1754 ++current_decision_level_;
1759 void SatSolver::Untrail(
int target_trail_index) {
1762 for (SatPropagator* propagator : propagators_) {
1763 propagator->Untrail(*trail_, target_trail_index);
1765 decision_policy_->
Untrail(target_trail_index);
1766 trail_->
Untrail(target_trail_index);
1769 std::string SatSolver::DebugString(
const SatClause& clause)
const {
1771 for (
const Literal
literal : clause) {
1772 if (!result.empty()) {
1773 result.append(
" || ");
1775 const std::string
value =
1780 result.append(absl::StrFormat(
"%s(%s)",
literal.DebugString(),
value));
1785 int SatSolver::ComputeMaxTrailIndex(absl::Span<const Literal> clause)
const {
1787 int trail_index = -1;
1788 for (
const Literal
literal : clause) {
1798 void SatSolver::ComputeFirstUIPConflict(
1799 int max_trail_index, std::vector<Literal>* conflict,
1800 std::vector<Literal>* reason_used_to_infer_the_conflict,
1801 std::vector<SatClause*>* subsumed_clauses) {
1809 reason_used_to_infer_the_conflict->clear();
1810 subsumed_clauses->clear();
1811 if (max_trail_index == -1)
return;
1817 int trail_index = max_trail_index;
1818 const int highest_level = DecisionLevel((*trail_)[trail_index].Variable());
1819 if (highest_level == 0)
return;
1836 absl::Span<const Literal> clause_to_expand = trail_->
FailingClause();
1838 DCHECK(!clause_to_expand.empty());
1839 int num_literal_at_highest_level_that_needs_to_be_processed = 0;
1841 int num_new_vars_at_positive_level = 0;
1842 int num_vars_at_positive_level_in_clause_to_expand = 0;
1843 for (
const Literal
literal : clause_to_expand) {
1844 const BooleanVariable
var =
literal.Variable();
1845 const int level = DecisionLevel(
var);
1846 if (level > 0) ++num_vars_at_positive_level_in_clause_to_expand;
1847 if (!is_marked_[
var]) {
1849 if (level == highest_level) {
1850 ++num_new_vars_at_positive_level;
1851 ++num_literal_at_highest_level_that_needs_to_be_processed;
1852 }
else if (level > 0) {
1853 ++num_new_vars_at_positive_level;
1859 reason_used_to_infer_the_conflict->push_back(
literal);
1866 if (num_new_vars_at_positive_level > 0) {
1869 subsumed_clauses->clear();
1876 if (sat_clause !=
nullptr &&
1877 num_vars_at_positive_level_in_clause_to_expand ==
1879 num_literal_at_highest_level_that_needs_to_be_processed) {
1880 subsumed_clauses->push_back(sat_clause);
1884 DCHECK_GT(num_literal_at_highest_level_that_needs_to_be_processed, 0);
1885 while (!is_marked_[(*trail_)[trail_index].Variable()]) {
1888 DCHECK_EQ(DecisionLevel((*trail_)[trail_index].Variable()),
1892 if (num_literal_at_highest_level_that_needs_to_be_processed == 1) {
1896 conflict->push_back((*trail_)[trail_index].Negated());
1899 std::swap(conflict->back(), conflict->front());
1903 const Literal
literal = (*trail_)[trail_index];
1904 reason_used_to_infer_the_conflict->push_back(
literal);
1910 clause_to_expand = {};
1914 sat_clause = ReasonClauseOrNull(
literal.Variable());
1916 --num_literal_at_highest_level_that_needs_to_be_processed;
1921 void SatSolver::ComputeUnionOfReasons(
const std::vector<Literal>&
input,
1922 std::vector<Literal>* literals) {
1925 for (
const Literal l :
input) tmp_mark_.
Set(l.Variable());
1926 for (
const Literal l :
input) {
1927 for (
const Literal r : trail_->
Reason(l.Variable())) {
1928 if (!tmp_mark_[r.Variable()]) {
1929 tmp_mark_.
Set(r.Variable());
1930 literals->push_back(r);
1934 for (
const Literal l :
input) tmp_mark_.
Clear(l.Variable());
1935 for (
const Literal l : *literals) tmp_mark_.
Clear(l.Variable());
1939 void SatSolver::ComputePBConflict(
int max_trail_index,
1940 Coefficient initial_slack,
1941 MutableUpperBoundedLinearConstraint* conflict,
1942 int* pb_backjump_level) {
1944 int trail_index = max_trail_index;
1948 Coefficient slack = initial_slack;
1950 conflict->ComputeSlackForTrailPrefix(*trail_, trail_index + 1));
1951 CHECK_LT(slack, 0) <<
"We don't have a conflict!";
1954 int backjump_level = 0;
1956 const BooleanVariable
var = (*trail_)[trail_index].Variable();
1959 if (conflict->GetCoefficient(
var) > 0 &&
1961 if (parameters_->minimize_reduction_during_pb_resolution()) {
1966 conflict->ReduceGivenCoefficient(
var);
1970 slack += conflict->GetCoefficient(
var);
1974 if (slack < 0)
continue;
1980 const int current_level = DecisionLevel(
var);
1981 int i = trail_index;
1983 const BooleanVariable previous_var = (*trail_)[i].Variable();
1984 if (conflict->GetCoefficient(previous_var) > 0 &&
1986 conflict->GetLiteral(previous_var))) {
1991 if (i < 0 || DecisionLevel((*trail_)[i].Variable()) < current_level) {
1992 backjump_level = i < 0 ? 0 : DecisionLevel((*trail_)[i].Variable());
1998 const bool clause_used = ResolvePBConflict(
var, conflict, &slack);
2007 const Coefficient slack_only_for_debug =
2009 ? conflict->ComputeSlackForTrailPrefix(*trail_, trail_index + 1)
2014 if (!parameters_->minimize_reduction_during_pb_resolution()) {
2015 conflict->ReduceCoefficients();
2021 if (parameters_->minimize_reduction_during_pb_resolution()) {
2023 conflict->ComputeSlackForTrailPrefix(*trail_, trail_index + 1);
2025 slack = conflict->ReduceCoefficientsAndComputeSlackForTrailPrefix(
2026 *trail_, trail_index + 1);
2031 if (conflict->Rhs() < 0) {
2032 *pb_backjump_level = -1;
2040 if (!parameters_->minimize_reduction_during_pb_resolution()) {
2041 conflict->ReduceCoefficients();
2046 std::vector<Coefficient> sum_for_le_level(backjump_level + 2, Coefficient(0));
2047 std::vector<Coefficient> max_coeff_for_ge_level(backjump_level + 2,
2050 Coefficient max_sum(0);
2051 for (BooleanVariable
var : conflict->PossibleNonZeros()) {
2052 const Coefficient coeff = conflict->GetCoefficient(
var);
2053 if (coeff == 0)
continue;
2057 DecisionLevel(
var) > backjump_level) {
2058 max_coeff_for_ge_level[backjump_level + 1] =
2059 std::max(max_coeff_for_ge_level[backjump_level + 1], coeff);
2061 const int level = DecisionLevel(
var);
2063 sum_for_le_level[level] += coeff;
2065 max_coeff_for_ge_level[level] =
2066 std::max(max_coeff_for_ge_level[level], coeff);
2071 for (
int i = 1; i < sum_for_le_level.size(); ++i) {
2072 sum_for_le_level[i] += sum_for_le_level[i - 1];
2074 for (
int i = max_coeff_for_ge_level.size() - 2; i >= 0; --i) {
2075 max_coeff_for_ge_level[i] =
2076 std::max(max_coeff_for_ge_level[i], max_coeff_for_ge_level[i + 1]);
2081 if (sum_for_le_level[0] > conflict->Rhs()) {
2082 *pb_backjump_level = -1;
2085 for (
int i = 0; i <= backjump_level; ++i) {
2086 const Coefficient level_sum = sum_for_le_level[i];
2087 CHECK_LE(level_sum, conflict->Rhs());
2088 if (conflict->Rhs() - level_sum < max_coeff_for_ge_level[i + 1]) {
2089 *pb_backjump_level = i;
2093 LOG(
FATAL) <<
"The code should never reach here.";
2096 void SatSolver::MinimizeConflict(
2097 std::vector<Literal>* conflict,
2098 std::vector<Literal>* reason_used_to_infer_the_conflict) {
2101 const int old_size = conflict->size();
2102 switch (parameters_->minimization_algorithm()) {
2103 case SatParameters::NONE:
2105 case SatParameters::SIMPLE: {
2106 MinimizeConflictSimple(conflict);
2109 case SatParameters::RECURSIVE: {
2110 MinimizeConflictRecursively(conflict);
2113 case SatParameters::EXPERIMENTAL: {
2114 MinimizeConflictExperimental(conflict);
2118 if (conflict->size() < old_size) {
2119 ++counters_.num_minimizations;
2120 counters_.num_literals_removed += old_size - conflict->size();
2131 void SatSolver::MinimizeConflictSimple(std::vector<Literal>* conflict) {
2138 for (
int i = 1; i < conflict->size(); ++i) {
2139 const BooleanVariable
var = (*conflict)[i].Variable();
2140 bool can_be_removed =
false;
2141 if (DecisionLevel(
var) != current_level) {
2143 const absl::Span<const Literal> reason = trail_->
Reason(
var);
2144 if (!reason.empty()) {
2145 can_be_removed =
true;
2146 for (Literal
literal : reason) {
2147 if (DecisionLevel(
literal.Variable()) == 0)
continue;
2148 if (!is_marked_[
literal.Variable()]) {
2149 can_be_removed =
false;
2155 if (!can_be_removed) {
2156 (*conflict)[
index] = (*conflict)[i];
2160 conflict->erase(conflict->begin() +
index, conflict->end());
2169 void SatSolver::MinimizeConflictRecursively(std::vector<Literal>* conflict) {
2203 const int level = DecisionLevel(
var);
2204 min_trail_index_per_level_[level] =
std::min(
2212 for (
int i = 1; i < conflict->size(); ++i) {
2213 const BooleanVariable
var = (*conflict)[i].Variable();
2216 min_trail_index_per_level_[DecisionLevel(
var)] ||
2217 !CanBeInferedFromConflictVariables(
var)) {
2220 is_independent_.
Set(
var);
2221 (*conflict)[
index] = (*conflict)[i];
2225 conflict->resize(
index);
2229 const int threshold = min_trail_index_per_level_.size() / 2;
2232 min_trail_index_per_level_[DecisionLevel(
var)] =
2236 min_trail_index_per_level_.clear();
2240 bool SatSolver::CanBeInferedFromConflictVariables(BooleanVariable variable) {
2243 DCHECK(is_marked_[variable]);
2244 const BooleanVariable v =
2246 if (v != variable)
return !is_independent_[v];
2259 dfs_stack_.push_back(variable);
2260 variable_to_process_.clear();
2261 variable_to_process_.push_back(variable);
2265 const BooleanVariable
var =
literal.Variable();
2267 if (is_marked_[
var])
continue;
2268 const int level = DecisionLevel(
var);
2278 is_independent_[
var]) {
2281 variable_to_process_.push_back(
var);
2285 while (!variable_to_process_.empty()) {
2286 const BooleanVariable current_var = variable_to_process_.back();
2287 if (current_var == dfs_stack_.back()) {
2290 if (dfs_stack_.size() > 1) {
2291 DCHECK(!is_marked_[current_var]);
2292 is_marked_.
Set(current_var);
2294 variable_to_process_.pop_back();
2295 dfs_stack_.pop_back();
2300 if (is_marked_[current_var]) {
2301 variable_to_process_.pop_back();
2307 DCHECK(!is_independent_[current_var]);
2311 const BooleanVariable v =
2313 if (v != current_var) {
2314 if (is_independent_[v])
break;
2316 variable_to_process_.pop_back();
2322 dfs_stack_.push_back(current_var);
2323 bool abort_early =
false;
2325 const BooleanVariable
var =
literal.Variable();
2327 const int level = DecisionLevel(
var);
2328 if (level == 0 || is_marked_[
var])
continue;
2330 is_independent_[
var]) {
2334 variable_to_process_.push_back(
var);
2336 if (abort_early)
break;
2340 for (
const BooleanVariable
var : dfs_stack_) {
2341 is_independent_.
Set(
var);
2343 return dfs_stack_.empty();
2348 struct WeightedVariable {
2349 WeightedVariable(BooleanVariable v,
int w) :
var(v),
weight(w) {}
2357 struct VariableWithLargerWeightFirst {
2358 bool operator()(
const WeightedVariable& wv1,
2359 const WeightedVariable& wv2)
const {
2360 return (wv1.weight > wv2.weight ||
2361 (wv1.weight == wv2.weight && wv1.var < wv2.var));
2377 void SatSolver::MinimizeConflictExperimental(std::vector<Literal>* conflict) {
2384 std::vector<WeightedVariable> variables_sorted_by_level;
2385 for (Literal
literal : *conflict) {
2386 const BooleanVariable
var =
literal.Variable();
2388 const int level = DecisionLevel(
var);
2389 if (level < current_level) {
2390 variables_sorted_by_level.push_back(WeightedVariable(
var, level));
2393 std::sort(variables_sorted_by_level.begin(), variables_sorted_by_level.end(),
2394 VariableWithLargerWeightFirst());
2397 std::vector<BooleanVariable> to_remove;
2398 for (WeightedVariable weighted_var : variables_sorted_by_level) {
2399 const BooleanVariable
var = weighted_var.var;
2403 const absl::Span<const Literal> reason = trail_->
Reason(
var);
2404 if (reason.empty())
continue;
2408 std::vector<Literal> not_contained_literals;
2409 for (
const Literal reason_literal : reason) {
2410 const BooleanVariable reason_var = reason_literal.Variable();
2413 if (DecisionLevel(reason_var) == 0)
continue;
2418 if (!is_marked_[reason_var]) {
2419 not_contained_literals.push_back(reason_literal);
2420 if (not_contained_literals.size() > 1)
break;
2423 if (not_contained_literals.empty()) {
2428 to_remove.push_back(
var);
2429 }
else if (not_contained_literals.size() == 1) {
2432 to_remove.push_back(
var);
2433 is_marked_.
Set(not_contained_literals.front().Variable());
2434 conflict->push_back(not_contained_literals.front());
2439 for (BooleanVariable
var : to_remove) {
2445 for (
int i = 0; i < conflict->size(); ++i) {
2446 const Literal
literal = (*conflict)[i];
2447 if (is_marked_[
literal.Variable()]) {
2452 conflict->erase(conflict->begin() +
index, conflict->end());
2455 void SatSolver::CleanClauseDatabaseIfNeeded() {
2456 if (num_learned_clause_before_cleanup_ > 0)
return;
2461 typedef std::pair<SatClause*, ClauseInfo> Entry;
2462 std::vector<Entry> entries;
2464 for (
auto& entry : clauses_info) {
2465 if (ClauseIsUsedAsReason(entry.first))
continue;
2466 if (entry.second.protected_during_next_cleanup) {
2467 entry.second.protected_during_next_cleanup =
false;
2470 entries.push_back(entry);
2472 const int num_protected_clauses = clauses_info.size() - entries.size();
2474 if (parameters_->clause_cleanup_ordering() == SatParameters::CLAUSE_LBD) {
2476 std::sort(entries.begin(), entries.end(),
2477 [](
const Entry&
a,
const Entry&
b) {
2478 if (a.second.lbd == b.second.lbd) {
2479 return a.second.activity < b.second.activity;
2481 return a.second.lbd >
b.second.lbd;
2485 std::sort(entries.begin(), entries.end(),
2486 [](
const Entry&
a,
const Entry&
b) {
2487 if (a.second.activity == b.second.activity) {
2488 return a.second.lbd > b.second.lbd;
2490 return a.second.activity <
b.second.activity;
2495 int num_kept_clauses =
std::min(
static_cast<int>(entries.size()),
2496 parameters_->clause_cleanup_target());
2497 int num_deleted_clauses = entries.size() - num_kept_clauses;
2502 while (num_deleted_clauses > 0) {
2503 const ClauseInfo&
a = entries[num_deleted_clauses].second;
2504 const ClauseInfo&
b = entries[num_deleted_clauses - 1].second;
2505 if (
a.activity !=
b.activity ||
a.lbd !=
b.lbd)
break;
2506 --num_deleted_clauses;
2509 if (num_deleted_clauses > 0) {
2510 entries.resize(num_deleted_clauses);
2511 for (
const Entry& entry : entries) {
2512 SatClause* clause = entry.first;
2513 counters_.num_literals_forgotten += clause->size();
2514 clauses_propagator_->LazyDetach(clause);
2516 clauses_propagator_->CleanUpWatchers();
2520 if (!block_clause_deletion_) {
2521 clauses_propagator_->DeleteRemovedClauses();
2525 num_learned_clause_before_cleanup_ = parameters_->clause_cleanup_period();
2526 VLOG(1) <<
"Database cleanup, #protected:" << num_protected_clauses
2527 <<
" #kept:" << num_kept_clauses
2528 <<
" #deleted:" << num_deleted_clauses;
2533 case SatSolver::ASSUMPTIONS_UNSAT:
2534 return "ASSUMPTIONS_UNSAT";
2536 return "INFEASIBLE";
2539 case SatSolver::LIMIT_REACHED:
2540 return "LIMIT_REACHED";
2544 LOG(DFATAL) <<
"Invalid SatSolver::Status " << status;
2549 std::vector<Literal> temp = *core;
2550 std::reverse(temp.begin(), temp.end());
2560 if (status != SatSolver::ASSUMPTIONS_UNSAT) {
2561 if (status != SatSolver::LIMIT_REACHED) {
2566 LOG(
WARNING) <<
"This should only happen rarely! otherwise, investigate. "
2572 if (temp.size() < core->size()) {
2573 VLOG(1) <<
"minimization " << core->size() <<
" -> " << temp.size();
2574 std::reverse(temp.begin(), temp.end());
#define DCHECK_LE(val1, val2)
#define DCHECK_NE(val1, val2)
#define CHECK_LT(val1, val2)
#define CHECK_EQ(val1, val2)
#define CHECK_GE(val1, val2)
#define CHECK_GT(val1, val2)
#define DCHECK_GE(val1, val2)
#define CHECK_NE(val1, val2)
#define DCHECK_GT(val1, val2)
#define DCHECK_LT(val1, val2)
#define DCHECK(condition)
#define CHECK_LE(val1, val2)
#define DCHECK_EQ(val1, val2)
#define VLOG(verboselevel)
const std::vector< IntegerType > & PositionsSetAtLeastOnce() const
void Set(IntegerType index)
int NumberOfSetCallsWithDifferentArguments() const
void Clear(IntegerType index)
void ClearAndResize(IntegerType size)
std::string StatString() const
A simple class to enforce both an elapsed time limit and a deterministic time limit in the same threa...
void ResetLimitFromParameters(const Parameters ¶meters)
Sets new time limits.
bool LimitReached()
Returns true when the external limit is true, or the deterministic time is over the deterministic lim...
const std::vector< BinaryClause > & newly_added() const
void AddBinaryClause(Literal a, Literal b)
void MinimizeConflictWithReachability(std::vector< Literal > *c)
bool AddBinaryClauseDuringSearch(Literal a, Literal b)
void MinimizeConflictFirstWithTransitiveReduction(const Trail &trail, std::vector< Literal > *c, SparseBitset< BooleanVariable > *marked, absl::BitGenRef random)
int64_t num_inspections() const
int64_t num_redundant_implications() const
void MinimizeConflictFirst(const Trail &trail, std::vector< Literal > *c, SparseBitset< BooleanVariable > *marked)
int64_t num_literals_removed() const
int64_t num_propagations() const
void RemoveFixedVariables()
int64_t num_minimization() const
int64_t num_implications() const
ABSL_MUST_USE_RESULT bool AddAtMostOne(absl::Span< const Literal > at_most_one)
void MinimizeConflictExperimental(const Trail &trail, std::vector< Literal > *c)
void Resize(int num_variables)
void DeleteClause(absl::Span< const Literal > clause)
void AddClause(absl::Span< const Literal > clause)
BooleanVariable Variable() const
const std::vector< SatClause * > & AllClausesInCreationOrder() const
absl::flat_hash_map< SatClause *, ClauseInfo > * mutable_clauses_info()
SatClause * AddRemovableClause(const std::vector< Literal > &literals, Trail *trail)
int64_t num_inspected_clauses() const
int64_t num_clauses() const
SatClause * NextClauseToMinimize()
bool AddClause(absl::Span< const Literal > literals, Trail *trail)
SatClause * ReasonClause(int trail_index) const
bool IsRemovable(SatClause *const clause) const
ABSL_MUST_USE_RESULT bool InprocessingRewriteClause(SatClause *clause, absl::Span< const Literal > new_clause)
int64_t num_watched_clauses() const
void LazyDetach(SatClause *clause)
int64_t num_removable_clauses() const
int64_t num_inspected_clause_literals() const
void ResetToMinimizeIndex()
void DeleteRemovedClauses()
void Detach(SatClause *clause)
void Resize(int num_variables)
Class that owns everything related to a particular optimization model.
void Register(T *non_owned_class)
Register a non-owned class that will be "singleton" in the model.
T * GetOrCreate()
Returns an object of type T that is unique to this model (like a "local" singleton).
Coefficient ComputeSlackForTrailPrefix(const Trail &trail, int trail_index) const
void AddTerm(Literal literal, Coefficient coeff)
void AddToRhs(Coefficient value)
void ClearAndResize(int num_variables)
void CopyIntoVector(std::vector< LiteralWithCoeff > *output)
int NumberOfConstraints() const
void ClearConflictingConstraint()
int64_t num_inspected_constraint_literals() const
bool AddConstraint(const std::vector< LiteralWithCoeff > &cst, Coefficient rhs, Trail *trail)
int64_t num_threshold_updates() const
UpperBoundedLinearConstraint * ConflictingConstraint()
UpperBoundedLinearConstraint * ReasonPbConstraint(int trail_index) const
void UpdateActivityIncrement()
void BumpActivity(UpperBoundedLinearConstraint *constraint)
int64_t num_constraint_lookups() const
void Resize(int num_variables)
bool AddLearnedConstraint(const std::vector< LiteralWithCoeff > &cst, Coefficient rhs, Trail *trail)
std::string InfoString() const
void OnConflict(int conflict_trail_index, int conflict_decision_level, int conflict_lbd)
void IncreaseNumVariables(int num_variables)
void UpdateVariableActivityIncrement()
void Untrail(int target_trail_index)
void BumpVariableActivities(const std::vector< Literal > &literals)
void BeforeConflict(int trail_index)
void UpdateWeightedSign(const std::vector< LiteralWithCoeff > &terms, Coefficient rhs)
const Trail & LiteralTrail() const
bool AddLinearConstraint(bool use_lower_bound, Coefficient lower_bound, bool use_upper_bound, Coefficient upper_bound, std::vector< LiteralWithCoeff > *cst)
bool EnqueueDecisionIfNotConflicting(Literal true_literal)
void SetNumVariables(int num_variables)
bool AddTernaryClause(Literal a, Literal b, Literal c)
void AddLastPropagator(SatPropagator *propagator)
const SatParameters & parameters() const
bool AddClauseDuringSearch(absl::Span< const Literal > literals)
Status SolveWithTimeLimit(TimeLimit *time_limit)
void ProcessNewlyFixedVariables()
Status ResetAndSolveWithGivenAssumptions(const std::vector< Literal > &assumptions)
void AddPropagator(SatPropagator *propagator)
const std::vector< BinaryClause > & NewlyAddedBinaryClauses()
bool AddBinaryClauses(const std::vector< BinaryClause > &clauses)
Status UnsatStatus() const
void SetAssumptionLevel(int assumption_level)
void SaveDebugAssignment()
void AdvanceDeterministicTime(TimeLimit *limit)
int64_t num_restarts() const
void MinimizeSomeClauses(int decisions_budget)
int64_t num_branches() const
const VariablesAssignment & Assignment() const
int EnqueueDecisionAndBackjumpOnConflict(Literal true_literal)
void SetParameters(const SatParameters ¶meters)
bool AddBinaryClause(Literal a, Literal b)
int EnqueueDecisionAndBacktrackOnConflict(Literal true_literal)
int64_t num_propagations() const
void Backtrack(int target_level)
bool RestoreSolverToAssumptionLevel()
int64_t num_failures() const
std::vector< Literal > GetLastIncompatibleDecisions()
bool ReapplyAssumptionsIfNeeded()
bool ResetWithGivenAssumptions(const std::vector< Literal > &assumptions)
int CurrentDecisionLevel() const
double deterministic_time() const
bool AddProblemClause(absl::Span< const Literal > literals)
bool AddUnitClause(Literal true_literal)
void ClearNewlyAddedBinaryClauses()
absl::Span< const Literal > FailingClause() const
void RegisterPropagator(SatPropagator *propagator)
const AssignmentInfo & Info(BooleanVariable var) const
int64_t NumberOfEnqueues() const
SatClause * FailingSatClause() const
int AssignmentType(BooleanVariable var) const
absl::Span< const Literal > Reason(BooleanVariable var) const
BooleanVariable ReferenceVarWithSameReason(BooleanVariable var) const
const VariablesAssignment & Assignment() const
void Untrail(int target_trail_index)
void SetDecisionLevel(int level)
void Resize(int num_variables)
void EnqueueWithUnitReason(Literal true_literal)
void EnqueueSearchDecision(Literal true_literal)
void AddToConflict(MutableUpperBoundedLinearConstraint *conflict)
BooleanVariable FirstVariableWithSameReason(BooleanVariable var)
void Resize(int num_variables)
bool VariableIsAssigned(BooleanVariable var) const
bool LiteralIsTrue(Literal literal) const
void AssignFromTrueLiteral(Literal literal)
Literal GetTrueLiteralForAssignedVariable(BooleanVariable var) const
bool LiteralIsFalse(Literal literal) const
int NumberOfVariables() const
void Resize(int num_variables)
SharedTimeLimit * time_limit
void swap(IdMap< K, V > &a, IdMap< K, V > &b)
Coefficient ComputeCanonicalRhs(Coefficient upper_bound, Coefficient bound_shift, Coefficient max_value)
int MoveOneUnprocessedLiteralLast(const std::set< LiteralIndex > &processed, int relevant_prefix_size, std::vector< Literal > *literals)
Coefficient ComputeNegatedCanonicalRhs(Coefficient lower_bound, Coefficient bound_shift, Coefficient max_value)
void MinimizeCore(SatSolver *solver, std::vector< Literal > *core)
std::string SatStatusString(SatSolver::Status status)
bool ComputeBooleanLinearExpressionCanonicalForm(std::vector< LiteralWithCoeff > *cst, Coefficient *bound_shift, Coefficient *max_value)
bool BooleanLinearExpressionIsCanonical(const std::vector< LiteralWithCoeff > &cst)
const int kUnsatTrailIndex
int64_t MemoryUsageProcess()
Collection of objects used to extend the Constraint Solver library.
std::string ProtobufShortDebugString(const P &message)
std::string MemoryUsage()
bool SafeAddInto(IntegerType a, IntegerType *b)
static int input(yyscan_t yyscanner)
#define IF_STATS_ENABLED(instructions)
#define SCOPED_TIME_STAT(stats)
static constexpr int kSearchDecision