24#include "absl/container/inlined_vector.h"
25#include "absl/random/distributions.h"
26#include "absl/types/span.h"
36#include "ortools/sat/sat_parameters.pb.h"
49 clauses.emplace_back(clause.begin(), clause.end());
50 for (
int i = 0; i < clause.size(); ++i) {
60#define RETURN_IF_FALSE(f) \
61 if (!(f)) return false;
71 double probing_time = 0.0;
103 !implication_graph_->
IsDag()) {
109 !implication_graph_->
IsDag()) {
116 blocked_clause_simplifier_->
DoOneRound(log_round_info);
122 const double time_left =
124 if (time_left <= 0)
break;
126 probing_options.
log_info = log_round_info;
134 !implication_graph_->
IsDag()) {
146 <<
" num_fixed: " << trail_->
Index()
154 <<
" non-probing time: " << (
wall_timer.
Get() - probing_time);
166 double probing_time = 0.0;
170 if (total_dtime_ > 0.1 * start_dtime)
return true;
186 probing_options.
log_info = log_round_info;
207 blocked_clause_simplifier_->
DoOneRound(log_round_info);
214 <<
" num_fixed: " << trail_->
Index()
221 <<
" non-probing time: " << (
wall_timer.
Get() - probing_time);
227#undef RETURN_IF_FALSE
230 const int64_t new_num_fixed_variables = trail_->
Index();
231 return last_num_fixed_variables_ < new_num_fixed_variables;
235 const int64_t new_num_redundant_literals =
237 return last_num_redundant_literals_ < new_num_redundant_literals;
252 if (!implication_graph_->
IsDag()) {
258 if (use_transitive_reduction) {
285 const int64_t new_num_redundant_literals =
287 const int64_t new_num_fixed_variables = trail_->
Index();
288 if (last_num_redundant_literals_ == new_num_redundant_literals &&
289 last_num_fixed_variables_ == new_num_fixed_variables) {
292 last_num_fixed_variables_ = new_num_fixed_variables;
293 last_num_redundant_literals_ = new_num_redundant_literals;
299 int64_t num_removed_literals = 0;
300 int64_t num_inspected_literals = 0;
304 std::vector<Literal> new_clause;
307 const int num_literals(sat_solver_->
NumVariables() * 2);
313 bool removed =
false;
314 bool need_rewrite =
false;
317 for (
const Literal l : clause->AsSpan()) {
324 num_removed_literals += clause->size();
334 num_inspected_literals += clause->size();
335 if (removed || !need_rewrite)
continue;
336 num_inspected_literals += clause->size();
340 for (
const Literal l : clause->AsSpan()) {
347 num_removed_literals += clause->size();
351 marked[r.
Index()] =
true;
356 for (
const Literal l : new_clause) marked[l.Index()] =
false;
357 if (removed)
continue;
359 num_removed_literals += clause->
size() - new_clause.size();
366 const double dtime =
static_cast<double>(num_inspected_literals) * 1e-8;
368 LOG_IF(
INFO, log_info) <<
"Cleanup. num_removed_literals: "
369 << num_removed_literals <<
" dtime: " << dtime
383 int64_t num_subsumed_clauses = 0;
384 int64_t num_removed_literals = 0;
385 int64_t num_inspected_signatures = 0;
386 int64_t num_inspected_literals = 0;
390 std::vector<Literal> new_clause;
402 std::vector<SatClause*>
clauses =
408 const LiteralIndex num_literals(sat_solver_->
NumVariables() * 2);
414 num_literals.value());
417 std::vector<uint64_t> signatures(
clauses.size());
419 std::vector<Literal> candidates_for_removal;
420 for (
int clause_index = 0; clause_index <
clauses.size(); ++clause_index) {
427 if (num_inspected_literals + num_inspected_signatures > 1e9) {
442 uint64_t signature = 0;
445 marked.
Set(l.Index());
446 signature |= (uint64_t{1} << (l.Variable().value() % 64));
452 bool removed =
false;
453 candidates_for_removal.clear();
454 const uint64_t mask = ~signature;
456 num_inspected_signatures += one_watcher[l.Index()].
size();
457 for (
const int i : one_watcher[l.Index()]) {
458 if ((mask & signatures[i]) != 0)
continue;
460 bool subsumed =
true;
461 bool stengthen =
true;
463 num_inspected_literals +=
clauses[i]->size();
465 if (!marked[o.Index()]) {
468 to_remove = o.NegatedIndex();
476 ++num_subsumed_clauses;
477 num_removed_literals += clause->
size();
484 candidates_for_removal.push_back(
Literal(to_remove));
489 if (removed)
continue;
493 num_inspected_signatures += one_watcher[l.NegatedIndex()].
size();
494 for (
const int i : one_watcher[l.NegatedIndex()]) {
495 if ((mask & signatures[i]) != 0)
continue;
497 bool stengthen =
true;
498 num_inspected_literals +=
clauses[i]->size();
500 if (o == l.Negated())
continue;
501 if (!marked[o.Index()]) {
507 candidates_for_removal.push_back(l);
518 if (!candidates_for_removal.empty()) {
521 new_clause.push_back(l);
525 for (
const Literal l : new_clause) {
526 if (l == candidates_for_removal[0])
continue;
527 new_clause[new_size++] = l;
529 CHECK_EQ(new_size + 1, new_clause.size());
530 new_clause.resize(new_size);
532 num_removed_literals += clause->
size() - new_clause.size();
536 if (clause->
size() == 0)
continue;
541 signature |= (uint64_t{1} << (l.Variable().value() % 64));
562 if (one_watcher[l.Index()].
size() < min_size) {
563 min_size = one_watcher[l.Index()].
size();
564 min_literal = l.Index();
574 signatures[clause_index] = signature;
575 one_watcher[min_literal].
push_back(clause_index);
583 const double dtime =
static_cast<double>(num_inspected_signatures) * 1e-8 +
584 static_cast<double>(num_inspected_literals) * 5e-9;
586 LOG_IF(
INFO, log_info) <<
"Subsume. num_removed_literals: "
587 << num_removed_literals
588 <<
" num_subsumed: " << num_subsumed_clauses
589 <<
" dtime: " << dtime
599 num_subsumed_clauses_ = 0;
600 num_removed_literals_ = 0;
603 if (implication_graph_->
literal_size() == 0)
return true;
606 if (!stamps_are_already_computed_) {
615 stamps_are_already_computed_ =
false;
622 LOG_IF(
INFO, log_info) <<
"Stamping. num_removed_literals: "
623 << num_removed_literals_
624 <<
" num_subsumed: " << num_subsumed_clauses_
625 <<
" num_fixed: " << num_fixed_ <<
" dtime: " << dtime_
636 if (implication_graph_->
literal_size() == 0)
return true;
643 stamps_are_already_computed_ =
true;
649 <<
" num_fixed: " << num_fixed_ <<
" dtime: " << dtime_
658 for (LiteralIndex i(0); i < size; ++i) {
671 const auto& children_of_not_l =
673 if (children_of_not_l.empty())
continue;
674 for (
int num_tries = 0; num_tries < 10; ++num_tries) {
676 children_of_not_l[absl::Uniform<int>(*random_, 0,
677 children_of_not_l.size())]
679 if (implication_graph_->
IsRedundant(candidate))
continue;
680 if (i == candidate.
Index())
continue;
683 parents_[i] = candidate.
Index();
694 for (LiteralIndex i(0); i < size; ++i) {
695 if (parents_[i] == i)
continue;
696 sizes_[parents_[i]]++;
701 starts_[LiteralIndex(0)] = 0;
702 for (LiteralIndex i(1); i <= size; ++i) {
703 starts_[i] = starts_[i - 1] + sizes_[i - 1];
707 children_.resize(size);
708 for (LiteralIndex i(0); i < size; ++i) {
709 if (parents_[i] == i)
continue;
710 children_[starts_[parents_[i]]++] = i;
714 for (LiteralIndex i(0); i < size; ++i) {
715 starts_[i] -= sizes_[i];
719 CHECK_EQ(starts_[LiteralIndex(0)], 0);
720 for (LiteralIndex i(1); i <= size; ++i) {
721 CHECK_EQ(starts_[i], starts_[i - 1] + sizes_[i - 1]);
727 first_stamps_.
resize(size);
728 last_stamps_.
resize(size);
729 marked_.
assign(size,
false);
730 for (LiteralIndex i(0); i < size; ++i) {
731 if (parents_[i] != i)
continue;
733 const LiteralIndex tree_root = i;
734 dfs_stack_.push_back(i);
735 while (!dfs_stack_.empty()) {
736 const LiteralIndex top = dfs_stack_.back();
738 dfs_stack_.pop_back();
739 last_stamps_[top] = stamp++;
742 first_stamps_[top] = stamp++;
747 if (marked_[
Literal(top).NegatedIndex()] &&
748 first_stamps_[
Literal(top).NegatedIndex()] >=
749 first_stamps_[tree_root]) {
752 LiteralIndex lca = top;
753 while (first_stamps_[lca] > first_stamp) {
762 const int end = starts_[top + 1];
763 for (
int j = starts_[top]; j <
end; ++j) {
765 DCHECK(!marked_[children_[j]]);
766 dfs_stack_.push_back(children_[j]);
780 bool operator<(
const Entry& o)
const {
return start < o.start; }
782 std::vector<int> to_remove;
783 std::vector<Literal> new_clause;
784 std::vector<Entry> entries;
788 const auto span = clause->AsSpan();
789 if (span.empty())
continue;
798 for (
int i = 0; i < span.size(); ++i) {
804 entries.push_back({i,
false, first_stamps_[span[i].Index()],
805 last_stamps_[span[i].
Index()]});
806 entries.push_back({i,
true, first_stamps_[span[i].NegatedIndex()],
807 last_stamps_[span[i].NegatedIndex()]});
809 if (clause->empty())
continue;
812 if (!entries.empty()) {
813 const double n =
static_cast<double>(entries.size());
814 dtime_ += 1.5e-8 * n * std::log(n);
815 std::sort(entries.begin(), entries.end());
821 for (
const Entry& e : entries) {
822 if (e.end < top_entry.end) {
824 const Literal lhs = top_entry.is_negated ? span[top_entry.i].
Negated()
826 const Literal rhs = e.is_negated ? span[e.i].
Negated() : span[e.i];
829 if (top_entry.is_negated != e.is_negated) {
831 if (top_entry.i == e.i) {
833 if (top_entry.is_negated) {
842 span[top_entry.i].Negated())) {
845 to_remove.push_back(top_entry.i);
854 if (top_entry.is_negated) {
855 num_subsumed_clauses_++;
861 if (top_entry.is_negated) {
863 to_remove.push_back(e.i);
872 to_remove.push_back(top_entry.i);
880 if (clause->empty())
continue;
883 if (!to_remove.empty() || entries.size() < span.size()) {
886 int to_remove_index = 0;
887 for (
int i = 0; i < span.size(); ++i) {
888 if (to_remove_index < to_remove.size() &&
889 i == to_remove[to_remove_index]) {
898 new_clause.push_back(span[i]);
900 num_removed_literals_ += span.size() - new_clause.size();
914 num_blocked_clauses_ = 0;
915 num_inspected_literals_ = 0;
917 InitializeForNewRound();
919 while (!time_limit_->
LimitReached() && !queue_.empty()) {
920 const Literal l = queue_.front();
921 in_queue_[l.
Index()] =
false;
927 literal_to_clauses_.
clear();
929 dtime_ += 1e-8 * num_inspected_literals_;
932 LOG_IF(
INFO, log_info) <<
"Blocked clause. num_blocked_clauses: "
933 << num_blocked_clauses_ <<
" dtime: " << dtime_
937void BlockedClauseSimplifier::InitializeForNewRound() {
945 clauses_.push_back(c);
947 const int num_literals = clause_manager_->
literal_size();
951 in_queue_.
assign(num_literals,
true);
952 for (LiteralIndex l(0); l < num_literals; ++l) {
953 queue_.push_back(Literal(l));
956 marked_.
resize(num_literals);
958 std::all_of(marked_.
begin(), marked_.
end(), [](
bool b) { return !b; }));
962 literal_to_clauses_.
clear();
963 literal_to_clauses_.
resize(num_literals);
964 for (ClauseIndex i(0); i < clauses_.size(); ++i) {
965 for (
const Literal l : clauses_[i]->AsSpan()) {
966 literal_to_clauses_[l.Index()].
push_back(i);
968 num_inspected_literals_ += clauses_[i]->size();
972void BlockedClauseSimplifier::ProcessLiteral(Literal current_literal) {
974 if (implication_graph_->
IsRemoved(current_literal))
return;
989 const std::vector<Literal>& implications =
991 for (
const Literal l : implications) {
992 if (l == current_literal)
continue;
994 marked_[l.Index()] =
true;
1000 std::vector<ClauseIndex> clauses_to_process;
1001 for (
const ClauseIndex i : literal_to_clauses_[current_literal.Index()]) {
1002 if (clauses_[i]->empty())
continue;
1008 if (num_binary > 0) {
1009 if (clauses_[i]->size() <= num_binary)
continue;
1010 int num_with_negation_marked = 0;
1011 for (
const Literal l : clauses_[i]->AsSpan()) {
1012 if (l == current_literal)
continue;
1013 if (marked_[l.NegatedIndex()]) {
1014 ++num_with_negation_marked;
1017 num_inspected_literals_ += clauses_[i]->size();
1018 if (num_with_negation_marked < num_binary)
continue;
1020 clauses_to_process.push_back(i);
1024 for (
const Literal l : implications) {
1025 marked_[l.Index()] =
false;
1036 for (
const ClauseIndex i : clauses_to_process) {
1037 const auto c = clauses_[i]->AsSpan();
1038 if (ClauseIsBlocked(current_literal, c)) {
1045 for (
const Literal l : c) {
1046 if (!in_queue_[l.NegatedIndex()]) {
1047 in_queue_[l.NegatedIndex()] =
true;
1048 queue_.push_back(l.Negated());
1056 ++num_blocked_clauses_;
1063bool BlockedClauseSimplifier::ClauseIsBlocked(
1064 Literal current_literal, absl::Span<const Literal> clause) {
1065 bool is_blocked =
true;
1066 for (
const Literal l : clause) marked_[l.Index()] =
true;
1070 for (
const ClauseIndex i :
1071 literal_to_clauses_[current_literal.NegatedIndex()]) {
1072 if (clauses_[i]->empty())
continue;
1073 bool some_marked =
false;
1074 for (
const Literal l : clauses_[i]->AsSpan()) {
1076 ++num_inspected_literals_;
1078 if (l == current_literal.Negated())
continue;
1079 if (marked_[l.NegatedIndex()]) {
1090 for (
const Literal l : clause) marked_[l.Index()] =
false;
1099 num_inspected_literals_ = 0;
1100 num_eliminated_variables_ = 0;
1101 num_literals_diff_ = 0;
1102 num_clauses_diff_ = 0;
1103 num_simplifications_ = 0;
1104 num_blocked_clauses_ = 0;
1115 clauses_.push_back(c);
1117 const int num_literals = clause_manager_->
literal_size();
1118 const int num_variables = num_literals / 2;
1120 literal_to_clauses_.
clear();
1121 literal_to_clauses_.
resize(num_literals);
1122 literal_to_num_clauses_.
assign(num_literals, 0);
1123 for (ClauseIndex i(0); i < clauses_.size(); ++i) {
1124 for (
const Literal l : clauses_[i]->AsSpan()) {
1125 literal_to_clauses_[l.Index()].
push_back(i);
1126 literal_to_num_clauses_[l.Index()]++;
1128 num_inspected_literals_ += clauses_[i]->size();
1131 const int saved_trail_index = trail_->
Index();
1132 propagation_index_ = trail_->
Index();
1134 need_to_be_updated_.clear();
1135 in_need_to_be_updated_.
resize(num_variables);
1136 queue_.
Reserve(num_variables);
1137 for (BooleanVariable v(0); v < num_variables; ++v) {
1140 UpdatePriorityQueue(v);
1143 marked_.
resize(num_literals);
1145 std::all_of(marked_.
begin(), marked_.
end(), [](
bool b) { return !b; }));
1151 const BooleanVariable top = queue_.
Top().var;
1159 bool is_unsat =
false;
1160 if (!Propagate())
return false;
1162 if (!Propagate())
return false;
1164 if (is_unsat)
return false;
1166 if (!CrossProduct(top))
return false;
1168 for (
const BooleanVariable v : need_to_be_updated_) {
1169 in_need_to_be_updated_[v] =
false;
1172 if (v != top) UpdatePriorityQueue(v);
1174 in_need_to_be_updated_.
clear();
1175 need_to_be_updated_.clear();
1184 bool remove =
false;
1185 for (
const Literal l : c->AsSpan()) {
1195 literal_to_clauses_.
clear();
1196 literal_to_num_clauses_.
clear();
1198 dtime_ += 1e-8 * num_inspected_literals_;
1203 << trail_->
Index() - saved_trail_index
1204 <<
" num_simplified_literals: " << num_simplifications_
1205 <<
" num_blocked_clauses_: " << num_blocked_clauses_
1206 <<
" num_eliminations: " << num_eliminated_variables_
1207 <<
" num_literals_diff: " << num_literals_diff_
1208 <<
" num_clause_diff: " << num_clauses_diff_
1209 <<
" dtime: " << dtime_
1214bool BoundedVariableElimination::RemoveLiteralFromClause(
1216 num_literals_diff_ -= sat_clause->
size();
1220 literal_to_num_clauses_[l.Index()]--;
1224 num_clauses_diff_--;
1228 resolvant_.push_back(l);
1233 if (sat_clause->
empty()) {
1234 --num_clauses_diff_;
1235 for (
const Literal l : resolvant_) literal_to_num_clauses_[l.Index()]--;
1237 num_literals_diff_ += sat_clause->
size();
1242bool BoundedVariableElimination::Propagate() {
1243 for (; propagation_index_ < trail_->
Index(); ++propagation_index_) {
1245 if (!implication_graph_->
Propagate(trail_))
return false;
1247 const Literal l = (*trail_)[propagation_index_];
1248 for (
const ClauseIndex
index : literal_to_clauses_[l.Index()]) {
1249 if (clauses_[
index]->empty())
continue;
1250 num_clauses_diff_--;
1251 num_literals_diff_ -= clauses_[
index]->size();
1254 literal_to_clauses_[l.Index()].
clear();
1255 for (
const ClauseIndex
index : literal_to_clauses_[l.NegatedIndex()]) {
1256 if (clauses_[
index]->empty())
continue;
1257 if (!RemoveLiteralFromClause(l.Negated(), clauses_[
index]))
return false;
1259 literal_to_clauses_[l.NegatedIndex()].
clear();
1266int BoundedVariableElimination::NumClausesContaining(Literal l) {
1267 return literal_to_num_clauses_[l.Index()] +
1272void BoundedVariableElimination::UpdatePriorityQueue(BooleanVariable
var) {
1274 const int priority = -NumClausesContaining(Literal(
var,
true)) -
1275 NumClausesContaining(Literal(
var,
false));
1279 queue_.
Add({
var, priority});
1283void BoundedVariableElimination::DeleteClause(SatClause* sat_clause) {
1284 const auto clause = sat_clause->AsSpan();
1286 num_clauses_diff_--;
1287 num_literals_diff_ -= clause.size();
1290 for (
const Literal l : clause) {
1291 literal_to_num_clauses_[l.Index()]--;
1292 if (!in_need_to_be_updated_[l.Variable()]) {
1293 in_need_to_be_updated_[l.Variable()] =
true;
1294 need_to_be_updated_.push_back(l.Variable());
1302void BoundedVariableElimination::DeleteAllClausesContaining(Literal
literal) {
1303 for (
const ClauseIndex i : literal_to_clauses_[
literal.Index()]) {
1304 const auto clause = clauses_[i]->AsSpan();
1305 if (clause.empty())
continue;
1307 DeleteClause(clauses_[i]);
1312void BoundedVariableElimination::AddClause(absl::Span<const Literal> clause) {
1314 if (pt ==
nullptr)
return;
1316 num_clauses_diff_++;
1317 num_literals_diff_ += clause.size();
1319 const ClauseIndex
index(clauses_.size());
1320 clauses_.push_back(pt);
1321 for (
const Literal l : clause) {
1322 literal_to_num_clauses_[l.Index()]++;
1324 if (!in_need_to_be_updated_[l.Variable()]) {
1325 in_need_to_be_updated_[l.Variable()] =
true;
1326 need_to_be_updated_.push_back(l.Variable());
1331template <
bool score_only,
bool with_binary_only>
1332bool BoundedVariableElimination::ResolveAllClauseContaining(Literal lit) {
1333 const int clause_weight = parameters_.presolve_bve_clause_weight();
1335 const std::vector<Literal>& implications =
1337 auto& clause_containing_lit = literal_to_clauses_[lit.Index()];
1338 for (
int i = 0; i < clause_containing_lit.size(); ++i) {
1339 const ClauseIndex clause_index = clause_containing_lit[i];
1340 const auto clause = clauses_[clause_index]->AsSpan();
1341 if (clause.empty())
continue;
1343 if (!score_only) resolvant_.clear();
1344 for (
const Literal l : clause) {
1345 if (!score_only && l != lit) resolvant_.push_back(l);
1346 marked_[l.Index()] =
true;
1348 DCHECK(marked_[lit.Index()]);
1349 num_inspected_literals_ += clause.size() + implications.size();
1353 bool clause_can_be_simplified =
false;
1354 const int64_t saved_score = new_score_;
1357 for (
const Literal l : implications) {
1359 if (marked_[l.NegatedIndex()])
continue;
1360 if (marked_[l.Index()]) {
1361 clause_can_be_simplified =
true;
1365 new_score_ += clause_weight + clause.size();
1367 resolvant_.push_back(l);
1368 AddClause(resolvant_);
1369 resolvant_.pop_back();
1375 if (!with_binary_only && !clause_can_be_simplified) {
1376 auto& clause_containing_not_lit = literal_to_clauses_[lit.NegatedIndex()];
1377 for (
int j = 0; j < clause_containing_not_lit.size(); ++j) {
1378 if (score_only && new_score_ > score_threshold_)
break;
1379 const ClauseIndex other_index = clause_containing_not_lit[j];
1380 const auto other = clauses_[other_index]->AsSpan();
1381 if (other.empty())
continue;
1382 bool trivial =
false;
1384 for (
const Literal l : other) {
1386 ++num_inspected_literals_;
1387 if (l == lit.Negated())
continue;
1388 if (marked_[l.NegatedIndex()]) {
1392 if (!marked_[l.Index()]) {
1394 if (!score_only) resolvant_.push_back(l);
1398 if (!score_only) resolvant_.resize(resolvant_.size() - extra_size);
1404 if (score_only && clause.size() + extra_size <= other.size()) {
1410 if (
false)
DCHECK_EQ(clause.size() + extra_size, other.size());
1411 ++num_simplifications_;
1415 score_threshold_ -= clause_weight + other.size();
1417 if (extra_size == 0) {
1421 DeleteClause(clauses_[other_index]);
1423 if (!RemoveLiteralFromClause(lit.Negated(),
1424 clauses_[other_index])) {
1428 clause_containing_not_lit.back());
1429 clause_containing_not_lit.pop_back();
1435 if (extra_size == 0) {
1436 clause_can_be_simplified =
true;
1441 if (clause.size() - 1 + extra_size > 100) {
1442 new_score_ = score_threshold_ + 1;
1446 new_score_ += clause_weight + clause.size() - 1 + extra_size;
1448 AddClause(resolvant_);
1449 resolvant_.resize(resolvant_.size() - extra_size);
1456 for (
const Literal l : clause) marked_[l.Index()] =
false;
1459 if (clause_can_be_simplified) {
1460 ++num_simplifications_;
1463 new_score_ = saved_score;
1464 score_threshold_ -= clause_weight + clause.size();
1466 if (!RemoveLiteralFromClause(lit, clauses_[clause_index]))
return false;
1467 std::swap(clause_containing_lit[i], clause_containing_lit.back());
1468 clause_containing_lit.pop_back();
1472 if (score_only && new_score_ > score_threshold_)
return true;
1484 if (score_only && !with_binary_only && !clause_can_be_simplified &&
1485 new_score_ == saved_score) {
1486 ++num_blocked_clauses_;
1487 score_threshold_ -= clause_weight + clause.size();
1489 DeleteClause(clauses_[clause_index]);
1495bool BoundedVariableElimination::CrossProduct(BooleanVariable
var) {
1498 const Literal lit(
var,
true);
1499 const Literal not_lit(
var,
false);
1501 const int s1 = NumClausesContaining(lit);
1502 const int s2 = NumClausesContaining(not_lit);
1503 if (s1 == 0 && s2 == 0)
return true;
1504 if (s1 > 0 && s2 == 0) {
1505 num_eliminated_variables_++;
1507 DeleteAllClausesContaining(lit);
1510 if (s1 == 0 && s2 > 0) {
1511 num_eliminated_variables_++;
1513 DeleteAllClausesContaining(not_lit);
1521 num_eliminated_variables_++;
1528 if (s1 > 1 && s2 > 1 && s1 * s2 > parameters_.presolve_bve_threshold()) {
1541 const int clause_weight = parameters_.presolve_bve_clause_weight();
1545 (clause_weight + 2);
1546 for (
const ClauseIndex i : literal_to_clauses_[lit.Index()]) {
1547 const auto c = clauses_[i]->AsSpan();
1548 if (!c.empty()) score += clause_weight + c.size();
1550 for (
const ClauseIndex i : literal_to_clauses_[not_lit.Index()]) {
1551 const auto c = clauses_[i]->AsSpan();
1552 if (!c.empty()) score += clause_weight + c.size();
1563 score_threshold_ = score;
1565 (clause_weight + 2);
1566 if (new_score_ > score_threshold_)
return true;
1567 if (!ResolveAllClauseContaining<
true,
1571 if (new_score_ > score_threshold_)
return true;
1572 if (!ResolveAllClauseContaining<
true,
1576 if (new_score_ > score_threshold_)
return true;
1579 if (new_score_ > 0) {
1580 if (!ResolveAllClauseContaining<
false,
1584 if (!ResolveAllClauseContaining<
false,
1590 ++num_eliminated_variables_;
1592 DeleteAllClausesContaining(lit);
1593 DeleteAllClausesContaining(not_lit);
#define LOG_IF(severity, condition)
#define DCHECK_NE(val1, val2)
#define CHECK_EQ(val1, val2)
#define CHECK_NE(val1, val2)
#define DCHECK(condition)
#define DCHECK_EQ(val1, val2)
void assign(size_type n, const value_type &val)
void resize(size_type new_size)
void push_back(const value_type &x)
bool Contains(int index) const
void ChangePriority(Element element)
void Add(Element element)
void Set(IntegerType index)
bool LimitReached()
Returns true when the external limit is true, or the deterministic time is over the deterministic lim...
double GetElapsedDeterministicTime() const
Returns the elapsed deterministic time since the construction of this object.
void AdvanceDeterministicTime(double deterministic_duration)
Advances the deterministic time.
int64_t NumImplicationOnVariableRemoval(BooleanVariable var)
bool Propagate(Trail *trail) final
bool ComputeTransitiveReduction(bool log_info=false)
void RemoveBooleanVariable(BooleanVariable var, std::deque< std::vector< Literal > > *postsolve_clauses)
Literal RepresentativeOf(Literal l) const
int64_t num_redundant_literals() const
const std::vector< Literal > & DirectImplications(Literal literal)
bool IsRedundant(Literal l) const
bool DetectEquivalences(bool log_info=false)
void CleanupAllRemovedVariables()
bool FindFailedLiteralAroundVar(BooleanVariable var, bool *is_unsat)
void RemoveFixedVariables()
bool IsRemoved(Literal l) const
int64_t num_implications() const
int64_t literal_size() const
int DirectImplicationsEstimatedSize(Literal literal) const
void DoOneRound(bool log_info)
bool DoOneRound(bool log_info)
bool PresolveLoop(SatPresolveOptions options)
bool MoreFixedVariableToClean() const
bool RemoveFixedAndEquivalentVariables(bool log_info)
bool LevelZeroPropagate()
bool MoreRedundantVariableToClean() const
bool SubsumeAndStrenghtenRound(bool log_info)
bool DetectEquivalencesAndStamp(bool use_transitive_reduction, bool log_info)
LiteralIndex NegatedIndex() const
LiteralIndex Index() const
ABSL_MUST_USE_RESULT bool InprocessingFixLiteral(Literal true_literal)
void InprocessingRemoveClause(SatClause *clause)
SatClause * InprocessingAddClause(absl::Span< const Literal > new_clause)
bool IsRemovable(SatClause *const clause) const
ABSL_MUST_USE_RESULT bool InprocessingRewriteClause(SatClause *clause, absl::Span< const Literal > new_clause)
int64_t num_watched_clauses() const
const std::vector< SatClause * > & AllClausesInCreationOrder() const
void DeleteRemovedClauses()
int64_t literal_size() const
absl::Span< const Literal > AsSpan() const
void MaybeEnablePhaseSaving(bool save_phase)
void MinimizeSomeClauses(int decisions_budget)
int CurrentDecisionLevel() const
bool DoOneRound(bool log_info)
bool ComputeStampsForNextRound(bool log_info)
bool ImplicationIsInTree(Literal a, Literal b) const
void SampleTreeAndFillParent()
bool LiteralIsAssigned(Literal literal) const
bool VariableIsAssigned(BooleanVariable var) const
bool LiteralIsTrue(Literal literal) const
bool LiteralIsFalse(Literal literal) const
SharedClausesManager * clauses
void STLSortAndRemoveDuplicates(T *v, const LessFunc &less_func)
void swap(IdMap< K, V > &a, IdMap< K, V > &b)
const LiteralIndex kNoLiteralIndex(-1)
bool FailedLiteralProbingRound(ProbingOptions options, Model *model)
Collection of objects used to extend the Constraint Solver library.
#define RETURN_IF_FALSE(f)
std::optional< int64_t > end
std::deque< std::vector< Literal > > clauses
void AddClauseWithSpecialLiteral(Literal literal, absl::Span< const Literal > clause)
double deterministic_limit
bool extract_binary_clauses
bool use_transitive_reduction
bool extract_binary_clauses_in_probing
double deterministic_time_limit
#define VLOG_IS_ON(verboselevel)