#include "internal.hpp"
namespace CaDiCaL {
bool Internal::rephasing () {
if (!opts.rephase)
return false;
if (opts.forcephase)
return false;
if (opts.rephase == 2) {
if (stable)
return stats.stabconflicts > lim.rephase;
else
return false;
}
return stats.conflicts > lim.rephase;
}
char Internal::rephase_original () {
stats.rephased.original++;
signed char val = opts.phase ? 1 : -1; PHASE ("rephase", stats.rephased.total, "switching to original phase %d",
val);
for (auto idx : vars)
phases.saved[idx] = val;
return 'O';
}
char Internal::rephase_inverted () {
stats.rephased.inverted++;
signed char val = opts.phase ? -1 : 1; PHASE ("rephase", stats.rephased.total,
"switching to inverted original phase %d", val);
for (auto idx : vars)
phases.saved[idx] = val;
return 'I';
}
char Internal::rephase_flipping () {
stats.rephased.flipped++;
PHASE ("rephase", stats.rephased.total,
"flipping all phases individually");
for (auto idx : vars)
phases.saved[idx] *= -1;
return 'F';
}
char Internal::rephase_random () {
stats.rephased.random++;
PHASE ("rephase", stats.rephased.total, "resetting all phases randomly");
Random random (opts.seed); random += stats.rephased.random; for (auto idx : vars)
phases.saved[idx] = random.generate_bool () ? -1 : 1;
return '#';
}
char Internal::rephase_best () {
stats.rephased.best++;
PHASE ("rephase", stats.rephased.total,
"overwriting saved phases by best phases");
signed char val;
for (auto idx : vars)
if ((val = phases.best[idx]))
phases.saved[idx] = val;
return 'B';
}
char Internal::rephase_walk () {
stats.rephased.walk++;
PHASE ("rephase", stats.rephased.total,
"starting local search to improve current phase");
if (opts.walkfullocc)
walk_full_occs ();
else
walk ();
return 'W';
}
void Internal::rephase () {
stats.rephased.total++;
last.stabilize.rephased++;
assert (last.stabilize.rephased <= stats.rephased.total);
PHASE ("rephase", stats.rephased.total,
"reached rephase limit %" PRId64 " after %" PRId64 " conflicts",
lim.rephase,
opts.rephase == 2 ? stats.stabconflicts : stats.conflicts);
report ('~', 1);
backtrack ();
size_t count = lim.rephased[stable]++;
bool single;
char type;
if (opts.stabilize && opts.stabilizeonly)
single = true;
else
single = !opts.stabilize;
if (single && !opts.walk) {
switch (count % 8) {
case 0:
type = rephase_inverted ();
break;
case 1:
type = rephase_best ();
break;
case 2:
type = rephase_flipping ();
break;
case 3:
type = rephase_best ();
break;
case 4:
type = rephase_random ();
break;
case 5:
type = rephase_best ();
break;
case 6:
type = rephase_original ();
break;
case 7:
type = rephase_best ();
break;
default:
type = 0;
break;
}
} else if (single && opts.walk) {
switch (count % 12) {
case 0:
type = rephase_inverted ();
break;
case 1:
type = rephase_best ();
break;
case 2:
type = rephase_walk ();
break;
case 3:
type = rephase_flipping ();
break;
case 4:
type = rephase_best ();
break;
case 5:
type = rephase_walk ();
break;
case 6:
type = rephase_random ();
break;
case 7:
type = rephase_best ();
break;
case 8:
type = rephase_walk ();
break;
case 9:
type = rephase_original ();
break;
case 10:
type = rephase_best ();
break;
case 11:
type = rephase_walk ();
break;
default:
type = 0;
break;
}
} else if (opts.rephase == 2 && opts.walk) {
switch (count % 12) {
case 0:
type = rephase_inverted ();
break;
case 1:
type = rephase_best ();
break;
case 2:
type = rephase_walk ();
break;
case 3:
type = rephase_flipping ();
break;
case 4:
type = rephase_best ();
break;
case 5:
type = rephase_walk ();
break;
case 6:
type = rephase_random ();
break;
case 7:
type = rephase_best ();
break;
case 8:
type = rephase_walk ();
break;
case 9:
type = rephase_original ();
break;
case 10:
type = rephase_best ();
break;
case 11:
type = rephase_walk ();
break;
default:
type = 0;
break;
}
} else if (stable && !opts.walk) {
if (!count)
type = rephase_original ();
else if (count == 1)
type = rephase_inverted ();
else
switch ((count - 2) % 4) {
case 0:
type = rephase_best ();
break;
case 1:
type = rephase_original ();
break;
case 2:
type = rephase_best ();
break;
case 3:
type = rephase_inverted ();
break;
default:
type = 0;
break;
}
} else if (stable && opts.walk) {
if (!count)
type = rephase_original ();
else if (count == 1)
type = rephase_inverted ();
else
switch ((count - 2) % 6) {
case 0:
type = rephase_best ();
break;
case 1:
type = rephase_walk ();
break;
case 2:
type = rephase_original ();
break;
case 3:
type = rephase_best ();
break;
case 4:
type = rephase_walk ();
break;
case 5:
type = rephase_inverted ();
break;
default:
type = 0;
break;
}
} else if (!stable && (!opts.walk || !opts.walknonstable)) {
if (!count)
type = rephase_flipping ();
else
switch ((count - 1) % 4) {
case 0:
type = rephase_random ();
break;
case 1:
type = rephase_best ();
break;
case 2:
type = rephase_flipping ();
break;
case 3:
type = rephase_best ();
break;
default:
type = 0;
break;
}
} else {
assert (!stable && opts.walk && opts.walknonstable);
if (!count)
type = rephase_original ();
else
switch ((count - 1) % 6) {
case 0:
type = rephase_random ();
break;
case 1:
type = rephase_best ();
break;
case 2:
type = rephase_walk ();
break;
case 3:
type = rephase_flipping ();
break;
case 4:
type = rephase_best ();
break;
case 5:
type = rephase_walk ();
break;
default:
type = 0;
break;
}
}
assert (type);
copy_phases (phases.target);
target_assigned = 0;
int64_t delta = opts.rephaseint * (stats.rephased.total + 1);
lim.rephase =
(opts.rephase == 2 ? stats.stabconflicts : stats.conflicts) + delta;
PHASE ("rephase", stats.rephased.total,
"new rephase limit %" PRId64 " after %" PRId64 " conflicts",
lim.rephase, delta);
last.rephase.conflicts = stats.conflicts;
rephased = type;
if (!marked_failed || unsat_constraint) {
assert (opts.warmup);
return;
}
if (stable)
shuffle_scores ();
else
shuffle_queue ();
}
}