21 #include "absl/memory/memory.h"
38 : initial_num_variables_(num_variables), num_variables_(num_variables) {
39 reverse_mapping_.
resize(num_variables);
40 for (BooleanVariable
var(0);
var < num_variables; ++
var) {
41 reverse_mapping_[
var] =
var;
43 assignment_.
Resize(num_variables);
48 DCHECK(std::find(clause.begin(), clause.end(), x) != clause.end());
49 associated_literal_.push_back(ApplyReverseMapping(x));
50 clauses_start_.push_back(clauses_literals_.size());
51 for (
const Literal& l : clause) {
52 clauses_literals_.push_back(ApplyReverseMapping(l));
57 const Literal l = ApplyReverseMapping(x);
64 if (reverse_mapping_.
size() < mapping.
size()) {
66 while (reverse_mapping_.
size() < mapping.
size()) {
67 reverse_mapping_.
push_back(BooleanVariable(num_variables_++));
69 assignment_.
Resize(num_variables_);
71 for (BooleanVariable v(0); v < mapping.
size(); ++v) {
72 const BooleanVariable image = mapping[v];
74 if (image >= new_mapping.
size()) {
77 new_mapping[image] = reverse_mapping_[v];
81 std::swap(new_mapping, reverse_mapping_);
88 reverse_mapping_.
push_back(BooleanVariable(num_variables_++));
90 assignment_.
Resize(num_variables_);
98 void SatPostsolver::Postsolve(VariablesAssignment* assignment)
const {
101 for (BooleanVariable
var(0);
var < assignment->NumberOfVariables(); ++
var) {
102 if (!assignment->VariableIsAssigned(
var)) {
103 assignment->AssignFromTrueLiteral(Literal(
var,
true));
107 int previous_start = clauses_literals_.size();
108 for (
int i =
static_cast<int>(clauses_start_.size()) - 1; i >= 0; --i) {
109 bool set_associated_var =
true;
110 const int new_start = clauses_start_[i];
111 for (
int j = new_start; j < previous_start; ++j) {
112 if (assignment->LiteralIsTrue(clauses_literals_[j])) {
113 set_associated_var =
false;
117 previous_start = new_start;
118 if (set_associated_var) {
119 assignment->UnassignLiteral(associated_literal_[i].Negated());
120 assignment->AssignFromTrueLiteral(associated_literal_[i]);
125 assignment->Resize(initial_num_variables_);
133 solution[
var.value()] =
140 const std::vector<bool>& solution) {
141 for (BooleanVariable
var(0);
var < solution.size(); ++
var) {
148 Postsolve(&assignment_);
149 std::vector<bool> postsolved_solution;
150 postsolved_solution.reserve(initial_num_variables_);
151 for (
int i = 0; i < initial_num_variables_; ++i) {
152 postsolved_solution.push_back(
155 return postsolved_solution;
161 DCHECK_GT(clause.size(), 0) <<
"Added an empty clause to the presolver";
163 clauses_.push_back(std::vector<Literal>(clause.begin(), clause.end()));
164 in_clause_to_process_.push_back(
true);
165 clause_to_process_.push_back(ci);
167 bool changed =
false;
168 std::vector<Literal>& clause_ref = clauses_.back();
169 if (!equiv_mapping_.
empty()) {
170 for (
int i = 0; i < clause_ref.size(); ++i) {
171 const Literal old_literal = clause_ref[i];
172 clause_ref[i] =
Literal(equiv_mapping_[clause_ref[i].
Index()]);
173 if (old_literal != clause_ref[i]) changed =
true;
176 std::sort(clause_ref.begin(), clause_ref.end());
177 clause_ref.erase(std::unique(clause_ref.begin(), clause_ref.end()),
181 for (
int i = 1; i < clause_ref.size(); ++i) {
182 if (clause_ref[i] == clause_ref[i - 1].Negated()) {
184 ++num_trivial_clauses_;
185 clause_to_process_.pop_back();
187 in_clause_to_process_.pop_back();
193 signatures_.push_back(ComputeSignatureOfClauseVariables(ci));
194 DCHECK_EQ(signatures_.size(), clauses_.size());
196 if (drat_proof_handler_ !=
nullptr && changed) {
197 drat_proof_handler_->
AddClause(clause_ref);
201 const Literal max_literal = clause_ref.back();
202 const int required_size =
std::max(max_literal.
Index().value(),
205 if (required_size > literal_to_clauses_.
size()) {
206 literal_to_clauses_.
resize(required_size);
207 literal_to_clause_sizes_.
resize(required_size);
210 literal_to_clauses_[e.Index()].
push_back(ci);
211 literal_to_clause_sizes_[e.Index()]++;
216 const int required_size = 2 * num_variables;
217 if (required_size > literal_to_clauses_.
size()) {
218 literal_to_clauses_.
resize(required_size);
219 literal_to_clause_sizes_.
resize(required_size);
223 void SatPresolver::AddClauseInternal(std::vector<Literal>* clause) {
224 if (drat_proof_handler_ !=
nullptr) drat_proof_handler_->
AddClause(*clause);
226 DCHECK(std::is_sorted(clause->begin(), clause->end()));
227 DCHECK_GT(clause->size(), 0) <<
"TODO(fdid): Unsat during presolve?";
229 clauses_.push_back(std::vector<Literal>());
230 clauses_.back().swap(*clause);
231 in_clause_to_process_.push_back(
true);
232 clause_to_process_.push_back(ci);
233 for (
const Literal e : clauses_.back()) {
234 literal_to_clauses_[e.Index()].
push_back(ci);
235 literal_to_clause_sizes_[e.Index()]++;
236 UpdatePriorityQueue(e.Variable());
237 UpdateBvaPriorityQueue(e.Index());
240 signatures_.push_back(ComputeSignatureOfClauseVariables(ci));
241 DCHECK_EQ(signatures_.size(), clauses_.size());
247 BooleanVariable new_var(0);
264 var_pq_elements_.
clear();
265 in_clause_to_process_.clear();
266 clause_to_process_.clear();
267 literal_to_clauses_.
clear();
273 for (BooleanVariable
index : mapping) {
277 std::vector<Literal> temp;
279 for (std::vector<Literal>& clause_ref : clauses_) {
290 bool SatPresolver::ProcessAllClauses() {
291 int num_skipped_checks = 0;
292 const int kCheckFrequency = 1000;
296 std::sort(clause_to_process_.begin(), clause_to_process_.end(),
298 return clauses_[c1].size() < clauses_[c2].size();
300 while (!clause_to_process_.empty()) {
302 in_clause_to_process_[ci] =
false;
303 clause_to_process_.pop_front();
305 if (++num_skipped_checks >= kCheckFrequency) {
306 if (num_inspected_signatures_ + num_inspected_literals_ > 1e9) {
307 VLOG(1) <<
"Aborting ProcessAllClauses() because work limit has been "
311 if (time_limit_ !=
nullptr && time_limit_->
LimitReached())
return true;
312 num_skipped_checks = 0;
332 int64 num_removable = 0;
333 for (
const bool b : can_be_removed) {
334 if (
b) ++num_removable;
336 LOG(
INFO) <<
"num removable Booleans: " << num_removable <<
" / "
337 << can_be_removed.size();
338 LOG(
INFO) <<
"num trivial clauses: " << num_trivial_clauses_;
344 if (!ProcessAllClauses())
return false;
345 if (log_info) DisplayStats(timer.
Get());
347 if (time_limit_ !=
nullptr && time_limit_->
LimitReached())
return true;
348 if (num_inspected_signatures_ + num_inspected_literals_ > 1e9)
return true;
350 InitializePriorityQueue();
351 while (var_pq_.
Size() > 0) {
352 const BooleanVariable
var = var_pq_.
Top()->variable;
354 if (!can_be_removed[
var.value()])
continue;
356 if (!ProcessAllClauses())
return false;
358 if (time_limit_ !=
nullptr && time_limit_->
LimitReached())
return true;
359 if (num_inspected_signatures_ + num_inspected_literals_ > 1e9)
return true;
361 if (log_info) DisplayStats(timer.
Get());
364 if (parameters_.presolve_use_bva()) {
366 if (log_info) DisplayStats(timer.
Get());
373 var_pq_elements_.
clear();
374 InitializeBvaPriorityQueue();
375 while (bva_pq_.
Size() > 0) {
376 const LiteralIndex lit = bva_pq_.
Top()->literal;
383 void SatPresolver::SimpleBva(LiteralIndex l) {
384 literal_to_p_size_.
resize(literal_to_clauses_.
size(), 0);
385 DCHECK(std::all_of(literal_to_p_size_.
begin(), literal_to_p_size_.
end(),
386 [](
int v) { return v == 0; }));
391 m_cls_ = literal_to_clauses_[l];
398 flattened_p_.clear();
400 const std::vector<Literal>& clause = clauses_[c];
401 if (clause.empty())
continue;
405 const LiteralIndex l_min =
406 FindLiteralWithShortestOccurrenceListExcluding(clause, Literal(l));
411 for (
const ClauseIndex d : literal_to_clauses_[l_min]) {
412 if (clause.size() != clauses_[d].size())
continue;
413 const LiteralIndex l_diff =
416 if (l_diff == Literal(l).NegatedIndex()) {
421 VLOG(1) <<
"self-subsumbtion";
424 flattened_p_.push_back({l_diff, c});
425 const int new_size = ++literal_to_p_size_[l_diff];
426 if (new_size > max_size) {
434 const int new_m_lit_size = m_lit_.size() + 1;
435 const int new_m_cls_size = max_size;
436 const int new_reduction =
437 new_m_lit_size * new_m_cls_size - new_m_cls_size - new_m_lit_size;
439 if (new_reduction <= reduction)
break;
447 reduction = new_reduction;
452 for (
const auto entry : flattened_p_) {
453 literal_to_p_size_[entry.first] = 0;
454 if (entry.first == lmax) m_cls_.
push_back(entry.second);
456 flattened_p_.clear();
460 for (
const auto entry : flattened_p_) literal_to_p_size_[entry.first] = 0;
461 flattened_p_.
clear();
466 if (reduction <= parameters_.presolve_bva_threshold())
return;
470 const int old_size = literal_to_clauses_.
size();
471 const LiteralIndex x_true = LiteralIndex(old_size);
472 const LiteralIndex x_false = LiteralIndex(old_size + 1);
473 literal_to_clauses_.
resize(old_size + 2);
474 literal_to_clause_sizes_.
resize(old_size + 2);
475 bva_pq_elements_.resize(old_size + 2);
476 bva_pq_elements_[x_true.value()].literal = x_true;
477 bva_pq_elements_[x_false.value()].literal = x_false;
480 if (drat_proof_handler_ !=
nullptr) drat_proof_handler_->
AddOneVariable();
481 for (
const LiteralIndex lit : m_lit_) {
482 tmp_new_clause_ = {Literal(lit), Literal(x_true)};
483 AddClauseInternal(&tmp_new_clause_);
486 tmp_new_clause_ = clauses_[ci];
487 DCHECK(!tmp_new_clause_.empty());
488 for (Literal& ref : tmp_new_clause_) {
489 if (ref.Index() == l) {
490 ref = Literal(x_false);
498 std::sort(tmp_new_clause_.begin(), tmp_new_clause_.end());
499 AddClauseInternal(&tmp_new_clause_);
509 const std::vector<Literal>& clause = clauses_[c];
511 const LiteralIndex l_min =
512 FindLiteralWithShortestOccurrenceListExcluding(clause, Literal(l));
513 for (
const LiteralIndex lit : m_lit_) {
514 if (lit == l)
continue;
515 for (
const ClauseIndex d : literal_to_clauses_[l_min]) {
516 if (clause.size() != clauses_[d].size())
continue;
517 const LiteralIndex l_diff =
533 AddToBvaPriorityQueue(x_true);
534 AddToBvaPriorityQueue(x_false);
535 AddToBvaPriorityQueue(l);
538 uint64 SatPresolver::ComputeSignatureOfClauseVariables(ClauseIndex ci) {
540 for (
const Literal l : clauses_[ci]) {
541 signature |= (
uint64{1} << (l.Variable().value() % 64));
543 DCHECK_EQ(signature == 0, clauses_[ci].empty());
550 bool SatPresolver::ProcessClauseToSimplifyOthersUsingLiteral(
551 ClauseIndex clause_index, Literal lit) {
552 const std::vector<Literal>& clause = clauses_[clause_index];
553 const uint64 clause_signature = signatures_[clause_index];
554 LiteralIndex opposite_literal;
559 bool need_cleaning =
false;
560 num_inspected_signatures_ += literal_to_clauses_[lit.Index()].
size();
561 for (
const ClauseIndex ci : literal_to_clauses_[lit.Index()]) {
562 const uint64 ci_signature = signatures_[ci];
566 DCHECK_EQ(ci_signature, ComputeSignatureOfClauseVariables(ci));
567 if (ci_signature == 0) {
568 need_cleaning =
true;
575 if (ci != clause_index && (clause_signature & ~ci_signature) == 0 &&
577 &num_inspected_literals_)) {
579 need_cleaning =
true;
583 DCHECK_NE(opposite_literal, lit.Index());
584 if (clauses_[ci].empty())
return false;
585 if (drat_proof_handler_ !=
nullptr) {
587 drat_proof_handler_->
AddClause(clauses_[ci]);
591 signatures_[ci] = ComputeSignatureOfClauseVariables(ci);
597 --literal_to_clause_sizes_[opposite_literal];
598 UpdatePriorityQueue(Literal(opposite_literal).Variable());
600 if (!in_clause_to_process_[ci]) {
601 in_clause_to_process_[ci] =
true;
602 clause_to_process_.push_back(ci);
610 auto& occurrence_list_ref = literal_to_clauses_[lit.Index()];
612 if (signatures_[ci] != 0) occurrence_list_ref[new_index++] = ci;
614 occurrence_list_ref.
resize(new_index);
615 DCHECK_EQ(literal_to_clause_sizes_[lit.Index()], new_index);
625 const std::vector<Literal>& clause = clauses_[clause_index];
626 if (clause.empty())
return true;
627 DCHECK(std::is_sorted(clause.begin(), clause.end()));
629 LiteralIndex opposite_literal;
630 const Literal lit = FindLiteralWithShortestOccurrenceList(clause);
632 if (!ProcessClauseToSimplifyOthersUsingLiteral(clause_index, lit)) {
638 const LiteralIndex other_lit_index =
639 FindLiteralWithShortestOccurrenceListExcluding(clause, lit);
641 literal_to_clause_sizes_[other_lit_index] <
643 return ProcessClauseToSimplifyOthersUsingLiteral(clause_index,
648 bool something_removed =
false;
649 auto& occurrence_list_ref = literal_to_clauses_[lit.
NegatedIndex()];
650 const uint64 clause_signature = signatures_[clause_index];
652 const uint64 ci_signature = signatures_[ci];
653 DCHECK_EQ(ci_signature, ComputeSignatureOfClauseVariables(ci));
654 if (ci_signature == 0)
continue;
660 if ((clause_signature & ~ci_signature) == 0 &&
662 &num_inspected_literals_)) {
664 if (clauses_[ci].empty())
return false;
665 if (drat_proof_handler_ !=
nullptr) {
667 drat_proof_handler_->
AddClause(clauses_[ci]);
671 signatures_[ci] = ComputeSignatureOfClauseVariables(ci);
673 if (!in_clause_to_process_[ci]) {
674 in_clause_to_process_[ci] =
true;
675 clause_to_process_.push_back(ci);
677 something_removed =
true;
680 occurrence_list_ref[new_index] = ci;
683 occurrence_list_ref.resize(new_index);
684 literal_to_clause_sizes_[lit.
NegatedIndex()] = new_index;
685 if (something_removed) {
692 void SatPresolver::RemoveAndRegisterForPostsolveAllClauseContaining(
Literal x) {
694 if (!clauses_[i].empty()) RemoveAndRegisterForPostsolve(i, x);
697 literal_to_clause_sizes_[x.
Index()] = 0;
701 const int s1 = literal_to_clause_sizes_[x.
Index()];
702 const int s2 = literal_to_clause_sizes_[x.
NegatedIndex()];
706 if (s1 == 0 && s2 == 0)
return false;
710 if (s1 > 1 && s2 > 1 && s1 * s2 > parameters_.presolve_bve_threshold()) {
716 const int clause_weight = parameters_.presolve_bve_clause_weight();
718 if (!clauses_[i].empty()) {
719 threshold += clause_weight + clauses_[i].size();
723 if (!clauses_[i].empty()) {
724 threshold += clause_weight + clauses_[i].size();
734 if (clauses_[i].empty())
continue;
735 bool no_resolvant =
true;
737 if (clauses_[j].empty())
continue;
740 no_resolvant =
false;
741 size += clause_weight + rs;
744 if (size > threshold)
return false;
747 if (no_resolvant && parameters_.presolve_blocked_clause()) {
760 RemoveAndRegisterForPostsolve(i, x);
767 std::vector<Literal> temp;
769 if (clauses_[i].empty())
continue;
771 if (clauses_[j].empty())
continue;
773 AddClauseInternal(&temp);
782 RemoveAndRegisterForPostsolveAllClauseContaining(x);
783 RemoveAndRegisterForPostsolveAllClauseContaining(x.
Negated());
790 void SatPresolver::Remove(ClauseIndex ci) {
792 for (
Literal e : clauses_[ci]) {
793 literal_to_clause_sizes_[e.Index()]--;
794 UpdatePriorityQueue(e.Variable());
795 UpdateBvaPriorityQueue(
Literal(e.Variable(),
true).
Index());
796 UpdateBvaPriorityQueue(
Literal(e.Variable(),
false).
Index());
798 if (drat_proof_handler_ !=
nullptr) {
804 void SatPresolver::RemoveAndRegisterForPostsolve(ClauseIndex ci, Literal x) {
805 postsolver_->
Add(x, clauses_[ci]);
809 Literal SatPresolver::FindLiteralWithShortestOccurrenceList(
810 const std::vector<Literal>& clause) {
812 Literal result = clause.front();
813 int best_size = literal_to_clause_sizes_[result.Index()];
814 for (
const Literal l : clause) {
815 const int size = literal_to_clause_sizes_[l.Index()];
816 if (size < best_size) {
824 LiteralIndex SatPresolver::FindLiteralWithShortestOccurrenceListExcluding(
825 const std::vector<Literal>& clause, Literal to_exclude) {
829 for (
const Literal l : clause) {
830 if (l == to_exclude)
continue;
831 if (literal_to_clause_sizes_[l.Index()] < num_occurrences) {
833 num_occurrences = literal_to_clause_sizes_[l.Index()];
839 void SatPresolver::UpdatePriorityQueue(BooleanVariable
var) {
840 if (var_pq_elements_.
empty())
return;
841 PQElement* element = &var_pq_elements_[
var];
842 element->weight = literal_to_clause_sizes_[Literal(
var,
true).Index()] +
843 literal_to_clause_sizes_[Literal(
var,
false).Index()];
847 var_pq_.
Add(element);
851 void SatPresolver::InitializePriorityQueue() {
853 var_pq_elements_.
resize(num_vars);
854 for (BooleanVariable
var(0);
var < num_vars; ++
var) {
855 PQElement* element = &var_pq_elements_[
var];
856 element->variable =
var;
857 element->weight = literal_to_clause_sizes_[Literal(
var,
true).Index()] +
858 literal_to_clause_sizes_[Literal(
var,
false).Index()];
859 var_pq_.
Add(element);
863 void SatPresolver::UpdateBvaPriorityQueue(LiteralIndex lit) {
864 if (bva_pq_elements_.empty())
return;
866 BvaPqElement* element = &bva_pq_elements_[lit.value()];
867 element->weight = literal_to_clause_sizes_[lit];
873 void SatPresolver::AddToBvaPriorityQueue(LiteralIndex lit) {
874 if (bva_pq_elements_.empty())
return;
876 BvaPqElement* element = &bva_pq_elements_[lit.value()];
877 element->weight = literal_to_clause_sizes_[lit];
879 if (element->weight > 2) bva_pq_.
Add(element);
882 void SatPresolver::InitializeBvaPriorityQueue() {
885 bva_pq_elements_.assign(num_literals, BvaPqElement());
886 for (LiteralIndex lit(0); lit < num_literals; ++lit) {
887 BvaPqElement* element = &bva_pq_elements_[lit.value()];
888 element->literal = lit;
889 element->weight = literal_to_clause_sizes_[lit];
893 if (element->weight > 2) bva_pq_.
Add(element);
897 void SatPresolver::DisplayStats(
double elapsed_seconds) {
898 int num_literals = 0;
900 int num_singleton_clauses = 0;
901 for (
const std::vector<Literal>& c : clauses_) {
903 if (c.size() == 1) ++num_singleton_clauses;
905 num_literals += c.size();
908 int num_one_side = 0;
909 int num_simple_definition = 0;
912 const int s1 = literal_to_clause_sizes_[Literal(
var,
true).Index()];
913 const int s2 = literal_to_clause_sizes_[Literal(
var,
false).Index()];
914 if (s1 == 0 && s2 == 0)
continue;
917 if (s1 == 0 || s2 == 0) {
919 }
else if (s1 == 1 || s2 == 1) {
920 num_simple_definition++;
923 LOG(
INFO) <<
" [" << elapsed_seconds <<
"s]"
924 <<
" clauses:" << num_clauses <<
" literals:" << num_literals
925 <<
" vars:" << num_vars <<
" one_side_vars:" << num_one_side
926 <<
" simple_definition:" << num_simple_definition
927 <<
" singleton_clauses:" << num_singleton_clauses;
931 LiteralIndex* opposite_literal,
932 int64* num_inspected_literals) {
933 if (
b->size() <
a.size())
return false;
934 DCHECK(std::is_sorted(
a.begin(),
a.end()));
935 DCHECK(std::is_sorted(
b->begin(),
b->end()));
936 if (num_inspected_literals !=
nullptr) {
937 *num_inspected_literals +=
a.size();
938 *num_inspected_literals +=
b->size();
941 *opposite_literal = LiteralIndex(-1);
944 std::vector<Literal>::const_iterator ia =
a.begin();
945 std::vector<Literal>::const_iterator ib =
b->begin();
946 std::vector<Literal>::const_iterator to_remove;
950 int size_diff =
b->size() -
a.size();
951 while (ia !=
a.end() ) {
955 }
else if (*ia == ib->Negated()) {
957 if (num_diff > 1)
return false;
961 }
else if (*ia < *ib) {
968 if (--size_diff < 0)
return false;
972 *opposite_literal = to_remove->Index();
979 const std::vector<Literal>&
b,
Literal l) {
981 DCHECK(std::is_sorted(
a.begin(),
a.end()));
982 DCHECK(std::is_sorted(
b.begin(),
b.end()));
984 std::vector<Literal>::const_iterator ia =
a.begin();
985 std::vector<Literal>::const_iterator ib =
b.begin();
986 while (ia !=
a.end() && ib !=
b.end()) {
990 }
else if (*ia < *ib) {
999 result = (*ib).Index();
1005 if (ib !=
b.end()) {
1007 result = (*ib).Index();
1013 const std::vector<Literal>&
b,
1014 std::vector<Literal>* out) {
1015 DCHECK(std::is_sorted(
a.begin(),
a.end()));
1016 DCHECK(std::is_sorted(
b.begin(),
b.end()));
1019 std::vector<Literal>::const_iterator ia =
a.begin();
1020 std::vector<Literal>::const_iterator ib =
b.begin();
1021 while ((ia !=
a.end()) && (ib !=
b.end())) {
1023 out->push_back(*ia);
1026 }
else if (*ia == ib->Negated()) {
1027 if (*ia != x)
return false;
1031 }
else if (*ia < *ib) {
1032 out->push_back(*ia);
1035 out->push_back(*ib);
1041 out->insert(out->end(), ia,
a.end());
1042 out->insert(out->end(), ib,
b.end());
1048 const std::vector<Literal>&
b) {
1049 DCHECK(std::is_sorted(
a.begin(),
a.end()));
1050 DCHECK(std::is_sorted(
b.begin(),
b.end()));
1052 int size =
static_cast<int>(
a.size() +
b.size()) - 2;
1053 std::vector<Literal>::const_iterator ia =
a.begin();
1054 std::vector<Literal>::const_iterator ib =
b.begin();
1055 while ((ia !=
a.end()) && (ib !=
b.end())) {
1060 }
else if (*ia == ib->Negated()) {
1061 if (*ia != x)
return -1;
1065 }
else if (*ia < *ib) {
1086 deterministic_time_limit(solver->deterministic_time() +
1087 deterministic_time_limit) {}
1093 scratchpad_.clear();
1121 mutable std::vector<int32> scratchpad_;
1123 const double deterministic_time_limit;
1140 solver->
parameters().presolve_probing_deterministic_time_limit(), solver);
1142 std::vector<std::vector<int32>> scc;
1155 for (
const std::vector<int32>& component : scc) {
1156 if (component.size() > 1) {
1157 if (mapping->
empty()) mapping->
resize(size, LiteralIndex(-1));
1159 for (
int i = 1; i < component.size(); ++i) {
1160 const Literal l((LiteralIndex(component[i])));
1181 if (!mapping->
empty()) {
1191 for (LiteralIndex i(0); i < size; ++i) {
1199 if (drat_proof_handler !=
nullptr) {
1200 drat_proof_handler->
AddClause({true_lit});
1204 for (LiteralIndex i(0); i < size; ++i) {
1206 (*mapping)[i] = rep;
1213 if (drat_proof_handler !=
nullptr) {
1214 drat_proof_handler->
AddClause({true_lit});
1223 if (drat_proof_handler !=
nullptr) {
1224 drat_proof_handler->
AddClause({true_lit});
1227 }
else if (rep != i) {
1230 if (drat_proof_handler !=
nullptr) {
1237 const bool log_info =
1239 LOG_IF(
INFO, log_info) <<
"Probing. fixed " << num_already_fixed_vars <<
" + "
1241 num_already_fixed_vars
1242 <<
" equiv " << num_equiv / 2 <<
" total "
1248 std::vector<bool>* solution,
1251 const SatParameters
parameters = (*solver)->parameters();
1264 VLOG(1) <<
"UNSAT during probing.";
1267 const int num_variables = (*solver)->NumVariables();
1268 if ((*solver)->LiteralTrail().Index() == num_variables) {
1269 VLOG(1) <<
"Problem solved by trivial heuristic!";
1271 for (
int i = 0; i < (*solver)->NumVariables(); ++i) {
1272 solution->push_back((*solver)->Assignment().LiteralIsTrue(
1273 Literal(BooleanVariable(i),
true)));
1281 const int max_num_passes = 4;
1282 for (
int i = 0; i < max_num_passes && !
time_limit->LimitReached(); ++i) {
1283 const int saved_num_variables = (*solver)->NumVariables();
1298 parameters.presolve_probing_deterministic_time_limit();
1301 VLOG(1) <<
"UNSAT during probing.";
1305 postsolver.
Add(c[0], c);
1313 drat_proof_handler, &equiv_map);
1314 if ((*solver)->IsModelUnsat()) {
1315 VLOG(1) <<
"UNSAT during probing.";
1320 if (!(*solver)->ProblemIsPureSat()) {
1321 VLOG(1) <<
"The problem is not a pure SAT problem, skipping the SAT "
1322 "specific presolve.";
1328 (*solver)->Backtrack(0);
1329 for (
int i = 0; i < (*solver)->LiteralTrail().
Index(); ++i) {
1330 postsolver.
FixVariable((*solver)->LiteralTrail()[i]);
1338 (*solver)->ExtractClauses(&presolver);
1339 (*solver)->AdvanceDeterministicTime(
time_limit);
1343 time_limit->AdvanceDeterministicTime((*solver)
1345 ->GetOrCreate<TimeLimit>()
1346 ->GetElapsedDeterministicTime());
1348 (*solver).reset(
nullptr);
1349 std::vector<bool> can_be_removed(presolver.
NumVariables(),
true);
1350 if (!presolver.
Presolve(can_be_removed, log_info)) {
1351 VLOG(1) <<
"UNSAT during presolve.";
1354 (*solver) = absl::make_unique<SatSolver>();
1359 if (drat_proof_handler !=
nullptr) {
1364 (*solver) = absl::make_unique<SatSolver>();
1365 (*solver)->SetDratProofHandler(drat_proof_handler);
1370 if ((*solver)->NumVariables() == saved_num_variables)
break;
1390 model->GetOrCreate<SatParameters>()
1391 ->presolve_probing_deterministic_time_limit();
1396 postsolver.
Add(c[0], c);