43 std::vector<BooleanVariable> bool_vars;
44 for (BooleanVariable
b(0);
b < num_variables; ++
b) {
49 bool_vars.push_back(
b);
54 bool Prober::ProbeOneVariableInternal(BooleanVariable
b) {
55 new_integer_bounds_.clear();
61 const int saved_index = trail_.
Index();
70 for (
int i = saved_index + 1; i < trail_.
Index(); ++i) {
71 const Literal l = trail_[i];
74 if (decision.IsPositive()) {
75 propagated_.
Set(l.Index());
77 if (propagated_[l.Index()]) {
78 to_fix_at_true_.push_back(l);
87 new_binary_clauses_.push_back({decision.Negated(), l});
93 for (
const Literal l : to_fix_at_true_) {
96 to_fix_at_true_.clear();
98 num_new_binary_ += new_binary_clauses_.size();
99 for (
auto binary : new_binary_clauses_) {
102 new_binary_clauses_.clear();
118 std::sort(new_integer_bounds_.begin(), new_integer_bounds_.end(),
119 [](IntegerLiteral
a, IntegerLiteral
b) { return a.var < b.var; });
125 new_integer_bounds_.push_back(IntegerLiteral());
127 for (
int i = 0; i < new_integer_bounds_.size(); ++i) {
128 const IntegerVariable
var = new_integer_bounds_[i].var;
132 if (ub_min + 1 < lb_max) {
137 const Domain old_domain =
140 Domain(ub_min.value() + 1, lb_max.value() - 1).Complement());
141 if (new_domain != old_domain) {
162 if (i == 0 || new_integer_bounds_[i - 1].
var !=
var)
continue;
163 const IntegerValue new_bound =
std::min(new_integer_bounds_[i - 1].
bound,
164 new_integer_bounds_[i].
bound);
166 ++num_new_integer_bounds_;
182 num_new_integer_bounds_ = 0;
192 return ProbeOneVariableInternal(
b);
196 absl::Span<const BooleanVariable> bool_vars,
205 num_new_integer_bounds_ = 0;
216 const double initial_deterministic_time =
218 const double limit = initial_deterministic_time + deterministic_time_limit;
220 bool limit_reached =
false;
223 for (
const BooleanVariable
b : bool_vars) {
233 limit_reached =
true;
239 if (!ProbeOneVariableInternal(
b)) {
246 const double time_diff =
249 const int num_newly_fixed = num_fixed - initial_num_fixed;
250 LOG(
INFO) <<
"Probing deterministic_time: " << time_diff
251 <<
" (limit: " << deterministic_time_limit
253 << (limit_reached ?
"Aborted " :
"") << num_probed <<
"/"
254 << bool_vars.size() <<
")";
256 <<
" - new fixed Boolean: " << num_newly_fixed <<
" (" << num_fixed
259 <<
" - new integer holes: " << num_new_holes_;
261 <<
" - new integer bounds: " << num_new_integer_bounds_;
263 <<
" - new binary clause: " << num_new_binary_;
278 if (!sat_solver->RestoreSolverToAssumptionLevel())
return false;
281 const int initial_num_fixed = sat_solver->LiteralTrail().Index();
285 SatParameters initial_params = *
model->GetOrCreate<SatParameters>();
286 SatParameters new_params = initial_params;
287 new_params.set_log_search_progress(
false);
288 new_params.set_max_number_of_conflicts(1);
289 new_params.set_max_deterministic_time(deterministic_time_limit);
291 double elapsed_dtime = 0.0;
293 const int num_times = 1000;
294 bool limit_reached =
false;
296 for (
int i = 0; i < num_times; ++i) {
298 elapsed_dtime > deterministic_time_limit) {
299 limit_reached =
true;
304 sat_solver->SetParameters(new_params);
305 sat_solver->ResetDecisionHeuristic();
307 elapsed_dtime +=
time_limit->GetElapsedDeterministicTime();
310 LOG_IF(
INFO, log_info) <<
"Trivial exploration found feasible solution!";
311 time_limit->AdvanceDeterministicTime(elapsed_dtime);
315 if (!sat_solver->RestoreSolverToAssumptionLevel()) {
316 LOG_IF(
INFO, log_info) <<
"UNSAT during trivial exploration heuristic.";
317 time_limit->AdvanceDeterministicTime(elapsed_dtime);
324 new_params.set_random_seed(i);
325 new_params.set_max_deterministic_time(deterministic_time_limit -
330 sat_solver->SetParameters(initial_params);
331 sat_solver->ResetDecisionHeuristic();
332 time_limit->AdvanceDeterministicTime(elapsed_dtime);
333 if (!sat_solver->RestoreSolverToAssumptionLevel())
return false;
336 const int num_fixed = sat_solver->LiteralTrail().Index();
337 const int num_newly_fixed = num_fixed - initial_num_fixed;
338 const int num_variables = sat_solver->NumVariables();
339 LOG(
INFO) <<
"Random exploration."
340 <<
" num_fixed: +" << num_newly_fixed <<
" (" << num_fixed <<
"/"
341 << num_variables <<
")"
342 <<
" dtime: " << elapsed_dtime <<
"/" << deterministic_time_limit
344 << (limit_reached ?
" (Aborted)" :
"");
346 return sat_solver->FinishPropagation();
357 if (!sat_solver->RestoreSolverToAssumptionLevel())
return false;
363 if (!implication_graph->DetectEquivalences())
return false;
364 if (!sat_solver->FinishPropagation())
return false;
367 const int initial_num_fixed = sat_solver->LiteralTrail().Index();
368 const double initial_deterministic_time =
372 const int num_variables = sat_solver->NumVariables();
375 int64 num_probed = 0;
376 int64 num_explicit_fix = 0;
377 int64 num_conflicts = 0;
378 int64 num_new_binary = 0;
379 int64 num_subsumed = 0;
382 const auto& assignment = trail.Assignment();
385 const int clause_id = clause_manager->PropagatorId();
388 struct SavedNextLiteral {
389 LiteralIndex literal_index;
392 bool operator<(
const SavedNextLiteral& o)
const {
return rank < o.rank; }
394 std::vector<SavedNextLiteral> queue;
403 std::vector<Literal> to_fix;
417 std::vector<LiteralIndex> probing_order =
418 implication_graph->ReverseTopologicalOrder();
420 std::reverse(probing_order.begin(), probing_order.end());
425 position_in_order.
assign(2 * num_variables, -1);
426 for (
int i = 0; i < probing_order.size(); ++i) {
427 position_in_order[probing_order[i]] = i;
432 time_limit->GetElapsedDeterministicTime() <= limit) {
437 if (options.
use_queue && sat_solver->CurrentDecisionLevel() > 0) {
442 sat_solver->Decisions()[sat_solver->CurrentDecisionLevel() - 1]
445 implication_graph->Implications(prev_decision.
Negated());
446 const int saved_queue_size = queue.size();
449 if (processed[candidate.
Index()])
continue;
450 if (position_in_order[candidate.
Index()] == -1)
continue;
451 if (assignment.LiteralIsAssigned(candidate)) {
452 if (assignment.LiteralIsFalse(candidate)) {
458 {candidate.
Index(), -position_in_order[candidate.
Index()]});
460 std::sort(queue.begin() + saved_queue_size, queue.end());
463 while (!queue.empty()) {
464 const LiteralIndex
index = queue.back().literal_index;
468 CHECK_GT(sat_solver->CurrentDecisionLevel(), 0);
469 sat_solver->Backtrack(sat_solver->CurrentDecisionLevel() - 1);
473 if (processed[candidate.
Index()])
continue;
474 if (assignment.LiteralIsAssigned(candidate)) {
475 if (assignment.LiteralIsFalse(candidate)) {
480 next_decision = candidate.
Index();
485 if (sat_solver->CurrentDecisionLevel() == 0) {
488 if (!assignment.LiteralIsTrue(
literal)) {
490 sat_solver->AddUnitClause(
literal);
494 if (!sat_solver->FinishPropagation())
return false;
497 for (; order_index < probing_order.size(); ++order_index) {
498 const Literal candidate(probing_order[order_index]);
499 if (processed[candidate.
Index()])
continue;
500 if (assignment.LiteralIsAssigned(candidate))
continue;
501 next_decision = candidate.
Index();
508 const int level = sat_solver->CurrentDecisionLevel();
509 const Literal prev_decision = sat_solver->Decisions()[level - 1].literal;
511 implication_graph->Implications(prev_decision.
Negated());
518 for (
int i = 0; i < list.size(); ++i, ++j) {
521 if (processed[candidate.
Index()])
continue;
522 if (assignment.LiteralIsFalse(candidate)) {
529 if (assignment.LiteralIsTrue(candidate))
continue;
530 next_decision = candidate.
Index();
535 sat_solver->Backtrack(level - 1);
541 processed.
Set(next_decision);
544 const int level = sat_solver->CurrentDecisionLevel();
545 const int first_new_trail_index =
546 sat_solver->EnqueueDecisionAndBackjumpOnConflict(
548 const int new_level = sat_solver->CurrentDecisionLevel();
549 sat_solver->AdvanceDeterministicTime(
time_limit);
550 if (sat_solver->IsModelUnsat())
return false;
551 if (new_level <= level) {
556 if (new_level == 0) {
559 int queue_level = level + 1;
560 while (queue_level > new_level) {
561 CHECK(!queue.empty());
583 if (sat_solver->CurrentDecisionLevel() != 0 ||
584 assignment.LiteralIsFalse(
Literal(next_decision))) {
585 to_fix.push_back(
Literal(next_decision).Negated());
592 if (new_level == 0)
continue;
594 sat_solver->Decisions()[new_level - 1].literal;
595 int num_new_subsumed = 0;
596 for (
int i = first_new_trail_index; i < trail.Index(); ++i) {
598 if (l == last_decision)
continue;
605 bool subsumed =
false;
607 trail.AssignmentType(l.
Variable()) == clause_id) {
609 if (lit == last_decision.
Negated()) {
617 implication_graph->AddBinaryClause(last_decision.
Negated(), l);
618 const int trail_index = trail.Info(l.
Variable()).trail_index;
622 clause_manager->ReasonClause(trail_index)->AsSpan()) {
623 if (lit == l) ++test;
624 if (lit == last_decision.
Negated()) ++test;
627 clause_manager->LazyDetach(clause_manager->ReasonClause(trail_index));
630 implication_graph->ChangeReason(trail_index, last_decision);
652 if (!subsumed && trail.AssignmentType(l.
Variable()) !=
id) {
654 implication_graph->AddBinaryClause(last_decision.
Negated(), l);
674 clause_manager->WatcherListOnFalse(last_decision.
Negated())) {
675 if (assignment.LiteralIsTrue(w.blocking_literal)) {
676 if (w.clause->empty())
continue;
687 if (trail.AssignmentType(w.blocking_literal.Variable()) !=
id) {
689 implication_graph->AddBinaryClause(last_decision.
Negated(),
692 const auto& info = trail.Info(w.blocking_literal.Variable());
693 if (info.level > 0) {
694 const Literal d = sat_solver->Decisions()[info.level - 1].literal;
695 if (d != w.blocking_literal) {
696 implication_graph->ChangeReason(info.trail_index, d);
702 clause_manager->LazyDetach(w.clause);
707 if (num_new_subsumed > 0) {
711 clause_manager->CleanUpWatchers();
712 num_subsumed += num_new_subsumed;
716 if (!sat_solver->ResetToLevelZero())
return false;
719 sat_solver->AddUnitClause(
literal);
722 if (!sat_solver->FinishPropagation())
return false;
725 const int num_fixed = sat_solver->LiteralTrail().
Index();
726 const int num_newly_fixed = num_fixed - initial_num_fixed;
727 const double time_diff =
728 time_limit->GetElapsedDeterministicTime() - initial_deterministic_time;
729 const bool limit_reached =
time_limit->LimitReached() ||
730 time_limit->GetElapsedDeterministicTime() > limit;
733 <<
" num_probed: " << num_probed <<
" num_fixed: +" << num_newly_fixed
734 <<
" (" << num_fixed <<
"/" << num_variables <<
")"
735 <<
" explicit_fix:" << num_explicit_fix
736 <<
" num_conflicts:" << num_conflicts
737 <<
" new_binary_clauses: " << num_new_binary
738 <<
" subsumed: " << num_subsumed <<
" dtime: " << time_diff
739 <<
" wtime: " <<
wall_timer.
Get() << (limit_reached ?
" (Aborted)" :
"");
740 return sat_solver->FinishPropagation();