221 const double deterministic_time_limit,
222 absl::Span<const BooleanVariable> bool_vars) {
230 num_new_integer_bounds_ = 0;
231 num_new_literals_fixed_ = 0;
241 const double initial_deterministic_time =
243 const double limit = initial_deterministic_time + deterministic_time_limit;
245 bool limit_reached =
false;
248 for (
const BooleanVariable
b : bool_vars) {
258 limit_reached =
true;
264 if (!ProbeOneVariableInternal(
b)) {
271 num_new_literals_fixed_ = num_fixed - initial_num_fixed;
275 const double time_diff =
277 SOLVER_LOG(logger_,
"[Probing] deterministic_time: ", time_diff,
278 " (limit: ", deterministic_time_limit,
279 ") wall_time: ", wall_timer.
Get(),
" (",
280 (limit_reached ?
"Aborted " :
""), num_probed,
"/",
281 bool_vars.size(),
")");
282 if (num_new_literals_fixed_ > 0) {
284 "[Probing] - new fixed Boolean: ", num_new_literals_fixed_,
285 " (", num_fixed,
"/", sat_solver_->
NumVariables(),
")");
287 if (num_new_holes_ > 0) {
288 SOLVER_LOG(logger_,
"[Probing] - new integer holes: ", num_new_holes_);
290 if (num_new_integer_bounds_ > 0) {
292 "[Probing] - new integer bounds: ", num_new_integer_bounds_);
294 if (num_new_binary_ > 0) {
295 SOLVER_LOG(logger_,
"[Probing] - new binary clause: ", num_new_binary_);
303 absl::Span<
const std::vector<Literal>> dnf) {
304 if (dnf.size() <= 1)
return true;
309 always_propagated_bounds_.clear();
310 always_propagated_literals_.clear();
311 int num_valid_conjunctions = 0;
312 for (
const std::vector<Literal>& conjunction : dnf) {
314 if (num_valid_conjunctions > 0 && always_propagated_bounds_.empty() &&
315 always_propagated_literals_.empty()) {
320 bool conjunction_is_valid =
true;
321 int num_literals_enqueued = 0;
322 const int root_trail_index = trail_.
Index();
323 const int root_integer_trail_index = integer_trail_->
Index();
327 conjunction_is_valid =
false;
330 ++num_literals_enqueued;
331 const int decision_level_before_enqueue =
335 const int decision_level_after_enqueue =
342 if (decision_level_after_enqueue <= decision_level_before_enqueue) {
343 conjunction_is_valid =
false;
348 if (conjunction_is_valid) {
349 ++num_valid_conjunctions;
355 new_propagated_literals_.clear();
356 for (
int i = root_trail_index;
i < trail_.
Index(); ++
i) {
357 const LiteralIndex literal_index = trail_[
i].
Index();
358 if (num_valid_conjunctions == 1 ||
359 always_propagated_literals_.contains(literal_index)) {
360 new_propagated_literals_.insert(literal_index);
363 std::swap(new_propagated_literals_, always_propagated_literals_);
366 new_integer_bounds_.clear();
368 &new_integer_bounds_);
369 new_propagated_bounds_.clear();
371 const auto it = always_propagated_bounds_.find(entry.var);
372 if (num_valid_conjunctions == 1) {
373 new_propagated_bounds_[entry.var] = entry.bound;
374 }
else if (it != always_propagated_bounds_.end()) {
375 new_propagated_bounds_[entry.var] = std::min(entry.bound, it->second);
378 std::swap(new_propagated_bounds_, always_propagated_bounds_);
383 const int previous_num_literals_fixed = num_new_literals_fixed_;
384 for (
const LiteralIndex literal_index : always_propagated_literals_) {
387 ++num_new_literals_fixed_;
392 int previous_num_integer_bounds = num_new_integer_bounds_;
393 for (
const auto& [
var,
bound] : always_propagated_bounds_) {
395 ++num_new_integer_bounds_;
405 if (num_new_integer_bounds_ > previous_num_integer_bounds ||
406 num_new_literals_fixed_ > previous_num_literals_fixed) {
407 VLOG(1) <<
"ProbeDnf(" <<
name <<
", num_fixed_literals="
408 << num_new_literals_fixed_ - previous_num_literals_fixed
409 <<
", num_pushed_integer_bounds="
410 << num_new_integer_bounds_ - previous_num_integer_bounds
411 <<
", num_valid_conjunctions=" << num_valid_conjunctions <<
"/"
412 << dnf.size() <<
")";
428 if (!sat_solver->ResetToLevelZero())
return false;
431 const int initial_num_fixed = sat_solver->LiteralTrail().Index();
435 SatParameters initial_params = *
model->GetOrCreate<SatParameters>();
436 SatParameters new_params = initial_params;
437 new_params.set_log_search_progress(
false);
438 new_params.set_max_number_of_conflicts(1);
439 new_params.set_max_deterministic_time(deterministic_time_limit);
441 double elapsed_dtime = 0.0;
443 const int num_times = 1000;
444 bool limit_reached =
false;
446 for (
int i = 0;
i < num_times; ++
i) {
448 elapsed_dtime > deterministic_time_limit) {
449 limit_reached =
true;
454 sat_solver->SetParameters(new_params);
455 sat_solver->ResetDecisionHeuristic();
457 elapsed_dtime +=
time_limit->GetElapsedDeterministicTime();
460 SOLVER_LOG(logger,
"Trivial exploration found feasible solution!");
461 time_limit->AdvanceDeterministicTime(elapsed_dtime);
465 if (!sat_solver->ResetToLevelZero()) {
466 SOLVER_LOG(logger,
"UNSAT during trivial exploration heuristic.");
467 time_limit->AdvanceDeterministicTime(elapsed_dtime);
474 new_params.set_random_seed(
i);
475 new_params.set_max_deterministic_time(deterministic_time_limit -
480 sat_solver->SetParameters(initial_params);
481 sat_solver->ResetDecisionHeuristic();
482 time_limit->AdvanceDeterministicTime(elapsed_dtime);
483 if (!sat_solver->ResetToLevelZero())
return false;
486 const int num_fixed = sat_solver->LiteralTrail().Index();
487 const int num_newly_fixed = num_fixed - initial_num_fixed;
488 const int num_variables = sat_solver->NumVariables();
489 SOLVER_LOG(logger,
"[Random exploration]",
" num_fixed: +", num_newly_fixed,
490 " (", num_fixed,
"/", num_variables,
")",
491 " dtime: ", elapsed_dtime,
"/", deterministic_time_limit,
492 " wtime: ", wall_timer.
Get(),
493 (limit_reached ?
" (Aborted)" :
""));
495 return sat_solver->FinishPropagation();
505 if (!sat_solver->ResetToLevelZero())
return false;
511 if (!implication_graph->DetectEquivalences())
return false;
512 if (!sat_solver->FinishPropagation())
return false;
515 const int initial_num_fixed = sat_solver->LiteralTrail().Index();
516 const double initial_deterministic_time =
520 const int num_variables = sat_solver->NumVariables();
523 int64_t num_probed = 0;
524 int64_t num_explicit_fix = 0;
525 int64_t num_conflicts = 0;
526 int64_t num_new_binary = 0;
527 int64_t num_subsumed = 0;
530 const auto& assignment = trail.Assignment();
533 const int clause_id = clause_manager->PropagatorId();
536 struct SavedNextLiteral {
537 LiteralIndex literal_index;
540 bool operator<(
const SavedNextLiteral& o)
const {
return rank < o.rank; }
542 std::vector<SavedNextLiteral> queue;
551 std::vector<Literal> to_fix;
565 std::vector<LiteralIndex> probing_order =
566 implication_graph->ReverseTopologicalOrder();
568 std::reverse(probing_order.begin(), probing_order.end());
573 position_in_order.
assign(2 * num_variables, -1);
574 for (
int i = 0;
i < probing_order.size(); ++
i) {
575 position_in_order[probing_order[
i]] =
i;
580 time_limit->GetElapsedDeterministicTime() <= limit) {
585 if (options.
use_queue && sat_solver->CurrentDecisionLevel() > 0) {
590 sat_solver->Decisions()[sat_solver->CurrentDecisionLevel() - 1]
593 implication_graph->Implications(prev_decision.
Negated());
594 const int saved_queue_size = queue.size();
597 if (processed[candidate])
continue;
598 if (position_in_order[candidate] == -1)
continue;
599 if (assignment.LiteralIsAssigned(candidate)) {
600 if (assignment.LiteralIsFalse(candidate)) {
605 queue.push_back({candidate.
Index(), -position_in_order[candidate]});
607 std::sort(queue.begin() + saved_queue_size, queue.end());
610 while (!queue.empty()) {
611 const LiteralIndex
index = queue.back().literal_index;
615 CHECK_GT(sat_solver->CurrentDecisionLevel(), 0);
616 sat_solver->Backtrack(sat_solver->CurrentDecisionLevel() - 1);
620 if (processed[candidate])
continue;
621 if (assignment.LiteralIsAssigned(candidate)) {
622 if (assignment.LiteralIsFalse(candidate)) {
627 next_decision = candidate.
Index();
632 if (sat_solver->CurrentDecisionLevel() == 0) {
635 if (!assignment.LiteralIsTrue(
literal)) {
637 if (!sat_solver->AddUnitClause(
literal))
return false;
641 if (!sat_solver->FinishPropagation())
return false;
644 for (; order_index < probing_order.size(); ++order_index) {
645 const Literal candidate(probing_order[order_index]);
646 if (processed[candidate])
continue;
647 if (assignment.LiteralIsAssigned(candidate))
continue;
648 next_decision = candidate.
Index();
655 const int level = sat_solver->CurrentDecisionLevel();
656 const Literal prev_decision = sat_solver->Decisions()[level - 1].literal;
658 implication_graph->Implications(prev_decision.
Negated());
665 for (
int i = 0;
i < list.size(); ++
i, ++j) {
668 if (processed[candidate])
continue;
669 if (assignment.LiteralIsFalse(candidate)) {
676 if (assignment.LiteralIsTrue(candidate))
continue;
677 next_decision = candidate.
Index();
682 sat_solver->Backtrack(level - 1);
688 processed.
Set(next_decision);
691 const int level = sat_solver->CurrentDecisionLevel();
692 const int first_new_trail_index =
693 sat_solver->EnqueueDecisionAndBackjumpOnConflict(
695 const int new_level = sat_solver->CurrentDecisionLevel();
696 sat_solver->AdvanceDeterministicTime(
time_limit);
697 if (sat_solver->ModelIsUnsat())
return false;
698 if (new_level <= level) {
703 if (new_level == 0) {
706 int queue_level = level + 1;
707 while (queue_level > new_level) {
708 CHECK(!queue.empty());
730 if (sat_solver->CurrentDecisionLevel() != 0 ||
731 assignment.LiteralIsFalse(
Literal(next_decision))) {
732 to_fix.push_back(
Literal(next_decision).Negated());
739 if (new_level == 0)
continue;
741 sat_solver->Decisions()[new_level - 1].literal;
742 int num_new_subsumed = 0;
743 for (
int i = first_new_trail_index;
i < trail.Index(); ++
i) {
745 if (l == last_decision)
continue;
752 bool subsumed =
false;
754 trail.AssignmentType(l.
Variable()) == clause_id) {
764 CHECK(implication_graph->AddBinaryClause(last_decision.
Negated(), l));
765 const int trail_index = trail.Info(l.
Variable()).trail_index;
769 clause_manager->ReasonClause(trail_index)->AsSpan()) {
770 if (
lit == l) ++test;
774 clause_manager->LazyDetach(clause_manager->ReasonClause(trail_index));
777 implication_graph->ChangeReason(trail_index, last_decision);
799 if (!subsumed && trail.AssignmentType(l.
Variable()) !=
id) {
801 CHECK(implication_graph->AddBinaryClause(last_decision.
Negated(), l));
827 const bool always_add_binary = sat_solver->CurrentDecisionLevel() > 1 &&
831 clause_manager->WatcherListOnFalse(last_decision.
Negated())) {
832 if (assignment.LiteralIsTrue(
w.blocking_literal)) {
833 if (
w.clause->IsRemoved())
continue;
834 CHECK_NE(
w.blocking_literal, last_decision.
Negated());
844 if (always_add_binary ||
845 trail.AssignmentType(
w.blocking_literal.Variable()) !=
id) {
848 const auto& info = trail.Info(
w.blocking_literal.Variable());
849 if (info.level > 0) {
851 CHECK(implication_graph->AddBinaryClause(last_decision.
Negated(),
852 w.blocking_literal));
854 const Literal d = sat_solver->Decisions()[info.level - 1].literal;
855 if (d !=
w.blocking_literal) {
856 implication_graph->ChangeReason(info.trail_index, d);
862 clause_manager->LazyDetach(
w.clause);
867 if (num_new_subsumed > 0) {
871 clause_manager->CleanUpWatchers();
872 num_subsumed += num_new_subsumed;
876 if (!sat_solver->ResetToLevelZero())
return false;
879 if (!sat_solver->AddUnitClause(
literal))
return false;
882 if (!sat_solver->FinishPropagation())
return false;
885 const int num_fixed = sat_solver->LiteralTrail().Index();
886 const int num_newly_fixed = num_fixed - initial_num_fixed;
887 const double time_diff =
888 time_limit->GetElapsedDeterministicTime() - initial_deterministic_time;
889 const bool limit_reached =
time_limit->LimitReached() ||
890 time_limit->GetElapsedDeterministicTime() > limit;
892 <<
"Probing. " <<
" num_probed: " << num_probed <<
" num_fixed: +"
893 << num_newly_fixed <<
" (" << num_fixed <<
"/" << num_variables <<
")"
894 <<
" explicit_fix:" << num_explicit_fix
895 <<
" num_conflicts:" << num_conflicts
896 <<
" new_binary_clauses: " << num_new_binary
897 <<
" subsumed: " << num_subsumed <<
" dtime: " << time_diff
898 <<
" wtime: " << wall_timer.
Get() << (limit_reached ?
" (Aborted)" :
"");
899 return sat_solver->FinishPropagation();