#include "internal.hpp"
namespace CaDiCaL {
inline void Internal::unassign (int lit) {
assert (val (lit) > 0);
set_val (lit, 0);
int idx = vidx (lit);
LOG ("unassign %d @ %d", lit, var (idx).level);
num_assigned--;
if (!scores.contains (idx))
scores.push_back (idx);
if (queue.bumped < btab[idx])
update_queue_unassigned (idx);
}
void Internal::update_target_and_best () {
if (opts.rephase == 2 && !stable)
return;
bool reset = (rephased && stats.conflicts > last.rephase.conflicts);
if (reset) {
target_assigned = 0;
if (rephased == 'B')
best_assigned = 0; }
if (no_conflict_until > target_assigned) {
copy_phases (phases.target);
target_assigned = no_conflict_until;
LOG ("new target trail level %zu", target_assigned);
}
if (no_conflict_until > best_assigned) {
copy_phases (phases.best);
best_assigned = no_conflict_until;
LOG ("new best trail level %zu", best_assigned);
}
if (reset) {
report (rephased);
rephased = 0;
}
}
void Internal::backtrack (int new_level) {
assert (new_level <= level);
if (new_level == level)
return;
update_target_and_best ();
backtrack_without_updating_phases (new_level);
}
void Internal::backtrack_without_updating_phases (int new_level) {
assert (new_level <= level);
if (new_level == level)
return;
stats.backtracks++;
assert (num_assigned == trail.size ());
const size_t assigned = control[new_level + 1].trail;
LOG ("backtracking to decision level %d with decision %d and trail %zd",
new_level, control[new_level].decision, assigned);
const size_t end_of_trail = trail.size ();
size_t i = assigned, j = i;
#ifdef LOGGING
int unassigned = 0;
#endif
int reassigned = 0;
notify_backtrack (new_level);
if (external_prop && !external_prop_is_lazy && !private_steps &&
notified > assigned) {
LOG ("external propagator is notified about some unassignments (trail: "
"%zd, notified: %zd).",
trail.size (), notified);
notified = assigned;
}
while (i < end_of_trail) {
int lit = trail[i++];
Var &v = var (lit);
if (v.level > new_level) {
unassign (lit);
#ifdef LOGGING
unassigned++;
#endif
} else {
assert ((in_mode (BACKBONE)) || opts.chrono || external_prop ||
did_external_prop);
#ifdef LOGGING
if (!v.level)
LOG ("reassign %d @ 0 unit clause %d", lit, lit);
else
LOG (v.reason, "reassign %d @ %d", lit, v.level);
#endif
trail[j] = lit;
v.trail = j++;
reassigned++;
}
}
trail.resize (j);
LOG ("unassigned %d literals %.0f%%", unassigned,
percent (unassigned, unassigned + reassigned));
LOG ("reassigned %d literals %.0f%%", reassigned,
percent (reassigned, unassigned + reassigned));
if (propagated > assigned)
propagated = assigned;
if (propagated2 > assigned)
propagated2 = assigned;
if (no_conflict_until > assigned)
no_conflict_until = assigned;
propergated = 0;
assert (notified <= assigned + reassigned);
if (reassigned) {
notify_assignments ();
}
control.resize (new_level + 1);
level = new_level;
if (changed_val) {
assert (opts.ilb);
if (!val (changed_val)) {
changed_val = 0;
}
}
assert (num_assigned == trail.size ());
}
}