23#include "absl/container/btree_set.h"
24#include "absl/log/check.h"
25#include "absl/log/log.h"
26#include "absl/log/vlog_is_on.h"
27#include "absl/types/span.h"
48 : initial_num_variables_(num_variables), num_variables_(num_variables) {
49 reverse_mapping_.resize(num_variables);
50 for (BooleanVariable var(0); var < num_variables; ++var) {
51 reverse_mapping_[var] = var;
53 assignment_.Resize(num_variables);
57 DCHECK(!clause.empty());
58 DCHECK(std::find(clause.begin(), clause.end(), x) != clause.end());
59 associated_literal_.push_back(ApplyReverseMapping(x));
60 clauses_start_.push_back(clauses_literals_.size());
61 for (
const Literal& l : clause) {
62 clauses_literals_.push_back(ApplyReverseMapping(l));
67 const Literal l = ApplyReverseMapping(x);
68 assignment_.AssignFromTrueLiteral(l);
75 if (reverse_mapping_.size() < mapping.size()) {
77 while (reverse_mapping_.size() < mapping.size()) {
78 reverse_mapping_.push_back(BooleanVariable(num_variables_++));
80 assignment_.Resize(num_variables_);
82 for (BooleanVariable v(0); v < mapping.size(); ++v) {
83 const BooleanVariable image = mapping[v];
85 if (image >= new_mapping.size()) {
88 new_mapping[image] = reverse_mapping_[v];
92 std::swap(new_mapping, reverse_mapping_);
96 if (l.
Variable() >= reverse_mapping_.size()) {
98 while (l.
Variable() >= reverse_mapping_.size()) {
99 reverse_mapping_.
push_back(BooleanVariable(num_variables_++));
101 assignment_.
Resize(num_variables_);
112 for (BooleanVariable var(0); var <
assignment->NumberOfVariables(); ++var) {
114 assignment->AssignFromTrueLiteral(Literal(var,
true));
118 int previous_start = clauses_literals_.size();
119 for (
int i =
static_cast<int>(clauses_start_.size()) - 1;
i >= 0; --
i) {
120 bool set_associated_var =
true;
121 const int new_start = clauses_start_[
i];
122 for (
int j = new_start; j < previous_start; ++j) {
123 if (
assignment->LiteralIsTrue(clauses_literals_[j])) {
124 set_associated_var =
false;
128 previous_start = new_start;
129 if (set_associated_var) {
130 assignment->UnassignLiteral(associated_literal_[
i].Negated());
131 assignment->AssignFromTrueLiteral(associated_literal_[
i]);
142 for (BooleanVariable var(0); var < solver.
NumVariables(); ++var) {
151 const std::vector<bool>&
solution) {
152 for (BooleanVariable var(0); var <
solution.size(); ++var) {
153 DCHECK_LT(var, reverse_mapping_.size());
155 DCHECK(!assignment_.VariableIsAssigned(reverse_mapping_[var]));
156 assignment_.AssignFromTrueLiteral(
159 Postsolve(&assignment_);
160 std::vector<bool> postsolved_solution;
161 postsolved_solution.reserve(initial_num_variables_);
162 for (
int i = 0;
i < initial_num_variables_; ++
i) {
163 postsolved_solution.push_back(
164 assignment_.LiteralIsTrue(
Literal(BooleanVariable(
i),
true)));
166 return postsolved_solution;
172 DCHECK_GT(clause.size(), 0) <<
"Added an empty clause to the presolver";
174 clauses_.push_back(std::vector<Literal>(clause.begin(), clause.end()));
175 in_clause_to_process_.push_back(
true);
176 clause_to_process_.push_back(ci);
178 bool changed =
false;
179 std::vector<Literal>& clause_ref = clauses_.back();
180 if (!equiv_mapping_.empty()) {
181 for (
int i = 0;
i < clause_ref.size(); ++
i) {
182 const Literal old_literal = clause_ref[
i];
183 clause_ref[
i] =
Literal(equiv_mapping_[clause_ref[
i]]);
184 if (old_literal != clause_ref[
i]) changed =
true;
187 std::sort(clause_ref.begin(), clause_ref.end());
188 clause_ref.erase(std::unique(clause_ref.begin(), clause_ref.end()),
192 for (
int i = 1;
i < clause_ref.size(); ++
i) {
193 if (clause_ref[
i] == clause_ref[
i - 1].Negated()) {
195 ++num_trivial_clauses_;
196 clause_to_process_.pop_back();
198 in_clause_to_process_.pop_back();
204 signatures_.push_back(ComputeSignatureOfClauseVariables(ci));
205 DCHECK_EQ(signatures_.size(), clauses_.size());
207 const Literal max_literal = clause_ref.back();
208 const int required_size = std::max(max_literal.
Index().value(),
211 if (required_size > literal_to_clauses_.size()) {
212 literal_to_clauses_.resize(required_size);
213 literal_to_clause_sizes_.resize(required_size);
216 literal_to_clauses_[e].push_back(ci);
217 literal_to_clause_sizes_[e]++;
222 const int required_size = 2 * num_variables;
223 if (required_size > literal_to_clauses_.size()) {
224 literal_to_clauses_.resize(required_size);
225 literal_to_clause_sizes_.resize(required_size);
229void SatPresolver::RebuildLiteralToClauses() {
230 const int size = literal_to_clauses_.size();
231 literal_to_clauses_.clear();
232 literal_to_clauses_.
resize(size);
233 for (
ClauseIndex ci(0); ci < clauses_.size(); ++ci) {
234 for (
const Literal lit : clauses_[ci]) {
238 num_deleted_literals_since_last_cleanup_ = 0;
241void SatPresolver::AddClauseInternal(std::vector<Literal>* clause) {
242 DCHECK(std::is_sorted(clause->begin(), clause->end()));
243 DCHECK_GT(clause->size(), 0) <<
"TODO(user): Unsat during presolve?";
245 clauses_.push_back(std::vector<Literal>());
246 clauses_.back().swap(*clause);
247 in_clause_to_process_.push_back(
true);
248 clause_to_process_.push_back(ci);
249 for (
const Literal e : clauses_.back()) {
250 literal_to_clauses_[e].push_back(ci);
251 literal_to_clause_sizes_[e]++;
252 UpdatePriorityQueue(e.Variable());
253 UpdateBvaPriorityQueue(e.Index());
256 signatures_.push_back(ComputeSignatureOfClauseVariables(ci));
257 DCHECK_EQ(signatures_.size(), clauses_.size());
260util_intops::StrongVector<BooleanVariable, BooleanVariable>
263 BooleanVariable new_var(0);
264 for (BooleanVariable var(0); var <
NumVariables(); ++var) {
265 if (literal_to_clause_sizes_[
Literal(var,
true)] > 0 ||
266 literal_to_clause_sizes_[
Literal(var,
false)] > 0) {
280 var_pq_elements_.clear();
281 in_clause_to_process_.clear();
282 clause_to_process_.clear();
283 literal_to_clauses_.clear();
289 for (BooleanVariable index : mapping) {
293 std::vector<Literal> temp;
295 for (std::vector<Literal>& clause_ref : clauses_) {
306bool SatPresolver::ProcessAllClauses() {
307 int num_skipped_checks = 0;
308 const int kCheckFrequency = 1000;
312 std::stable_sort(clause_to_process_.begin(), clause_to_process_.end(),
314 return clauses_[c1].size() < clauses_[c2].size();
316 while (!clause_to_process_.empty()) {
318 in_clause_to_process_[ci] =
false;
319 clause_to_process_.pop_front();
321 if (++num_skipped_checks >= kCheckFrequency) {
322 if (num_inspected_signatures_ + num_inspected_literals_ > 1e9) {
323 VLOG(1) <<
"Aborting ProcessAllClauses() because work limit has been "
327 if (time_limit_ !=
nullptr && time_limit_->
LimitReached())
return true;
328 num_skipped_checks = 0;
345 if (logger_->LoggingIsEnabled()) {
346 int64_t num_removable = 0;
347 for (
const bool b : can_be_removed) {
348 if (
b) ++num_removable;
350 SOLVER_LOG(logger_,
"[SAT presolve] num removable Booleans: ",
353 SOLVER_LOG(logger_,
"[SAT presolve] num trivial clauses: ",
360 if (!ProcessAllClauses())
return false;
361 if (logger_->LoggingIsEnabled()) DisplayStats(timer.
Get());
363 if (time_limit_ !=
nullptr && time_limit_->LimitReached())
return true;
364 if (num_inspected_signatures_ + num_inspected_literals_ > 1e9)
return true;
366 InitializePriorityQueue();
367 while (var_pq_.Size() > 0) {
368 const BooleanVariable var = var_pq_.Top()->variable;
370 if (!can_be_removed[var.value()])
continue;
372 if (!ProcessAllClauses())
return false;
374 if (num_deleted_literals_since_last_cleanup_ > 1e7) {
375 RebuildLiteralToClauses();
378 if (time_limit_ !=
nullptr && time_limit_->LimitReached())
return true;
379 if (num_inspected_signatures_ + num_inspected_literals_ > 1e9)
return true;
381 if (logger_->LoggingIsEnabled()) DisplayStats(timer.
Get());
384 if (parameters_.presolve_use_bva()) {
386 if (logger_->LoggingIsEnabled()) DisplayStats(timer.
Get());
394 var_pq_elements_.clear();
395 InitializeBvaPriorityQueue();
396 while (bva_pq_.Size() > 0) {
397 const LiteralIndex lit = bva_pq_.Top()->literal;
400 if (time_limit_ !=
nullptr && time_limit_->LimitReached())
break;
405void SatPresolver::SimpleBva(LiteralIndex l) {
406 literal_to_p_size_.
resize(literal_to_clauses_.size(), 0);
407 DCHECK(std::all_of(literal_to_p_size_.begin(), literal_to_p_size_.end(),
408 [](
int v) { return v == 0; }));
413 m_cls_ = literal_to_clauses_[l];
416 for (
int loop = 0; loop < 100; ++loop) {
420 flattened_p_.clear();
422 const std::vector<Literal>& clause = clauses_[c];
423 if (clause.empty())
continue;
427 const LiteralIndex l_min =
428 FindLiteralWithShortestOccurrenceListExcluding(clause, Literal(l));
433 for (
const ClauseIndex d : literal_to_clauses_[l_min]) {
434 if (clause.size() != clauses_[d].size())
continue;
435 const LiteralIndex l_diff =
438 if (l_diff == Literal(l).NegatedIndex()) {
443 VLOG(1) <<
"self-subsumbtion";
446 flattened_p_.push_back({l_diff, c});
447 const int new_size = ++literal_to_p_size_[l_diff];
448 if (new_size > max_size) {
456 const int new_m_lit_size = m_lit_.size() + 1;
457 const int new_m_cls_size = max_size;
458 const int new_reduction =
459 new_m_lit_size * new_m_cls_size - new_m_cls_size - new_m_lit_size;
461 if (new_reduction <= reduction)
break;
462 DCHECK_NE(1, new_m_lit_size);
463 DCHECK_NE(1, new_m_cls_size);
469 reduction = new_reduction;
474 for (
const auto& entry : flattened_p_) {
475 literal_to_p_size_[entry.first] = 0;
476 if (entry.first == lmax) m_cls_.push_back(entry.second);
478 flattened_p_.clear();
482 for (
const auto& entry : flattened_p_) literal_to_p_size_[entry.first] = 0;
483 flattened_p_.clear();
488 if (reduction <= parameters_.presolve_bva_threshold())
return;
489 DCHECK_GT(m_lit_.size(), 1);
492 const int old_size = literal_to_clauses_.size();
493 const LiteralIndex x_true = LiteralIndex(old_size);
494 const LiteralIndex x_false = LiteralIndex(old_size + 1);
495 literal_to_clauses_.resize(old_size + 2);
496 literal_to_clause_sizes_.resize(old_size + 2);
497 bva_pq_elements_.resize(old_size + 2);
498 bva_pq_elements_[x_true.value()].literal = x_true;
499 bva_pq_elements_[x_false.value()].literal = x_false;
502 for (
const LiteralIndex lit : m_lit_) {
503 tmp_new_clause_ = {Literal(lit), Literal(x_true)};
504 AddClauseInternal(&tmp_new_clause_);
507 tmp_new_clause_ = clauses_[ci];
508 DCHECK(!tmp_new_clause_.empty());
509 for (Literal& ref : tmp_new_clause_) {
510 if (ref.Index() == l) {
511 ref = Literal(x_false);
519 std::sort(tmp_new_clause_.begin(), tmp_new_clause_.end());
520 AddClauseInternal(&tmp_new_clause_);
530 const std::vector<Literal>& clause = clauses_[
c];
531 DCHECK(!clause.empty());
532 const LiteralIndex l_min =
533 FindLiteralWithShortestOccurrenceListExcluding(clause, Literal(l));
534 for (
const LiteralIndex lit : m_lit_) {
535 if (lit == l)
continue;
536 for (
const ClauseIndex d : literal_to_clauses_[l_min]) {
537 if (clause.size() != clauses_[d].size())
continue;
538 const LiteralIndex l_diff =
554 AddToBvaPriorityQueue(x_true);
555 AddToBvaPriorityQueue(x_false);
556 AddToBvaPriorityQueue(l);
559uint64_t SatPresolver::ComputeSignatureOfClauseVariables(ClauseIndex ci) {
560 uint64_t signature = 0;
561 for (
const Literal l : clauses_[ci]) {
562 signature |= (uint64_t{1} << (l.Variable().value() % 64));
564 DCHECK_EQ(signature == 0, clauses_[ci].empty());
571bool SatPresolver::ProcessClauseToSimplifyOthersUsingLiteral(
572 ClauseIndex clause_index,
Literal lit) {
573 const std::vector<Literal>& clause = clauses_[clause_index];
574 const uint64_t clause_signature = signatures_[clause_index];
575 LiteralIndex opposite_literal;
580 bool need_cleaning =
false;
581 num_inspected_signatures_ += literal_to_clauses_[lit].size();
582 for (
const ClauseIndex ci : literal_to_clauses_[lit]) {
583 const uint64_t ci_signature = signatures_[ci];
587 DCHECK_EQ(ci_signature, ComputeSignatureOfClauseVariables(ci));
588 if (ci_signature == 0) {
589 need_cleaning =
true;
596 if (ci != clause_index && (clause_signature & ~ci_signature) == 0 &&
598 &num_inspected_literals_)) {
600 need_cleaning =
true;
604 DCHECK_NE(opposite_literal, lit.Index());
605 if (clauses_[ci].empty())
return false;
608 signatures_[ci] = ComputeSignatureOfClauseVariables(ci);
614 --literal_to_clause_sizes_[opposite_literal];
615 UpdatePriorityQueue(Literal(opposite_literal).Variable());
617 if (!in_clause_to_process_[ci]) {
618 in_clause_to_process_[ci] =
true;
619 clause_to_process_.push_back(ci);
627 auto& occurrence_list_ref = literal_to_clauses_[lit];
629 if (signatures_[ci] != 0) occurrence_list_ref[new_index++] = ci;
631 occurrence_list_ref.resize(new_index);
632 DCHECK_EQ(literal_to_clause_sizes_[lit], new_index);
642 const std::vector<Literal>& clause = clauses_[clause_index];
643 if (clause.empty())
return true;
644 DCHECK(std::is_sorted(clause.begin(), clause.end()));
646 LiteralIndex opposite_literal;
647 const Literal lit = FindLiteralWithShortestOccurrenceList(clause);
649 if (!ProcessClauseToSimplifyOthersUsingLiteral(clause_index, lit)) {
655 const LiteralIndex other_lit_index =
656 FindLiteralWithShortestOccurrenceListExcluding(clause, lit);
658 literal_to_clause_sizes_[other_lit_index] <
660 return ProcessClauseToSimplifyOthersUsingLiteral(clause_index,
665 bool something_removed =
false;
666 auto& occurrence_list_ref = literal_to_clauses_[lit.
NegatedIndex()];
667 const uint64_t clause_signature = signatures_[clause_index];
669 const uint64_t ci_signature = signatures_[ci];
670 DCHECK_EQ(ci_signature, ComputeSignatureOfClauseVariables(ci));
671 if (ci_signature == 0)
continue;
677 if ((clause_signature & ~ci_signature) == 0 &&
679 &num_inspected_literals_)) {
681 if (clauses_[ci].empty())
return false;
684 signatures_[ci] = ComputeSignatureOfClauseVariables(ci);
686 if (!in_clause_to_process_[ci]) {
687 in_clause_to_process_[ci] =
true;
688 clause_to_process_.push_back(ci);
690 something_removed =
true;
693 occurrence_list_ref[new_index] = ci;
696 occurrence_list_ref.resize(new_index);
697 literal_to_clause_sizes_[lit.
NegatedIndex()] = new_index;
698 if (something_removed) {
705void SatPresolver::RemoveAllClauseContaining(
Literal x,
706 bool register_for_postsolve) {
707 if (register_for_postsolve) {
709 if (!clauses_[
i].empty()) {
710 RemoveAndRegisterForPostsolve(
i, x);
715 if (!clauses_[
i].empty()) Remove(
i);
719 literal_to_clause_sizes_[
x] = 0;
723 const int s1 = literal_to_clause_sizes_[x];
724 const int s2 = literal_to_clause_sizes_[x.NegatedIndex()];
728 if (s1 == 0 && s2 == 0)
return false;
732 if (s1 > 1 && s2 > 1 && s1 * s2 > parameters_.presolve_bve_threshold()) {
738 int64_t sum_for_x = 0;
739 int64_t sum_for_not_x = 0;
740 const int clause_weight = parameters_.presolve_bve_clause_weight();
742 if (!clauses_[
i].empty()) {
744 sum_for_x += clauses_[
i].size();
747 for (
ClauseIndex i : literal_to_clauses_[x.NegatedIndex()]) {
748 if (!clauses_[
i].empty()) {
750 sum_for_not_x += clauses_[
i].size();
753 const int64_t threshold =
754 clause_weight * num_clauses + sum_for_x + sum_for_not_x;
757 if (s1 < s2) x = x.Negated();
762 if (clauses_[
i].empty())
continue;
763 bool no_resolvant =
true;
764 for (
ClauseIndex j : literal_to_clauses_[x.NegatedIndex()]) {
765 if (clauses_[j].empty())
continue;
768 no_resolvant =
false;
769 size += clause_weight + rs;
772 if (size > threshold)
return false;
775 if (no_resolvant && parameters_.presolve_blocked_clause()) {
788 RemoveAndRegisterForPostsolve(
i, x);
795 std::vector<Literal> temp;
797 if (clauses_[
i].empty())
continue;
798 for (
ClauseIndex j : literal_to_clauses_[x.NegatedIndex()]) {
799 if (clauses_[j].empty())
continue;
801 AddClauseInternal(&temp);
810 bool push_x_for_postsolve =
true;
811 bool push_not_x_for_postsolve =
true;
812 if (parameters_.filter_sat_postsolve_clauses()) {
813 if (sum_for_x <= sum_for_not_x) {
814 push_not_x_for_postsolve =
false;
816 push_x_for_postsolve =
false;
819 RemoveAllClauseContaining(x, push_x_for_postsolve);
820 RemoveAllClauseContaining(x.Negated(), push_not_x_for_postsolve);
827void SatPresolver::Remove(ClauseIndex ci) {
828 num_deleted_literals_since_last_cleanup_ += clauses_[ci].size();
830 for (
const Literal e : clauses_[ci]) {
831 literal_to_clause_sizes_[e]--;
832 UpdatePriorityQueue(e.Variable());
833 UpdateBvaPriorityQueue(
Literal(e.Variable(),
true).
Index());
834 UpdateBvaPriorityQueue(
Literal(e.Variable(),
false).
Index());
839void SatPresolver::RemoveAndRegisterForPostsolve(ClauseIndex ci, Literal x) {
840 postsolver_->
Add(x, clauses_[ci]);
844Literal SatPresolver::FindLiteralWithShortestOccurrenceList(
845 absl::Span<const Literal> clause) {
846 DCHECK(!clause.empty());
847 Literal result = clause.front();
848 int best_size = literal_to_clause_sizes_[result];
849 for (
const Literal l : clause) {
850 const int size = literal_to_clause_sizes_[l];
851 if (size < best_size) {
859LiteralIndex SatPresolver::FindLiteralWithShortestOccurrenceListExcluding(
860 const std::vector<Literal>& clause,
Literal to_exclude) {
861 DCHECK(!clause.empty());
863 int num_occurrences = std::numeric_limits<int>::max();
864 for (
const Literal l : clause) {
865 if (l == to_exclude)
continue;
866 if (literal_to_clause_sizes_[l] < num_occurrences) {
868 num_occurrences = literal_to_clause_sizes_[l];
874void SatPresolver::UpdatePriorityQueue(BooleanVariable var) {
875 if (var_pq_elements_.empty())
return;
876 PQElement* element = &var_pq_elements_[var];
877 element->weight = literal_to_clause_sizes_[Literal(var,
true)] +
878 literal_to_clause_sizes_[Literal(var,
false)];
879 if (var_pq_.Contains(element)) {
880 var_pq_.NoteChangedPriority(element);
882 var_pq_.Add(element);
886void SatPresolver::InitializePriorityQueue() {
888 var_pq_elements_.resize(num_vars);
889 for (BooleanVariable var(0); var < num_vars; ++var) {
890 PQElement* element = &var_pq_elements_[var];
891 element->variable = var;
892 element->weight = literal_to_clause_sizes_[Literal(var,
true)] +
893 literal_to_clause_sizes_[Literal(var,
false)];
894 var_pq_.Add(element);
898void SatPresolver::UpdateBvaPriorityQueue(LiteralIndex lit) {
899 if (bva_pq_elements_.empty())
return;
900 DCHECK_LT(lit, bva_pq_elements_.size());
901 BvaPqElement* element = &bva_pq_elements_[lit.value()];
902 element->weight = literal_to_clause_sizes_[lit];
903 if (bva_pq_.Contains(element)) {
904 bva_pq_.NoteChangedPriority(element);
908void SatPresolver::AddToBvaPriorityQueue(LiteralIndex lit) {
909 if (bva_pq_elements_.empty())
return;
910 DCHECK_LT(lit, bva_pq_elements_.size());
911 BvaPqElement* element = &bva_pq_elements_[lit.value()];
912 element->weight = literal_to_clause_sizes_[lit];
913 DCHECK(!bva_pq_.Contains(element));
914 if (element->weight > 2) bva_pq_.Add(element);
917void SatPresolver::InitializeBvaPriorityQueue() {
920 bva_pq_elements_.assign(num_literals, BvaPqElement());
921 for (LiteralIndex lit(0); lit < num_literals; ++lit) {
922 BvaPqElement* element = &bva_pq_elements_[lit.value()];
923 element->literal = lit;
924 element->weight = literal_to_clause_sizes_[lit];
928 if (element->weight > 2) bva_pq_.Add(element);
932void SatPresolver::DisplayStats(
double elapsed_seconds) {
933 int num_literals = 0;
935 int num_singleton_clauses = 0;
936 for (
const std::vector<Literal>& c : clauses_) {
938 if (
c.size() == 1) ++num_singleton_clauses;
940 num_literals +=
c.size();
943 int num_one_side = 0;
944 int num_simple_definition = 0;
946 for (BooleanVariable var(0); var <
NumVariables(); ++var) {
947 const int s1 = literal_to_clause_sizes_[Literal(var,
true)];
948 const int s2 = literal_to_clause_sizes_[Literal(var,
false)];
949 if (s1 == 0 && s2 == 0)
continue;
952 if (s1 == 0 || s2 == 0) {
954 }
else if (s1 == 1 || s2 == 1) {
955 num_simple_definition++;
958 SOLVER_LOG(logger_,
"[SAT presolve] [", elapsed_seconds,
"s]",
961 " vars:",
FormatCounter(num_vars),
" one_side_vars:", num_one_side,
963 " singleton_clauses:",
FormatCounter(num_singleton_clauses));
967 LiteralIndex* opposite_literal,
968 int64_t* num_inspected_literals) {
969 if (
b->size() < a.size())
return false;
970 DCHECK(std::is_sorted(a.begin(), a.end()));
971 DCHECK(std::is_sorted(
b->begin(),
b->end()));
972 if (num_inspected_literals !=
nullptr) {
973 *num_inspected_literals += a.size();
974 *num_inspected_literals +=
b->size();
977 *opposite_literal = LiteralIndex(-1);
980 std::vector<Literal>::const_iterator ia = a.begin();
981 std::vector<Literal>::const_iterator ib =
b->begin();
982 std::vector<Literal>::const_iterator to_remove;
986 int size_diff =
b->size() - a.size();
987 while (ia != a.end() ) {
991 }
else if (*ia == ib->Negated()) {
993 if (num_diff > 1)
return false;
997 }
else if (*ia < *ib) {
1004 if (--size_diff < 0)
return false;
1007 if (num_diff == 1) {
1008 *opposite_literal = to_remove->Index();
1009 b->erase(to_remove);
1015 const std::vector<Literal>&
b,
Literal l) {
1016 DCHECK_EQ(
b.size(), a.size());
1017 DCHECK(std::is_sorted(a.begin(), a.end()));
1018 DCHECK(std::is_sorted(
b.begin(),
b.end()));
1020 std::vector<Literal>::const_iterator ia = a.begin();
1021 std::vector<Literal>::const_iterator ib =
b.begin();
1022 while (ia != a.end() && ib !=
b.end()) {
1026 }
else if (*ia < *ib) {
1035 result = (*ib).Index();
1041 if (ib !=
b.end()) {
1043 result = (*ib).Index();
1049 const std::vector<Literal>&
b,
1050 std::vector<Literal>* out) {
1051 DCHECK(std::is_sorted(a.begin(), a.end()));
1052 DCHECK(std::is_sorted(
b.begin(),
b.end()));
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())) {
1059 out->push_back(*ia);
1062 }
else if (*ia == ib->Negated()) {
1063 if (*ia != x)
return false;
1064 DCHECK_EQ(*ib, x.Negated());
1067 }
else if (*ia < *ib) {
1068 out->push_back(*ia);
1071 out->push_back(*ib);
1077 out->insert(out->end(), ia, a.end());
1078 out->insert(out->end(), ib,
b.end());
1084 const std::vector<Literal>&
b) {
1085 DCHECK(std::is_sorted(a.begin(), a.end()));
1086 DCHECK(std::is_sorted(
b.begin(),
b.end()));
1088 int size =
static_cast<int>(a.size() +
b.size()) - 2;
1089 std::vector<Literal>::const_iterator ia = a.begin();
1090 std::vector<Literal>::const_iterator ib =
b.begin();
1091 while ((ia != a.end()) && (ib !=
b.end())) {
1096 }
else if (*ia == ib->Negated()) {
1097 if (*ia != x)
return -1;
1098 DCHECK_EQ(*ib, x.Negated());
1101 }
else if (*ia < *ib) {
1122 deterministic_time_limit(solver->deterministic_time() +
1123 deterministic_time_limit) {}
1133 scratchpad_.clear();
1134 solver_->Backtrack(0);
1141 if (solver_->deterministic_time() > deterministic_time_limit) {
1146 if (!solver_->Assignment().LiteralIsAssigned(l)) {
1147 const int trail_index = solver_->LiteralTrail().Index();
1148 solver_->EnqueueDecisionAndBackjumpOnConflict(l);
1149 if (solver_->CurrentDecisionLevel() > 0) {
1151 for (
int i = trail_index + 1;
i < solver_->LiteralTrail().Index();
1153 scratchpad_.push_back(solver_->LiteralTrail()[
i].Index().value());
1161 mutable std::vector<int32_t> scratchpad_;
1163 const double deterministic_time_limit;
1180 std::vector<std::vector<int32_t>> scc;
1193 for (
const std::vector<int32_t>& component : scc) {
1194 if (component.size() > 1) {
1195 if (mapping->empty()) mapping->
resize(size, LiteralIndex(-1));
1196 const Literal representative((LiteralIndex(component[0])));
1197 for (
int i = 1;
i < component.size(); ++
i) {
1198 const Literal l((LiteralIndex(component[
i])));
1210 representative.
Index().value()))),
1219 if (!mapping->empty()) {
1229 for (LiteralIndex
i(0);
i < size; ++
i) {
1239 for (LiteralIndex
i(0);
i < size; ++
i) {
1241 (*mapping)[
i] = rep;
1256 }
else if (rep !=
i) {
1263 if (logger !=
nullptr) {
1265 logger,
"[Pure SAT probing] fixed ",
1271 const bool log_info =
1273 LOG_IF(INFO, log_info) <<
"Probing. fixed " << num_already_fixed_vars
1276 num_already_fixed_vars
1277 <<
" equiv " << num_equiv / 2 <<
" total "
1279 <<
" wtime: " << timer.
Get();
int MergePartsOf(int node1, int node2)
int GetRootAndCompressPath(int node)
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
PropagationGraph(double deterministic_time_limit, SatSolver *solver)
bool log_search_progress() const
double presolve_probing_deterministic_time_limit() const
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)
bool ProcessClauseToSimplifyOthers(ClauseIndex clause_index)
util_intops::StrongVector< BooleanVariable, BooleanVariable > VariableMapping() const
void AddClause(absl::Span< const Literal > clause)
void LoadProblemIntoSatSolver(SatSolver *solver)
bool AddProblemClause(absl::Span< const Literal > literals, bool shared=false)
void Backtrack(int target_level)
const SatParameters & parameters() const
ABSL_MUST_USE_RESULT bool AddUnitClause(Literal true_literal)
const VariablesAssignment & Assignment() const
const Trail & LiteralTrail() const
void SetNumVariables(int num_variables)
bool VariableIsAssigned(BooleanVariable var) const
bool LiteralIsAssigned(Literal literal) const
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)
void ProbeAndFindEquivalentLiteral(SatSolver *solver, SatPostsolver *postsolver, util_intops::StrongVector< LiteralIndex, LiteralIndex > *mapping, SolverLogger *logger)
LiteralIndex DifferAtGivenLiteral(const std::vector< Literal > &a, const std::vector< Literal > &b, Literal l)
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)
Select next search node to expand Select next item_i to add this new search node to the search Generate a new search node where item_i is not in the knapsack Check validity of this new partial solution(using propagators) - If valid
std::string FormatCounter(int64_t num)
void FindStronglyConnectedComponents(NodeIndex num_nodes, const Graph &graph, SccOutput *components)
#define SOLVER_LOG(logger,...)