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()) {
144 LOG_IF(INFO, log_info)
146 <<
" num_fixed: " << trail_->
Index()
154 <<
" non-probing time: " << (
wall_timer.
Get() - probing_time);
167 double probing_time = 0.0;
171 if (total_dtime_ > 0.1 * start_dtime)
return true;
187 probing_options.
log_info = log_round_info;
208 blocked_clause_simplifier_->
DoOneRound(log_round_info);
213 LOG_IF(INFO, log_info)
215 <<
" num_fixed: " << trail_->
Index()
222 <<
" non-probing time: " << (
wall_timer.
Get() - probing_time);
228 #undef RETURN_IF_FALSE
231 const int64_t new_num_fixed_variables = trail_->
Index();
232 return last_num_fixed_variables_ < new_num_fixed_variables;
236 const int64_t new_num_redundant_literals =
238 return last_num_redundant_literals_ < new_num_redundant_literals;
253 if (!implication_graph_->
IsDag()) {
259 if (use_transitive_reduction) {
286 const int64_t new_num_redundant_literals =
288 const int64_t new_num_fixed_variables = trail_->
Index();
289 if (last_num_redundant_literals_ == new_num_redundant_literals &&
290 last_num_fixed_variables_ == new_num_fixed_variables) {
293 last_num_fixed_variables_ = new_num_fixed_variables;
294 last_num_redundant_literals_ = new_num_redundant_literals;
300 int64_t num_removed_literals = 0;
301 int64_t num_inspected_literals = 0;
305 std::vector<Literal> new_clause;
308 const int num_literals(sat_solver_->
NumVariables() * 2);
314 bool removed =
false;
315 bool need_rewrite =
false;
318 for (
const Literal l : clause->AsSpan()) {
325 num_removed_literals += clause->size();
335 num_inspected_literals += clause->size();
336 if (removed || !need_rewrite)
continue;
337 num_inspected_literals += clause->size();
341 for (
const Literal l : clause->AsSpan()) {
348 num_removed_literals += clause->size();
352 marked[r.
Index()] =
true;
357 for (
const Literal l : new_clause) marked[l.Index()] =
false;
358 if (removed)
continue;
360 num_removed_literals += clause->
size() - new_clause.size();
367 const double dtime =
static_cast<double>(num_inspected_literals) * 1e-8;
369 LOG_IF(INFO, log_info) <<
"Cleanup. num_removed_literals: "
370 << num_removed_literals <<
" dtime: " << dtime
384 int64_t num_subsumed_clauses = 0;
385 int64_t num_removed_literals = 0;
386 int64_t num_inspected_signatures = 0;
387 int64_t num_inspected_literals = 0;
391 std::vector<Literal> new_clause;
403 std::vector<SatClause*>
clauses =
409 const LiteralIndex num_literals(sat_solver_->
NumVariables() * 2);
415 num_literals.value());
418 std::vector<uint64_t> signatures(
clauses.size());
420 std::vector<Literal> candidates_for_removal;
421 for (
int clause_index = 0; clause_index <
clauses.size(); ++clause_index) {
428 if (num_inspected_literals + num_inspected_signatures > 1e9) {
443 uint64_t signature = 0;
446 marked.
Set(l.Index());
447 signature |= (uint64_t{1} << (l.Variable().value() % 64));
453 bool removed =
false;
454 candidates_for_removal.clear();
455 const uint64_t mask = ~signature;
457 num_inspected_signatures += one_watcher[l.Index()].
size();
458 for (
const int i : one_watcher[l.Index()]) {
459 if ((mask & signatures[i]) != 0)
continue;
461 bool subsumed =
true;
462 bool stengthen =
true;
464 num_inspected_literals +=
clauses[i]->size();
466 if (!marked[o.Index()]) {
469 to_remove = o.NegatedIndex();
477 ++num_subsumed_clauses;
478 num_removed_literals += clause->
size();
485 candidates_for_removal.push_back(
Literal(to_remove));
490 if (removed)
continue;
494 num_inspected_signatures += one_watcher[l.NegatedIndex()].
size();
495 for (
const int i : one_watcher[l.NegatedIndex()]) {
496 if ((mask & signatures[i]) != 0)
continue;
498 bool stengthen =
true;
499 num_inspected_literals +=
clauses[i]->size();
501 if (o == l.Negated())
continue;
502 if (!marked[o.Index()]) {
508 candidates_for_removal.push_back(l);
519 if (!candidates_for_removal.empty()) {
522 new_clause.push_back(l);
526 for (
const Literal l : new_clause) {
527 if (l == candidates_for_removal[0])
continue;
528 new_clause[new_size++] = l;
530 CHECK_EQ(new_size + 1, new_clause.size());
531 new_clause.resize(new_size);
533 num_removed_literals += clause->
size() - new_clause.size();
537 if (clause->
size() == 0)
continue;
542 signature |= (uint64_t{1} << (l.Variable().value() % 64));
563 if (one_watcher[l.Index()].
size() < min_size) {
564 min_size = one_watcher[l.Index()].
size();
565 min_literal = l.Index();
575 signatures[clause_index] = signature;
576 one_watcher[min_literal].
push_back(clause_index);
584 const double dtime =
static_cast<double>(num_inspected_signatures) * 1e-8 +
585 static_cast<double>(num_inspected_literals) * 5e-9;
587 LOG_IF(INFO, log_info) <<
"Subsume. num_removed_literals: "
588 << num_removed_literals
589 <<
" num_subsumed: " << num_subsumed_clauses
590 <<
" dtime: " << dtime
600 num_subsumed_clauses_ = 0;
601 num_removed_literals_ = 0;
604 if (implication_graph_->
literal_size() == 0)
return true;
607 if (!stamps_are_already_computed_) {
616 stamps_are_already_computed_ =
false;
623 LOG_IF(INFO, log_info) <<
"Stamping. num_removed_literals: "
624 << num_removed_literals_
625 <<
" num_subsumed: " << num_subsumed_clauses_
626 <<
" num_fixed: " << num_fixed_ <<
" dtime: " << dtime_
637 if (implication_graph_->
literal_size() == 0)
return true;
644 stamps_are_already_computed_ =
true;
649 LOG_IF(INFO, log_info) <<
"Prestamping."
650 <<
" num_fixed: " << num_fixed_ <<
" dtime: " << dtime_
657 CHECK(implication_graph_->
IsDag());
659 for (LiteralIndex i(0); i < size; ++i) {
672 const auto& children_of_not_l =
674 if (children_of_not_l.empty())
continue;
675 for (
int num_tries = 0; num_tries < 10; ++num_tries) {
677 children_of_not_l[absl::Uniform<int>(*random_, 0,
678 children_of_not_l.size())]
680 if (implication_graph_->
IsRedundant(candidate))
continue;
681 if (i == candidate.
Index())
continue;
684 parents_[i] = candidate.
Index();
695 for (LiteralIndex i(0); i < size; ++i) {
696 if (parents_[i] == i)
continue;
697 sizes_[parents_[i]]++;
702 starts_[LiteralIndex(0)] = 0;
703 for (LiteralIndex i(1); i <= size; ++i) {
704 starts_[i] = starts_[i - 1] + sizes_[i - 1];
708 children_.resize(size);
709 for (LiteralIndex i(0); i < size; ++i) {
710 if (parents_[i] == i)
continue;
711 children_[starts_[parents_[i]]++] = i;
715 for (LiteralIndex i(0); i < size; ++i) {
716 starts_[i] -= sizes_[i];
720 CHECK_EQ(starts_[LiteralIndex(0)], 0);
721 for (LiteralIndex i(1); i <= size; ++i) {
722 CHECK_EQ(starts_[i], starts_[i - 1] + sizes_[i - 1]);
728 first_stamps_.
resize(size);
729 last_stamps_.
resize(size);
730 marked_.
assign(size,
false);
731 for (LiteralIndex i(0); i < size; ++i) {
732 if (parents_[i] != i)
continue;
734 const LiteralIndex tree_root = i;
735 dfs_stack_.push_back(i);
736 while (!dfs_stack_.empty()) {
737 const LiteralIndex top = dfs_stack_.back();
739 dfs_stack_.pop_back();
740 last_stamps_[top] =
stamp++;
743 first_stamps_[top] =
stamp++;
748 if (marked_[
Literal(top).NegatedIndex()] &&
749 first_stamps_[
Literal(top).NegatedIndex()] >=
750 first_stamps_[tree_root]) {
753 LiteralIndex lca = top;
754 while (first_stamps_[lca] > first_stamp) {
763 const int end = starts_[top + 1];
764 for (
int j = starts_[top]; j <
end; ++j) {
765 DCHECK_NE(top, children_[j]);
766 DCHECK(!marked_[children_[j]]);
767 dfs_stack_.push_back(children_[j]);
771 DCHECK_EQ(
stamp, 2 * size);
781 bool operator<(
const Entry& o)
const {
return start < o.start; }
783 std::vector<int> to_remove;
784 std::vector<Literal> new_clause;
785 std::vector<Entry> entries;
789 const auto span = clause->AsSpan();
790 if (span.empty())
continue;
799 for (
int i = 0; i < span.size(); ++i) {
805 entries.push_back({i,
false, first_stamps_[span[i].Index()],
806 last_stamps_[span[i].
Index()]});
807 entries.push_back({i,
true, first_stamps_[span[i].NegatedIndex()],
808 last_stamps_[span[i].NegatedIndex()]});
810 if (clause->empty())
continue;
813 if (!entries.empty()) {
814 const double n =
static_cast<double>(entries.size());
815 dtime_ += 1.5e-8 * n * std::log(n);
816 std::sort(entries.begin(), entries.end());
822 for (
const Entry& e : entries) {
823 if (e.end < top_entry.end) {
825 const Literal lhs = top_entry.is_negated ? span[top_entry.i].
Negated()
827 const Literal rhs = e.is_negated ? span[e.i].
Negated() : span[e.i];
830 if (top_entry.is_negated != e.is_negated) {
832 if (top_entry.i == e.i) {
834 if (top_entry.is_negated) {
843 span[top_entry.i].Negated())) {
846 to_remove.push_back(top_entry.i);
855 if (top_entry.is_negated) {
856 num_subsumed_clauses_++;
861 CHECK_NE(top_entry.i, e.i);
862 if (top_entry.is_negated) {
864 to_remove.push_back(e.i);
873 to_remove.push_back(top_entry.i);
881 if (clause->empty())
continue;
884 if (!to_remove.empty() || entries.size() < span.size()) {
887 int to_remove_index = 0;
888 for (
int i = 0; i < span.size(); ++i) {
889 if (to_remove_index < to_remove.size() &&
890 i == to_remove[to_remove_index]) {
899 new_clause.push_back(span[i]);
901 num_removed_literals_ += span.size() - new_clause.size();
915 num_blocked_clauses_ = 0;
916 num_inspected_literals_ = 0;
918 InitializeForNewRound();
920 while (!time_limit_->
LimitReached() && !queue_.empty()) {
921 const Literal l = queue_.front();
922 in_queue_[l.
Index()] =
false;
928 literal_to_clauses_.
clear();
930 dtime_ += 1e-8 * num_inspected_literals_;
933 LOG_IF(INFO, log_info) <<
"Blocked clause. num_blocked_clauses: "
934 << num_blocked_clauses_ <<
" dtime: " << dtime_
938 void BlockedClauseSimplifier::InitializeForNewRound() {
946 clauses_.push_back(c);
948 const int num_literals = clause_manager_->
literal_size();
952 in_queue_.
assign(num_literals,
true);
953 for (LiteralIndex l(0); l < num_literals; ++l) {
954 queue_.push_back(Literal(l));
957 marked_.
resize(num_literals);
959 std::all_of(marked_.
begin(), marked_.
end(), [](
bool b) { return !b; }));
963 literal_to_clauses_.
clear();
964 literal_to_clauses_.
resize(num_literals);
965 for (ClauseIndex i(0); i < clauses_.size(); ++i) {
966 for (
const Literal l : clauses_[i]->AsSpan()) {
967 literal_to_clauses_[l.Index()].
push_back(i);
969 num_inspected_literals_ += clauses_[i]->size();
973 void BlockedClauseSimplifier::ProcessLiteral(Literal current_literal) {
975 if (implication_graph_->
IsRemoved(current_literal))
return;
990 const std::vector<Literal>& implications =
992 for (
const Literal l : implications) {
993 if (l == current_literal)
continue;
995 marked_[l.Index()] =
true;
1001 std::vector<ClauseIndex> clauses_to_process;
1002 for (
const ClauseIndex i : literal_to_clauses_[current_literal.Index()]) {
1003 if (clauses_[i]->empty())
continue;
1009 if (num_binary > 0) {
1010 if (clauses_[i]->size() <= num_binary)
continue;
1011 int num_with_negation_marked = 0;
1012 for (
const Literal l : clauses_[i]->AsSpan()) {
1013 if (l == current_literal)
continue;
1014 if (marked_[l.NegatedIndex()]) {
1015 ++num_with_negation_marked;
1018 num_inspected_literals_ += clauses_[i]->size();
1019 if (num_with_negation_marked < num_binary)
continue;
1021 clauses_to_process.push_back(i);
1025 for (
const Literal l : implications) {
1026 marked_[l.Index()] =
false;
1037 for (
const ClauseIndex i : clauses_to_process) {
1038 const auto c = clauses_[i]->AsSpan();
1039 if (ClauseIsBlocked(current_literal, c)) {
1046 for (
const Literal l : c) {
1047 if (!in_queue_[l.NegatedIndex()]) {
1048 in_queue_[l.NegatedIndex()] =
true;
1049 queue_.push_back(l.Negated());
1057 ++num_blocked_clauses_;
1064 bool BlockedClauseSimplifier::ClauseIsBlocked(
1065 Literal current_literal, absl::Span<const Literal> clause) {
1066 bool is_blocked =
true;
1067 for (
const Literal l : clause) marked_[l.Index()] =
true;
1071 for (
const ClauseIndex i :
1072 literal_to_clauses_[current_literal.NegatedIndex()]) {
1073 if (clauses_[i]->empty())
continue;
1074 bool some_marked =
false;
1075 for (
const Literal l : clauses_[i]->AsSpan()) {
1077 ++num_inspected_literals_;
1079 if (l == current_literal.Negated())
continue;
1080 if (marked_[l.NegatedIndex()]) {
1091 for (
const Literal l : clause) marked_[l.Index()] =
false;
1100 num_inspected_literals_ = 0;
1101 num_eliminated_variables_ = 0;
1102 num_literals_diff_ = 0;
1103 num_clauses_diff_ = 0;
1104 num_simplifications_ = 0;
1105 num_blocked_clauses_ = 0;
1116 clauses_.push_back(c);
1118 const int num_literals = clause_manager_->
literal_size();
1119 const int num_variables = num_literals / 2;
1121 literal_to_clauses_.
clear();
1122 literal_to_clauses_.
resize(num_literals);
1123 literal_to_num_clauses_.
assign(num_literals, 0);
1124 for (ClauseIndex i(0); i < clauses_.size(); ++i) {
1125 for (
const Literal l : clauses_[i]->AsSpan()) {
1126 literal_to_clauses_[l.Index()].
push_back(i);
1127 literal_to_num_clauses_[l.Index()]++;
1129 num_inspected_literals_ += clauses_[i]->size();
1132 const int saved_trail_index = trail_->
Index();
1133 propagation_index_ = trail_->
Index();
1135 need_to_be_updated_.clear();
1136 in_need_to_be_updated_.
resize(num_variables);
1137 queue_.
Reserve(num_variables);
1138 for (BooleanVariable v(0); v < num_variables; ++v) {
1141 UpdatePriorityQueue(v);
1144 marked_.
resize(num_literals);
1146 std::all_of(marked_.
begin(), marked_.
end(), [](
bool b) { return !b; }));
1152 const BooleanVariable top = queue_.
Top().var;
1160 bool is_unsat =
false;
1161 if (!Propagate())
return false;
1163 if (!Propagate())
return false;
1165 if (is_unsat)
return false;
1167 if (!CrossProduct(top))
return false;
1169 for (
const BooleanVariable v : need_to_be_updated_) {
1170 in_need_to_be_updated_[v] =
false;
1173 if (v != top) UpdatePriorityQueue(v);
1175 in_need_to_be_updated_.
clear();
1176 need_to_be_updated_.clear();
1185 bool remove =
false;
1186 for (
const Literal l : c->AsSpan()) {
1196 literal_to_clauses_.
clear();
1197 literal_to_num_clauses_.
clear();
1199 dtime_ += 1e-8 * num_inspected_literals_;
1202 LOG_IF(INFO, log_info) <<
"BVE."
1204 << trail_->
Index() - saved_trail_index
1205 <<
" num_simplified_literals: " << num_simplifications_
1206 <<
" num_blocked_clauses_: " << num_blocked_clauses_
1207 <<
" num_eliminations: " << num_eliminated_variables_
1208 <<
" num_literals_diff: " << num_literals_diff_
1209 <<
" num_clause_diff: " << num_clauses_diff_
1210 <<
" dtime: " << dtime_
1215 bool BoundedVariableElimination::RemoveLiteralFromClause(
1217 num_literals_diff_ -= sat_clause->
size();
1221 literal_to_num_clauses_[l.Index()]--;
1225 num_clauses_diff_--;
1229 resolvant_.push_back(l);
1234 if (sat_clause->
empty()) {
1235 --num_clauses_diff_;
1236 for (
const Literal l : resolvant_) literal_to_num_clauses_[l.Index()]--;
1238 num_literals_diff_ += sat_clause->
size();
1243 bool BoundedVariableElimination::Propagate() {
1244 for (; propagation_index_ < trail_->
Index(); ++propagation_index_) {
1246 if (!implication_graph_->
Propagate(trail_))
return false;
1248 const Literal l = (*trail_)[propagation_index_];
1249 for (
const ClauseIndex
index : literal_to_clauses_[l.Index()]) {
1250 if (clauses_[
index]->empty())
continue;
1251 num_clauses_diff_--;
1252 num_literals_diff_ -= clauses_[
index]->size();
1255 literal_to_clauses_[l.Index()].
clear();
1256 for (
const ClauseIndex
index : literal_to_clauses_[l.NegatedIndex()]) {
1257 if (clauses_[
index]->empty())
continue;
1258 if (!RemoveLiteralFromClause(l.Negated(), clauses_[
index]))
return false;
1260 literal_to_clauses_[l.NegatedIndex()].
clear();
1267 int BoundedVariableElimination::NumClausesContaining(Literal l) {
1268 return literal_to_num_clauses_[l.Index()] +
1273 void BoundedVariableElimination::UpdatePriorityQueue(BooleanVariable
var) {
1275 const int priority = -NumClausesContaining(Literal(
var,
true)) -
1276 NumClausesContaining(Literal(
var,
false));
1280 queue_.
Add({
var, priority});
1284 void BoundedVariableElimination::DeleteClause(SatClause* sat_clause) {
1285 const auto clause = sat_clause->AsSpan();
1287 num_clauses_diff_--;
1288 num_literals_diff_ -= clause.size();
1291 for (
const Literal l : clause) {
1292 literal_to_num_clauses_[l.Index()]--;
1293 if (!in_need_to_be_updated_[l.Variable()]) {
1294 in_need_to_be_updated_[l.Variable()] =
true;
1295 need_to_be_updated_.push_back(l.Variable());
1303 void BoundedVariableElimination::DeleteAllClausesContaining(Literal
literal) {
1304 for (
const ClauseIndex i : literal_to_clauses_[
literal.Index()]) {
1305 const auto clause = clauses_[i]->AsSpan();
1306 if (clause.empty())
continue;
1308 DeleteClause(clauses_[i]);
1313 void BoundedVariableElimination::AddClause(absl::Span<const Literal> clause) {
1315 if (pt ==
nullptr)
return;
1317 num_clauses_diff_++;
1318 num_literals_diff_ += clause.size();
1320 const ClauseIndex
index(clauses_.size());
1321 clauses_.push_back(pt);
1322 for (
const Literal l : clause) {
1323 literal_to_num_clauses_[l.Index()]++;
1325 if (!in_need_to_be_updated_[l.Variable()]) {
1326 in_need_to_be_updated_[l.Variable()] =
true;
1327 need_to_be_updated_.push_back(l.Variable());
1332 template <
bool score_only,
bool with_binary_only>
1333 bool BoundedVariableElimination::ResolveAllClauseContaining(Literal lit) {
1334 const int clause_weight = parameters_.presolve_bve_clause_weight();
1336 const std::vector<Literal>& implications =
1338 auto& clause_containing_lit = literal_to_clauses_[lit.Index()];
1339 for (
int i = 0; i < clause_containing_lit.size(); ++i) {
1340 const ClauseIndex clause_index = clause_containing_lit[i];
1341 const auto clause = clauses_[clause_index]->AsSpan();
1342 if (clause.empty())
continue;
1344 if (!score_only) resolvant_.clear();
1345 for (
const Literal l : clause) {
1346 if (!score_only && l != lit) resolvant_.push_back(l);
1347 marked_[l.Index()] =
true;
1349 DCHECK(marked_[lit.Index()]);
1350 num_inspected_literals_ += clause.size() + implications.size();
1354 bool clause_can_be_simplified =
false;
1355 const int64_t saved_score = new_score_;
1358 for (
const Literal l : implications) {
1360 if (marked_[l.NegatedIndex()])
continue;
1361 if (marked_[l.Index()]) {
1362 clause_can_be_simplified =
true;
1366 new_score_ += clause_weight + clause.size();
1368 resolvant_.push_back(l);
1369 AddClause(resolvant_);
1370 resolvant_.pop_back();
1376 if (!with_binary_only && !clause_can_be_simplified) {
1377 auto& clause_containing_not_lit = literal_to_clauses_[lit.NegatedIndex()];
1378 for (
int j = 0; j < clause_containing_not_lit.size(); ++j) {
1379 if (score_only && new_score_ > score_threshold_)
break;
1380 const ClauseIndex other_index = clause_containing_not_lit[j];
1381 const auto other = clauses_[other_index]->AsSpan();
1382 if (other.empty())
continue;
1383 bool trivial =
false;
1385 for (
const Literal l : other) {
1387 ++num_inspected_literals_;
1388 if (l == lit.Negated())
continue;
1389 if (marked_[l.NegatedIndex()]) {
1393 if (!marked_[l.Index()]) {
1395 if (!score_only) resolvant_.push_back(l);
1399 if (!score_only) resolvant_.resize(resolvant_.size() - extra_size);
1405 if (score_only && clause.size() + extra_size <= other.size()) {
1411 if (
false) DCHECK_EQ(clause.size() + extra_size, other.size());
1412 ++num_simplifications_;
1416 score_threshold_ -= clause_weight + other.size();
1418 if (extra_size == 0) {
1422 DeleteClause(clauses_[other_index]);
1424 if (!RemoveLiteralFromClause(lit.Negated(),
1425 clauses_[other_index])) {
1429 clause_containing_not_lit.back());
1430 clause_containing_not_lit.pop_back();
1436 if (extra_size == 0) {
1437 clause_can_be_simplified =
true;
1442 if (clause.size() - 1 + extra_size > 100) {
1443 new_score_ = score_threshold_ + 1;
1447 new_score_ += clause_weight + clause.size() - 1 + extra_size;
1449 AddClause(resolvant_);
1450 resolvant_.resize(resolvant_.size() - extra_size);
1457 for (
const Literal l : clause) marked_[l.Index()] =
false;
1460 if (clause_can_be_simplified) {
1461 ++num_simplifications_;
1464 new_score_ = saved_score;
1465 score_threshold_ -= clause_weight + clause.size();
1467 if (!RemoveLiteralFromClause(lit, clauses_[clause_index]))
return false;
1468 std::swap(clause_containing_lit[i], clause_containing_lit.back());
1469 clause_containing_lit.pop_back();
1473 if (score_only && new_score_ > score_threshold_)
return true;
1485 if (score_only && !with_binary_only && !clause_can_be_simplified &&
1486 new_score_ == saved_score) {
1487 ++num_blocked_clauses_;
1488 score_threshold_ -= clause_weight + clause.size();
1490 DeleteClause(clauses_[clause_index]);
1496 bool BoundedVariableElimination::CrossProduct(BooleanVariable
var) {
1499 const Literal lit(
var,
true);
1500 const Literal not_lit(
var,
false);
1502 const int s1 = NumClausesContaining(lit);
1503 const int s2 = NumClausesContaining(not_lit);
1504 if (s1 == 0 && s2 == 0)
return true;
1505 if (s1 > 0 && s2 == 0) {
1506 num_eliminated_variables_++;
1508 DeleteAllClausesContaining(lit);
1511 if (s1 == 0 && s2 > 0) {
1512 num_eliminated_variables_++;
1514 DeleteAllClausesContaining(not_lit);
1522 num_eliminated_variables_++;
1529 if (s1 > 1 && s2 > 1 && s1 * s2 > parameters_.presolve_bve_threshold()) {
1542 const int clause_weight = parameters_.presolve_bve_clause_weight();
1546 (clause_weight + 2);
1547 for (
const ClauseIndex i : literal_to_clauses_[lit.Index()]) {
1548 const auto c = clauses_[i]->AsSpan();
1549 if (!c.empty()) score += clause_weight + c.size();
1551 for (
const ClauseIndex i : literal_to_clauses_[not_lit.Index()]) {
1552 const auto c = clauses_[i]->AsSpan();
1553 if (!c.empty()) score += clause_weight + c.size();
1564 score_threshold_ = score;
1566 (clause_weight + 2);
1567 if (new_score_ > score_threshold_)
return true;
1568 if (!ResolveAllClauseContaining<
true,
1572 if (new_score_ > score_threshold_)
return true;
1573 if (!ResolveAllClauseContaining<
true,
1577 if (new_score_ > score_threshold_)
return true;
1580 if (new_score_ > 0) {
1581 if (!ResolveAllClauseContaining<
false,
1585 if (!ResolveAllClauseContaining<
false,
1591 ++num_eliminated_variables_;
1593 DeleteAllClausesContaining(lit);
1594 DeleteAllClausesContaining(not_lit);
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)
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()
void RemoveBooleanVariable(BooleanVariable var, std::deque< std::vector< Literal >> *postsolve_clauses)
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
const std::vector< SatClause * > & AllClausesInCreationOrder() 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
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)