#include "internal.hpp"
namespace CaDiCaL {
bool Internal::stabilizing () {
if (!opts.stabilize)
return false;
if (stable && opts.stabilizeonly)
return true;
if (!inc.stabilize) {
assert (!stable);
if (stats.conflicts <= lim.stabilize)
return false;
} else if (stats.ticks.search[stable] <= lim.stabilize)
return stable;
report (stable ? ']' : '}');
if (stable)
STOP (stable);
else
STOP (unstable);
assert (last.stabilize.ticks >= 0);
assert (last.stabilize.conflicts >= 0 &&
last.stabilize.conflicts <= stats.conflicts);
assert (last.stabilize.ticks <= stats.ticks.search[stable]);
const int64_t delta_ticks =
stats.ticks.search[stable] - last.stabilize.ticks;
#ifndef QUIET
const int64_t delta_conflicts =
stats.conflicts - last.stabilize.conflicts;
const char *current_mode = stable ? "stable" : "unstable";
const char *next_mode = stable ? "unstable" : "stable";
#endif
PHASE ("stabilizing", stats.stabphases,
"reached %s stabilization limit %" PRId64 " after %" PRId64
" conflicts and %" PRId64 " ticks at %" PRId64
" conflicts and %" PRId64 " ticks",
current_mode, lim.stabilize, delta_conflicts, delta_ticks,
stats.conflicts, stats.ticks.search[stable]);
if (!inc.stabilize)
inc.stabilize = delta_ticks;
if (!inc.stabilize) inc.stabilize = 1;
int64_t next_delta_ticks = inc.stabilize;
int64_t stabphases = stats.stabphases + 1;
next_delta_ticks *= stabphases * stabphases;
const bool next_stable = !stable;
lim.stabilize = stats.ticks.search[next_stable] + next_delta_ticks;
last.stabilize.ticks = stats.ticks.search[next_stable];
if (lim.stabilize <= stats.ticks.search[next_stable])
lim.stabilize = stats.ticks.search[next_stable] + 1;
PHASE ("stabilizing", stats.stabphases,
"next %s stabilization limit %" PRId64
" at ticks interval %" PRId64,
next_mode, lim.stabilize, next_delta_ticks);
stable = !stable;
if (stable)
stats.stabphases++;
swap_averages ();
report (stable ? '[' : '{');
if (stable)
START (stable);
else
START (unstable);
return stable;
}
bool Internal::restarting () {
if (!opts.restart)
return false;
if ((size_t) level < assumptions.size () + 2)
return false;
if (stabilizing () && opts.reluctant)
return reluctant;
if (stats.conflicts <= lim.restart)
return false;
double f = averages.current.glue.fast;
int p = stable ? opts.restartmarginstable : opts.restartmarginfocused;
double m = (100.0 + p) / 100.0;
double s = averages.current.glue.slow;
double l = m * s;
#ifndef QUIET
char c = l > f ? '>' : l < f ? '<' : '=';
VERBOSE (3,
"restart glue limit "
"%g = %.2f * %g (slow glue) %c %g (fast glue)",
l, m, s, c, f);
#endif
return l <= f;
}
int Internal::reuse_trail () {
const int trivial_decisions =
assumptions.size ()
+ !control[assumptions.size () + 1].decision;
if (!opts.restartreusetrail)
return trivial_decisions;
int next_decision = next_decision_variable ();
assert (1 <= next_decision);
int res = trivial_decisions;
if (use_scores ()) {
while (res < level) {
int decision = control[res + 1].decision;
if (decision && score_smaller (this) (abs (decision), next_decision))
break;
res++;
}
} else {
int64_t limit = bumped (next_decision);
while (res < level) {
int decision = control[res + 1].decision;
if (decision && bumped (decision) < limit)
break;
res++;
}
}
int reused = res - trivial_decisions;
if (reused > 0) {
stats.reused++;
stats.reusedlevels += reused;
if (stable)
stats.reusedstable++;
}
return res;
}
void Internal::restart () {
START (restart);
stats.restarts++;
stats.restartlevels += level;
if (stable)
stats.restartstable++;
LOG ("restart %" PRId64 "", stats.restarts);
backtrack (reuse_trail ());
lim.restart = stats.conflicts + opts.restartint;
LOG ("new restart limit at %" PRId64 " conflicts", lim.restart);
report ('R', 2);
STOP (restart);
}
}