223 const double deterministic_time_limit,
224 absl::Span<const BooleanVariable> bool_vars) {
232 num_new_integer_bounds_ = 0;
233 num_new_literals_fixed_ = 0;
236 const int num_variables = sat_solver_->NumVariables();
237 propagated_.ClearAndResize(LiteralIndex(2 * num_variables));
240 if (!sat_solver_->ResetToLevelZero())
return false;
242 const int initial_num_fixed = sat_solver_->LiteralTrail().Index();
243 const double initial_deterministic_time =
244 time_limit_->GetElapsedDeterministicTime();
245 const double limit = initial_deterministic_time + deterministic_time_limit;
247 bool limit_reached =
false;
250 for (
const BooleanVariable
b : bool_vars) {
252 if (implication_graph_->RepresentativeOf(literal) != literal) {
258 if (time_limit_->LimitReached() ||
259 time_limit_->GetElapsedDeterministicTime() > limit) {
260 limit_reached =
true;
266 if (!ProbeOneVariableInternal(
b)) {
272 const int num_fixed = sat_solver_->LiteralTrail().Index();
273 num_new_literals_fixed_ = num_fixed - initial_num_fixed;
276 if (logger_->LoggingIsEnabled()) {
277 const double time_diff =
278 time_limit_->GetElapsedDeterministicTime() - initial_deterministic_time;
279 SOLVER_LOG(logger_,
"[Probing] deterministic_time: ", time_diff,
280 " (limit: ", deterministic_time_limit,
281 ") wall_time: ", wall_timer.
Get(),
" (",
282 (limit_reached ?
"Aborted " :
""), num_probed,
"/",
283 bool_vars.size(),
")");
284 if (num_new_literals_fixed_ > 0) {
286 "[Probing] - new fixed Boolean: ", num_new_literals_fixed_,
287 " (", num_fixed,
"/", sat_solver_->NumVariables(),
")");
289 if (num_new_holes_ > 0) {
290 SOLVER_LOG(logger_,
"[Probing] - new integer holes: ", num_new_holes_);
292 if (num_new_integer_bounds_ > 0) {
294 "[Probing] - new integer bounds: ", num_new_integer_bounds_);
296 if (num_new_binary_ > 0) {
297 SOLVER_LOG(logger_,
"[Probing] - new binary clause: ", num_new_binary_);
305 absl::Span<
const std::vector<Literal>> dnf) {
306 if (dnf.size() <= 1)
return true;
309 if (!sat_solver_->ResetToLevelZero())
return false;
311 always_propagated_bounds_.clear();
312 always_propagated_literals_.clear();
313 int num_valid_conjunctions = 0;
314 for (
const std::vector<Literal>& conjunction : dnf) {
315 if (!sat_solver_->ResetToLevelZero())
return false;
316 if (num_valid_conjunctions > 0 && always_propagated_bounds_.empty() &&
317 always_propagated_literals_.empty()) {
322 bool conjunction_is_valid =
true;
323 int num_literals_enqueued = 0;
324 const int root_trail_index = trail_.Index();
325 const int root_integer_trail_index = integer_trail_->Index();
326 for (
const Literal& lit : conjunction) {
327 if (assignment_.LiteralIsAssigned(lit)) {
328 if (assignment_.LiteralIsTrue(lit))
continue;
329 conjunction_is_valid =
false;
332 ++num_literals_enqueued;
333 const int decision_level_before_enqueue =
334 sat_solver_->CurrentDecisionLevel();
335 sat_solver_->EnqueueDecisionAndBackjumpOnConflict(lit);
336 sat_solver_->AdvanceDeterministicTime(time_limit_);
337 const int decision_level_after_enqueue =
338 sat_solver_->CurrentDecisionLevel();
341 if (sat_solver_->ModelIsUnsat())
return false;
344 if (decision_level_after_enqueue <= decision_level_before_enqueue) {
345 conjunction_is_valid =
false;
350 if (conjunction_is_valid) {
351 ++num_valid_conjunctions;
357 new_propagated_literals_.clear();
358 for (
int i = root_trail_index;
i < trail_.Index(); ++
i) {
359 const LiteralIndex literal_index = trail_[
i].Index();
360 if (num_valid_conjunctions == 1 ||
361 always_propagated_literals_.contains(literal_index)) {
362 new_propagated_literals_.insert(literal_index);
365 std::swap(new_propagated_literals_, always_propagated_literals_);
368 new_integer_bounds_.clear();
369 integer_trail_->AppendNewBoundsFrom(root_integer_trail_index,
370 &new_integer_bounds_);
371 new_propagated_bounds_.clear();
373 const auto it = always_propagated_bounds_.find(entry.var);
374 if (num_valid_conjunctions == 1) {
375 new_propagated_bounds_[entry.var] = entry.bound;
376 }
else if (it != always_propagated_bounds_.end()) {
377 new_propagated_bounds_[entry.var] = std::min(entry.bound, it->second);
380 std::swap(new_propagated_bounds_, always_propagated_bounds_);
383 if (!sat_solver_->ResetToLevelZero())
return false;
385 const int previous_num_literals_fixed = num_new_literals_fixed_;
386 for (
const LiteralIndex literal_index : always_propagated_literals_) {
387 const Literal lit(literal_index);
388 if (assignment_.LiteralIsTrue(lit))
continue;
389 ++num_new_literals_fixed_;
390 if (!sat_solver_->AddUnitClause(lit))
return false;
394 int previous_num_integer_bounds = num_new_integer_bounds_;
395 for (
const auto& [var, bound] : always_propagated_bounds_) {
396 if (bound > integer_trail_->LowerBound(var)) {
397 ++num_new_integer_bounds_;
405 if (!sat_solver_->FinishPropagation())
return false;
407 if (num_new_integer_bounds_ > previous_num_integer_bounds ||
408 num_new_literals_fixed_ > previous_num_literals_fixed) {
409 VLOG(1) <<
"ProbeDnf(" << name <<
", num_fixed_literals="
410 << num_new_literals_fixed_ - previous_num_literals_fixed
411 <<
", num_pushed_integer_bounds="
412 << num_new_integer_bounds_ - previous_num_integer_bounds
413 <<
", num_valid_conjunctions=" << num_valid_conjunctions <<
"/"
414 << dnf.size() <<
")";
430 if (!sat_solver->ResetToLevelZero())
return false;
433 const int initial_num_fixed = sat_solver->LiteralTrail().Index();
437 SatParameters initial_params = *model->
GetOrCreate<SatParameters>();
438 SatParameters new_params = initial_params;
439 new_params.set_log_search_progress(
false);
440 new_params.set_max_number_of_conflicts(1);
441 new_params.set_max_deterministic_time(deterministic_time_limit);
443 double elapsed_dtime = 0.0;
445 const int num_times = 1000;
446 bool limit_reached =
false;
448 for (
int i = 0;
i < num_times; ++
i) {
450 elapsed_dtime > deterministic_time_limit) {
451 limit_reached =
true;
456 sat_solver->SetParameters(new_params);
457 sat_solver->ResetDecisionHeuristic();
459 elapsed_dtime +=
time_limit->GetElapsedDeterministicTime();
462 SOLVER_LOG(logger,
"Trivial exploration found feasible solution!");
463 time_limit->AdvanceDeterministicTime(elapsed_dtime);
467 if (!sat_solver->ResetToLevelZero()) {
468 SOLVER_LOG(logger,
"UNSAT during trivial exploration heuristic.");
469 time_limit->AdvanceDeterministicTime(elapsed_dtime);
476 new_params.set_random_seed(
i);
477 new_params.set_max_deterministic_time(deterministic_time_limit -
482 sat_solver->SetParameters(initial_params);
483 sat_solver->ResetDecisionHeuristic();
484 time_limit->AdvanceDeterministicTime(elapsed_dtime);
485 if (!sat_solver->ResetToLevelZero())
return false;
488 const int num_fixed = sat_solver->LiteralTrail().Index();
489 const int num_newly_fixed = num_fixed - initial_num_fixed;
490 const int num_variables = sat_solver->NumVariables();
491 SOLVER_LOG(logger,
"[Random exploration]",
" num_fixed: +", num_newly_fixed,
492 " (", num_fixed,
"/", num_variables,
")",
493 " dtime: ", elapsed_dtime,
"/", deterministic_time_limit,
494 " wtime: ", wall_timer.
Get(),
495 (limit_reached ?
" (Aborted)" :
""));
497 return sat_solver->FinishPropagation();
507 if (!sat_solver->ResetToLevelZero())
return false;
513 if (!implication_graph->DetectEquivalences())
return false;
514 if (!sat_solver->FinishPropagation())
return false;
517 const int initial_num_fixed = sat_solver->LiteralTrail().Index();
518 const double initial_deterministic_time =
522 const int num_variables = sat_solver->NumVariables();
525 int64_t num_probed = 0;
526 int64_t num_explicit_fix = 0;
527 int64_t num_conflicts = 0;
528 int64_t num_new_binary = 0;
529 int64_t num_subsumed = 0;
531 const auto& trail = *(model->
Get<
Trail>());
532 const auto& assignment = trail.Assignment();
535 const int clause_id = clause_manager->PropagatorId();
538 struct SavedNextLiteral {
539 LiteralIndex literal_index;
542 bool operator<(
const SavedNextLiteral& o)
const {
return rank < o.rank; }
544 std::vector<SavedNextLiteral> queue;
553 std::vector<Literal> to_fix;
567 std::vector<LiteralIndex> probing_order =
568 implication_graph->ReverseTopologicalOrder();
570 std::reverse(probing_order.begin(), probing_order.end());
575 position_in_order.
assign(2 * num_variables, -1);
576 for (
int i = 0;
i < probing_order.size(); ++
i) {
577 position_in_order[probing_order[
i]] =
i;
582 time_limit->GetElapsedDeterministicTime() <= limit) {
587 if (options.
use_queue && sat_solver->CurrentDecisionLevel() > 0) {
592 sat_solver->Decisions()[sat_solver->CurrentDecisionLevel() - 1]
595 implication_graph->Implications(prev_decision.
Negated());
596 const int saved_queue_size = queue.size();
599 if (processed[candidate])
continue;
600 if (position_in_order[candidate] == -1)
continue;
601 if (assignment.LiteralIsAssigned(candidate)) {
602 if (assignment.LiteralIsFalse(candidate)) {
607 queue.push_back({candidate.
Index(), -position_in_order[candidate]});
609 std::sort(queue.begin() + saved_queue_size, queue.end());
612 while (!queue.empty()) {
613 const LiteralIndex index = queue.back().literal_index;
617 CHECK_GT(sat_solver->CurrentDecisionLevel(), 0);
618 sat_solver->Backtrack(sat_solver->CurrentDecisionLevel() - 1);
621 const Literal candidate(index);
622 if (processed[candidate])
continue;
623 if (assignment.LiteralIsAssigned(candidate)) {
624 if (assignment.LiteralIsFalse(candidate)) {
629 next_decision = candidate.
Index();
634 if (sat_solver->CurrentDecisionLevel() == 0) {
636 for (
const Literal literal : to_fix) {
637 if (!assignment.LiteralIsTrue(literal)) {
639 if (!sat_solver->AddUnitClause(literal))
return false;
643 if (!sat_solver->FinishPropagation())
return false;
646 for (; order_index < probing_order.size(); ++order_index) {
647 const Literal candidate(probing_order[order_index]);
648 if (processed[candidate])
continue;
649 if (assignment.LiteralIsAssigned(candidate))
continue;
650 next_decision = candidate.
Index();
657 const int level = sat_solver->CurrentDecisionLevel();
658 const Literal prev_decision = sat_solver->Decisions()[level - 1].literal;
660 implication_graph->Implications(prev_decision.
Negated());
667 for (
int i = 0;
i < list.size(); ++
i, ++j) {
670 if (processed[candidate])
continue;
671 if (assignment.LiteralIsFalse(candidate)) {
678 if (assignment.LiteralIsTrue(candidate))
continue;
679 next_decision = candidate.
Index();
684 sat_solver->Backtrack(level - 1);
690 processed.
Set(next_decision);
693 const int level = sat_solver->CurrentDecisionLevel();
694 const int first_new_trail_index =
695 sat_solver->EnqueueDecisionAndBackjumpOnConflict(
697 const int new_level = sat_solver->CurrentDecisionLevel();
698 sat_solver->AdvanceDeterministicTime(
time_limit);
699 if (sat_solver->ModelIsUnsat())
return false;
700 if (new_level <= level) {
705 if (new_level == 0) {
708 int queue_level = level + 1;
709 while (queue_level > new_level) {
710 CHECK(!queue.empty());
732 if (sat_solver->CurrentDecisionLevel() != 0 ||
733 assignment.LiteralIsFalse(
Literal(next_decision))) {
734 to_fix.push_back(
Literal(next_decision).Negated());
741 if (new_level == 0)
continue;
743 sat_solver->Decisions()[new_level - 1].literal;
744 int num_new_subsumed = 0;
745 for (
int i = first_new_trail_index;
i < trail.Index(); ++
i) {
747 if (l == last_decision)
continue;
754 bool subsumed =
false;
756 trail.AssignmentType(l.
Variable()) == clause_id) {
758 if (lit == last_decision.
Negated()) {
766 CHECK(implication_graph->AddBinaryClause(last_decision.
Negated(), l));
767 const int trail_index = trail.Info(l.
Variable()).trail_index;
771 clause_manager->ReasonClause(trail_index)->AsSpan()) {
772 if (lit == l) ++test;
773 if (lit == last_decision.
Negated()) ++test;
776 clause_manager->LazyDetach(clause_manager->ReasonClause(trail_index));
779 implication_graph->ChangeReason(trail_index, last_decision);
801 if (!subsumed && trail.AssignmentType(l.
Variable()) !=
id) {
803 CHECK(implication_graph->AddBinaryClause(last_decision.
Negated(), l));
829 const bool always_add_binary = sat_solver->CurrentDecisionLevel() > 1 &&
833 clause_manager->WatcherListOnFalse(last_decision.
Negated())) {
834 if (assignment.LiteralIsTrue(
w.blocking_literal)) {
835 if (
w.clause->IsRemoved())
continue;
836 CHECK_NE(
w.blocking_literal, last_decision.
Negated());
846 if (always_add_binary ||
847 trail.AssignmentType(
w.blocking_literal.Variable()) !=
id) {
850 const auto& info = trail.Info(
w.blocking_literal.Variable());
851 if (info.level > 0) {
853 CHECK(implication_graph->AddBinaryClause(last_decision.
Negated(),
854 w.blocking_literal));
856 const Literal d = sat_solver->Decisions()[info.level - 1].literal;
857 if (d !=
w.blocking_literal) {
858 implication_graph->ChangeReason(info.trail_index, d);
864 clause_manager->LazyDetach(
w.clause);
869 if (num_new_subsumed > 0) {
873 clause_manager->CleanUpWatchers();
874 num_subsumed += num_new_subsumed;
878 if (!sat_solver->ResetToLevelZero())
return false;
879 for (
const Literal literal : to_fix) {
881 if (!sat_solver->AddUnitClause(literal))
return false;
884 if (!sat_solver->FinishPropagation())
return false;
887 const int num_fixed = sat_solver->LiteralTrail().Index();
888 const int num_newly_fixed = num_fixed - initial_num_fixed;
889 const double time_diff =
890 time_limit->GetElapsedDeterministicTime() - initial_deterministic_time;
891 const bool limit_reached =
time_limit->LimitReached() ||
892 time_limit->GetElapsedDeterministicTime() > limit;
895 <<
" num_probed: " << num_probed <<
" num_fixed: +" << num_newly_fixed
896 <<
" (" << num_fixed <<
"/" << num_variables <<
")"
897 <<
" explicit_fix:" << num_explicit_fix
898 <<
" num_conflicts:" << num_conflicts
899 <<
" new_binary_clauses: " << num_new_binary
900 <<
" subsumed: " << num_subsumed <<
" dtime: " << time_diff
901 <<
" wtime: " << wall_timer.
Get() << (limit_reached ?
" (Aborted)" :
"");
902 return sat_solver->FinishPropagation();