22#include "absl/memory/memory.h"
40 : initial_num_variables_(num_variables), num_variables_(num_variables) {
41 reverse_mapping_.resize(num_variables);
42 for (BooleanVariable
var(0);
var < num_variables; ++
var) {
43 reverse_mapping_[
var] =
var;
45 assignment_.
Resize(num_variables);
50 DCHECK(std::find(clause.begin(), clause.end(), x) != clause.end());
51 associated_literal_.push_back(ApplyReverseMapping(x));
52 clauses_start_.push_back(clauses_literals_.size());
53 for (
const Literal& l : clause) {
54 clauses_literals_.push_back(ApplyReverseMapping(l));
59 const Literal l = ApplyReverseMapping(x);
66 if (reverse_mapping_.size() < mapping.
size()) {
68 while (reverse_mapping_.size() < mapping.
size()) {
69 reverse_mapping_.push_back(BooleanVariable(num_variables_++));
71 assignment_.
Resize(num_variables_);
73 for (BooleanVariable v(0); v < mapping.
size(); ++v) {
74 const BooleanVariable image = mapping[v];
76 if (image >= new_mapping.
size()) {
79 new_mapping[image] = reverse_mapping_[v];
87 if (l.
Variable() >= reverse_mapping_.size()) {
89 while (l.
Variable() >= reverse_mapping_.size()) {
90 reverse_mapping_.push_back(BooleanVariable(num_variables_++));
92 assignment_.
Resize(num_variables_);
100void SatPostsolver::Postsolve(VariablesAssignment* assignment)
const {
103 for (BooleanVariable
var(0);
var < assignment->NumberOfVariables(); ++
var) {
104 if (!assignment->VariableIsAssigned(
var)) {
105 assignment->AssignFromTrueLiteral(Literal(
var,
true));
109 int previous_start = clauses_literals_.size();
110 for (
int i =
static_cast<int>(clauses_start_.size()) - 1; i >= 0; --i) {
111 bool set_associated_var =
true;
112 const int new_start = clauses_start_[i];
113 for (
int j = new_start; j < previous_start; ++j) {
114 if (assignment->LiteralIsTrue(clauses_literals_[j])) {
115 set_associated_var =
false;
119 previous_start = new_start;
120 if (set_associated_var) {
121 assignment->UnassignLiteral(associated_literal_[i].Negated());
122 assignment->AssignFromTrueLiteral(associated_literal_[i]);
127 assignment->Resize(initial_num_variables_);
135 solution[
var.value()] =
142 const std::vector<bool>& solution) {
143 for (BooleanVariable
var(0);
var < solution.size(); ++
var) {
150 Postsolve(&assignment_);
151 std::vector<bool> postsolved_solution;
152 postsolved_solution.reserve(initial_num_variables_);
153 for (
int i = 0; i < initial_num_variables_; ++i) {
154 postsolved_solution.push_back(
157 return postsolved_solution;
163 DCHECK_GT(clause.size(), 0) <<
"Added an empty clause to the presolver";
165 clauses_.push_back(std::vector<Literal>(clause.begin(), clause.end()));
166 in_clause_to_process_.push_back(
true);
167 clause_to_process_.push_back(ci);
169 bool changed =
false;
170 std::vector<Literal>& clause_ref = clauses_.back();
171 if (!equiv_mapping_.empty()) {
172 for (
int i = 0; i < clause_ref.size(); ++i) {
173 const Literal old_literal = clause_ref[i];
174 clause_ref[i] =
Literal(equiv_mapping_[clause_ref[i].
Index()]);
175 if (old_literal != clause_ref[i]) changed =
true;
178 std::sort(clause_ref.begin(), clause_ref.end());
179 clause_ref.erase(std::unique(clause_ref.begin(), clause_ref.end()),
183 for (
int i = 1; i < clause_ref.size(); ++i) {
184 if (clause_ref[i] == clause_ref[i - 1].Negated()) {
186 ++num_trivial_clauses_;
187 clause_to_process_.pop_back();
189 in_clause_to_process_.pop_back();
195 signatures_.push_back(ComputeSignatureOfClauseVariables(ci));
196 DCHECK_EQ(signatures_.size(), clauses_.size());
198 if (drat_proof_handler_ !=
nullptr && changed) {
199 drat_proof_handler_->
AddClause(clause_ref);
203 const Literal max_literal = clause_ref.back();
204 const int required_size =
std::max(max_literal.
Index().value(),
207 if (required_size > literal_to_clauses_.size()) {
208 literal_to_clauses_.resize(required_size);
209 literal_to_clause_sizes_.resize(required_size);
212 literal_to_clauses_[e.Index()].push_back(ci);
213 literal_to_clause_sizes_[e.Index()]++;
218 const int required_size = 2 * num_variables;
219 if (required_size > literal_to_clauses_.size()) {
220 literal_to_clauses_.resize(required_size);
221 literal_to_clause_sizes_.resize(required_size);
225void SatPresolver::AddClauseInternal(std::vector<Literal>* clause) {
226 if (drat_proof_handler_ !=
nullptr) drat_proof_handler_->
AddClause(*clause);
228 DCHECK(std::is_sorted(clause->begin(), clause->end()));
229 DCHECK_GT(clause->size(), 0) <<
"TODO(user): Unsat during presolve?";
231 clauses_.push_back(std::vector<Literal>());
232 clauses_.back().swap(*clause);
233 in_clause_to_process_.push_back(
true);
234 clause_to_process_.push_back(ci);
235 for (
const Literal e : clauses_.back()) {
236 literal_to_clauses_[e.Index()].push_back(ci);
237 literal_to_clause_sizes_[e.Index()]++;
238 UpdatePriorityQueue(e.Variable());
239 UpdateBvaPriorityQueue(e.Index());
242 signatures_.push_back(ComputeSignatureOfClauseVariables(ci));
243 DCHECK_EQ(signatures_.size(), clauses_.size());
249 BooleanVariable new_var(0);
266 var_pq_elements_.clear();
267 in_clause_to_process_.clear();
268 clause_to_process_.clear();
269 literal_to_clauses_.clear();
275 for (BooleanVariable
index : mapping) {
279 std::vector<Literal> temp;
281 for (std::vector<Literal>& clause_ref : clauses_) {
292bool SatPresolver::ProcessAllClauses() {
293 int num_skipped_checks = 0;
294 const int kCheckFrequency = 1000;
298 std::sort(clause_to_process_.begin(), clause_to_process_.end(),
300 return clauses_[c1].size() < clauses_[c2].size();
302 while (!clause_to_process_.empty()) {
304 in_clause_to_process_[ci] =
false;
305 clause_to_process_.pop_front();
307 if (++num_skipped_checks >= kCheckFrequency) {
308 if (num_inspected_signatures_ + num_inspected_literals_ > 1e9) {
309 VLOG(1) <<
"Aborting ProcessAllClauses() because work limit has been "
313 if (time_limit_ !=
nullptr && time_limit_->
LimitReached())
return true;
314 num_skipped_checks = 0;
332 int64_t num_removable = 0;
333 for (
const bool b : can_be_removed) {
334 if (
b) ++num_removable;
337 "[SAT presolve] num removable Booleans: ", num_removable,
" / ",
338 can_be_removed.size());
340 "[SAT presolve] num trivial clauses: ", num_trivial_clauses_);
346 if (!ProcessAllClauses())
return false;
349 if (time_limit_ !=
nullptr && time_limit_->
LimitReached())
return true;
350 if (num_inspected_signatures_ + num_inspected_literals_ > 1e9)
return true;
352 InitializePriorityQueue();
353 while (var_pq_.Size() > 0) {
354 const BooleanVariable
var = var_pq_.Top()->variable;
356 if (!can_be_removed[
var.value()])
continue;
358 if (!ProcessAllClauses())
return false;
360 if (time_limit_ !=
nullptr && time_limit_->
LimitReached())
return true;
361 if (num_inspected_signatures_ + num_inspected_literals_ > 1e9)
return true;
375 var_pq_elements_.clear();
376 InitializeBvaPriorityQueue();
377 while (bva_pq_.Size() > 0) {
378 const LiteralIndex lit = bva_pq_.Top()->literal;
385void SatPresolver::SimpleBva(LiteralIndex l) {
386 literal_to_p_size_.resize(literal_to_clauses_.size(), 0);
387 DCHECK(std::all_of(literal_to_p_size_.begin(), literal_to_p_size_.end(),
388 [](
int v) { return v == 0; }));
393 m_cls_ = literal_to_clauses_[l];
400 flattened_p_.clear();
402 const std::vector<Literal>& clause = clauses_[c];
403 if (clause.empty())
continue;
407 const LiteralIndex l_min =
408 FindLiteralWithShortestOccurrenceListExcluding(clause, Literal(l));
413 for (
const ClauseIndex d : literal_to_clauses_[l_min]) {
414 if (clause.size() != clauses_[d].size())
continue;
415 const LiteralIndex l_diff =
418 if (l_diff == Literal(l).NegatedIndex()) {
423 VLOG(1) <<
"self-subsumbtion";
426 flattened_p_.push_back({l_diff, c});
427 const int new_size = ++literal_to_p_size_[l_diff];
428 if (new_size > max_size) {
436 const int new_m_lit_size = m_lit_.size() + 1;
437 const int new_m_cls_size = max_size;
438 const int new_reduction =
439 new_m_lit_size * new_m_cls_size - new_m_cls_size - new_m_lit_size;
441 if (new_reduction <= reduction)
break;
449 reduction = new_reduction;
454 for (
const auto entry : flattened_p_) {
455 literal_to_p_size_[entry.first] = 0;
456 if (entry.first == lmax) m_cls_.push_back(entry.second);
458 flattened_p_.clear();
462 for (
const auto entry : flattened_p_) literal_to_p_size_[entry.first] = 0;
463 flattened_p_.clear();
472 const int old_size = literal_to_clauses_.size();
473 const LiteralIndex x_true = LiteralIndex(old_size);
474 const LiteralIndex x_false = LiteralIndex(old_size + 1);
475 literal_to_clauses_.resize(old_size + 2);
476 literal_to_clause_sizes_.resize(old_size + 2);
477 bva_pq_elements_.resize(old_size + 2);
478 bva_pq_elements_[x_true.value()].literal = x_true;
479 bva_pq_elements_[x_false.value()].literal = x_false;
482 if (drat_proof_handler_ !=
nullptr) drat_proof_handler_->
AddOneVariable();
483 for (
const LiteralIndex lit : m_lit_) {
484 tmp_new_clause_ = {Literal(lit), Literal(x_true)};
485 AddClauseInternal(&tmp_new_clause_);
488 tmp_new_clause_ = clauses_[ci];
489 DCHECK(!tmp_new_clause_.empty());
490 for (Literal& ref : tmp_new_clause_) {
491 if (ref.Index() == l) {
492 ref = Literal(x_false);
500 std::sort(tmp_new_clause_.begin(), tmp_new_clause_.end());
501 AddClauseInternal(&tmp_new_clause_);
511 const std::vector<Literal>& clause = clauses_[c];
513 const LiteralIndex l_min =
514 FindLiteralWithShortestOccurrenceListExcluding(clause, Literal(l));
515 for (
const LiteralIndex lit : m_lit_) {
516 if (lit == l)
continue;
517 for (
const ClauseIndex d : literal_to_clauses_[l_min]) {
518 if (clause.size() != clauses_[d].size())
continue;
519 const LiteralIndex l_diff =
535 AddToBvaPriorityQueue(x_true);
536 AddToBvaPriorityQueue(x_false);
537 AddToBvaPriorityQueue(l);
540uint64_t SatPresolver::ComputeSignatureOfClauseVariables(ClauseIndex ci) {
541 uint64_t signature = 0;
542 for (
const Literal l : clauses_[ci]) {
543 signature |= (uint64_t{1} << (l.Variable().value() % 64));
545 DCHECK_EQ(signature == 0, clauses_[ci].empty());
552bool SatPresolver::ProcessClauseToSimplifyOthersUsingLiteral(
553 ClauseIndex clause_index, Literal lit) {
554 const std::vector<Literal>& clause = clauses_[clause_index];
555 const uint64_t clause_signature = signatures_[clause_index];
556 LiteralIndex opposite_literal;
561 bool need_cleaning =
false;
562 num_inspected_signatures_ += literal_to_clauses_[lit.Index()].size();
563 for (
const ClauseIndex ci : literal_to_clauses_[lit.Index()]) {
564 const uint64_t ci_signature = signatures_[ci];
568 DCHECK_EQ(ci_signature, ComputeSignatureOfClauseVariables(ci));
569 if (ci_signature == 0) {
570 need_cleaning =
true;
577 if (ci != clause_index && (clause_signature & ~ci_signature) == 0 &&
579 &num_inspected_literals_)) {
581 need_cleaning =
true;
585 DCHECK_NE(opposite_literal, lit.Index());
586 if (clauses_[ci].empty())
return false;
587 if (drat_proof_handler_ !=
nullptr) {
589 drat_proof_handler_->
AddClause(clauses_[ci]);
593 signatures_[ci] = ComputeSignatureOfClauseVariables(ci);
599 --literal_to_clause_sizes_[opposite_literal];
600 UpdatePriorityQueue(Literal(opposite_literal).Variable());
602 if (!in_clause_to_process_[ci]) {
603 in_clause_to_process_[ci] =
true;
604 clause_to_process_.push_back(ci);
612 auto& occurrence_list_ref = literal_to_clauses_[lit.Index()];
614 if (signatures_[ci] != 0) occurrence_list_ref[new_index++] = ci;
616 occurrence_list_ref.resize(new_index);
617 DCHECK_EQ(literal_to_clause_sizes_[lit.Index()], new_index);
627 const std::vector<Literal>& clause = clauses_[clause_index];
628 if (clause.empty())
return true;
629 DCHECK(std::is_sorted(clause.begin(), clause.end()));
631 LiteralIndex opposite_literal;
632 const Literal lit = FindLiteralWithShortestOccurrenceList(clause);
634 if (!ProcessClauseToSimplifyOthersUsingLiteral(clause_index, lit)) {
640 const LiteralIndex other_lit_index =
641 FindLiteralWithShortestOccurrenceListExcluding(clause, lit);
643 literal_to_clause_sizes_[other_lit_index] <
645 return ProcessClauseToSimplifyOthersUsingLiteral(clause_index,
650 bool something_removed =
false;
651 auto& occurrence_list_ref = literal_to_clauses_[lit.
NegatedIndex()];
652 const uint64_t clause_signature = signatures_[clause_index];
654 const uint64_t ci_signature = signatures_[ci];
655 DCHECK_EQ(ci_signature, ComputeSignatureOfClauseVariables(ci));
656 if (ci_signature == 0)
continue;
662 if ((clause_signature & ~ci_signature) == 0 &&
664 &num_inspected_literals_)) {
666 if (clauses_[ci].empty())
return false;
667 if (drat_proof_handler_ !=
nullptr) {
669 drat_proof_handler_->
AddClause(clauses_[ci]);
673 signatures_[ci] = ComputeSignatureOfClauseVariables(ci);
675 if (!in_clause_to_process_[ci]) {
676 in_clause_to_process_[ci] =
true;
677 clause_to_process_.push_back(ci);
679 something_removed =
true;
682 occurrence_list_ref[new_index] = ci;
685 occurrence_list_ref.resize(new_index);
686 literal_to_clause_sizes_[lit.
NegatedIndex()] = new_index;
687 if (something_removed) {
694void SatPresolver::RemoveAndRegisterForPostsolveAllClauseContaining(
Literal x) {
696 if (!clauses_[i].empty()) RemoveAndRegisterForPostsolve(i, x);
699 literal_to_clause_sizes_[x.
Index()] = 0;
703 const int s1 = literal_to_clause_sizes_[x.
Index()];
704 const int s2 = literal_to_clause_sizes_[x.
NegatedIndex()];
708 if (s1 == 0 && s2 == 0)
return false;
720 if (!clauses_[i].empty()) {
721 threshold += clause_weight + clauses_[i].size();
725 if (!clauses_[i].empty()) {
726 threshold += clause_weight + clauses_[i].size();
736 if (clauses_[i].empty())
continue;
737 bool no_resolvant =
true;
739 if (clauses_[j].empty())
continue;
742 no_resolvant =
false;
743 size += clause_weight + rs;
746 if (size > threshold)
return false;
762 RemoveAndRegisterForPostsolve(i, x);
769 std::vector<Literal> temp;
771 if (clauses_[i].empty())
continue;
773 if (clauses_[j].empty())
continue;
775 AddClauseInternal(&temp);
784 RemoveAndRegisterForPostsolveAllClauseContaining(x);
785 RemoveAndRegisterForPostsolveAllClauseContaining(x.
Negated());
792void SatPresolver::Remove(ClauseIndex ci) {
794 for (
Literal e : clauses_[ci]) {
795 literal_to_clause_sizes_[e.Index()]--;
796 UpdatePriorityQueue(e.Variable());
797 UpdateBvaPriorityQueue(
Literal(e.Variable(),
true).
Index());
798 UpdateBvaPriorityQueue(
Literal(e.Variable(),
false).
Index());
800 if (drat_proof_handler_ !=
nullptr) {
806void SatPresolver::RemoveAndRegisterForPostsolve(ClauseIndex ci, Literal x) {
807 postsolver_->
Add(x, clauses_[ci]);
811Literal SatPresolver::FindLiteralWithShortestOccurrenceList(
812 const std::vector<Literal>& clause) {
814 Literal result = clause.front();
815 int best_size = literal_to_clause_sizes_[result.Index()];
816 for (
const Literal l : clause) {
817 const int size = literal_to_clause_sizes_[l.Index()];
818 if (size < best_size) {
826LiteralIndex SatPresolver::FindLiteralWithShortestOccurrenceListExcluding(
827 const std::vector<Literal>& clause, Literal to_exclude) {
831 for (
const Literal l : clause) {
832 if (l == to_exclude)
continue;
833 if (literal_to_clause_sizes_[l.Index()] < num_occurrences) {
835 num_occurrences = literal_to_clause_sizes_[l.Index()];
841void SatPresolver::UpdatePriorityQueue(BooleanVariable
var) {
842 if (var_pq_elements_.empty())
return;
843 PQElement* element = &var_pq_elements_[
var];
844 element->weight = literal_to_clause_sizes_[Literal(
var,
true).Index()] +
845 literal_to_clause_sizes_[Literal(
var,
false).Index()];
846 if (var_pq_.Contains(element)) {
847 var_pq_.NoteChangedPriority(element);
849 var_pq_.Add(element);
853void SatPresolver::InitializePriorityQueue() {
855 var_pq_elements_.resize(num_vars);
856 for (BooleanVariable
var(0);
var < num_vars; ++
var) {
857 PQElement* element = &var_pq_elements_[
var];
858 element->variable =
var;
859 element->weight = literal_to_clause_sizes_[Literal(
var,
true).Index()] +
860 literal_to_clause_sizes_[Literal(
var,
false).Index()];
861 var_pq_.Add(element);
865void SatPresolver::UpdateBvaPriorityQueue(LiteralIndex lit) {
866 if (bva_pq_elements_.empty())
return;
868 BvaPqElement* element = &bva_pq_elements_[lit.value()];
869 element->weight = literal_to_clause_sizes_[lit];
870 if (bva_pq_.Contains(element)) {
871 bva_pq_.NoteChangedPriority(element);
875void SatPresolver::AddToBvaPriorityQueue(LiteralIndex lit) {
876 if (bva_pq_elements_.empty())
return;
878 BvaPqElement* element = &bva_pq_elements_[lit.value()];
879 element->weight = literal_to_clause_sizes_[lit];
880 DCHECK(!bva_pq_.Contains(element));
881 if (element->weight > 2) bva_pq_.Add(element);
884void SatPresolver::InitializeBvaPriorityQueue() {
887 bva_pq_elements_.assign(num_literals, BvaPqElement());
888 for (LiteralIndex lit(0); lit < num_literals; ++lit) {
889 BvaPqElement* element = &bva_pq_elements_[lit.value()];
890 element->literal = lit;
891 element->weight = literal_to_clause_sizes_[lit];
895 if (element->weight > 2) bva_pq_.Add(element);
899void SatPresolver::DisplayStats(
double elapsed_seconds) {
900 int num_literals = 0;
902 int num_singleton_clauses = 0;
903 for (
const std::vector<Literal>& c : clauses_) {
905 if (c.size() == 1) ++num_singleton_clauses;
907 num_literals += c.size();
910 int num_one_side = 0;
911 int num_simple_definition = 0;
914 const int s1 = literal_to_clause_sizes_[Literal(
var,
true).Index()];
915 const int s2 = literal_to_clause_sizes_[Literal(
var,
false).Index()];
916 if (s1 == 0 && s2 == 0)
continue;
919 if (s1 == 0 || s2 == 0) {
921 }
else if (s1 == 1 || s2 == 1) {
922 num_simple_definition++;
925 SOLVER_LOG(logger_,
"[SAT presolve] [", elapsed_seconds,
"s]",
926 " clauses:", num_clauses,
" literals:", num_literals,
927 " vars:", num_vars,
" one_side_vars:", num_one_side,
928 " simple_definition:", num_simple_definition,
929 " singleton_clauses:", num_singleton_clauses);
933 LiteralIndex* opposite_literal,
934 int64_t* num_inspected_literals) {
935 if (
b->size() <
a.size())
return false;
936 DCHECK(std::is_sorted(
a.begin(),
a.end()));
937 DCHECK(std::is_sorted(
b->begin(),
b->end()));
938 if (num_inspected_literals !=
nullptr) {
939 *num_inspected_literals +=
a.size();
940 *num_inspected_literals +=
b->size();
943 *opposite_literal = LiteralIndex(-1);
946 std::vector<Literal>::const_iterator ia =
a.begin();
947 std::vector<Literal>::const_iterator ib =
b->begin();
948 std::vector<Literal>::const_iterator to_remove;
952 int size_diff =
b->size() -
a.size();
953 while (ia !=
a.end() ) {
957 }
else if (*ia == ib->Negated()) {
959 if (num_diff > 1)
return false;
963 }
else if (*ia < *ib) {
970 if (--size_diff < 0)
return false;
974 *opposite_literal = to_remove->Index();
981 const std::vector<Literal>&
b,
Literal l) {
983 DCHECK(std::is_sorted(
a.begin(),
a.end()));
984 DCHECK(std::is_sorted(
b.begin(),
b.end()));
986 std::vector<Literal>::const_iterator ia =
a.begin();
987 std::vector<Literal>::const_iterator ib =
b.begin();
988 while (ia !=
a.end() && ib !=
b.end()) {
992 }
else if (*ia < *ib) {
1001 result = (*ib).Index();
1007 if (ib !=
b.end()) {
1009 result = (*ib).Index();
1015 const std::vector<Literal>&
b,
1016 std::vector<Literal>* out) {
1017 DCHECK(std::is_sorted(
a.begin(),
a.end()));
1018 DCHECK(std::is_sorted(
b.begin(),
b.end()));
1021 std::vector<Literal>::const_iterator ia =
a.begin();
1022 std::vector<Literal>::const_iterator ib =
b.begin();
1023 while ((ia !=
a.end()) && (ib !=
b.end())) {
1025 out->push_back(*ia);
1028 }
else if (*ia == ib->Negated()) {
1029 if (*ia != x)
return false;
1033 }
else if (*ia < *ib) {
1034 out->push_back(*ia);
1037 out->push_back(*ib);
1043 out->insert(out->end(), ia,
a.end());
1044 out->insert(out->end(), ib,
b.end());
1050 const std::vector<Literal>&
b) {
1051 DCHECK(std::is_sorted(
a.begin(),
a.end()));
1052 DCHECK(std::is_sorted(
b.begin(),
b.end()));
1054 int size =
static_cast<int>(
a.size() +
b.size()) - 2;
1055 std::vector<Literal>::const_iterator ia =
a.begin();
1056 std::vector<Literal>::const_iterator ib =
b.begin();
1057 while ((ia !=
a.end()) && (ib !=
b.end())) {
1062 }
else if (*ia == ib->Negated()) {
1063 if (*ia != x)
return -1;
1067 }
else if (*ia < *ib) {
1088 deterministic_time_limit(solver->deterministic_time() +
1089 deterministic_time_limit) {}
1095 scratchpad_.clear();
1123 mutable std::vector<int32_t> scratchpad_;
1125 const double deterministic_time_limit;
1144 std::vector<std::vector<int32_t>> scc;
1157 for (
const std::vector<int32_t>& component : scc) {
1158 if (component.size() > 1) {
1159 if (mapping->
empty()) mapping->
resize(size, LiteralIndex(-1));
1161 for (
int i = 1; i < component.size(); ++i) {
1162 const Literal l((LiteralIndex(component[i])));
1183 if (!mapping->
empty()) {
1193 for (LiteralIndex i(0); i < size; ++i) {
1201 if (drat_proof_handler !=
nullptr) {
1202 drat_proof_handler->
AddClause({true_lit});
1206 for (LiteralIndex i(0); i < size; ++i) {
1208 (*mapping)[i] = rep;
1215 if (drat_proof_handler !=
nullptr) {
1216 drat_proof_handler->
AddClause({true_lit});
1225 if (drat_proof_handler !=
nullptr) {
1226 drat_proof_handler->
AddClause({true_lit});
1229 }
else if (rep != i) {
1232 if (drat_proof_handler !=
nullptr) {
1239 const bool log_info =
1241 LOG_IF(
INFO, log_info) <<
"Probing. fixed " << num_already_fixed_vars <<
" + "
1243 num_already_fixed_vars
1244 <<
" equiv " << num_equiv / 2 <<
" total "
1250 std::vector<bool>* solution,
1267 VLOG(1) <<
"UNSAT during probing.";
1270 const int num_variables = (*solver)->NumVariables();
1271 if ((*solver)->LiteralTrail().Index() == num_variables) {
1272 VLOG(1) <<
"Problem solved by trivial heuristic!";
1274 for (
int i = 0; i < (*solver)->NumVariables(); ++i) {
1275 solution->push_back((*solver)->Assignment().LiteralIsTrue(
1276 Literal(BooleanVariable(i),
true)));
1284 const int max_num_passes = 4;
1286 const int saved_num_variables = (*solver)->NumVariables();
1304 VLOG(1) <<
"UNSAT during probing.";
1308 postsolver.
Add(c[0], c);
1316 drat_proof_handler, &equiv_map);
1317 if ((*solver)->IsModelUnsat()) {
1318 VLOG(1) <<
"UNSAT during probing.";
1323 if (!(*solver)->ProblemIsPureSat()) {
1324 VLOG(1) <<
"The problem is not a pure SAT problem, skipping the SAT "
1325 "specific presolve.";
1331 (*solver)->Backtrack(0);
1332 for (
int i = 0; i < (*solver)->LiteralTrail().
Index(); ++i) {
1333 postsolver.
FixVariable((*solver)->LiteralTrail()[i]);
1341 (*solver)->ExtractClauses(&presolver);
1342 (*solver)->AdvanceDeterministicTime(
time_limit);
1348 ->GetOrCreate<TimeLimit>()
1349 ->GetElapsedDeterministicTime());
1351 (*solver).reset(
nullptr);
1352 std::vector<bool> can_be_removed(presolver.
NumVariables(),
true);
1353 if (!presolver.
Presolve(can_be_removed)) {
1354 VLOG(1) <<
"UNSAT during presolve.";
1357 (*solver) = absl::make_unique<SatSolver>();
1362 if (drat_proof_handler !=
nullptr) {
1367 (*solver) = absl::make_unique<SatSolver>();
1368 (*solver)->SetDratProofHandler(drat_proof_handler);
1373 if ((*solver)->NumVariables() == saved_num_variables)
break;
1394 ->presolve_probing_deterministic_time_limit();
1399 postsolver.
Add(c[0], c);
#define LOG_IF(severity, condition)
#define DCHECK_NE(val1, val2)
#define DCHECK_GE(val1, val2)
#define DCHECK_GT(val1, val2)
#define DCHECK_LT(val1, val2)
#define DCHECK(condition)
#define DCHECK_EQ(val1, val2)
#define VLOG(verboselevel)
void resize(size_type new_size)
void push_back(const value_type &x)
int MergePartsOf(int node1, int node2)
int GetRootAndCompressPath(int node)
bool LimitReached() const
void AdvanceDeterministicTime(double deterministic_duration)
bool LoggingIsEnabled() const
A simple class to enforce both an elapsed time limit and a deterministic time limit in the same threa...
bool LimitReached()
Returns true when the external limit is true, or the deterministic time is over the deterministic lim...
void DeleteClause(absl::Span< const Literal > clause)
void ApplyMapping(const absl::StrongVector< BooleanVariable, BooleanVariable > &mapping)
void AddClause(absl::Span< const Literal > clause)
bool PresolveLoop(SatPresolveOptions options)
LiteralIndex NegatedIndex() const
LiteralIndex Index() const
BooleanVariable Variable() const
Class that owns everything related to a particular optimization model.
const std::vector< int32_t > & operator[](int32_t index) const
PropagationGraph(double deterministic_time_limit, SatSolver *solver)
bool log_search_progress() const
bool presolve_blocked_clause() const
::PROTOBUF_NAMESPACE_ID::int32 presolve_bve_clause_weight() const
double presolve_probing_deterministic_time_limit() const
::PROTOBUF_NAMESPACE_ID::int32 presolve_bva_threshold() const
::PROTOBUF_NAMESPACE_ID::int32 presolve_bve_threshold() const
bool presolve_use_bva() const
void Add(Literal x, const absl::Span< const Literal > clause)
SatPostsolver(int num_variables)
void FixVariable(Literal x)
void ApplyMapping(const absl::StrongVector< BooleanVariable, BooleanVariable > &mapping)
std::vector< bool > PostsolveSolution(const std::vector< bool > &solution)
std::vector< bool > ExtractAndPostsolveSolution(const SatSolver &solver)
void SetNumVariables(int num_variables)
void LoadProblemIntoSatSolver(SatSolver *solver)
void AddBinaryClause(Literal a, Literal b)
void SetEquivalentLiteralMapping(const absl::StrongVector< LiteralIndex, LiteralIndex > &mapping)
void SetParameters(const SatParameters ¶ms)
absl::StrongVector< BooleanVariable, BooleanVariable > VariableMapping() const
void SetDratProofHandler(DratProofHandler *drat_proof_handler)
void AddClause(absl::Span< const Literal > clause)
bool ProcessClauseToSimplifyOthers(ClauseIndex clause_index)
bool CrossProduct(Literal x)
void SetNumVariables(int num_variables)
const SatParameters & parameters() const
const VariablesAssignment & Assignment() const
const Trail & LiteralTrail() const
int EnqueueDecisionAndBackjumpOnConflict(Literal true_literal)
void Backtrack(int target_level)
int CurrentDecisionLevel() const
double deterministic_time() const
bool AddProblemClause(absl::Span< const Literal > literals)
bool AddUnitClause(Literal true_literal)
bool LiteralIsAssigned(Literal literal) const
bool VariableIsAssigned(BooleanVariable var) const
bool LiteralIsTrue(Literal literal) const
void AssignFromTrueLiteral(Literal literal)
void Resize(int num_variables)
ModelSharedTimeLimit * time_limit
void STLEraseAllFromSequence(T *v, const E &e)
void STLClearObject(T *obj)
void swap(IdMap< K, V > &a, IdMap< K, V > &b)
bool LookForTrivialSatSolution(double deterministic_time_limit, Model *model)
int ComputeResolvantSize(Literal x, const std::vector< Literal > &a, const std::vector< Literal > &b)
const LiteralIndex kNoLiteralIndex(-1)
LiteralIndex DifferAtGivenLiteral(const std::vector< Literal > &a, const std::vector< Literal > &b, Literal l)
bool SimplifyClause(const std::vector< Literal > &a, std::vector< Literal > *b, LiteralIndex *opposite_literal, int64_t *num_inspected_literals)
bool ComputeResolvant(Literal x, const std::vector< Literal > &a, const std::vector< Literal > &b, std::vector< Literal > *out)
SatSolver::Status SolveWithPresolve(std::unique_ptr< SatSolver > *solver, TimeLimit *time_limit, std::vector< bool > *solution, DratProofHandler *drat_proof_handler, SolverLogger *logger)
void ProbeAndFindEquivalentLiteral(SatSolver *solver, SatPostsolver *postsolver, DratProofHandler *drat_proof_handler, absl::StrongVector< LiteralIndex, LiteralIndex > *mapping)
const BooleanVariable kNoBooleanVariable(-1)
Collection of objects used to extend the Constraint Solver library.
void FindStronglyConnectedComponents(const NodeIndex num_nodes, const Graph &graph, SccOutput *components)
std::deque< std::vector< Literal > > clauses
bool use_transitive_reduction
bool extract_binary_clauses_in_probing
double deterministic_time_limit
#define SOLVER_LOG(logger,...)
#define VLOG_IS_ON(verboselevel)