satlike3.0/heuristic.h

408 lines
12 KiB
C
Raw Normal View History

2023-02-14 16:58:22 +08:00
#ifndef _HEURISTIC_H_
#define _HEURISTIC_H_
#include "basis_pms.h"
#include "deci.h"
void Satlike::init(vector<int> &init_solution)
{
soft_large_weight_clauses_count = 0;
//Initialize clause information
for (int c = 0; c < num_clauses; c++)
{
already_in_soft_large_weight_stack[c] = 0;
clause_selected_count[c] = 0;
if (org_clause_weight[c] == top_clause_weight)
clause_weight[c] = 1;
else
{
if (best_soln_feasible == 0)
{
clause_weight[c] = 0;
}
else
{
clause_weight[c] = org_clause_weight[c];
if (clause_weight[c] > 1 && already_in_soft_large_weight_stack[c] == 0)
{
already_in_soft_large_weight_stack[c] = 1;
soft_large_weight_clauses[soft_large_weight_clauses_count++] = c;
}
}
}
}
//init solution
if (best_soln_feasible == 1)
{
best_soln_feasible = 2;
for (int v = 1; v <= num_vars; v++)
{
//cur_soln[v] = rand() % 2;
time_stamp[v] = 0;
unsat_app_count[v] = 0;
}
}
else if (init_solution.size() == 0)
{
for (int v = 1; v <= num_vars; v++)
{
cur_soln[v] = rand() % 2;
time_stamp[v] = 0;
unsat_app_count[v] = 0;
}
}
else
{
for (int v = 1; v <= num_vars; v++)
{
cur_soln[v] = init_solution[v];
if (cur_soln[v] != 0 && cur_soln[v] != 1)
cur_soln[v] = rand() % 2;
time_stamp[v] = 0;
unsat_app_count[v] = 0;
}
}
//init stacks
hard_unsat_nb = 0;
soft_unsat_weight = 0;
hardunsat_stack_fill_pointer = 0;
softunsat_stack_fill_pointer = 0;
unsatvar_stack_fill_pointer = 0;
large_weight_clauses_count = 0;
/* figure out sat_count, sat_var and init unsat_stack */
for (int c = 0; c < num_clauses; ++c)
{
sat_count[c] = 0;
for (int j = 0; j < clause_lit_count[c]; ++j)
{
if (cur_soln[clause_lit[c][j].var_num] == clause_lit[c][j].sense)
{
sat_count[c]++;
sat_var[c] = clause_lit[c][j].var_num;
}
}
if (sat_count[c] == 0)
{
unsat(c);
}
}
/*figure out score*/
for (int v = 1; v <= num_vars; v++)
{
score[v] = 0;
for (int i = 0; i < var_lit_count[v]; ++i)
{
int c = var_lit[v][i].clause_num;
if (sat_count[c] == 0)
score[v] += clause_weight[c];
else if (sat_count[c] == 1 && var_lit[v][i].sense == cur_soln[v])
score[v] -= clause_weight[c];
}
}
//init goodvars stack
goodvar_stack_fill_pointer = 0;
for (int v = 1; v <= num_vars; v++)
{
if (score[v] > 0)
{
already_in_goodvar_stack[v] = goodvar_stack_fill_pointer;
mypush(v, goodvar_stack);
}
else
already_in_goodvar_stack[v] = -1;
}
//cout << goodvar_stack_fill_pointer << endl;
//cout << hard_unsat_nb << endl;
//cout << soft_unsat_weight << endl;
}
int Satlike::pick_var()
{
int i, v;
int best_var;
if (goodvar_stack_fill_pointer > 0)
{
if ((rand() % MY_RAND_MAX_INT) * BASIC_SCALE < rdprob)
return goodvar_stack[rand() % goodvar_stack_fill_pointer];
if (goodvar_stack_fill_pointer < hd_count_threshold)
{
best_var = goodvar_stack[0];
for (i = 1; i < goodvar_stack_fill_pointer; ++i)
{
v = goodvar_stack[i];
if (score[v] > score[best_var])
best_var = v;
else if (score[v] == score[best_var])
{
if (time_stamp[v] < time_stamp[best_var])
best_var = v;
}
}
return best_var;
}
else
{
best_var = goodvar_stack[rand() % goodvar_stack_fill_pointer];
for (i = 1; i < hd_count_threshold; ++i)
{
v = goodvar_stack[rand() % goodvar_stack_fill_pointer];
if (score[v] > score[best_var])
best_var = v;
else if (score[v] == score[best_var])
{
if (time_stamp[v] < time_stamp[best_var])
best_var = v;
}
}
return best_var;
}
}
update_clause_weights();
int sel_c;
lit *p;
if (hardunsat_stack_fill_pointer > 0)
{
sel_c = hardunsat_stack[rand() % hardunsat_stack_fill_pointer];
}
else
{
sel_c = softunsat_stack[rand() % softunsat_stack_fill_pointer];
}
if ((rand() % MY_RAND_MAX_INT) * BASIC_SCALE < rwprob)
return clause_lit[sel_c][rand() % clause_lit_count[sel_c]].var_num;
best_var = clause_lit[sel_c][0].var_num;
p = clause_lit[sel_c];
for (p++; (v = p->var_num) != 0; p++)
{
if (score[v] > score[best_var])
best_var = v;
else if (score[v] == score[best_var])
{
if (time_stamp[v] < time_stamp[best_var])
best_var = v;
}
}
return best_var;
}
void Satlike::local_search(char *inputfile)
{
vector<int> init_solution;
settings();
for (tries = 1; tries < max_tries; ++tries)
{
init(init_solution);
for (step = 1; step < max_flips; ++step)
{
if (hard_unsat_nb == 0 && (soft_unsat_weight < opt_unsat_weight || best_soln_feasible == 0))
{
if (soft_unsat_weight < opt_unsat_weight)
{
best_soln_feasible = 1;
opt_unsat_weight = soft_unsat_weight;
opt_time = get_runtime();
for (int v = 1; v <= num_vars; ++v)
best_soln[v] = cur_soln[v];
}
if (opt_unsat_weight == 0)
return;
}
if (step % 1000 == 0)
{
double elapse_time = get_runtime();
if (elapse_time >= cutoff_time)
return;
else if (opt_unsat_weight == 0)
return;
}
int flipvar = pick_var();
flip(flipvar);
time_stamp[flipvar] = step;
}
}
}
void Satlike::local_search_with_decimation(char *inputfile)
{
settings();
Decimation deci(var_lit, var_lit_count, clause_lit, org_clause_weight, top_clause_weight);
deci.make_space(num_clauses, num_vars);
opt_unsat_weight = __LONG_LONG_MAX__;
for (tries = 1; tries < max_tries; ++tries)
{
if (best_soln_feasible != 1)
{
deci.init(local_opt_soln, best_soln, unit_clause, unit_clause_count, clause_lit_count);
deci.unit_prosess();
init(deci.fix);
}
else
init(deci.fix);
long long local_opt = __LONG_LONG_MAX__;
max_flips = max_non_improve_flip;
for (step = 1; step < max_flips; ++step)
{
if (hard_unsat_nb == 0)
{
if (local_opt > soft_unsat_weight)
{
local_opt = soft_unsat_weight;
max_flips = step + max_non_improve_flip;
}
if (soft_unsat_weight < opt_unsat_weight)
{
cout << "o " << soft_unsat_weight << endl;
opt_unsat_weight = soft_unsat_weight;
opt_time = get_runtime();
for (int v = 1; v <= num_vars; ++v)
best_soln[v] = cur_soln[v];
}
if (best_soln_feasible == 0)
{
best_soln_feasible = 1;
break;
}
}
//if(goodvar_stack_fill_pointer==0) cout<<step<<": 0"<<endl;
int flipvar = pick_var();
flip(flipvar);
time_stamp[flipvar] = step;
}
}
}
void Satlike::increase_weights()
{
int i, c, v;
for (i = 0; i < hardunsat_stack_fill_pointer; ++i)
{
c = hardunsat_stack[i];
clause_weight[c] += h_inc;
if (clause_weight[c] == (h_inc + 1))
large_weight_clauses[large_weight_clauses_count++] = c;
for (lit *p = clause_lit[c]; (v = p->var_num) != 0; p++)
{
score[v] += h_inc;
if (score[v] > 0 && already_in_goodvar_stack[v] == -1)
{
already_in_goodvar_stack[v] = goodvar_stack_fill_pointer;
mypush(v, goodvar_stack);
}
}
}
for (i = 0; i < softunsat_stack_fill_pointer; ++i)
{
c = softunsat_stack[i];
if (clause_weight[c] > softclause_weight_threshold)
continue;
else
clause_weight[c]++;
if (clause_weight[c] > 1 && already_in_soft_large_weight_stack[c] == 0)
{
already_in_soft_large_weight_stack[c] = 1;
soft_large_weight_clauses[soft_large_weight_clauses_count++] = c;
}
for (lit *p = clause_lit[c]; (v = p->var_num) != 0; p++)
{
score[v]++;
if (score[v] > 0 && already_in_goodvar_stack[v] == -1)
{
already_in_goodvar_stack[v] = goodvar_stack_fill_pointer;
mypush(v, goodvar_stack);
}
}
}
}
void Satlike::smooth_weights()
{
int i, clause, v;
for (i = 0; i < large_weight_clauses_count; i++)
{
clause = large_weight_clauses[i];
if (sat_count[clause] > 0)
{
clause_weight[clause] -= h_inc;
if (clause_weight[clause] == 1)
{
large_weight_clauses[i] = large_weight_clauses[--large_weight_clauses_count];
i--;
}
if (sat_count[clause] == 1)
{
v = sat_var[clause];
score[v] += h_inc;
if (score[v] > 0 && already_in_goodvar_stack[v] == -1)
{
already_in_goodvar_stack[v] = goodvar_stack_fill_pointer;
mypush(v, goodvar_stack);
}
}
}
}
for (i = 0; i < soft_large_weight_clauses_count; i++)
{
clause = soft_large_weight_clauses[i];
if (sat_count[clause] > 0)
{
clause_weight[clause]--;
if (clause_weight[clause] == 1 && already_in_soft_large_weight_stack[clause] == 1)
{
already_in_soft_large_weight_stack[clause] = 0;
soft_large_weight_clauses[i] = soft_large_weight_clauses[--soft_large_weight_clauses_count];
i--;
}
if (sat_count[clause] == 1)
{
v = sat_var[clause];
score[v]++;
if (score[v] > 0 && already_in_goodvar_stack[v] == -1)
{
already_in_goodvar_stack[v] = goodvar_stack_fill_pointer;
mypush(v, goodvar_stack);
}
}
}
}
}
void Satlike::update_clause_weights()
{
if (((rand() % MY_RAND_MAX_INT) * BASIC_SCALE) < smooth_probability && large_weight_clauses_count > large_clause_count_threshold)
{
smooth_weights();
}
else
{
increase_weights();
}
}
#endif