int32_t choose_unfixed_variable(atom_table_t *atom_table) { samp_truth_value_t *assignment = atom_table->assignment; int32_t num_vars = atom_table->num_vars; int32_t num_unfixed_vars = atom_table->num_unfixed_vars; uint32_t var, d, y; if (num_unfixed_vars == 0) return -1; // var = random_uint(num_vars); var = genrand_uint(num_vars); if (unfixed_tval(assignment[var])) return var; // d = 1 + random_uint(num_vars - 1); d = 1 + genrand_uint(num_vars - 1); while (gcd32(d, num_vars) != 1) d--; y = var; do { y += d; if (y >= num_vars) y -= num_vars; assert(var != y); } while (!unfixed_tval(assignment[y])); return y; }
samp_clause_t *choose_random_clause(samp_clause_list_t *list) { //int32_t clsidx = random_uint(list->length); int32_t clsidx = genrand_uint(list->length); samp_clause_t *ptr = list->head; for (; clsidx > 0; clsidx--) { ptr = next_clause_ptr(ptr); } return ptr->link; }
int32_t choose_clause_var(samp_table_t *table, samp_clause_t *clause, double rvar_probability) { rule_inst_table_t *rule_inst_table = &table->rule_inst_table; atom_table_t *atom_table = &table->atom_table; integer_stack_t *clause_var_stack = &table->clause_var_stack; uint32_t i, sidx, vidx; if (clause_var_stack->size == 0) { init_integer_stack(clause_var_stack, 0); } else { clear_integer_stack(clause_var_stack); } double choice = choose(); if (choice < rvar_probability) { /* flip a random unfixed variable */ for (i = 0; i < clause->num_lits; i++) { if (unfixed_tval(atom_table->assignment[var_of(clause->disjunct[i])])) push_integer_stack(i, clause_var_stack); } if (unfixed_tval(rule_inst_table->assignment[clause->rule_index])) push_integer_stack(clause->num_lits, clause_var_stack); /* all unfixed vars are now in clause_var_stack */ } else { int32_t dcost = INT32_MAX, vcost = 0; for (i = 0; i < clause->num_lits; i++) { if (unfixed_tval(atom_table->assignment[var_of(clause->disjunct[i])])) { cost_flip_unfixed_variable(table, var_of(clause->disjunct[i]), &vcost); if (dcost >= vcost) { if (dcost > vcost) { dcost = vcost; clear_integer_stack(clause_var_stack); } push_integer_stack(i, clause_var_stack); } } } if (unfixed_tval(rule_inst_table->assignment[clause->rule_index])) { cost_flip_unfixed_rule(table, clause->rule_index, &vcost); if (dcost > vcost) { dcost = vcost; clear_integer_stack(clause_var_stack); push_integer_stack(clause->num_lits, clause_var_stack); } } } //sidx = random_uint(length_integer_stack(clause_var_stack)); sidx = genrand_uint(length_integer_stack(clause_var_stack)); vidx = nth_integer_stack(sidx, clause_var_stack); return vidx; }
/* MaxWalkSAT */ void mw_sat(samp_table_t *table, int32_t num_trials, double rvar_probability, int32_t max_flips, uint32_t timeout) { rule_inst_table_t *rule_inst_table = &table->rule_inst_table; atom_table_t *atom_table = &table->atom_table; int32_t i, j; time_t fintime; if (timeout != 0) { fintime = time(NULL) + timeout; } double best_cost = DBL_MAX; for (i = 0; i < num_trials; i++) { init_random_assignment(table); //scan_rule_instances(table); for (j = 0; j < rule_inst_table->num_rule_insts; j++) { if (rule_inst_table->rule_insts[j]->weight == DBL_MAX) rule_inst_table->assignment[j] = v_up_true; else rule_inst_table->assignment[j] = v_true; } init_live_clauses(table); scan_live_clauses(table); if (get_verbosity_level() >= 3) { printf("\n[mw_sat] Trial %d: \n", i); print_live_clauses(table); } for (j = 0; j < max_flips; j++) { if (timeout != 0 && time(NULL) >= fintime) { printf("Timeout after %"PRIu32" samples\n", i); break; } if (rule_inst_table->unsat_clauses.length == 0 && rule_inst_table->unsat_soft_rules.nelems == 0) { return; } int32_t c = genrand_uint(rule_inst_table->unsat_clauses.length + rule_inst_table->unsat_soft_rules.nelems); if (c < rule_inst_table->unsat_clauses.length) { /* picked a hard clause */ samp_clause_t *clause = choose_random_clause(&rule_inst_table->unsat_clauses); int32_t litidx = choose_clause_var(table, clause, rvar_probability); if (litidx == clause->num_lits) { if (get_verbosity_level() >= 3) { printf("[flip_rule_to_unsat] Rule %d: ", clause->rule_index); print_rule_instance(rule_inst_table->rule_insts[clause->rule_index], table); printf("\n"); } /* picked the rule auxiliary variable, i.e., rinst T -> F */ hmap_get(&rule_inst_table->unsat_soft_rules, clause->rule_index); rule_inst_table->assignment[clause->rule_index] = v_false; rule_inst_t *rinst = rule_inst_table->rule_insts[clause->rule_index]; rule_inst_table->unsat_weight += rinst->weight; /* Is this really going to do the right thing?? */ rule_inst_table->sat_weight -= rinst->weight; /* move unsat_clauses to live_clause_list and rescan */ clause_list_concat(&rule_inst_table->unsat_clauses, &rule_inst_table->live_clauses); scan_live_clauses(table); } else { flip_unfixed_variable(table, var_of(clause->disjunct[litidx])); } } else { /* picked a soft rule auxiliary variable, i.e., rinst F -> T */ int32_t rule_index = hmap_remove_random(&rule_inst_table->unsat_soft_rules); rule_inst_table->assignment[rule_index] = v_true; rule_inst_t *rinst = rule_inst_table->rule_insts[rule_index]; rule_inst_table->unsat_weight -= rinst->weight; rule_inst_table->sat_weight += rinst->weight; if (get_verbosity_level() >= 3) { printf("[flip_rule_to_sat] Rule %d: ", rule_index); print_rule_instance(rinst, table); printf("\n"); } /* move watch[~r] to live_clause_list and rescan */ clause_list_concat(&rule_inst_table->rule_watched[rule_index], &rule_inst_table->live_clauses); scan_live_clauses(table); } if (get_verbosity_level() >= 1) { printf("[mw_sat] Flip %d: # unsat hard = %d, # unsat soft = %d, " "weight of unsat soft = %f; weight of sat soft = %f\n", j, rule_inst_table->unsat_clauses.length, rule_inst_table->unsat_soft_rules.nelems, rule_inst_table->unsat_weight, rule_inst_table->sat_weight ); } if (get_verbosity_level() >= 3) { print_live_clauses(table); } if (best_cost > rule_inst_table->unsat_weight) { best_cost = rule_inst_table->unsat_weight; copy_assignment_array(atom_table); } } } restore_assignment_array(atom_table); }
/* * [lazy only] Choose a random atom for simulated annealing step in sample SAT. * The lazy version of choose_unfixed_variable. First choose a random atom, * regardless whether its value is fixed or not (because we can calculate the * total number of atoms and it is convenient to randomly choose one from * them). If its value is fixed, we skip this flip using the following * statement (return 0). */ int32_t choose_random_atom(samp_table_t *table) { uint32_t i, atom_num, anum; int32_t card, all_card, acard, pcard, predicate; pred_tbl_t *pred_tbl = &table->pred_table.pred_tbl; // Indirect preds atom_table_t *atom_table = &table->atom_table; sort_table_t *sort_table = &table->sort_table; pred_entry_t *pred_entry; assert(valid_table(table)); /* Get the number of possible indirect atoms */ all_card = all_atoms_cardinality(pred_tbl, sort_table); //atom_num = random_uint(all_card); atom_num = genrand_uint(all_card); predicate = 1; /* Skip past true */ acard = 0; while (true) { /* determine the predicate */ assert(predicate <= pred_tbl->num_preds); pcard = pred_cardinality(pred_tbl, sort_table, predicate); if (acard + pcard > atom_num) { break; } acard += pcard; predicate++; } assert(pred_cardinality(pred_tbl, sort_table, predicate) != 0); /* gives the position of atom within predicate */ anum = atom_num - acard; /* * Now calculate the arguments. We represent the arguments in * little-endian form */ pred_entry = &pred_tbl->entries[predicate]; int32_t *signature = pred_entry->signature; int32_t arity = pred_entry->arity; atom_buffer_resize(arity); int32_t constant; samp_atom_t *atom = (samp_atom_t *) atom_buffer.data; /* Build atom from atom_num by successive division */ atom->pred = predicate; for (i = 0; i < arity; i++) { card = sort_table->entries[signature[i]].cardinality; constant = anum % card; anum = anum / card; sort_entry_t *sort_entry = &sort_table->entries[signature[i]]; if (sort_entry->constants == NULL) { /* Must be an integer */ if (sort_entry->ints == NULL) { atom->args[i] = sort_entry->lower_bound + constant; } else { atom->args[i] = sort_entry->ints[constant]; } } else { atom->args[i] = sort_entry->constants[constant]; /* Quick typecheck */ assert(const_sort_index(atom->args[i], &table->const_table) == signature[i]); } } assert(valid_table(table)); array_hmap_pair_t *atom_map; atom_map = array_size_hmap_find(&atom_table->atom_var_hash, arity + 1, (int32_t *) atom); int32_t atom_index; if (atom_map == NULL) { /* need to activate atom */ atom_index = add_internal_atom(table, atom, false); atom_map = array_size_hmap_find(&atom_table->atom_var_hash, arity + 1, (int32_t *) atom); assert(atom_map != NULL); activate_atom(table, atom_index); } else { atom_index = atom_map->val; } return atom_index; }