2023-03-26 19:15:17 +08:00

214 lines
5.6 KiB
C

#include "bump.h"
#include "internal.h"
#include "logging.h"
#include "print.h"
#include "rank.h"
#include "sort.h"
static inline unsigned
rank_of_idxrank (idxrank ir)
{
return ir.rank;
}
static inline bool
smaller_idxrank (idxrank ir, idxrank jr)
{
return ir.rank < jr.rank;
}
#define RADIX_SORT_BUMP_LIMIT 800
#define RADIX_SORT_BUMP_LENGTH 8
static void
sort_bump (kissat * solver)
{
const size_t size = SIZE_STACK (solver->analyzed);
if (size < RADIX_SORT_BUMP_LIMIT)
{
LOG ("quick sorting %zu analyzed variables", size);
SORT_STACK (idxrank, solver->bump, smaller_idxrank);
}
else
{
LOG ("radix sorting %zu analyzed variables", size);
RADIX_STACK (RADIX_SORT_BUMP_LENGTH, idxrank,
unsigned, solver->bump, rank_of_idxrank);
}
}
static void
rescale_scores (kissat * solver, heap * scores)
{
INC (rescaled);
const double max_score = kissat_max_score_on_heap (scores);
kissat_phase (solver, "rescale", GET (rescaled),
"maximum score %g increment %g", max_score, solver->scinc);
const double rescale = MAX (max_score, solver->scinc);
assert (rescale > 0);
const double factor = 1.0 / rescale;
kissat_rescale_heap (solver, scores, factor);
solver->scinc *= factor;
kissat_phase (solver, "rescale",
GET (rescaled), "rescaled by factor %g", factor);
}
void kissat_init_shuffle(kissat * solver, int maxvar) {
int seed = GET_OPTION(order_reset);
if (seed != -1)
{
// printf("c init shuffle %d\n", seed);
int *id;
id = (int *)malloc(sizeof(int) * (maxvar + 1));
for (int i = 1; i <= maxvar; i++)
id[i] = i;
for (int i = 1; i <= maxvar; i++)
{
int j = (rand_r(&seed) % maxvar) + 1;
int x = id[i];
id[i] = id[j];
id[j] = x;
}
for (int i = 1; i <= maxvar; i++)
kissat_activate_literal(solver, kissat_import_literal(solver, id[i]));
free(id);
}
else
{
for (int i = 1; i <= maxvar; i++)
kissat_import_literal(solver, i);
}
}
void kissat_shuffle_score(kissat * solver) {
heap *scores = &solver->scores;
heap *scores_chb = &solver->scores_chb;
flags *flags = solver->flags;
int *id = (int *)malloc(sizeof(int) * (VARS));
for (int i = 0; i < VARS; i++) id[i] = i;
for (int i = 0; i < VARS; i++)
{
int j = (rand() % VARS);
int x = id[i];
id[i] = id[j];
id[j] = x;
}
for (int i = 0; i < VARS; i++) {
int idx = id[i];
if (flags[idx].active) {
double new_score = 1.0 * i / VARS;
kissat_update_heap (solver, scores, idx, new_score);
kissat_update_heap (solver, scores_chb, idx, new_score);
}
}
for (int i = 0; i < VARS; i++) {
int idx = id[i];
if (flags[idx].active)
kissat_move_to_front(solver, idx);
}
solver->scinc = 1.0;
free(id);
}
static void
bump_score_increment (kissat * solver, heap * scores)
{
const double old_scinc = solver->scinc;
const double decay = GET_OPTION (decay) * 1e-3;
assert (0 <= decay), assert (decay <= 0.5);
const double factor = 1.0 / (1.0 - decay);
const double new_scinc = old_scinc * factor;
LOG ("new score increment %g = %g * %g", new_scinc, factor, old_scinc);
solver->scinc = new_scinc;
if (new_scinc > MAX_SCORE)
rescale_scores (solver, scores);
}
static inline void
bump_variable_score (kissat * solver, heap * scores, unsigned idx)
{
const double old_score = kissat_get_heap_score (scores, idx);
const double new_score = old_score + solver->scinc;
LOG ("new score[%u] = %g = %g + %g",
idx, new_score, old_score, solver->scinc);
kissat_update_heap (solver, scores, idx, new_score);
if (new_score > MAX_SCORE)
rescale_scores (solver, scores);
}
static void
bump_analyzed_variable_scores (kissat * solver)
{
heap *scores = &solver->scores;
flags *flags = solver->flags;
for (all_stack (unsigned, idx, solver->analyzed))
if (flags[idx].active)
bump_variable_score (solver, scores, idx);
bump_score_increment (solver, scores);
}
static void
move_analyzed_variables_to_front_of_queue (kissat * solver)
{
assert (EMPTY_STACK (solver->bump));
const links *links = solver->links;
for (all_stack (unsigned, idx, solver->analyzed))
{
// *INDENT-OFF*
const idxrank idxrank = { .idx = idx, .rank = links[idx].stamp };
// *INDENT-ON*
PUSH_STACK (solver->bump, idxrank);
}
sort_bump (solver);
flags *flags = solver->flags;
unsigned idx;
for (all_stack (idxrank, idxrank, solver->bump))
if (flags[idx = idxrank.idx].active)
kissat_move_to_front (solver, idx);
CLEAR_STACK (solver->bump);
}
void
kissat_bump_variables (kissat * solver)
{
START (bump);
assert (!solver->probing);
if (solver->stable)
bump_analyzed_variable_scores (solver);
else
move_analyzed_variables_to_front_of_queue (solver);
STOP (bump);
}
// CHB
void kissat_bump_chb(kissat * solver, unsigned v, double multiplier) {
int64_t age = solver->statistics.conflicts - solver->conflicted_chb[v] + 1;
double reward_chb = multiplier / age;
double old_score = kissat_get_heap_score (&solver->scores_chb, v);
double new_score = solver->step_chb * reward_chb + (1 - solver->step_chb) * old_score;
LOG ("new score[%u] = %g vs %g",
v, new_score, old_score);
kissat_update_heap (solver, &solver->scores_chb, v, new_score);
}
void kissat_decay_chb(kissat * solver){
if (solver->step_chb > solver->step_min_chb) solver->step_chb -= solver->step_dec_chb;
}
void
kissat_update_conflicted_chb (kissat * solver)
{
flags *flags = solver->flags;
for (all_stack (unsigned, idx, solver->analyzed))
if (flags[idx].active)
solver->conflicted_chb[idx]=solver->statistics.conflicts;
}