22 #include <type_traits> 25 #include "absl/strings/str_format.h" 39 owned_model_.reset(model_);
48 track_binary_clauses_(false),
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;
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();
189 &tmp_pb_constraint_);
194 tmp_pb_constraint_.clear();
201 &tmp_pb_constraint_);
210 tmp_pb_constraint_.clear();
217 &tmp_pb_constraint_);
220 bool SatSolver::AddProblemClauseInternal(absl::Span<const Literal> literals) {
228 if (literals.size() == 1) {
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,
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_);
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;
319 (*cst)[
index] = term;
333 if (use_upper_bound) {
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();
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) {
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);
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 {
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_));
595 ComputeUnionOfReasons(learned_conflict_, &extra_reason_literals_);
605 BumpReasonActivities(reason_used_to_infer_the_conflict_);
609 UpdateClauseActivityIncrement();
615 if (counters_.num_failures % period == 0 &&
625 bool compute_pb_conflict =
false;
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) {
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) {
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()) {
734 *trail_, &learned_conflict_, &is_marked_);
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()) {
755 ABSL_FALLTHROUGH_INTENDED;
757 ABSL_FALLTHROUGH_INTENDED;
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() &&
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_);
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();
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;
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 =
1150 const int64_t kDisplayFrequency = 10000;
1153 : std::numeric_limits<int64_t>::
max();
1156 const int64_t kMemoryCheckFrequency = 10000;
1157 int64_t next_memory_check =
1162 const int64_t kFailureLimit =
1166 : counters_.
num_failures + parameters_->max_number_of_conflicts();
1175 LOG(
INFO) <<
"The time limit has been reached. Aborting.";
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()) {
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 =
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);
1379 it->second.protected_during_next_cleanup =
true;
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_;
1399 void SatSolver::RescaleClauseActivities(
double scaling_factor) {
1401 clause_activity_increment_ *= scaling_factor;
1403 entry.second.activity *= scaling_factor;
1407 void SatSolver::UpdateClauseActivityIncrement() {
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) {
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});
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,
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);
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);
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,
1941 MutableUpperBoundedLinearConstraint* conflict,
1942 int* pb_backjump_level) {
1944 int trail_index = max_trail_index;
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 &&
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);
2009 ? conflict->ComputeSlackForTrailPrefix(*trail_, trail_index + 1)
2015 conflict->ReduceCoefficients();
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;
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,
2051 for (BooleanVariable
var : conflict->PossibleNonZeros()) {
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();
2106 MinimizeConflictSimple(conflict);
2110 MinimizeConflictRecursively(conflict);
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();
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 =
2497 ?
std::min(static_cast<int>(entries.size()),
2500 static_cast<double>(entries.size()));
2502 int num_deleted_clauses = entries.size() - num_kept_clauses;
2507 while (num_deleted_clauses > 0) {
2508 const ClauseInfo&
a = entries[num_deleted_clauses].second;
2509 const ClauseInfo&
b = entries[num_deleted_clauses - 1].second;
2510 if (
a.activity !=
b.activity ||
a.lbd !=
b.lbd)
break;
2511 --num_deleted_clauses;
2514 if (num_deleted_clauses > 0) {
2515 entries.resize(num_deleted_clauses);
2516 for (
const Entry& entry : entries) {
2517 SatClause* clause = entry.first;
2518 counters_.num_literals_forgotten += clause->size();
2525 if (!block_clause_deletion_) {
2531 VLOG(1) <<
"Database cleanup, #protected:" << num_protected_clauses
2532 <<
" #kept:" << num_kept_clauses
2533 <<
" #deleted:" << num_deleted_clauses;
2539 return "ASSUMPTIONS_UNSAT";
2541 return "INFEASIBLE";
2545 return "LIMIT_REACHED";
2549 LOG(DFATAL) <<
"Invalid SatSolver::Status " << status;
2554 std::vector<Literal> temp = *core;
2555 std::reverse(temp.begin(), temp.end());
2571 LOG(
WARNING) <<
"This should only happen rarely! otherwise, investigate. " 2577 if (temp.size() < core->size()) {
2578 VLOG(1) <<
"minimization " << core->size() <<
" -> " << temp.size();
2579 std::reverse(temp.begin(), temp.end());
BooleanVariable FirstVariableWithSameReason(BooleanVariable var)
void SetParameters(const SatParameters ¶meters)
UpperBoundedLinearConstraint * ReasonPbConstraint(int trail_index) const
bool SafeAddInto(IntegerType a, IntegerType *b)
static constexpr BinaryMinizationAlgorithm EXPERIMENTAL_BINARY_MINIMIZATION
A simple class to enforce both an elapsed time limit and a deterministic time limit in the same threa...
SatClause * AddRemovableClause(const std::vector< Literal > &literals, Trail *trail)
void MinimizeConflictWithReachability(std::vector< Literal > *c)
std::string StatString() const
const SatParameters & parameters() const
void Resize(int num_variables)
void Set(IntegerType index)
void LazyDetach(SatClause *clause)
int64_t num_clauses() const
#define CHECK_GE(val1, val2)
bool AddBinaryClauses(const std::vector< BinaryClause > &clauses)
bool BooleanLinearExpressionIsCanonical(const std::vector< LiteralWithCoeff > &cst)
Class that owns everything related to a particular optimization model.
ModelSharedTimeLimit * time_limit
bool minimize_reduction_during_pb_resolution() const
bool AddClause(absl::Span< const Literal > literals, Trail *trail)
std::vector< Literal > GetLastIncompatibleDecisions()
static constexpr ConflictMinimizationAlgorithm NONE
void SetAssumptionLevel(int assumption_level)
void ProcessNewlyFixedVariables()
void ResetToMinimizeIndex()
bool use_pb_resolution() const
void Resize(int num_variables)
const std::vector< BinaryClause > & newly_added() const
#define CHECK_GT(val1, val2)
SatClause * FailingSatClause() const
#define VLOG(verboselevel)
::PROTOBUF_NAMESPACE_ID::int32 minimize_with_propagation_num_decisions() const
void UpdateVariableActivityIncrement()
void ClearAndResize(int num_variables)
T * GetOrCreate()
Returns an object of type T that is unique to this model (like a "local" singleton).
static constexpr BinaryMinizationAlgorithm BINARY_MINIMIZATION_FIRST
bool LiteralIsFalse(Literal literal) const
void swap(IdMap< K, V > &a, IdMap< K, V > &b)
bool LiteralIsTrue(Literal literal) const
void UpdateActivityIncrement()
void AssignFromTrueLiteral(Literal literal)
void AddToRhs(Coefficient value)
void Clear(IntegerType index)
int64_t NumberOfEnqueues() const
int EnqueueDecisionAndBacktrackOnConflict(Literal true_literal)
#define SCOPED_TIME_STAT(stats)
void MinimizeCore(SatSolver *solver, std::vector< Literal > *core)
static constexpr ClauseProtection PROTECTION_NONE
UpperBoundedLinearConstraint * ConflictingConstraint()
void Detach(SatClause *clause)
::PROTOBUF_NAMESPACE_ID::int32 glucose_decay_increment_period() const
void AddClause(absl::Span< const Literal > clause)
void SetNumVariables(int num_variables)
static constexpr ClauseProtection PROTECTION_ALWAYS
bool AddUnitClause(Literal true_literal)
void SaveDebugAssignment()
#define DCHECK_GT(val1, val2)
int NumberOfVariables() const
void UpdateWeightedSign(const std::vector< LiteralWithCoeff > &terms, Coefficient rhs)
SatClause * NextClauseToMinimize()
bool AddBinaryClause(Literal a, Literal b)
int64_t num_failures() const
void MinimizeConflictFirst(const Trail &trail, std::vector< Literal > *c, SparseBitset< BooleanVariable > *marked)
bool EnqueueDecisionIfNotConflicting(Literal true_literal)
void ResetLimitFromParameters(const Parameters ¶meters)
Sets new time limits.
static constexpr ClauseOrdering CLAUSE_LBD
const int kUnsatTrailIndex
int64_t num_implications() const
::PROTOBUF_NAMESPACE_ID::int32 clause_cleanup_period() const
void RemoveFixedVariables()
#define CHECK_LT(val1, val2)
int64_t num_constraint_lookups() const
void ClearNewlyAddedBinaryClauses()
void MinimizeConflictFirstWithTransitiveReduction(const Trail &trail, std::vector< Literal > *c, SparseBitset< BooleanVariable > *marked, absl::BitGenRef random)
void EnqueueWithUnitReason(Literal true_literal)
void set_variable_activity_decay(double value)
void BeforeConflict(int trail_index)
bool AddTernaryClause(Literal a, Literal b, Literal c)
const std::vector< BinaryClause > & NewlyAddedBinaryClauses()
bool ReapplyAssumptionsIfNeeded()
absl::flat_hash_map< SatClause *, ClauseInfo > * mutable_clauses_info()
int64_t num_inspected_constraint_literals() const
int64_t MemoryUsageProcess()
BooleanVariable Variable() const
Status UnsatStatus() const
int64_t num_removable_clauses() const
#define DCHECK_NE(val1, val2)
void Untrail(int target_trail_index)
int EnqueueDecisionAndBackjumpOnConflict(Literal true_literal)
void AddToConflict(MutableUpperBoundedLinearConstraint *conflict)
void AddBinaryClause(Literal a, Literal b)
bool ResetWithGivenAssumptions(const std::vector< Literal > &assumptions)
void DeleteClause(absl::Span< const Literal > clause)
#define CHECK_LE(val1, val2)
bool VariableIsAssigned(BooleanVariable var) const
double max_clause_activity_value() const
void OnConflict(int conflict_trail_index, int conflict_decision_level, int conflict_lbd)
void AddPropagator(SatPropagator *propagator)
void DeleteRemovedClauses()
Status SolveWithTimeLimit(TimeLimit *time_limit)
Literal GetTrueLiteralForAssignedVariable(BooleanVariable var) const
void EnqueueSearchDecision(Literal true_literal)
static constexpr ConflictMinimizationAlgorithm SIMPLE
static int input(yyscan_t yyscanner)
int64_t num_inspected_clauses() const
bool IsRemovable(SatClause *const clause) const
int NumberOfSetCallsWithDifferentArguments() const
static constexpr BinaryMinizationAlgorithm BINARY_MINIMIZATION_WITH_REACHABILITY
void AdvanceDeterministicTime(TimeLimit *limit)
::PROTOBUF_NAMESPACE_ID::int32 clause_cleanup_lbd_bound() const
static constexpr ClauseProtection PROTECTION_LBD
int64_t num_watched_clauses() const
void Backtrack(int target_level)
bool AddClauseDuringSearch(absl::Span< const Literal > literals)
bool AddLinearConstraint(bool use_lower_bound, Coefficient lower_bound, bool use_upper_bound, Coefficient upper_bound, std::vector< LiteralWithCoeff > *cst)
void MinimizeSomeClauses(int decisions_budget)
::PROTOBUF_NAMESPACE_ID::int64 max_memory_in_mb() const
#define DCHECK_GE(val1, val2)
Status ResetAndSolveWithGivenAssumptions(const std::vector< Literal > &assumptions)
void AddLastPropagator(SatPropagator *propagator)
double variable_activity_decay() const
static constexpr BinaryMinizationAlgorithm BINARY_MINIMIZATION_FIRST_WITH_TRANSITIVE_REDUCTION
int64_t num_restarts() const
#define CHECK_EQ(val1, val2)
::operations_research::sat::SatParameters_ConflictMinimizationAlgorithm minimization_algorithm() const
bool RestoreSolverToAssumptionLevel()
const std::vector< SatClause * > & AllClausesInCreationOrder() const
std::string MemoryUsage()
ABSL_MUST_USE_RESULT bool AddAtMostOne(absl::Span< const Literal > at_most_one)
double glucose_max_decay() const
const VariablesAssignment & Assignment() const
int64_t num_threshold_updates() const
SatClause * ReasonClause(int trail_index) const
bool AddConstraint(const std::vector< LiteralWithCoeff > &cst, Coefficient rhs, Trail *trail)
double glucose_decay_increment() const
#define DCHECK(condition)
bool LimitReached()
Returns true when the external limit is true, or the deterministic time is over the deterministic lim...
std::tuple< int64_t, int64_t, const double > Coefficient
#define DCHECK_EQ(val1, val2)
void CopyIntoVector(std::vector< LiteralWithCoeff > *output)
void ClearAndResize(IntegerType size)
void BumpVariableActivities(const std::vector< Literal > &literals)
bool log_search_progress() const
Coefficient ComputeSlackForTrailPrefix(const Trail &trail, int trail_index) const
bool also_bump_variables_in_conflict_reasons() const
::operations_research::sat::SatParameters_BinaryMinizationAlgorithm binary_minimization_algorithm() const
::PROTOBUF_NAMESPACE_ID::int32 minimize_with_propagation_restart_period() const
std::string ProtobufShortDebugString(const P &message)
void MinimizeConflictExperimental(const Trail &trail, std::vector< Literal > *c)
void IncreaseNumVariables(int num_variables)
static constexpr BinaryMinizationAlgorithm NO_BINARY_MINIMIZATION
bool subsumption_during_conflict_analysis() const
Coefficient ComputeNegatedCanonicalRhs(Coefficient lower_bound, Coefficient bound_shift, Coefficient max_value)
#define DCHECK_LE(val1, val2)
void Untrail(int target_trail_index)
double deterministic_time() const
int64_t num_propagations() const
void RegisterPropagator(SatPropagator *propagator)
::PROTOBUF_NAMESPACE_ID::int64 max_number_of_conflicts() const
const std::vector< IntegerType > & PositionsSetAtLeastOnce() const
bool AddLearnedConstraint(const std::vector< LiteralWithCoeff > &cst, Coefficient rhs, Trail *trail)
int CurrentDecisionLevel() const
bool AddProblemClause(absl::Span< const Literal > literals)
BooleanVariable ReferenceVarWithSameReason(BooleanVariable var) const
Collection of objects used to extend the Constraint Solver library.
void Resize(int num_variables)
void Resize(int num_variables)
bool AddBinaryClauseDuringSearch(Literal a, Literal b)
::operations_research::sat::SatParameters_ClauseOrdering clause_cleanup_ordering() const
int NumberOfConstraints() const
::operations_research::sat::SatParameters_ClauseProtection clause_cleanup_protection() const
void ClearConflictingConstraint()
int AssignmentType(BooleanVariable var) const
static constexpr int kSearchDecision
int64_t num_redundant_implications() const
const VariablesAssignment & Assignment() const
void SetDecisionLevel(int level)
const Trail & LiteralTrail() const
std::string InfoString() const
absl::Span< const Literal > Reason(BooleanVariable var) const
std::string SatStatusString(SatSolver::Status status)
absl::Span< const Literal > FailingClause() const
double clause_activity_decay() const
int MoveOneUnprocessedLiteralLast(const std::set< LiteralIndex > &processed, int relevant_prefix_size, std::vector< Literal > *literals)
double clause_cleanup_ratio() const
Coefficient ComputeCanonicalRhs(Coefficient upper_bound, Coefficient bound_shift, Coefficient max_value)
bool treat_binary_clauses_separately() const
bool ComputeBooleanLinearExpressionCanonicalForm(std::vector< LiteralWithCoeff > *cst, Coefficient *bound_shift, Coefficient *max_value)
bool count_assumption_levels_in_lbd() const
::PROTOBUF_NAMESPACE_ID::int32 clause_cleanup_target() const
int64_t num_propagations() const
void BumpActivity(UpperBoundedLinearConstraint *constraint)
void Register(T *non_owned_class)
Register a non-owned class that will be "singleton" in the model.
int64_t num_minimization() const
int64_t num_branches() const
int64_t num_inspections() const
int64_t num_inspected_clause_literals() const
void Resize(int num_variables)
void Resize(int num_variables)
static constexpr ConflictMinimizationAlgorithm EXPERIMENTAL
#define CHECK_NE(val1, val2)
ABSL_MUST_USE_RESULT bool InprocessingRewriteClause(SatClause *clause, absl::Span< const Literal > new_clause)
void AddTerm(Literal literal, Coefficient coeff)
const AssignmentInfo & Info(BooleanVariable var) const
int64_t num_literals_removed() const
#define DCHECK_LT(val1, val2)
static constexpr ConflictMinimizationAlgorithm RECURSIVE
#define IF_STATS_ENABLED(instructions)