35 std::vector<BooleanVariable> bool_vars;
36 for (BooleanVariable
b(0);
b < num_variables; ++
b) {
41 bool_vars.push_back(
b);
48 absl::Span<const BooleanVariable> bool_vars,
50 log_info |= VLOG_IS_ON(1);
57 if (!sat_solver->RestoreSolverToAssumptionLevel())
return false;
60 const auto& assignment = sat_solver->LiteralTrail().Assignment();
62 const int initial_num_fixed = sat_solver->LiteralTrail().Index();
63 const double initial_deterministic_time =
65 const double limit = initial_deterministic_time + deterministic_time_limit;
68 int64 num_new_binary = 0;
69 std::vector<std::pair<Literal, Literal>> new_binary_clauses;
74 int num_new_holes = 0;
75 int num_new_integer_bounds = 0;
78 if (integer_trail !=
nullptr) {
81 std::vector<IntegerLiteral> new_integer_bounds;
86 std::vector<Literal> to_fix_at_true;
87 const int num_variables = sat_solver->NumVariables();
90 bool limit_reached =
false;
93 for (
const BooleanVariable
b : bool_vars) {
102 time_limit->GetElapsedDeterministicTime() > limit) {
103 limit_reached =
true;
109 new_integer_bounds.clear();
112 if (assignment.LiteralIsAssigned(decision))
continue;
114 CHECK_EQ(sat_solver->CurrentDecisionLevel(), 0);
115 const int saved_index = trail.Index();
116 sat_solver->EnqueueDecisionAndBackjumpOnConflict(decision);
117 sat_solver->AdvanceDeterministicTime(
time_limit);
119 if (sat_solver->IsModelUnsat())
return false;
120 if (sat_solver->CurrentDecisionLevel() == 0)
continue;
122 if (integer_trail !=
nullptr) {
123 implied_bounds->ProcessIntegerTrail(decision);
124 integer_trail->AppendNewBounds(&new_integer_bounds);
126 for (
int i = saved_index + 1; i < trail.Index(); ++i) {
130 if (decision.IsPositive()) {
133 if (propagated[l.
Index()]) {
134 to_fix_at_true.push_back(l);
141 if (trail.AssignmentType(l.
Variable()) !=
id) {
142 new_binary_clauses.push_back({decision.Negated(), l});
147 if (!sat_solver->RestoreSolverToAssumptionLevel())
return false;
148 for (
const Literal l : to_fix_at_true) {
149 sat_solver->AddUnitClause(l);
151 to_fix_at_true.clear();
152 if (!sat_solver->FinishPropagation())
return false;
153 num_new_binary += new_binary_clauses.size();
154 for (
auto binary : new_binary_clauses) {
155 sat_solver->AddBinaryClause(binary.first, binary.second);
157 new_binary_clauses.clear();
158 if (!sat_solver->FinishPropagation())
return false;
173 std::sort(new_integer_bounds.begin(), new_integer_bounds.end(),
182 for (
int i = 0; i < new_integer_bounds.size(); ++i) {
183 const IntegerVariable
var = new_integer_bounds[i].var;
187 if (ub_min + 1 < lb_max) {
193 integer_trail->InitialVariableDomain(prev_var);
196 if (new_domain != old_domain) {
198 if (!integer_trail->UpdateInitialDomain(prev_var, new_domain)) {
217 if (i == 0 || new_integer_bounds[i - 1].
var !=
var)
continue;
218 const IntegerValue new_bound =
std::min(new_integer_bounds[i - 1].
bound,
219 new_integer_bounds[i].
bound);
220 if (new_bound > integer_trail->LowerBound(
var)) {
221 ++num_new_integer_bounds;
222 if (!integer_trail->Enqueue(
230 if (!sat_solver->FinishPropagation())
return false;
235 const double time_diff =
236 time_limit->GetElapsedDeterministicTime() - initial_deterministic_time;
237 const int num_fixed = sat_solver->LiteralTrail().Index();
238 const int num_newly_fixed = num_fixed - initial_num_fixed;
239 LOG(INFO) <<
"Probing deterministic_time: " << time_diff
240 <<
" (limit: " << deterministic_time_limit
242 << (limit_reached ?
"Aborted " :
"") << num_probed <<
"/"
243 << num_variables <<
")";
244 LOG_IF(INFO, num_newly_fixed > 0)
245 <<
"Probing new fixed Boolean: " << num_newly_fixed <<
" (" << num_fixed
246 <<
"/" << num_variables <<
")";
247 LOG_IF(INFO, num_new_holes > 0)
248 <<
"Probing new integer holes: " << num_new_holes;
249 LOG_IF(INFO, num_new_integer_bounds > 0)
250 <<
"Probing new integer bounds: " << num_new_integer_bounds;
251 LOG_IF(INFO, num_new_binary > 0)
252 <<
"Probing new binary clause: " << num_new_binary;
260 log_info |= VLOG_IS_ON(1);
267 if (!sat_solver->RestoreSolverToAssumptionLevel())
return false;
270 const int initial_num_fixed = sat_solver->LiteralTrail().Index();
274 SatParameters initial_params = *
model->GetOrCreate<SatParameters>();
275 SatParameters new_params = initial_params;
276 new_params.set_log_search_progress(
false);
277 new_params.set_max_number_of_conflicts(1);
278 new_params.set_max_deterministic_time(deterministic_time_limit);
280 double elapsed_dtime = 0.0;
282 const int num_times = 1000;
283 bool limit_reached =
false;
285 for (
int i = 0; i < num_times; ++i) {
287 elapsed_dtime > deterministic_time_limit) {
288 limit_reached =
true;
293 sat_solver->SetParameters(new_params);
294 sat_solver->ResetDecisionHeuristic();
296 elapsed_dtime +=
time_limit->GetElapsedDeterministicTime();
299 LOG_IF(INFO, log_info) <<
"Trivial exploration found feasible solution!";
300 time_limit->AdvanceDeterministicTime(elapsed_dtime);
304 if (!sat_solver->RestoreSolverToAssumptionLevel()) {
305 LOG_IF(INFO, log_info) <<
"UNSAT during trivial exploration heuristic.";
306 time_limit->AdvanceDeterministicTime(elapsed_dtime);
313 new_params.set_random_seed(i);
314 new_params.set_max_deterministic_time(deterministic_time_limit -
319 sat_solver->SetParameters(initial_params);
320 sat_solver->ResetDecisionHeuristic();
321 time_limit->AdvanceDeterministicTime(elapsed_dtime);
322 if (!sat_solver->RestoreSolverToAssumptionLevel())
return false;
325 const int num_fixed = sat_solver->LiteralTrail().Index();
326 const int num_newly_fixed = num_fixed - initial_num_fixed;
327 const int num_variables = sat_solver->NumVariables();
328 LOG(INFO) <<
"Random exploration."
329 <<
" num_fixed: +" << num_newly_fixed <<
" (" << num_fixed <<
"/"
330 << num_variables <<
")"
331 <<
" dtime: " << elapsed_dtime <<
"/" << deterministic_time_limit
333 << (limit_reached ?
" (Aborted)" :
"");
335 return sat_solver->FinishPropagation();
346 if (!sat_solver->RestoreSolverToAssumptionLevel())
return false;
352 if (!implication_graph->DetectEquivalences())
return false;
353 if (!sat_solver->FinishPropagation())
return false;
356 const int initial_num_fixed = sat_solver->LiteralTrail().Index();
357 const double initial_deterministic_time =
361 const int num_variables = sat_solver->NumVariables();
364 int64 num_probed = 0;
365 int64 num_explicit_fix = 0;
366 int64 num_conflicts = 0;
367 int64 num_new_binary = 0;
368 int64 num_subsumed = 0;
371 const auto& assignment = trail.Assignment();
374 const int clause_id = clause_manager->PropagatorId();
377 struct SavedNextLiteral {
378 LiteralIndex literal_index;
381 bool operator<(
const SavedNextLiteral& o)
const {
return rank < o.rank; }
383 std::vector<SavedNextLiteral> queue;
392 std::vector<Literal> to_fix;
406 std::vector<LiteralIndex> probing_order =
407 implication_graph->ReverseTopologicalOrder();
409 std::reverse(probing_order.begin(), probing_order.end());
414 position_in_order.
assign(2 * num_variables, -1);
415 for (
int i = 0; i < probing_order.size(); ++i) {
416 position_in_order[probing_order[i]] = i;
421 time_limit->GetElapsedDeterministicTime() <= limit) {
426 if (options.
use_queue && sat_solver->CurrentDecisionLevel() > 0) {
431 sat_solver->Decisions()[sat_solver->CurrentDecisionLevel() - 1]
434 implication_graph->Implications(prev_decision.
Negated());
435 const int saved_queue_size = queue.size();
438 if (processed[candidate.
Index()])
continue;
439 if (position_in_order[candidate.
Index()] == -1)
continue;
440 if (assignment.LiteralIsAssigned(candidate)) {
441 if (assignment.LiteralIsFalse(candidate)) {
447 {candidate.
Index(), -position_in_order[candidate.
Index()]});
449 std::sort(queue.begin() + saved_queue_size, queue.end());
452 while (!queue.empty()) {
453 const LiteralIndex
index = queue.back().literal_index;
457 CHECK_GT(sat_solver->CurrentDecisionLevel(), 0);
458 sat_solver->Backtrack(sat_solver->CurrentDecisionLevel() - 1);
462 if (processed[candidate.
Index()])
continue;
463 if (assignment.LiteralIsAssigned(candidate)) {
464 if (assignment.LiteralIsFalse(candidate)) {
469 next_decision = candidate.
Index();
474 if (sat_solver->CurrentDecisionLevel() == 0) {
477 if (!assignment.LiteralIsTrue(
literal)) {
479 sat_solver->AddUnitClause(
literal);
483 if (!sat_solver->FinishPropagation())
return false;
486 for (; order_index < probing_order.size(); ++order_index) {
487 const Literal candidate(probing_order[order_index]);
488 if (processed[candidate.
Index()])
continue;
489 if (assignment.LiteralIsAssigned(candidate))
continue;
490 next_decision = candidate.
Index();
497 const int level = sat_solver->CurrentDecisionLevel();
498 const Literal prev_decision = sat_solver->Decisions()[level - 1].literal;
500 implication_graph->Implications(prev_decision.
Negated());
507 for (
int i = 0; i < list.size(); ++i, ++j) {
510 if (processed[candidate.
Index()])
continue;
511 if (assignment.LiteralIsFalse(candidate)) {
518 if (assignment.LiteralIsTrue(candidate))
continue;
519 next_decision = candidate.
Index();
524 sat_solver->Backtrack(level - 1);
530 processed.
Set(next_decision);
533 const int level = sat_solver->CurrentDecisionLevel();
534 const int first_new_trail_index =
535 sat_solver->EnqueueDecisionAndBackjumpOnConflict(
537 const int new_level = sat_solver->CurrentDecisionLevel();
538 sat_solver->AdvanceDeterministicTime(
time_limit);
539 if (sat_solver->IsModelUnsat())
return false;
540 if (new_level <= level) {
545 if (new_level == 0) {
548 int queue_level = level + 1;
549 while (queue_level > new_level) {
550 CHECK(!queue.empty());
572 if (sat_solver->CurrentDecisionLevel() != 0 ||
573 assignment.LiteralIsFalse(
Literal(next_decision))) {
574 to_fix.push_back(
Literal(next_decision).Negated());
581 if (new_level == 0)
continue;
583 sat_solver->Decisions()[new_level - 1].literal;
584 int num_new_subsumed = 0;
585 for (
int i = first_new_trail_index; i < trail.Index(); ++i) {
587 if (l == last_decision)
continue;
594 bool subsumed =
false;
596 trail.AssignmentType(l.
Variable()) == clause_id) {
598 if (lit == last_decision.
Negated()) {
606 implication_graph->AddBinaryClause(last_decision.
Negated(), l);
607 const int trail_index = trail.Info(l.
Variable()).trail_index;
611 clause_manager->ReasonClause(trail_index)->AsSpan()) {
612 if (lit == l) ++test;
613 if (lit == last_decision.
Negated()) ++test;
616 clause_manager->LazyDetach(clause_manager->ReasonClause(trail_index));
619 implication_graph->ChangeReason(trail_index, last_decision);
641 if (!subsumed && trail.AssignmentType(l.
Variable()) !=
id) {
643 implication_graph->AddBinaryClause(last_decision.
Negated(), l);
663 clause_manager->WatcherListOnFalse(last_decision.
Negated())) {
664 if (assignment.LiteralIsTrue(w.blocking_literal)) {
665 if (w.clause->empty())
continue;
666 CHECK_NE(w.blocking_literal, last_decision.
Negated());
676 if (trail.AssignmentType(w.blocking_literal.Variable()) !=
id) {
678 implication_graph->AddBinaryClause(last_decision.
Negated(),
681 const auto& info = trail.Info(w.blocking_literal.Variable());
682 if (info.level > 0) {
683 const Literal d = sat_solver->Decisions()[info.level - 1].literal;
684 if (d != w.blocking_literal) {
685 implication_graph->ChangeReason(info.trail_index, d);
691 clause_manager->LazyDetach(w.clause);
696 if (num_new_subsumed > 0) {
700 clause_manager->CleanUpWatchers();
701 num_subsumed += num_new_subsumed;
705 if (!sat_solver->ResetToLevelZero())
return false;
708 sat_solver->AddUnitClause(
literal);
711 if (!sat_solver->FinishPropagation())
return false;
714 const int num_fixed = sat_solver->LiteralTrail().
Index();
715 const int num_newly_fixed = num_fixed - initial_num_fixed;
716 const double time_diff =
717 time_limit->GetElapsedDeterministicTime() - initial_deterministic_time;
718 const bool limit_reached =
time_limit->LimitReached() ||
719 time_limit->GetElapsedDeterministicTime() > limit;
722 <<
" num_probed: " << num_probed <<
" num_fixed: +" << num_newly_fixed
723 <<
" (" << num_fixed <<
"/" << num_variables <<
")"
724 <<
" explicit_fix:" << num_explicit_fix
725 <<
" num_conflicts:" << num_conflicts
726 <<
" new_binary_clauses: " << num_new_binary
727 <<
" subsumed: " << num_subsumed <<
" dtime: " << time_diff
728 <<
" wtime: " <<
wall_timer.
Get() << (limit_reached ?
" (Aborted)" :
"");
729 return sat_solver->FinishPropagation();