25#include "absl/algorithm/container.h"
26#include "absl/cleanup/cleanup.h"
27#include "absl/container/btree_map.h"
28#include "absl/container/btree_set.h"
29#include "absl/container/flat_hash_map.h"
30#include "absl/container/inlined_vector.h"
31#include "absl/log/check.h"
32#include "absl/log/log.h"
33#include "absl/log/vlog_is_on.h"
34#include "absl/strings/string_view.h"
35#include "absl/types/span.h"
65 implication_graph_(implication_graph),
66 clause_manager_(clause_manager) {}
70 const int trail_size = trail_.Index();
71 trail_index_.resize(trail_.NumVariables(), -1);
72 trail_literals_.clear();
74 stored_reasons_.clear();
75 trail_literals_.reserve(trail_size);
76 trail_info_.reserve(trail_size);
77 for (
int i = 0;
i < trail_size; ++
i) {
79 const BooleanVariable var = literal.
Variable();
81 const int assignment_type = trail_.AssignmentType(var);
82 absl::Span<const Literal> reason;
85 std::variant<ClauseId, const SatClause*> reason_clause =
kNoClauseId;
87 const absl::Span<const Literal> cached_reason = trail_.Reason(var);
88 stored_reasons_.push_back({cached_reason.begin(), cached_reason.end()});
89 reason = stored_reasons_.back();
91 reason_clause = trail_.GetUnitClauseId(var);
92 }
else if (assignment_type == implication_graph_.PropagatorId()) {
93 absl::Span<const Literal> original_reason = trail_.Reason(var);
94 DCHECK_EQ(original_reason.size(), 1);
95 reason = absl::MakeConstSpan(trail_literals_)
96 .subspan(trail_index_[original_reason[0].
Variable()], 1);
97 DCHECK_EQ(reason[0], original_reason[0].Negated());
98 }
else if (assignment_type == clause_manager_.PropagatorId()) {
99 const SatClause* sat_clause = clause_manager_.ReasonClauseOrNull(var);
100 if (sat_clause !=
nullptr) {
101 reason = sat_clause->
AsSpan();
103 reason_clause = clause_manager_.ReasonClauseOrNull(var);
105 trail_index_[var] =
i;
106 trail_literals_.push_back(literal);
107 trail_info_.push_back(
108 {info.
level, assignment_type, reason, reason_clause});
111 const int num_decisions = trail_.CurrentDecisionLevel();
113 decisions_.reserve(num_decisions);
114 for (
int i = 0;
i < num_decisions; ++
i) {
115 decisions_.push_back(trail_.Decisions()[
i].literal);
122 absl::Span<const Literal> literals, std::vector<ClauseId>* clause_ids,
123 LiteralIndex decision,
124 absl::flat_hash_map<std::pair<Literal, Literal>, ClauseId>
125 tmp_binary_clause_ids) {
127 tmp_mark_.ClearAndResize(BooleanVariable(trail_index_.size()));
128 marked_trail_indices_heap_.clear();
129 for (
const Literal lit : literals) {
130 tmp_mark_.Set(lit.Variable());
131 marked_trail_indices_heap_.push_back(trail_index_[lit.Variable()]);
133 absl::c_make_heap(marked_trail_indices_heap_);
134 const int current_level = decisions_.size();
137 int min_level = current_level;
142 std::vector<ClauseId>& non_unit_clause_ids =
143 tmp_clause_ids_for_append_clauses_fixing_;
144 non_unit_clause_ids.clear();
146 while (!marked_trail_indices_heap_.empty()) {
147 absl::c_pop_heap(marked_trail_indices_heap_);
148 const int trail_index = marked_trail_indices_heap_.back();
149 marked_trail_indices_heap_.pop_back();
150 const Literal marked_literal = trail_literals_[trail_index];
151 const TrailInfo& trail_info = trail_info_[trail_index];
155 const int level = trail_info.level;
156 if (level > 0) min_level = std::min(min_level, level);
161 clause_ids->push_back(std::get<ClauseId>(trail_info.reason_clause));
164 const Literal level_decision = decisions_[level - 1];
165 ClauseId clause_id = implication_graph_.GetClauseId(
166 level_decision.
Negated(), marked_literal);
168 const auto it = tmp_binary_clause_ids.find(
169 std::minmax(level_decision.
Negated(), marked_literal));
170 if (it != tmp_binary_clause_ids.end()) {
171 clause_id = it->second;
175 non_unit_clause_ids.push_back(clause_id);
180 for (
const Literal literal : trail_info.reason) {
181 const BooleanVariable var = literal.
Variable();
182 if (!tmp_mark_[var]) {
183 const int trail_index = trail_index_[var];
184 const TrailInfo& info = trail_info_[trail_index];
186 if (info.level > 0) {
187 marked_trail_indices_heap_.push_back(trail_index);
188 absl::c_push_heap(marked_trail_indices_heap_);
190 clause_ids->push_back(std::get<ClauseId>(info.reason_clause));
194 non_unit_clause_ids.push_back(ReasonClauseId(trail_index));
199 if (
Literal(decision) != decisions_[current_level - 1]) {
201 clause_ids->push_back(implication_graph_.GetClauseId(
202 Literal(decision).Negated(), decisions_[current_level - 1]));
204 for (
int level = current_level - 1; level >= min_level; --level) {
205 clause_ids->push_back(implication_graph_.GetClauseId(
206 decisions_[level].Negated(), decisions_[level - 1]));
209 clause_ids->insert(clause_ids->end(), non_unit_clause_ids.rbegin(),
210 non_unit_clause_ids.rend());
216 ClauseId ReasonClauseId(
int trail_index)
const {
217 const TrailInfo& trail_info = trail_info_[trail_index];
218 const int assignment_type = trail_info.assignment_type;
221 return std::get<ClauseId>(trail_info.reason_clause);
222 }
else if (assignment_type == implication_graph_.
PropagatorId()) {
223 return implication_graph_.
GetClauseId(trail_literals_[trail_index],
224 trail_info.reason[0].Negated());
225 }
else if (assignment_type == clause_manager_.
PropagatorId()) {
226 const SatClause* reason =
227 std::get<const SatClause*>(trail_info.reason_clause);
228 if (reason !=
nullptr) {
242 absl::Span<const Literal> reason;
245 std::variant<ClauseId, const SatClause*> reason_clause;
249 const BinaryImplicationGraph& implication_graph_;
250 const ClauseManager& clause_manager_;
252 util_intops::StrongVector<BooleanVariable, int> trail_index_;
253 std::vector<Literal> trail_literals_;
254 std::vector<TrailInfo> trail_info_;
256 std::deque<std::vector<Literal>> stored_reasons_;
257 std::vector<Literal> decisions_;
259 SparseBitset<BooleanVariable> tmp_mark_;
260 std::vector<int> marked_trail_indices_heap_;
261 std::vector<ClauseId> tmp_clause_ids_for_append_clauses_fixing_;
265 : trail_(*model->GetOrCreate<
Trail>()),
270 sat_solver_(model->GetOrCreate<
SatSolver>()),
271 time_limit_(model->GetOrCreate<
TimeLimit>()),
276 trail_copy_(new
TrailCopy(trail_, *implication_graph_, *clause_manager_)),
277 drat_enabled_(lrat_proof_handler_ != nullptr &&
278 (lrat_proof_handler_->drat_check_enabled() ||
279 lrat_proof_handler_->drat_output_enabled())),
285 const int num_variables = sat_solver_->NumVariables();
287 std::vector<BooleanVariable> bool_vars;
288 for (BooleanVariable
b(0);
b < num_variables; ++
b) {
291 if (implication_graph_->RepresentativeOf(literal) != literal) {
294 bool_vars.push_back(
b);
299bool Prober::ProbeOneVariableInternal(BooleanVariable
b) {
300 new_integer_bounds_.clear();
302 tmp_binary_clause_ids_.clear();
306 absl::Cleanup unblock_clause_deletion = [&] {
309 for (
const Literal decision : {Literal(
b,
true), Literal(
b,
false)}) {
314 const int saved_index = trail_.
Index();
319 sat_solver_->AdvanceDeterministicTime(time_limit_);
321 if (sat_solver_->ModelIsUnsat())
return false;
322 if (sat_solver_->CurrentDecisionLevel() == 0)
continue;
323 if (trail_.Index() > saved_index) {
324 if (callback_ !=
nullptr) callback_(decision);
327 if (!implied_bounds_->ProcessIntegerTrail(decision))
return false;
328 product_detector_->ProcessTrailAtLevelOne();
329 integer_trail_->AppendNewBounds(&new_integer_bounds_);
330 to_fix_at_true_.clear();
331 new_literals_implied_by_decision_.clear();
332 new_implied_or_fixed_literals_.clear();
333 for (
int i = saved_index + 1;
i < trail_.Index(); ++
i) {
334 const Literal l = trail_[
i];
337 if (decision.IsPositive()) {
338 propagated_.Set(l.Index());
340 if (propagated_[l]) {
341 to_fix_at_true_.push_back(l);
342 if (lrat_proof_handler_ !=
nullptr) {
343 new_implied_or_fixed_literals_.push_back(l);
351 if (trail_.AssignmentType(l.Variable()) !=
352 implication_graph_->PropagatorId()) {
353 if (l == decision.Negated()) {
354 to_fix_at_true_.push_back(l);
355 }
else if (l != decision) {
356 new_literals_implied_by_decision_.push_back(l);
358 if (lrat_proof_handler_ !=
nullptr && l != decision) {
359 new_implied_or_fixed_literals_.push_back(l);
364 if (lrat_proof_handler_ !=
nullptr) {
365 for (
const Literal l : new_implied_or_fixed_literals_) {
366 tmp_clause_ids_.clear();
367 clause_manager_->AppendClauseIdsFixing(
368 {l}, &tmp_clause_ids_, decision.Index(),
369 [&](
int level,
int trail_index) {
370 const Literal decision = trail_.Decisions()[level - 1].literal;
371 const Literal lit = trail_[trail_index];
372 const auto it = tmp_binary_clause_ids_.find(
373 std::minmax(decision.Negated(), lit));
374 if (it != tmp_binary_clause_ids_.end())
return it->second;
377 const ClauseId clause_id = clause_id_generator_->GetNextId();
378 lrat_proof_handler_->AddInferredClause(
379 clause_id, {decision.Negated(), l}, tmp_clause_ids_);
380 tmp_binary_clause_ids_[std::minmax(decision.Negated(), l)] = clause_id;
382 num_lrat_proof_clauses_ += tmp_clause_ids_.size();
384 if (decision.IsPositive()) {
385 trail_copy_->CopyTrail();
386 }
else if (!to_fix_at_true_.empty()) {
387 for (
const Literal l : to_fix_at_true_) {
388 tmp_clause_ids_.clear();
389 trail_copy_->AppendClauseIdsFixing({l}, &tmp_clause_ids_,
390 decision.NegatedIndex(),
391 tmp_binary_clause_ids_);
392 const ClauseId clause_id = clause_id_generator_->GetNextId();
393 lrat_proof_handler_->AddInferredClause(clause_id, {decision, l},
395 tmp_binary_clause_ids_[std::minmax(decision, l)] = clause_id;
397 num_lrat_proof_clauses_ += tmp_clause_ids_.size();
403 if (!sat_solver_->ResetToLevelZero())
return false;
404 for (
const Literal l : to_fix_at_true_) {
406 if (lrat_proof_handler_ !=
nullptr) {
407 clause_id = clause_id_generator_->GetNextId();
408 absl::InlinedVector<ClauseId, 2> clause_ids;
409 clause_ids.push_back(
410 tmp_binary_clause_ids_.at(std::minmax(decision.Negated(), l)));
411 if (l != decision.Negated()) {
412 clause_ids.push_back(
413 tmp_binary_clause_ids_.at(std::minmax(decision, l)));
415 lrat_proof_handler_->AddInferredClause(clause_id, {l}, clause_ids);
417 num_lrat_proof_clauses_ += clause_ids.size();
419 if (!clause_manager_->InprocessingAddUnitClause(clause_id, l)) {
423 if (!sat_solver_->FinishPropagation())
return false;
424 for (
const Literal l : new_literals_implied_by_decision_) {
426 if (trail_.Assignment().LiteralIsAssigned(decision))
break;
427 if (trail_.Assignment().LiteralIsAssigned(l))
continue;
429 if (lrat_proof_handler_ !=
nullptr) {
431 tmp_binary_clause_ids_.at(std::minmax(decision.Negated(), l));
442 if (!implication_graph_->AddBinaryClause(
443 clause_id, decision.Negated(), l,
448 if (!sat_solver_->FinishPropagation())
return false;
450 if (lrat_proof_handler_ !=
nullptr) {
453 for (
const auto& [binary_clause, clause_id] : tmp_binary_clause_ids_) {
454 if (implication_graph_->GetClauseId(binary_clause.first,
455 binary_clause.second) != clause_id) {
456 lrat_proof_handler_->DeleteClause(
457 clause_id, {binary_clause.first, binary_clause.second});
458 num_unneeded_lrat_clauses_++;
475 std::sort(new_integer_bounds_.begin(), new_integer_bounds_.end(),
476 [](IntegerLiteral a, IntegerLiteral
b) { return a.var < b.var; });
482 new_integer_bounds_.push_back(IntegerLiteral());
484 const int limit = new_integer_bounds_.size();
485 for (
int i = 0;
i < limit; ++
i) {
486 const IntegerVariable var = new_integer_bounds_[
i].var;
490 if (ub_min + 1 < lb_max) {
495 const Domain old_domain =
496 integer_trail_->InitialVariableDomain(prev_var);
497 const Domain new_domain = old_domain.IntersectionWith(
498 Domain(ub_min.value() + 1, lb_max.value() - 1).Complement());
499 if (new_domain != old_domain) {
501 if (!integer_trail_->UpdateInitialDomain(prev_var, new_domain)) {
514 lb_max = std::max(lb_max, new_integer_bounds_[
i].bound);
516 ub_min = std::min(ub_min, -new_integer_bounds_[
i].bound);
520 if (
i == 0 || new_integer_bounds_[
i - 1].var != var)
continue;
521 const IntegerValue new_bound = std::min(new_integer_bounds_[
i - 1].bound,
522 new_integer_bounds_[
i].bound);
523 if (new_bound > integer_trail_->LowerBound(var)) {
524 ++num_new_integer_bounds_;
525 if (!integer_trail_->Enqueue(
533 return sat_solver_->FinishPropagation();
538 const int num_variables = sat_solver_->NumVariables();
539 propagated_.ClearAndResize(LiteralIndex(2 * num_variables));
542 if (!sat_solver_->ResetToLevelZero())
return false;
544 const int initial_num_fixed = sat_solver_->LiteralTrail().Index();
545 if (!ProbeOneVariableInternal(
b))
return false;
548 const int num_fixed = sat_solver_->LiteralTrail().Index();
549 num_new_literals_fixed_ += num_fixed - initial_num_fixed;
554 const double deterministic_time_limit,
555 absl::Span<const BooleanVariable> bool_vars) {
563 num_new_integer_bounds_ = 0;
564 num_new_literals_fixed_ = 0;
565 num_lrat_clauses_ = 0;
566 num_lrat_proof_clauses_ = 0;
567 num_unneeded_lrat_clauses_ = 0;
570 const int num_variables = sat_solver_->NumVariables();
571 propagated_.ClearAndResize(LiteralIndex(2 * num_variables));
574 if (!sat_solver_->ResetToLevelZero())
return false;
576 const int initial_num_fixed = sat_solver_->LiteralTrail().Index();
577 const double initial_deterministic_time =
578 time_limit_->GetElapsedDeterministicTime();
579 const double limit = initial_deterministic_time + deterministic_time_limit;
581 bool limit_reached =
false;
584 for (
const BooleanVariable
b : bool_vars) {
586 if (implication_graph_->RepresentativeOf(literal) != literal) {
592 if (time_limit_->LimitReached() ||
593 time_limit_->GetElapsedDeterministicTime() > limit) {
594 limit_reached =
true;
600 if (!ProbeOneVariableInternal(
b)) {
606 const int num_fixed = sat_solver_->LiteralTrail().Index();
607 num_new_literals_fixed_ = num_fixed - initial_num_fixed;
610 if (logger_->LoggingIsEnabled()) {
611 const double time_diff =
612 time_limit_->GetElapsedDeterministicTime() - initial_deterministic_time;
613 SOLVER_LOG(logger_,
"[Probing] deterministic_time: ", time_diff,
614 " (limit: ", deterministic_time_limit,
615 ") wall_time: ", wall_timer.
Get(),
" (",
616 (limit_reached ?
"Aborted " :
""), num_probed,
"/",
617 bool_vars.size(),
")");
618 if (num_new_literals_fixed_ > 0) {
620 "[Probing] - new fixed Boolean: ", num_new_literals_fixed_,
624 if (num_new_holes_ > 0) {
625 SOLVER_LOG(logger_,
"[Probing] - new integer holes: ",
628 if (num_new_integer_bounds_ > 0) {
629 SOLVER_LOG(logger_,
"[Probing] - new integer bounds: ",
632 if (num_new_binary_ > 0) {
633 SOLVER_LOG(logger_,
"[Probing] - new binary clause: ",
636 if (num_lrat_clauses_ > 0) {
637 SOLVER_LOG(logger_,
"[Probing] - new LRAT clauses: ",
640 if (num_lrat_proof_clauses_ > 0) {
641 SOLVER_LOG(logger_,
"[Probing] - new LRAT proof clauses: ",
644 if (num_unneeded_lrat_clauses_ > 0) {
645 SOLVER_LOG(logger_,
"[Probing] - unneeded LRAT clauses: ",
654 absl::Span<
const std::vector<Literal>> dnf,
656 if (dnf.size() <= 1)
return true;
662 std::vector<Literal> dnf_clause_literals;
663 if (dnf_clause !=
nullptr && lrat_proof_handler_ !=
nullptr) {
664 dnf_clause_id = clause_manager_->GetClauseId(dnf_clause);
665 dnf_clause_literals.assign(dnf_clause->
AsSpan().begin(),
666 dnf_clause->
AsSpan().end());
667 lrat_proof_handler_->PinClause(dnf_clause_id, dnf_clause_literals);
669 absl::Cleanup cleanup = [
this, dnf_clause_id] {
671 lrat_proof_handler_->UnpinClause(dnf_clause_id);
676 if (!sat_solver_->ResetToLevelZero())
return false;
678 always_propagated_bounds_.clear();
679 always_propagated_literals_.clear();
680 int num_valid_conjunctions = 0;
681 for (absl::Span<const Literal> conjunction : dnf) {
688 if (!sat_solver_->ResetToLevelZero())
return false;
689 if (num_valid_conjunctions > 0 && always_propagated_bounds_.empty() &&
690 always_propagated_literals_.empty()) {
695 bool conjunction_is_valid =
true;
696 const int root_trail_index = trail_.Index();
697 const int root_integer_trail_index = integer_trail_->Index();
698 for (
const Literal& lit : conjunction) {
699 if (assignment_.LiteralIsAssigned(lit)) {
700 if (assignment_.LiteralIsTrue(lit))
continue;
701 conjunction_is_valid =
false;
704 const int decision_level_before_enqueue =
705 sat_solver_->CurrentDecisionLevel();
706 sat_solver_->EnqueueDecisionAndBackjumpOnConflict(lit);
707 sat_solver_->AdvanceDeterministicTime(time_limit_);
708 const int decision_level_after_enqueue =
709 sat_solver_->CurrentDecisionLevel();
712 if (sat_solver_->ModelIsUnsat())
return false;
715 if (decision_level_after_enqueue <= decision_level_before_enqueue) {
716 conjunction_is_valid =
false;
721 if (conjunction_is_valid) {
722 ++num_valid_conjunctions;
728 new_propagated_literals_.clear();
729 for (
int i = root_trail_index;
i < trail_.Index(); ++
i) {
730 const LiteralIndex literal_index = trail_[
i].Index();
731 if (num_valid_conjunctions == 1 ||
732 always_propagated_literals_.contains(literal_index)) {
733 new_propagated_literals_.insert(literal_index);
736 std::swap(new_propagated_literals_, always_propagated_literals_);
739 new_integer_bounds_.clear();
740 integer_trail_->AppendNewBoundsFrom(root_integer_trail_index,
741 &new_integer_bounds_);
742 new_propagated_bounds_.clear();
744 const auto it = always_propagated_bounds_.find(entry.var);
745 if (num_valid_conjunctions == 1) {
746 new_propagated_bounds_[entry.var] = entry.bound;
747 }
else if (it != always_propagated_bounds_.end()) {
748 new_propagated_bounds_[entry.var] = std::min(entry.bound, it->second);
751 std::swap(new_propagated_bounds_, always_propagated_bounds_);
754 if (!sat_solver_->ResetToLevelZero())
return false;
756 const int previous_num_literals_fixed = num_new_literals_fixed_;
757 if (lrat_proof_handler_ !=
nullptr) {
758 if (!FixProbedDnfLiterals(dnf, always_propagated_literals_, dnf_type,
759 dnf_clause_id, dnf_clause_literals)) {
763 for (
const LiteralIndex literal_index : always_propagated_literals_) {
764 const Literal lit(literal_index);
765 if (assignment_.LiteralIsTrue(lit))
continue;
766 ++num_new_literals_fixed_;
767 if (!sat_solver_->AddUnitClause(lit))
return false;
772 int previous_num_integer_bounds = num_new_integer_bounds_;
773 for (
const auto& [var, bound] : always_propagated_bounds_) {
774 if (bound > integer_trail_->LowerBound(var)) {
775 ++num_new_integer_bounds_;
783 if (!sat_solver_->FinishPropagation())
return false;
785 if (num_new_integer_bounds_ > previous_num_integer_bounds ||
786 num_new_literals_fixed_ > previous_num_literals_fixed) {
787 VLOG(1) <<
"ProbeDnf(" << name <<
", num_fixed_literals="
788 << num_new_literals_fixed_ - previous_num_literals_fixed
789 <<
", num_pushed_integer_bounds="
790 << num_new_integer_bounds_ - previous_num_integer_bounds
791 <<
", num_valid_conjunctions=" << num_valid_conjunctions <<
"/"
792 << dnf.size() <<
")";
803bool GetConjunctionImpliesLiteralClause(absl::Span<const Literal> conjunction,
805 std::vector<Literal>& implication) {
807 for (
const Literal lit : conjunction) {
808 if (lit == literal)
return false;
809 if (lit.Negated() == literal)
continue;
810 implication.push_back(lit.Negated());
812 implication.push_back(literal);
817bool Prober::FixProbedDnfLiterals(
818 absl::Span<
const std::vector<Literal>> dnf,
819 const absl::btree_set<LiteralIndex>& propagated_literals, DnfType dnf_type,
820 ClauseId dnf_clause_id, absl::Span<const Literal> dnf_clause_literals) {
821 if (propagated_literals.empty())
return true;
827 CompactVectorVector<int, ClauseId>& propagation_clause_ids =
829 propagation_clause_ids.clear();
830 propagation_clause_ids.reserve(propagated_literals.size() * dnf.size());
831 for (
int i = 0;
i < propagated_literals.size(); ++
i) {
832 propagation_clause_ids.Add({});
833 for (
int j = 0; j < dnf.size(); ++j) {
834 propagation_clause_ids.AppendToLastVector(
kNoClauseId);
842 for (
int conjunction_index = 0; conjunction_index < dnf.size();
843 ++conjunction_index) {
844 absl::Span<const Literal> conjunction = dnf[conjunction_index];
846 if (!sat_solver_->ResetToLevelZero())
return false;
853 ClauseId first_false_literal_clause_id =
kNoClauseId;
854 tmp_literals_.clear();
855 for (
const Literal lit : conjunction) {
856 tmp_literals_.push_back(lit.Negated());
857 if (assignment_.LiteralIsAssigned(lit)) {
858 if (assignment_.LiteralIsTrue(lit))
continue;
859 first_false_literal = lit.Index();
860 first_false_literal_clause_id = clause_id_generator_->GetNextId();
861 tmp_clause_ids_.clear();
862 clause_manager_->AppendClauseIdsFixing({lit.Negated()},
864 lrat_proof_handler_->AddInferredClause(first_false_literal_clause_id,
865 tmp_literals_, tmp_clause_ids_);
871 auto conflict_callback = [&](ClauseId conflict_id,
872 absl::Span<const Literal> conflict_clause) {
874 first_false_literal = lit.Index();
875 first_false_literal_clause_id = clause_id_generator_->GetNextId();
876 tmp_clause_ids_.clear();
877 clause_manager_->AppendClauseIdsFixing(conflict_clause,
879 tmp_clause_ids_.push_back(conflict_id);
880 lrat_proof_handler_->AddInferredClause(first_false_literal_clause_id,
881 tmp_literals_, tmp_clause_ids_);
883 sat_solver_->EnqueueDecisionAndBackjumpOnConflict(lit, conflict_callback);
885 if (sat_solver_->ModelIsUnsat())
return false;
892 for (
const LiteralIndex literal_index : propagated_literals) {
893 const Literal propagated_lit(literal_index);
894 absl::Span<ClauseId> propagation_ids = propagation_clause_ids[
i++];
896 if (!GetConjunctionImpliesLiteralClause(conjunction, propagated_lit,
902 tmp_clause_ids_.clear();
903 if (first_false_literal_clause_id !=
kNoClauseId) {
907 tmp_clause_ids_.push_back(first_false_literal_clause_id);
912 clause_manager_->AppendClauseIdsFixing({propagated_lit},
916 const ClauseId clause_id = clause_id_generator_->GetNextId();
917 lrat_proof_handler_->AddInferredClause(clause_id, tmp_literals_,
919 propagation_ids[conjunction_index] = clause_id;
921 if (first_false_literal_clause_id !=
kNoClauseId) {
924 tmp_literals_.clear();
925 for (
const Literal lit : conjunction) {
926 tmp_literals_.push_back(lit.Negated());
927 if (lit.Index() == first_false_literal)
break;
929 lrat_proof_handler_->DeleteClause(first_false_literal_clause_id,
932 lrat_proof_handler_->DeleteClause(first_false_literal_clause_id, {});
937 if (!sat_solver_->ResetToLevelZero())
return false;
941 for (
const LiteralIndex literal_index : propagated_literals) {
942 const Literal propagated_lit(literal_index);
943 absl::Span<ClauseId> propagation_ids = propagation_clause_ids[
i++];
944 if (assignment_.LiteralIsTrue(propagated_lit))
continue;
946 ++num_new_literals_fixed_;
954 tmp_clause_ids_.clear();
955 for (
const ClauseId clause_id : propagation_ids) {
957 tmp_clause_ids_.push_back(clause_id);
959 for (
const Literal lit : dnf_clause_literals) {
960 if (assignment_.LiteralIsAssigned(lit)) {
961 tmp_clause_ids_.push_back(trail_.GetUnitClauseId(lit.Variable()));
964 tmp_clause_ids_.push_back(dnf_clause_id);
965 if (!clause_manager_->InprocessingFixLiteral(propagated_lit,
975 tmp_clause_ids_.clear();
976 for (
const ClauseId clause_id : propagation_ids) {
978 tmp_clause_ids_.push_back(clause_id);
980 if (!clause_manager_->InprocessingFixLiteral(propagated_lit,
986 if (!FixLiteralImpliedByAnAtLeastOneCombinationDnf(dnf, propagation_ids,
996 for (
const LiteralIndex literal_index : propagated_literals) {
997 const Literal propagated_lit(literal_index);
998 const absl::Span<ClauseId> propagation_ids = propagation_clause_ids[
i++];
999 for (
int j = 0; j < dnf.size(); ++j) {
1000 const ClauseId clause_id = propagation_ids[j];
1002 if (drat_enabled_) {
1004 GetConjunctionImpliesLiteralClause(dnf[j], propagated_lit,
1006 lrat_proof_handler_->DeleteClause(clause_id, tmp_literals_);
1008 lrat_proof_handler_->DeleteClause(clause_id, {});
1015bool Prober::FixLiteralImpliedByAnAtLeastOneCombinationDnf(
1016 absl::Span<
const std::vector<Literal>> conjunctions,
1017 absl::Span<ClauseId> clause_ids,
Literal propagated_lit) {
1018 const int num_clauses = clause_ids.size();
1019 CHECK_EQ(conjunctions.size(), num_clauses);
1036 int num_literals_per_conjunction = conjunctions[0].size();
1039 for (
int i = 0;
i < num_clauses;
i += 2 * stride) {
1042 tmp_clause_ids_.clear();
1045 tmp_clause_ids_.push_back(clause_ids[
i]);
1048 tmp_clause_ids_.push_back(clause_ids[
i + stride]);
1050 if (tmp_clause_ids_.empty())
continue;
1051 const ClauseId new_clause_id = clause_id_generator_->GetNextId();
1052 GetConjunctionImpliesLiteralClause(
1053 absl::MakeConstSpan(conjunctions[
i])
1054 .subspan(0, num_literals_per_conjunction - 1),
1055 propagated_lit, tmp_literals_);
1056 lrat_proof_handler_->AddInferredClause(new_clause_id, tmp_literals_,
1059 for (
const int index : {
i,
i + stride}) {
1061 if (drat_enabled_) {
1063 GetConjunctionImpliesLiteralClause(
1064 absl::MakeConstSpan(conjunctions[index])
1065 .subspan(0, num_literals_per_conjunction),
1066 propagated_lit, tmp_literals_);
1067 lrat_proof_handler_->DeleteClause(clause_ids[index], tmp_literals_);
1069 lrat_proof_handler_->DeleteClause(clause_ids[index], {});
1073 if (num_literals_per_conjunction == 1) {
1074 return clause_manager_->InprocessingAddUnitClause(new_clause_id,
1077 clause_ids[
i] = new_clause_id;
1079 num_literals_per_conjunction--;
1094 if (!sat_solver->ResetToLevelZero())
return false;
1097 const int initial_num_fixed = sat_solver->LiteralTrail().Index();
1104 new_params.set_max_number_of_conflicts(1);
1105 new_params.set_max_deterministic_time(deterministic_time_limit);
1107 double elapsed_dtime = 0.0;
1114 const int num_times = 1000;
1115 bool limit_reached =
false;
1117 for (
int i = 0;
i < num_times; ++
i) {
1118 if (time_limit->LimitReached() ||
1119 elapsed_dtime > deterministic_time_limit) {
1120 limit_reached =
true;
1125 sat_solver->SetParameters(new_params);
1126 time_limit->MergeWithGlobalTimeLimit(&original_time_limit);
1127 sat_solver->ResetDecisionHeuristic();
1129 elapsed_dtime += time_limit->GetElapsedDeterministicTime();
1132 SOLVER_LOG(logger,
"Trivial exploration found feasible solution!");
1133 time_limit->AdvanceDeterministicTime(elapsed_dtime);
1137 if (!sat_solver->ResetToLevelZero()) {
1138 SOLVER_LOG(logger,
"UNSAT during trivial exploration heuristic.");
1139 time_limit->AdvanceDeterministicTime(elapsed_dtime);
1146 new_params.set_random_seed(
i);
1147 new_params.set_max_deterministic_time(deterministic_time_limit -
1152 sat_solver->SetParameters(initial_params);
1153 sat_solver->ResetDecisionHeuristic();
1154 time_limit->MergeWithGlobalTimeLimit(&original_time_limit);
1155 time_limit->AdvanceDeterministicTime(elapsed_dtime);
1156 if (!sat_solver->ResetToLevelZero())
return false;
1159 const int num_fixed = sat_solver->LiteralTrail().Index();
1160 const int num_newly_fixed = num_fixed - initial_num_fixed;
1161 const int num_variables = sat_solver->NumVariables();
1162 SOLVER_LOG(logger,
"[Random exploration]",
" num_fixed: +",
1165 " dtime: ", elapsed_dtime,
"/", deterministic_time_limit,
1166 " wtime: ", wall_timer.
Get(),
1167 (limit_reached ?
" (Aborted)" :
""));
1169 return sat_solver->FinishPropagation();
1173 : sat_solver_(model->GetOrCreate<
SatSolver>()),
1175 time_limit_(model->GetOrCreate<
TimeLimit>()),
1176 trail_(*model->GetOrCreate<
Trail>()),
1181 binary_propagator_id_(implication_graph_->PropagatorId()),
1182 clause_propagator_id_(clause_manager_->PropagatorId()) {}
1192 num_variables_ = sat_solver_->NumVariables();
1194 to_fix_unit_id_.clear();
1196 num_explicit_fix_ = 0;
1198 num_new_binary_ = 0;
1200 num_lrat_clauses_ = 0;
1201 num_lrat_proof_clauses_ = 0;
1204 if (!sat_solver_->ResetToLevelZero())
return false;
1209 if (!implication_graph_->DetectEquivalences())
return false;
1210 if (!sat_solver_->FinishPropagation())
return false;
1212 const int initial_num_fixed = sat_solver_->LiteralTrail().Index();
1213 const double initial_deterministic_time =
1214 time_limit_->GetElapsedDeterministicTime();
1217 processed_.ClearAndResize(LiteralIndex(2 * num_variables_));
1222 starts_.resize(2 * num_variables_, 0);
1236 probing_order_ = implication_graph_->ReverseTopologicalOrder();
1238 std::reverse(probing_order_.begin(), probing_order_.end());
1243 position_in_order_.clear();
1245 position_in_order_.assign(2 * num_variables_, -1);
1246 for (
int i = 0;
i < probing_order_.size(); ++
i) {
1247 position_in_order_[probing_order_[
i]] =
i;
1251 binary_clause_extracted_.assign(trail_.Index(),
false);
1252 trail_implication_clauses_.assign(trail_.Index(), {kNoClauseId, false});
1254 while (!time_limit_->LimitReached() &&
1255 time_limit_->GetElapsedDeterministicTime() <= limit) {
1258 if (!sat_solver_->BacktrackAndPropagateReimplications(0))
return false;
1259 DeleteTemporaryLratImplicationsAfterBacktrack();
1270 if (sat_solver_->CurrentDecisionLevel() > 0 && options.
use_queue) {
1271 if (!ComputeNextDecisionInOrder(next_decision))
return false;
1273 if (sat_solver_->CurrentDecisionLevel() > 0 &&
1275 if (!GetNextDecisionInNoParticularOrder(next_decision))
return false;
1278 if (sat_solver_->CurrentDecisionLevel() == 0) {
1279 if (!GetFirstDecision(next_decision))
return false;
1285 int first_new_trail_index;
1286 if (!EnqueueDecisionAndBackjumpOnConflict(next_decision, options.
use_queue,
1287 first_new_trail_index)) {
1294 const int new_level = sat_solver_->CurrentDecisionLevel();
1295 if (new_level == 0)
continue;
1296 const Literal last_decision = trail_.Decisions()[new_level - 1].literal;
1297 binary_clauses_to_extract_.clear();
1298 for (
int i = first_new_trail_index;
i < trail_.Index(); ++
i) {
1300 if (l == last_decision)
continue;
1304 DCHECK(!binary_clause_extracted_[
i]);
1307 MaybeSubsumeWithBinaryClause(last_decision, l);
1320 if (trail_.AssignmentType(l.
Variable()) != binary_propagator_id_) {
1321 if (ShouldExtractImplication(l)) {
1322 binary_clauses_to_extract_.push_back(l);
1328 processed_.Set(l.
Index());
1331 if (!binary_clauses_to_extract_.empty()) {
1332 ExtractImplications(last_decision, binary_clauses_to_extract_);
1336 SubsumeWithBinaryClauseUsingBlockingLiteral(last_decision);
1340 if (!sat_solver_->ResetToLevelZero())
return false;
1341 if (!ProcessLiteralsToFix())
return false;
1342 DeleteTemporaryLratImplicationsAfterBacktrack();
1343 clause_manager_->CleanUpWatchers();
1346 const int num_fixed = sat_solver_->LiteralTrail().Index();
1347 const int num_newly_fixed = num_fixed - initial_num_fixed;
1348 const double time_diff =
1349 time_limit_->GetElapsedDeterministicTime() - initial_deterministic_time;
1350 const bool limit_reached = time_limit_->LimitReached() ||
1351 time_limit_->GetElapsedDeterministicTime() > limit;
1354 <<
" num_probed: " << num_probed_ <<
"/" << probing_order_.size()
1355 <<
" num_fixed: +" << num_newly_fixed <<
" (" << num_fixed <<
"/"
1356 << num_variables_ <<
")"
1357 <<
" explicit_fix:" << num_explicit_fix_
1358 <<
" num_conflicts:" << num_conflicts_
1359 <<
" new_binary_clauses: " << num_new_binary_
1360 <<
" num_lrat_clauses: " << num_lrat_clauses_
1361 <<
" num_lrat_proof_clauses: " << num_lrat_proof_clauses_
1362 <<
" subsumed: " << num_subsumed_ <<
" dtime: " << time_diff
1363 <<
" wtime: " << wall_timer.
Get() << (limit_reached ?
" (Aborted)" :
"");
1364 return sat_solver_->FinishPropagation();
1367bool FailedLiteralProbing::SkipCandidate(
Literal last_decision,
1369 if (processed_[candidate])
return true;
1370 if (implication_graph_->
IsRedundant(candidate))
return true;
1375 AddFailedLiteralToFix(candidate);
1383 MaybeExtractImplication(last_decision, candidate);
1393bool FailedLiteralProbing::ComputeNextDecisionInOrder(
1394 LiteralIndex& next_decision) {
1398 const Literal last_decision =
1399 trail_.Decisions()[sat_solver_->CurrentDecisionLevel() - 1].literal;
1403 const absl::Span<const Literal> list =
1404 implication_graph_->Implications(last_decision.Negated());
1405 const int saved_queue_size = queue_.size();
1406 for (
const Literal l : list) {
1407 const Literal candidate = l.Negated();
1408 if (position_in_order_[candidate] == -1)
continue;
1409 if (SkipCandidate(last_decision, candidate))
continue;
1410 queue_.push_back({candidate.Index(), -position_in_order_[candidate]});
1413 std::sort(queue_.begin() + saved_queue_size, queue_.end());
1416 while (!queue_.empty()) {
1417 const LiteralIndex index = queue_.back().literal_index;
1421 CHECK_GT(sat_solver_->CurrentDecisionLevel(), 0);
1422 if (!sat_solver_->BacktrackAndPropagateReimplications(
1423 sat_solver_->CurrentDecisionLevel() - 1)) {
1426 DeleteTemporaryLratImplicationsAfterBacktrack();
1429 const Literal candidate(index);
1430 if (SkipCandidate(last_decision, candidate))
continue;
1431 next_decision = candidate.Index();
1439bool FailedLiteralProbing::GetNextDecisionInNoParticularOrder(
1440 LiteralIndex& next_decision) {
1441 const int level = sat_solver_->CurrentDecisionLevel();
1442 const Literal last_decision = trail_.Decisions()[level - 1].literal;
1443 const absl::Span<const Literal> list =
1444 implication_graph_->Implications(last_decision.Negated());
1449 int j = starts_[last_decision.NegatedIndex()];
1450 for (
int i = 0;
i < list.size(); ++
i, ++j) {
1452 const Literal candidate = Literal(list[j]).Negated();
1453 if (SkipCandidate(last_decision, candidate))
continue;
1454 next_decision = candidate.Index();
1457 starts_[last_decision.NegatedIndex()] = j;
1459 if (!sat_solver_->BacktrackAndPropagateReimplications(level - 1)) {
1462 DeleteTemporaryLratImplicationsAfterBacktrack();
1469bool FailedLiteralProbing::GetFirstDecision(LiteralIndex& next_decision) {
1471 if (!ProcessLiteralsToFix())
return false;
1474 for (; order_index_ < probing_order_.size(); ++order_index_) {
1475 const Literal candidate(probing_order_[order_index_]);
1478 if (processed_[candidate])
continue;
1479 if (assignment_.LiteralIsAssigned(candidate))
continue;
1480 next_decision = candidate.Index();
1486bool FailedLiteralProbing::EnqueueDecisionAndBackjumpOnConflict(
1487 LiteralIndex next_decision,
bool use_queue,
int& first_new_trail_index) {
1489 processed_.Set(next_decision);
1492 const int level = sat_solver_->CurrentDecisionLevel();
1497 auto conflict_callback = [&](ClauseId conflict_id,
1498 absl::Span<const Literal> conflict_clause) {
1499 DeleteTemporaryLratImplicationsAfterBacktrack();
1500 if (fixed_decision_unit_id !=
kNoClauseId)
return;
1501 tmp_clause_ids_.clear();
1502 clause_manager_->AppendClauseIdsFixing(conflict_clause, &tmp_clause_ids_,
1504 tmp_clause_ids_.push_back(conflict_id);
1505 fixed_decision_unit_id = clause_id_generator_->GetNextId();
1506 lrat_proof_handler_->AddInferredClause(fixed_decision_unit_id,
1507 {Literal(next_decision).Negated()},
1509 num_lrat_clauses_++;
1510 num_lrat_proof_clauses_ += tmp_clause_ids_.size();
1512 first_new_trail_index = sat_solver_->EnqueueDecisionAndBackjumpOnConflict(
1513 Literal(next_decision),
1514 lrat_proof_handler_ !=
nullptr
1516 : std::optional<SatSolver::ConflictCallback>());
1519 binary_clause_extracted_.resize(first_new_trail_index);
1520 binary_clause_extracted_.resize(trail_.Index(),
false);
1521 trail_implication_clauses_.resize(first_new_trail_index);
1522 trail_implication_clauses_.resize(trail_.Index(), {kNoClauseId, false});
1526 if (sat_solver_->NumVariables() > num_variables_) {
1527 num_variables_ = sat_solver_->NumVariables();
1528 processed_.Resize(LiteralIndex(2 * num_variables_));
1530 starts_.resize(2 * num_variables_, 0);
1532 position_in_order_.resize(2 * num_variables_, -1);
1536 const int new_level = sat_solver_->CurrentDecisionLevel();
1537 sat_solver_->AdvanceDeterministicTime(time_limit_);
1538 if (sat_solver_->ModelIsUnsat())
return false;
1539 if (new_level <= level) {
1544 if (new_level == 0) {
1547 int queue_level = level + 1;
1548 while (queue_level > new_level) {
1549 CHECK(!queue_.empty());
1571 if (sat_solver_->CurrentDecisionLevel() != 0 ||
1572 !assignment_.LiteralIsFalse(Literal(next_decision))) {
1573 to_fix_.push_back(Literal(next_decision).Negated());
1574 if (lrat_proof_handler_ !=
nullptr) {
1575 to_fix_unit_id_.push_back(fixed_decision_unit_id);
1582bool FailedLiteralProbing::ShouldExtractImplication(
const Literal l) {
1583 const auto& info = trail_.Info(l.Variable());
1585 if (binary_clause_extracted_[info.trail_index])
return false;
1586 binary_clause_extracted_[info.trail_index] =
true;
1589 return info.level > 0;
1592void FailedLiteralProbing::ExtractImplication(
const Literal last_decision,
1593 const Literal l,
bool lrat_only) {
1594 const auto& info = trail_.Info(l.Variable());
1605 DCHECK(assignment_.LiteralIsTrue(l));
1606 CHECK_NE(l.Variable(), last_decision.Variable());
1613 DCHECK(!implication_graph_->IsRedundant(last_decision));
1616 if (lrat_proof_handler_ !=
nullptr) {
1617 clause_id = clause_id_generator_->GetNextId();
1618 tmp_clause_ids_.clear();
1619 clause_manager_->AppendClauseIdsFixing(
1620 {l}, &tmp_clause_ids_, last_decision,
1621 [&](
int ,
int trail_index) {
1622 return trail_implication_clauses_[trail_index].first;
1627 if (info.level == sat_solver_->CurrentDecisionLevel()) {
1628 trail_implication_clauses_[info.trail_index] = {clause_id, lrat_only};
1630 lrat_proof_handler_->AddInferredClause(
1631 clause_id, {last_decision.Negated(), l}, tmp_clause_ids_);
1632 num_lrat_clauses_++;
1633 num_lrat_proof_clauses_ += tmp_clause_ids_.size();
1635 if (lrat_only)
return;
1641 CHECK(implication_graph_->AddBinaryClauseAndChangeReason(
1642 clause_id, l, last_decision.Negated()));
1645void FailedLiteralProbing::MaybeExtractImplication(
const Literal last_decision,
1647 if (ShouldExtractImplication(l)) {
1648 ExtractImplication(last_decision, l);
1652void FailedLiteralProbing::ExtractImplications(
1653 Literal last_decision, absl::Span<const Literal> literals) {
1658 tmp_mark_.ClearAndResize(BooleanVariable(trail_.NumVariables()));
1660 const VariablesAssignment& assignment = trail_.Assignment();
1661 for (
const Literal lit : literals) {
1662 CHECK(assignment.LiteralIsAssigned(lit));
1663 tmp_mark_.Set(lit.Variable());
1664 tmp_heap_.push_back(trail_.Info(lit.Variable()).trail_index);
1666 absl::c_make_heap(tmp_heap_);
1671 tmp_marked_literals_.clear();
1672 while (!tmp_heap_.empty()) {
1673 absl::c_pop_heap(tmp_heap_);
1674 const int trail_index = tmp_heap_.back();
1675 tmp_heap_.pop_back();
1676 const Literal marked_literal = trail_[trail_index];
1677 tmp_marked_literals_.push_back(marked_literal);
1679 DCHECK_GT(trail_.Info(marked_literal.Variable()).level, 0);
1680 DCHECK_NE(trail_.AssignmentType(marked_literal.Variable()),
1683 for (
const Literal literal : trail_.Reason(marked_literal.Variable())) {
1684 const BooleanVariable var = literal.
Variable();
1685 const AssignmentInfo& info = trail_.Info(var);
1686 if (info.level > 0 && !tmp_mark_[var] &&
1689 tmp_heap_.push_back(info.trail_index);
1690 absl::c_push_heap(tmp_heap_);
1700 tmp_mark_.ClearAndResize(BooleanVariable(trail_.NumVariables()));
1701 for (
const Literal lit : literals) {
1702 tmp_mark_.Set(lit.Variable());
1704 for (
int i = tmp_marked_literals_.size() - 1;
i >= 0; --
i) {
1705 const bool lrat_only = !tmp_mark_[tmp_marked_literals_[
i].Variable()];
1706 ExtractImplication(last_decision, tmp_marked_literals_[
i], lrat_only);
1715void FailedLiteralProbing::MaybeSubsumeWithBinaryClause(
1717 const int trail_index = trail_.Info(l.Variable()).trail_index;
1718 if (trail_.AssignmentType(l.Variable()) != clause_propagator_id_)
return;
1719 SatClause* clause = clause_manager_->ReasonClause(trail_index);
1721 bool subsumed =
false;
1722 for (
const Literal lit : trail_.Reason(l.Variable())) {
1723 if (lit == last_decision.Negated()) {
1731 clause_manager_->ChangeLbdIfBetter(clause, 2);
1737 MaybeExtractImplication(last_decision, l);
1740 for (
const Literal lit :
1741 clause_manager_->ReasonClause(trail_index)->AsSpan()) {
1742 if (lit == l) ++test;
1743 if (lit == last_decision.Negated()) ++test;
1748 CHECK(!clause_manager_->ClauseIsUsedAsReason(clause));
1750 clause_manager_->LazyDelete(clause,
1763void FailedLiteralProbing::SubsumeWithBinaryClauseUsingBlockingLiteral(
1764 const Literal last_decision) {
1765 for (
const auto&
w :
1766 clause_manager_->WatcherListOnFalse(last_decision.Negated())) {
1767 if (!assignment_.LiteralIsTrue(
w.blocking_literal))
continue;
1768 if (
w.clause->IsRemoved())
continue;
1771 if (clause_manager_->ClauseIsUsedAsReason(
w.clause)) {
1772 MaybeExtractImplication(last_decision,
w.blocking_literal);
1775 CHECK(!clause_manager_->ClauseIsUsedAsReason(
w.clause));
1779 clause_manager_->LazyDelete(
w.clause,
1787void FailedLiteralProbing::AddFailedLiteralToFix(
const Literal literal) {
1790 if (trail_.AssignmentLevel(literal.Negated()) == 0)
return;
1791 to_fix_.push_back(literal.Negated());
1792 if (lrat_proof_handler_ ==
nullptr)
return;
1794 tmp_clause_ids_.clear();
1795 clause_manager_->AppendClauseIdsFixing({literal.Negated()}, &tmp_clause_ids_,
1797 const ClauseId unit_id = clause_id_generator_->GetNextId();
1798 lrat_proof_handler_->AddInferredClause(unit_id, {literal.Negated()},
1800 to_fix_unit_id_.push_back({unit_id});
1801 num_lrat_clauses_++;
1802 num_lrat_proof_clauses_ += tmp_clause_ids_.size();
1806bool FailedLiteralProbing::ProcessLiteralsToFix() {
1807 for (
int i = 0;
i < to_fix_.size(); ++
i) {
1808 const Literal literal = to_fix_[
i];
1809 if (assignment_.LiteralIsTrue(literal))
continue;
1810 ++num_explicit_fix_;
1811 const ClauseId clause_id =
1812 lrat_proof_handler_ !=
nullptr ? to_fix_unit_id_[
i] :
kNoClauseId;
1813 if (!clause_manager_->InprocessingAddUnitClause(clause_id, literal)) {
1818 to_fix_unit_id_.clear();
1819 return sat_solver_->FinishPropagation();
1822void FailedLiteralProbing::DeleteTemporaryLratImplicationsAfterBacktrack() {
1823 if (lrat_proof_handler_ ==
nullptr)
return;
1824 for (
int i = trail_.Index();
i < trail_implication_clauses_.size(); ++
i) {
1825 auto [clause_id, is_temporary] = trail_implication_clauses_[
i];
1827 lrat_proof_handler_->DeleteClause(clause_id, {});
1830 trail_implication_clauses_.resize(trail_.Index(), {kNoClauseId, false});
bool LoggingIsEnabled() const
void MergeWithGlobalTimeLimit(const TimeLimit *other)
bool IsRedundant(Literal l) const
ClauseId GetClauseId(Literal a, Literal b) const
ClauseId GetClauseId(const SatClause *clause) const
bool DoOneRound(ProbingOptions options)
FailedLiteralProbing(Model *model)
LiteralIndex Index() const
BooleanVariable Variable() const
bool ProbeBooleanVariables(double deterministic_time_limit)
bool ProbeOneVariable(BooleanVariable b)
bool ProbeDnf(absl::string_view name, absl::Span< const std::vector< Literal > > dnf, DnfType type, const SatClause *dnf_clause=nullptr)
absl::Span< const Literal > AsSpan() const
void set_log_search_progress(bool value)
void BlockClauseDeletion(bool value)
int CurrentDecisionLevel() const
int EnqueueDecisionAndBackjumpOnConflict(Literal true_literal, std::optional< ConflictCallback > callback=std::nullopt)
TrailCopy(const Trail &trail, const BinaryImplicationGraph &implication_graph, const ClauseManager &clause_manager)
void AppendClauseIdsFixing(absl::Span< const Literal > literals, std::vector< ClauseId > *clause_ids, LiteralIndex decision, absl::flat_hash_map< std::pair< Literal, Literal >, ClauseId > tmp_binary_clause_ids)
bool VariableIsAssigned(BooleanVariable var) const
bool LiteralIsAssigned(Literal literal) const
bool LiteralIsFalse(Literal literal) const
constexpr IntegerValue kMaxIntegerValue(std::numeric_limits< IntegerValue::ValueType >::max() - 1)
void RandomizeDecisionHeuristic(absl::BitGenRef random, SatParameters *parameters)
const LiteralIndex kNoLiteralIndex(-1)
constexpr IntegerValue kMinIntegerValue(-kMaxIntegerValue.value())
const IntegerVariable kNoIntegerVariable(-1)
bool LookForTrivialSatSolution(double deterministic_time_limit, Model *model, SolverLogger *logger)
IntegerVariable PositiveVariable(IntegerVariable i)
constexpr ClauseId kNoClauseId(0)
const int kUnsatTrailIndex
bool VariableIsPositive(IntegerVariable i)
std::string FormatCounter(int64_t num)
trees with all degrees equal w the current value of w
static constexpr int kSearchDecision
static constexpr int kUnitReason
static constexpr int kCachedReason
static IntegerLiteral GreaterOrEqual(IntegerVariable i, IntegerValue bound)
double deterministic_limit
bool subsume_with_binary_clause
bool extract_binary_clauses
#define SOLVER_LOG(logger,...)