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; }
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; }
/* * Pushes a clause to a list depending on its evaluation * * If it is fixed to be satisfied, push to sat_clauses * If it is satisfied, push to the corresponding watched list * If it is unsatisified, push to unsat_clauses */ void insert_live_clause(samp_clause_t *clause, samp_table_t *table) { rule_inst_table_t *rule_inst_table = &table->rule_inst_table; atom_table_t *atom_table = &table->atom_table; int32_t i, fixable; samp_literal_t lit; /* See if the clause is fixed-unit propagating */ fixable = get_fixable_literal(atom_table->assignment, rule_inst_table->assignment, clause); if (fixable == -2) { /* fixed unsat */ mcsat_err("There is a fixed unsat clause, no model exists."); return; } else if (fixable == -1) { /* more than one unfixed lits */ i = get_true_literal(atom_table->assignment, rule_inst_table->assignment, clause); if (i < 0) { /* currently unsat, put back to the unsat list */ clause_list_insert_head(clause, &rule_inst_table->unsat_clauses); } else if (i == clause->num_lits) { /* currently sat, put to the rule_watched list */ clause_list_insert_head(clause, &rule_inst_table->rule_watched[clause->rule_index]); } else { /* currently sat, put to the watched list */ clause_list_insert_head(clause, &rule_inst_table->watched[clause->disjunct[i]]); } } else { /* fix a soft rule to unsat, because one of its clauses is fixed unsat */ if (fixable == clause->num_lits) { rule_inst_t *rinst = rule_inst_table->rule_insts[clause->rule_index]; if (assigned_true(rule_inst_table->assignment[clause->rule_index])) { rule_inst_table->unsat_weight += rinst->weight; } else { rule_inst_table->sat_weight += rinst->weight; } if (get_verbosity_level() >= 3) { printf("[insert_live_clause] Fix rule %d: \n", clause->rule_index); print_rule_instance(rinst, table); printf(" to false\n"); } rule_inst_table->assignment[clause->rule_index] = v_up_false; } else { /* fixed sat if we fix the 'fixable' literal */ lit = clause->disjunct[fixable]; if (unfixed_tval(atom_table->assignment[var_of(lit)])) { /* unit propagation */ fix_lit_true(table, lit); } else { // already fixed sat } assert(assigned_fixed_true_lit(atom_table->assignment, lit)); } clause_list_insert_head(clause, &rule_inst_table->sat_clauses); } }
/* * Try to set the value of an atom. * * If the atom has a non-fixed value and is set to a fixed value, run * unit_propagation...; * If the atom has a non-fixed value and is set to the opposite non-fixed value, * just change the value (and change the state of the relavent clauses?) */ static int32_t update_atom_tval(int32_t var, samp_truth_value_t tval, samp_table_t *table) { pred_table_t *pred_table = &table->pred_table; atom_table_t *atom_table = &table->atom_table; samp_atom_t *atom = atom_table->atom[var]; pred_entry_t *pred_entry = get_pred_entry(pred_table, atom->pred); /* * Case 0: If the atom has been fixed, check if consistent: if it is * assigned to the opposite value, return inconsistency; otherwise do * nothing; */ samp_truth_value_t old_tval = atom_table->assignment[var]; if (!unfixed_tval(old_tval)) { if ((assigned_true(old_tval) && assigned_false(tval)) || (assigned_false(old_tval) && assigned_true(tval))) { mcsat_err("[update_atom_tval] Assigning a conflict truth value. No model exists.\n"); return -1; } else { return 0; } } #if USE_PTHREADS /* Internally, this is now theoretically protected with a mutex, but do we really want a multithreaded mcmc to be waiting for mutexes? */ #else /* Something's still bad here. For now, we ignore this code block if we are compiled for pthreads */ char *var_str = var_string(var, table); cprintf(3, "[update_atom_tval] Setting the value of %s to %s\n", var_str, samp_truth_value_string(tval)); free(var_str); #endif /* Not case 0: update the value */ atom_table->assignment[var] = tval; if (fixed_tval(tval)) { /* If fixed, this can break a later assertion that there are no fixed vars. Why? */ atom_table->num_unfixed_vars--; } /* Case 1: If the value just gets fixed but not changed, we are done. */ if (old_tval == unfix_tval(tval)) { return 0; } /* Case 2: the value has changed */ if (assigned_true(tval)) { link_propagate(table, neg_lit(var)); } else { link_propagate(table, pos_lit(var)); } //assert(valid_table(table)); /* If the atom is inactive AND the value is non-default, activate the atom. */ if (lazy_mcsat() && !atom_table->active[var] && assigned_false(tval) == pred_default_value(pred_entry)) { activate_atom(table, var); } //assert(valid_table(table)); samp_truth_value_t new_tval = atom_table->assignment[var]; assert(new_tval == tval || (fixed_tval(new_tval) && tval == unfix_tval(negate_tval(new_tval)))); /* * WARNING: in lazy mcsat, when we activate a new clause, it may force the * value of the atom being activated to be the nagation of the value we * intend to assign. E.g., when we want to set p(A) to v_true, and * activated (and kept alive of) the clause ~p(A) or q(B), where q(B) is * fixed to false (either by database or unit propagation), then p(A) has * to change back to v_fixed_false. */ if (new_tval != tval) return -1; return 0; }
/* * Checks that each atom is well-formed. */ bool valid_atom_table(atom_table_t *atom_table, pred_table_t *pred_table, const_table_t *const_table, sort_table_t *sort_table){ assert(atom_table->size >= 0); assert(atom_table->num_vars <= atom_table->size); if (atom_table->size < 0 || atom_table->num_vars > atom_table->size) { printf("Invalid atom table size\n"); return false; } uint32_t i, j, k; int32_t pred, arity; int32_t num_unfixed = 0; int32_t *sig; sort_entry_t *sort_entry; int32_t arg; bool int_exists; for (i = 0; i < atom_table->num_vars; i++) { pred = atom_table->atom[i]->pred; arity = pred_arity(pred, pred_table); sig = pred_signature(pred, pred_table); if (unfixed_tval(atom_table->assignment[i])){ num_unfixed++; } for (j = 0; j < arity; j++){ sort_entry = &sort_table->entries[sig[j]]; arg = atom_table->atom[i]->args[j]; if (sort_entry->constants == NULL) { if (sort_entry->ints == NULL) { assert(arg >= sort_entry->lower_bound); assert(arg <= sort_entry->upper_bound); if (arg < sort_entry->lower_bound || arg > sort_entry->upper_bound) { printf("Integer out of boundary\n"); } } else { /* Enumerate integers, check if in the set */ int_exists = false; for (k = 0; k < sort_entry->cardinality; k++) { if (arg == sort_entry->ints[k]) int_exists = true; } assert(int_exists); if (!int_exists) { printf("Enumerate integer not in set\n"); } } } else { /* constants have unique sorts, lookup directly */ assert(const_table->entries[arg].sort_index == sig[j]); if (const_table->entries[arg].sort_index != sig[j]) { printf("Invalid atom sort\n"); return false; } } } array_hmap_pair_t *hmap_pair; hmap_pair = array_size_hmap_find(&(atom_table->atom_var_hash), arity+1, (int32_t *) atom_table->atom[i]); assert(hmap_pair != NULL); assert(hmap_pair->val == i); if (hmap_pair == NULL || hmap_pair->val != i) { printf("Invalid atom hmap_pair\n"); return false; } } assert(num_unfixed == atom_table->num_unfixed_vars); if (num_unfixed != atom_table->num_unfixed_vars) { printf("Invalid atom num unfixed vars\n"); return false; } return true; }