24#include "absl/container/btree_set.h"
25#include "absl/log/check.h"
26#include "absl/types/span.h"
40#include "ortools/sat/sat_parameters.pb.h"
50 : initial_num_variables_(num_variables), num_variables_(num_variables) {
51 reverse_mapping_.
resize(num_variables);
52 for (BooleanVariable
var(0);
var < num_variables; ++
var) {
53 reverse_mapping_[
var] =
var;
55 assignment_.
Resize(num_variables);
59 DCHECK(!clause.empty());
60 DCHECK(std::find(clause.begin(), clause.end(),
x) != clause.end());
61 associated_literal_.push_back(ApplyReverseMapping(
x));
62 clauses_start_.push_back(clauses_literals_.size());
63 for (
const Literal& l : clause) {
64 clauses_literals_.push_back(ApplyReverseMapping(l));
69 const Literal l = ApplyReverseMapping(
x);
77 if (reverse_mapping_.size() < mapping.size()) {
79 while (reverse_mapping_.size() < mapping.size()) {
80 reverse_mapping_.
push_back(BooleanVariable(num_variables_++));
82 assignment_.
Resize(num_variables_);
84 for (BooleanVariable v(0); v < mapping.size(); ++v) {
85 const BooleanVariable image = mapping[v];
87 if (image >= new_mapping.size()) {
90 new_mapping[image] = reverse_mapping_[v];
94 std::swap(new_mapping, reverse_mapping_);
98 if (l.
Variable() >= reverse_mapping_.size()) {
100 while (l.
Variable() >= reverse_mapping_.size()) {
101 reverse_mapping_.
push_back(BooleanVariable(num_variables_++));
103 assignment_.
Resize(num_variables_);
111void SatPostsolver::Postsolve(VariablesAssignment* assignment)
const {
120 int previous_start = clauses_literals_.size();
121 for (
int i =
static_cast<int>(clauses_start_.size()) - 1;
i >= 0; --
i) {
122 bool set_associated_var =
true;
123 const int new_start = clauses_start_[
i];
124 for (
int j = new_start; j < previous_start; ++j) {
126 set_associated_var =
false;
130 previous_start = new_start;
131 if (set_associated_var) {
153 const std::vector<bool>&
solution) {
155 DCHECK_LT(
var, reverse_mapping_.size());
161 Postsolve(&assignment_);
162 std::vector<bool> postsolved_solution;
163 postsolved_solution.reserve(initial_num_variables_);
164 for (
int i = 0;
i < initial_num_variables_; ++
i) {
165 postsolved_solution.push_back(
168 return postsolved_solution;
174 DCHECK_GT(clause.size(), 0) <<
"Added an empty clause to the presolver";
176 clauses_.push_back(std::vector<Literal>(clause.begin(), clause.end()));
177 in_clause_to_process_.push_back(
true);
178 clause_to_process_.push_back(ci);
180 bool changed =
false;
181 std::vector<Literal>& clause_ref = clauses_.back();
182 if (!equiv_mapping_.empty()) {
183 for (
int i = 0;
i < clause_ref.size(); ++
i) {
184 const Literal old_literal = clause_ref[
i];
185 clause_ref[
i] =
Literal(equiv_mapping_[clause_ref[
i]]);
186 if (old_literal != clause_ref[
i]) changed =
true;
189 std::sort(clause_ref.begin(), clause_ref.end());
190 clause_ref.erase(std::unique(clause_ref.begin(), clause_ref.end()),
194 for (
int i = 1;
i < clause_ref.size(); ++
i) {
195 if (clause_ref[
i] == clause_ref[
i - 1].Negated()) {
197 ++num_trivial_clauses_;
198 clause_to_process_.pop_back();
200 in_clause_to_process_.pop_back();
206 signatures_.push_back(ComputeSignatureOfClauseVariables(ci));
207 DCHECK_EQ(signatures_.size(), clauses_.size());
209 if (drat_proof_handler_ !=
nullptr && changed) {
210 drat_proof_handler_->
AddClause(clause_ref);
214 const Literal max_literal = clause_ref.back();
215 const int required_size = std::max(max_literal.
Index().value(),
218 if (required_size > literal_to_clauses_.size()) {
219 literal_to_clauses_.
resize(required_size);
220 literal_to_clause_sizes_.
resize(required_size);
224 literal_to_clause_sizes_[e]++;
229 const int required_size = 2 * num_variables;
230 if (required_size > literal_to_clauses_.size()) {
231 literal_to_clauses_.
resize(required_size);
232 literal_to_clause_sizes_.
resize(required_size);
236void SatPresolver::AddClauseInternal(std::vector<Literal>* clause) {
237 if (drat_proof_handler_ !=
nullptr) drat_proof_handler_->
AddClause(*clause);
239 DCHECK(std::is_sorted(clause->begin(), clause->end()));
240 DCHECK_GT(clause->size(), 0) <<
"TODO(user): Unsat during presolve?";
242 clauses_.push_back(std::vector<Literal>());
243 clauses_.back().swap(*clause);
244 in_clause_to_process_.push_back(
true);
245 clause_to_process_.push_back(ci);
246 for (
const Literal e : clauses_.back()) {
248 literal_to_clause_sizes_[e]++;
249 UpdatePriorityQueue(e.Variable());
250 UpdateBvaPriorityQueue(e.Index());
253 signatures_.push_back(ComputeSignatureOfClauseVariables(ci));
254 DCHECK_EQ(signatures_.size(), clauses_.size());
260 BooleanVariable new_var(0);
262 if (literal_to_clause_sizes_[
Literal(
var,
true)] > 0 ||
263 literal_to_clause_sizes_[
Literal(
var,
false)] > 0) {
277 var_pq_elements_.clear();
278 in_clause_to_process_.clear();
279 clause_to_process_.clear();
280 literal_to_clauses_.clear();
286 for (BooleanVariable
index : mapping) {
290 std::vector<Literal> temp;
292 for (std::vector<Literal>& clause_ref : clauses_) {
303bool SatPresolver::ProcessAllClauses() {
304 int num_skipped_checks = 0;
305 const int kCheckFrequency = 1000;
309 std::stable_sort(clause_to_process_.begin(), clause_to_process_.end(),
311 return clauses_[c1].size() < clauses_[c2].size();
313 while (!clause_to_process_.empty()) {
315 in_clause_to_process_[ci] =
false;
316 clause_to_process_.pop_front();
318 if (++num_skipped_checks >= kCheckFrequency) {
319 if (num_inspected_signatures_ + num_inspected_literals_ > 1e9) {
320 VLOG(1) <<
"Aborting ProcessAllClauses() because work limit has been "
324 if (time_limit_ !=
nullptr && time_limit_->
LimitReached())
return true;
325 num_skipped_checks = 0;
343 int64_t num_removable = 0;
344 for (
const bool b : can_be_removed) {
345 if (
b) ++num_removable;
348 "[SAT presolve] num removable Booleans: ", num_removable,
" / ",
349 can_be_removed.size());
351 "[SAT presolve] num trivial clauses: ", num_trivial_clauses_);
357 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;
363 InitializePriorityQueue();
364 while (var_pq_.
Size() > 0) {
365 const BooleanVariable
var = var_pq_.
Top()->variable;
367 if (!can_be_removed[
var.value()])
continue;
369 if (!ProcessAllClauses())
return false;
371 if (time_limit_ !=
nullptr && time_limit_->
LimitReached())
return true;
372 if (num_inspected_signatures_ + num_inspected_literals_ > 1e9)
return true;
377 if (parameters_.presolve_use_bva()) {
387 var_pq_elements_.clear();
388 InitializeBvaPriorityQueue();
389 while (bva_pq_.
Size() > 0) {
390 const LiteralIndex
lit = bva_pq_.
Top()->literal;
393 if (time_limit_ !=
nullptr && time_limit_->
LimitReached())
break;
398void SatPresolver::SimpleBva(LiteralIndex l) {
399 literal_to_p_size_.
resize(literal_to_clauses_.size(), 0);
400 DCHECK(std::all_of(literal_to_p_size_.begin(), literal_to_p_size_.end(),
401 [](
int v) { return v == 0; }));
406 m_cls_ = literal_to_clauses_[l];
409 for (
int loop = 0; loop < 100; ++loop) {
413 flattened_p_.clear();
415 const std::vector<Literal>& clause = clauses_[c];
416 if (clause.empty())
continue;
420 const LiteralIndex l_min =
421 FindLiteralWithShortestOccurrenceListExcluding(clause, Literal(l));
426 for (
const ClauseIndex d : literal_to_clauses_[l_min]) {
427 if (clause.size() != clauses_[d].size())
continue;
428 const LiteralIndex l_diff =
431 if (l_diff == Literal(l).NegatedIndex()) {
436 VLOG(1) <<
"self-subsumbtion";
439 flattened_p_.push_back({l_diff, c});
440 const int new_size = ++literal_to_p_size_[l_diff];
441 if (new_size > max_size) {
449 const int new_m_lit_size = m_lit_.size() + 1;
450 const int new_m_cls_size = max_size;
451 const int new_reduction =
452 new_m_lit_size * new_m_cls_size - new_m_cls_size - new_m_lit_size;
454 if (new_reduction <= reduction)
break;
455 DCHECK_NE(1, new_m_lit_size);
456 DCHECK_NE(1, new_m_cls_size);
462 reduction = new_reduction;
467 for (
const auto& entry : flattened_p_) {
468 literal_to_p_size_[entry.first] = 0;
469 if (entry.first == lmax) m_cls_.
push_back(entry.second);
471 flattened_p_.clear();
475 for (
const auto& entry : flattened_p_) literal_to_p_size_[entry.first] = 0;
476 flattened_p_.clear();
481 if (reduction <= parameters_.presolve_bva_threshold())
return;
482 DCHECK_GT(m_lit_.size(), 1);
485 const int old_size = literal_to_clauses_.size();
486 const LiteralIndex x_true = LiteralIndex(old_size);
487 const LiteralIndex x_false = LiteralIndex(old_size + 1);
488 literal_to_clauses_.
resize(old_size + 2);
489 literal_to_clause_sizes_.
resize(old_size + 2);
490 bva_pq_elements_.resize(old_size + 2);
491 bva_pq_elements_[x_true.value()].literal = x_true;
492 bva_pq_elements_[x_false.value()].literal = x_false;
495 if (drat_proof_handler_ !=
nullptr) drat_proof_handler_->
AddOneVariable();
496 for (
const LiteralIndex
lit : m_lit_) {
497 tmp_new_clause_ = {Literal(
lit), Literal(x_true)};
498 AddClauseInternal(&tmp_new_clause_);
501 tmp_new_clause_ = clauses_[ci];
502 DCHECK(!tmp_new_clause_.empty());
503 for (Literal& ref : tmp_new_clause_) {
504 if (ref.Index() == l) {
505 ref = Literal(x_false);
513 std::sort(tmp_new_clause_.begin(), tmp_new_clause_.end());
514 AddClauseInternal(&tmp_new_clause_);
524 const std::vector<Literal>& clause = clauses_[
c];
525 DCHECK(!clause.empty());
526 const LiteralIndex l_min =
527 FindLiteralWithShortestOccurrenceListExcluding(clause, Literal(l));
528 for (
const LiteralIndex
lit : m_lit_) {
529 if (
lit == l)
continue;
530 for (
const ClauseIndex d : literal_to_clauses_[l_min]) {
531 if (clause.size() != clauses_[d].size())
continue;
532 const LiteralIndex l_diff =
548 AddToBvaPriorityQueue(x_true);
549 AddToBvaPriorityQueue(x_false);
550 AddToBvaPriorityQueue(l);
553uint64_t SatPresolver::ComputeSignatureOfClauseVariables(ClauseIndex ci) {
554 uint64_t signature = 0;
555 for (
const Literal l : clauses_[ci]) {
556 signature |= (uint64_t{1} << (l.Variable().
value() % 64));
558 DCHECK_EQ(signature == 0, clauses_[ci].empty());
565bool SatPresolver::ProcessClauseToSimplifyOthersUsingLiteral(
566 ClauseIndex clause_index, Literal
lit) {
567 const std::vector<Literal>& clause = clauses_[clause_index];
568 const uint64_t clause_signature = signatures_[clause_index];
569 LiteralIndex opposite_literal;
574 bool need_cleaning =
false;
575 num_inspected_signatures_ += literal_to_clauses_[
lit].size();
577 const uint64_t ci_signature = signatures_[ci];
581 DCHECK_EQ(ci_signature, ComputeSignatureOfClauseVariables(ci));
582 if (ci_signature == 0) {
583 need_cleaning =
true;
590 if (ci != clause_index && (clause_signature & ~ci_signature) == 0 &&
592 &num_inspected_literals_)) {
594 need_cleaning =
true;
598 DCHECK_NE(opposite_literal,
lit.Index());
599 if (clauses_[ci].empty())
return false;
600 if (drat_proof_handler_ !=
nullptr) {
602 drat_proof_handler_->
AddClause(clauses_[ci]);
606 signatures_[ci] = ComputeSignatureOfClauseVariables(ci);
612 --literal_to_clause_sizes_[opposite_literal];
613 UpdatePriorityQueue(Literal(opposite_literal).Variable());
615 if (!in_clause_to_process_[ci]) {
616 in_clause_to_process_[ci] =
true;
617 clause_to_process_.push_back(ci);
625 auto& occurrence_list_ref = literal_to_clauses_[
lit];
627 if (signatures_[ci] != 0) occurrence_list_ref[new_index++] = ci;
629 occurrence_list_ref.
resize(new_index);
630 DCHECK_EQ(literal_to_clause_sizes_[
lit], new_index);
640 const std::vector<Literal>& clause = clauses_[clause_index];
641 if (clause.empty())
return true;
642 DCHECK(std::is_sorted(clause.begin(), clause.end()));
644 LiteralIndex opposite_literal;
645 const Literal lit = FindLiteralWithShortestOccurrenceList(clause);
647 if (!ProcessClauseToSimplifyOthersUsingLiteral(clause_index,
lit)) {
653 const LiteralIndex other_lit_index =
654 FindLiteralWithShortestOccurrenceListExcluding(clause,
lit);
656 literal_to_clause_sizes_[other_lit_index] <
657 literal_to_clause_sizes_[
lit.NegatedIndex()]) {
658 return ProcessClauseToSimplifyOthersUsingLiteral(clause_index,
663 bool something_removed =
false;
664 auto& occurrence_list_ref = literal_to_clauses_[
lit.NegatedIndex()];
665 const uint64_t clause_signature = signatures_[clause_index];
667 const uint64_t ci_signature = signatures_[ci];
668 DCHECK_EQ(ci_signature, ComputeSignatureOfClauseVariables(ci));
669 if (ci_signature == 0)
continue;
675 if ((clause_signature & ~ci_signature) == 0 &&
677 &num_inspected_literals_)) {
678 DCHECK_EQ(opposite_literal,
lit.NegatedIndex());
679 if (clauses_[ci].empty())
return false;
680 if (drat_proof_handler_ !=
nullptr) {
682 drat_proof_handler_->
AddClause(clauses_[ci]);
686 signatures_[ci] = ComputeSignatureOfClauseVariables(ci);
688 if (!in_clause_to_process_[ci]) {
689 in_clause_to_process_[ci] =
true;
690 clause_to_process_.push_back(ci);
692 something_removed =
true;
695 occurrence_list_ref[new_index] = ci;
698 occurrence_list_ref.resize(new_index);
699 literal_to_clause_sizes_[
lit.NegatedIndex()] = new_index;
700 if (something_removed) {
707void SatPresolver::RemoveAndRegisterForPostsolveAllClauseContaining(
Literal x) {
709 if (!clauses_[
i].empty()) RemoveAndRegisterForPostsolve(
i,
x);
712 literal_to_clause_sizes_[
x] = 0;
716 const int s1 = literal_to_clause_sizes_[
x];
717 const int s2 = literal_to_clause_sizes_[
x.NegatedIndex()];
721 if (s1 == 0 && s2 == 0)
return false;
725 if (s1 > 1 && s2 > 1 && s1 * s2 > parameters_.presolve_bve_threshold()) {
731 const int clause_weight = parameters_.presolve_bve_clause_weight();
733 if (!clauses_[
i].empty()) {
734 threshold += clause_weight + clauses_[
i].size();
737 for (
ClauseIndex i : literal_to_clauses_[
x.NegatedIndex()]) {
738 if (!clauses_[
i].empty()) {
739 threshold += clause_weight + clauses_[
i].size();
744 if (s1 < s2)
x =
x.Negated();
749 if (clauses_[
i].empty())
continue;
750 bool no_resolvant =
true;
751 for (
ClauseIndex j : literal_to_clauses_[
x.NegatedIndex()]) {
752 if (clauses_[j].empty())
continue;
755 no_resolvant =
false;
756 size += clause_weight + rs;
759 if (
size > threshold)
return false;
762 if (no_resolvant && parameters_.presolve_blocked_clause()) {
775 RemoveAndRegisterForPostsolve(
i,
x);
782 std::vector<Literal> temp;
784 if (clauses_[
i].empty())
continue;
785 for (
ClauseIndex j : literal_to_clauses_[
x.NegatedIndex()]) {
786 if (clauses_[j].empty())
continue;
788 AddClauseInternal(&temp);
797 RemoveAndRegisterForPostsolveAllClauseContaining(
x);
798 RemoveAndRegisterForPostsolveAllClauseContaining(
x.Negated());
805void SatPresolver::Remove(ClauseIndex ci) {
807 for (
Literal e : clauses_[ci]) {
808 literal_to_clause_sizes_[e]--;
809 UpdatePriorityQueue(e.Variable());
810 UpdateBvaPriorityQueue(
Literal(e.Variable(),
true).
Index());
811 UpdateBvaPriorityQueue(
Literal(e.Variable(),
false).
Index());
813 if (drat_proof_handler_ !=
nullptr) {
819void SatPresolver::RemoveAndRegisterForPostsolve(ClauseIndex ci, Literal
x) {
820 postsolver_->
Add(
x, clauses_[ci]);
824Literal SatPresolver::FindLiteralWithShortestOccurrenceList(
825 const std::vector<Literal>& clause) {
826 DCHECK(!clause.empty());
827 Literal result = clause.front();
828 int best_size = literal_to_clause_sizes_[result];
829 for (
const Literal l : clause) {
830 const int size = literal_to_clause_sizes_[l];
831 if (
size < best_size) {
839LiteralIndex SatPresolver::FindLiteralWithShortestOccurrenceListExcluding(
840 const std::vector<Literal>& clause, Literal to_exclude) {
841 DCHECK(!clause.empty());
843 int num_occurrences = std::numeric_limits<int>::max();
844 for (
const Literal l : clause) {
845 if (l == to_exclude)
continue;
846 if (literal_to_clause_sizes_[l] < num_occurrences) {
848 num_occurrences = literal_to_clause_sizes_[l];
854void SatPresolver::UpdatePriorityQueue(BooleanVariable
var) {
855 if (var_pq_elements_.empty())
return;
856 PQElement* element = &var_pq_elements_[
var];
857 element->weight = literal_to_clause_sizes_[Literal(
var,
true)] +
858 literal_to_clause_sizes_[Literal(
var,
false)];
862 var_pq_.
Add(element);
866void SatPresolver::InitializePriorityQueue() {
868 var_pq_elements_.
resize(num_vars);
869 for (BooleanVariable
var(0);
var < num_vars; ++
var) {
870 PQElement* element = &var_pq_elements_[
var];
871 element->variable =
var;
872 element->weight = literal_to_clause_sizes_[Literal(
var,
true)] +
873 literal_to_clause_sizes_[Literal(
var,
false)];
874 var_pq_.
Add(element);
878void SatPresolver::UpdateBvaPriorityQueue(LiteralIndex
lit) {
879 if (bva_pq_elements_.empty())
return;
880 DCHECK_LT(
lit, bva_pq_elements_.size());
881 BvaPqElement* element = &bva_pq_elements_[
lit.value()];
882 element->weight = literal_to_clause_sizes_[
lit];
888void SatPresolver::AddToBvaPriorityQueue(LiteralIndex
lit) {
889 if (bva_pq_elements_.empty())
return;
890 DCHECK_LT(
lit, bva_pq_elements_.size());
891 BvaPqElement* element = &bva_pq_elements_[
lit.value()];
892 element->weight = literal_to_clause_sizes_[
lit];
894 if (element->weight > 2) bva_pq_.
Add(element);
897void SatPresolver::InitializeBvaPriorityQueue() {
900 bva_pq_elements_.assign(num_literals, BvaPqElement());
901 for (LiteralIndex
lit(0);
lit < num_literals; ++
lit) {
902 BvaPqElement* element = &bva_pq_elements_[
lit.value()];
903 element->literal =
lit;
904 element->weight = literal_to_clause_sizes_[
lit];
908 if (element->weight > 2) bva_pq_.
Add(element);
912void SatPresolver::DisplayStats(
double elapsed_seconds) {
913 int num_literals = 0;
915 int num_singleton_clauses = 0;
916 for (
const std::vector<Literal>& c : clauses_) {
918 if (
c.size() == 1) ++num_singleton_clauses;
920 num_literals +=
c.size();
923 int num_one_side = 0;
924 int num_simple_definition = 0;
927 const int s1 = literal_to_clause_sizes_[Literal(
var,
true)];
928 const int s2 = literal_to_clause_sizes_[Literal(
var,
false)];
929 if (s1 == 0 && s2 == 0)
continue;
932 if (s1 == 0 || s2 == 0) {
934 }
else if (s1 == 1 || s2 == 1) {
935 num_simple_definition++;
938 SOLVER_LOG(logger_,
"[SAT presolve] [", elapsed_seconds,
"s]",
939 " clauses:", num_clauses,
" literals:", num_literals,
940 " vars:", num_vars,
" one_side_vars:", num_one_side,
941 " simple_definition:", num_simple_definition,
942 " singleton_clauses:", num_singleton_clauses);
946 LiteralIndex* opposite_literal,
947 int64_t* num_inspected_literals) {
948 if (
b->size() <
a.size())
return false;
949 DCHECK(std::is_sorted(
a.begin(),
a.end()));
950 DCHECK(std::is_sorted(
b->begin(),
b->end()));
951 if (num_inspected_literals !=
nullptr) {
952 *num_inspected_literals +=
a.size();
953 *num_inspected_literals +=
b->size();
956 *opposite_literal = LiteralIndex(-1);
959 std::vector<Literal>::const_iterator ia =
a.begin();
960 std::vector<Literal>::const_iterator ib =
b->begin();
961 std::vector<Literal>::const_iterator to_remove;
965 int size_diff =
b->size() -
a.size();
966 while (ia !=
a.end() ) {
970 }
else if (*ia == ib->Negated()) {
972 if (num_diff > 1)
return false;
976 }
else if (*ia < *ib) {
983 if (--size_diff < 0)
return false;
987 *opposite_literal = to_remove->Index();
994 const std::vector<Literal>&
b,
Literal l) {
995 DCHECK_EQ(
b.size(),
a.size());
996 DCHECK(std::is_sorted(
a.begin(),
a.end()));
997 DCHECK(std::is_sorted(
b.begin(),
b.end()));
999 std::vector<Literal>::const_iterator ia =
a.begin();
1000 std::vector<Literal>::const_iterator ib =
b.begin();
1001 while (ia !=
a.end() && ib !=
b.end()) {
1005 }
else if (*ia < *ib) {
1014 result = (*ib).Index();
1020 if (ib !=
b.end()) {
1022 result = (*ib).Index();
1028 const std::vector<Literal>&
b,
1029 std::vector<Literal>* out) {
1030 DCHECK(std::is_sorted(
a.begin(),
a.end()));
1031 DCHECK(std::is_sorted(
b.begin(),
b.end()));
1034 std::vector<Literal>::const_iterator ia =
a.begin();
1035 std::vector<Literal>::const_iterator ib =
b.begin();
1036 while ((ia !=
a.end()) && (ib !=
b.end())) {
1038 out->push_back(*ia);
1041 }
else if (*ia == ib->Negated()) {
1042 if (*ia !=
x)
return false;
1043 DCHECK_EQ(*ib,
x.Negated());
1046 }
else if (*ia < *ib) {
1047 out->push_back(*ia);
1050 out->push_back(*ib);
1056 out->insert(out->end(), ia,
a.end());
1057 out->insert(out->end(), ib,
b.end());
1063 const std::vector<Literal>&
b) {
1064 DCHECK(std::is_sorted(
a.begin(),
a.end()));
1065 DCHECK(std::is_sorted(
b.begin(),
b.end()));
1067 int size =
static_cast<int>(
a.size() +
b.size()) - 2;
1068 std::vector<Literal>::const_iterator ia =
a.begin();
1069 std::vector<Literal>::const_iterator ib =
b.begin();
1070 while ((ia !=
a.end()) && (ib !=
b.end())) {
1075 }
else if (*ia == ib->Negated()) {
1076 if (*ia !=
x)
return -1;
1077 DCHECK_EQ(*ib,
x.Negated());
1080 }
else if (*ia < *ib) {
1101 deterministic_time_limit(solver->deterministic_time() +
1102 deterministic_time_limit) {}
1112 scratchpad_.clear();
1130 for (
int i = trail_index + 1;
i < solver_->
LiteralTrail().Index();
1140 mutable std::vector<int32_t> scratchpad_;
1142 const double deterministic_time_limit;
1158 solver->
parameters().presolve_probing_deterministic_time_limit(), solver);
1160 std::vector<std::vector<int32_t>> scc;
1173 for (
const std::vector<int32_t>& component : scc) {
1174 if (component.size() > 1) {
1175 if (mapping->empty()) mapping->
resize(
size, LiteralIndex(-1));
1177 for (
int i = 1;
i < component.size(); ++
i) {
1178 const Literal l((LiteralIndex(component[
i])));
1199 if (!mapping->empty()) {
1209 for (LiteralIndex
i(0);
i <
size; ++
i) {
1217 if (drat_proof_handler !=
nullptr) {
1218 drat_proof_handler->
AddClause({true_lit});
1222 for (LiteralIndex
i(0);
i <
size; ++
i) {
1224 (*mapping)[
i] = rep;
1231 if (drat_proof_handler !=
nullptr) {
1232 drat_proof_handler->
AddClause({true_lit});
1241 if (drat_proof_handler !=
nullptr) {
1242 drat_proof_handler->
AddClause({true_lit});
1245 }
else if (rep !=
i) {
1248 if (drat_proof_handler !=
nullptr) {
1255 if (logger !=
nullptr) {
1256 SOLVER_LOG(logger,
"[Pure SAT probing] fixed ", num_already_fixed_vars,
1258 " equiv ", num_equiv / 2,
" total ", solver->
NumVariables(),
1259 " wtime: ", timer.
Get());
1261 const bool log_info =
1262 solver->
parameters().log_search_progress() || VLOG_IS_ON(1);
1263 LOG_IF(INFO, log_info) <<
"Probing. fixed " << num_already_fixed_vars
1266 num_already_fixed_vars
1267 <<
" equiv " << num_equiv / 2 <<
" total "
1269 <<
" wtime: " << timer.
Get();
bool Contains(const T *val) const
void Pop()
If there are ties for the top, this returns all of them.
void NoteChangedPriority(T *val)
void Start()
When Start() is called multiple times, only the most recent is used.
int MergePartsOf(int node1, int node2)
int GetRootAndCompressPath(int node)
bool LoggingIsEnabled() const
Returns true iff logging is enabled.
void AddClause(absl::Span< const Literal > clause)
void DeleteClause(absl::Span< const Literal > clause)
LiteralIndex NegatedIndex() const
LiteralIndex Index() const
BooleanVariable Variable() const
PropagationGraph & operator=(const PropagationGraph &)=delete
const std::vector< int32_t > & operator[](int32_t index) const
PropagationGraph(const PropagationGraph &)=delete
This type is neither copyable nor movable.
PropagationGraph(double deterministic_time_limit, SatSolver *solver)
const VariablesAssignment & assignment()
std::vector< bool > PostsolveSolution(const std::vector< bool > &solution)
void ApplyMapping(const util_intops::StrongVector< BooleanVariable, BooleanVariable > &mapping)
SatPostsolver(int num_variables)
void Add(Literal x, absl::Span< const Literal > clause)
std::vector< bool > ExtractAndPostsolveSolution(const SatSolver &solver)
void FixVariable(Literal x)
void AddBinaryClause(Literal a, Literal b)
bool CrossProduct(Literal x)
void SetNumVariables(int num_variables)
Adds new clause to the SatPresolver.
bool ProcessClauseToSimplifyOthers(ClauseIndex clause_index)
util_intops::StrongVector< BooleanVariable, BooleanVariable > VariableMapping() const
void AddClause(absl::Span< const Literal > clause)
void LoadProblemIntoSatSolver(SatSolver *solver)
void PresolveWithBva()
Visible for testing. Just applies the BVA step of the presolve.
double deterministic_time() const
bool AddProblemClause(absl::Span< const Literal > literals, bool is_safe=true)
int EnqueueDecisionAndBackjumpOnConflict(Literal true_literal)
void Backtrack(int target_level)
const SatParameters & parameters() const
ABSL_MUST_USE_RESULT bool AddUnitClause(Literal true_literal)
const VariablesAssignment & Assignment() const
int CurrentDecisionLevel() const
const Trail & LiteralTrail() const
void SetNumVariables(int num_variables)
bool VariableIsAssigned(BooleanVariable var) const
Returns true iff the given variable is assigned.
bool LiteralIsAssigned(Literal literal) const
int NumberOfVariables() const
void AssignFromTrueLiteral(Literal literal)
void UnassignLiteral(Literal literal)
void Resize(int num_variables)
bool LiteralIsTrue(Literal literal) const
void push_back(const value_type &val)
void resize(size_type new_size)
void STLEraseAllFromSequence(T *v, const E &e)
void STLClearObject(T *obj)
const LiteralIndex kNoLiteralIndex(-1)
LiteralIndex DifferAtGivenLiteral(const std::vector< Literal > &a, const std::vector< Literal > &b, Literal l)
void ProbeAndFindEquivalentLiteral(SatSolver *solver, SatPostsolver *postsolver, DratProofHandler *drat_proof_handler, util_intops::StrongVector< LiteralIndex, LiteralIndex > *mapping, SolverLogger *logger)
int ComputeResolvantSize(Literal x, const std::vector< Literal > &a, const std::vector< Literal > &b)
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)
const BooleanVariable kNoBooleanVariable(-1)
In SWIG mode, we don't want anything besides these top-level includes.
void FindStronglyConnectedComponents(NodeIndex num_nodes, const Graph &graph, SccOutput *components)
Simple wrapper function for most usage.
#define SOLVER_LOG(logger,...)