//undoes the last literal decision and the corresponding implications obtained by unit resolution // //if the current decision level is L in the beginning of the call, it should be updated //to L-1 before the call ends void sat_undo_decide_literal(SatState* sat_state) { Lit* lit = vector_top(&sat_state->ds); sat_restore_literal(sat_state, lit); vector_pop(&sat_state->ds); vector_pop(&sat_state->s); sat_undo_unit_resolution(sat_state); }
//undoes sat_unit_resolution(), leading to un-instantiating variables that have been instantiated //after sat_unit_resolution() void sat_undo_unit_resolution(SatState* sat_state) { while (vector_size(&sat_state->il) > 0) { Lit* lit = vector_top(&sat_state->il); if (lit->var->level > vector_size(&sat_state->ds) + 1) { sat_restore_literal(sat_state, lit); vector_pop(&sat_state->il); vector_pop(&sat_state->s); } else break; } }
//adds clause to the set of learned clauses, and runs unit resolution //returns a learned clause if unit resolution finds a contradiction, NULL otherwise // //this function is called on a clause returned by sat_decide_literal() or sat_assert_clause() //moreover, it should be called only if sat_at_assertion_level() succeeds Clause* sat_assert_clause(Clause* clause, SatState* sat_state) { clause->index = sat_clause_count(sat_state) + sat_learned_clause_count(sat_state) + 1; for (c2dSize i = 0; i < sat_clause_size(clause); i++) { Lit* lit = vector_get(&clause->lits, i); Var* var = sat_literal_var(lit); if (vector_size(&var->mentions_lc) == 0 || vector_top(&var->mentions_lc) != clause) vector_push(&var->mentions_lc, clause); } vector_push(&sat_state->lc, clause); vector_push(&sat_state->q, clause); if (sat_unit_resolution(sat_state)) return NULL; return sat_state->ac; }
expression_t parse_expr() { expression_t parsed_expr; stack_sym_t top; stack_sym_t next; vector_char_t* stack = vector_init(VI_CHAR); vector_token_t* token_buffer = vector_init(VI_TOKEN); vector_expr_t* expr_buffer = vector_init(VI_EXPR); vector_push(stack, S_END); bool use_cached = cached_identificator.type != TT_NONE; token_t last_token; token_t expr_token = use_cached ? cached_identificator : next_token ; next = token_to_sym(&expr_token); do { top = vector_find(stack, top_term_cmp); switch (prec_table[top][next]) { case TAB_SP: vector_insert_after(stack, S_SEP, top_term_cmp); case TAB_P: vector_push(stack, next); //next is now top terminal on stack top = next; //store last token vector_push(token_buffer, expr_token); //choose between cached_identificator and next_token if (use_cached) { use_cached = false; cached_identificator.type = TT_NONE; expr_token = next_token; } else { expr_token = next_token = get_next_token(token_stream); } //convert next token to table symbol next = token_to_sym(&expr_token); break; case TAB_R: last_token = vector_pop(token_buffer); switch (reduce_sequence(stack)) { case RULE_REL: check_rule_rel(last_token.op_rel, expr_buffer); break; case RULE_ADDSUB: check_rule_arith(last_token.op_arith, expr_buffer); break; case RULE_MULDIV: check_rule_arith(last_token.op_arith, expr_buffer); break; case RULE_PAR: //only pop next token(TT_PARENTHESES_OPEN) from token buffer vector_pop(token_buffer); break; case RULE_ID: check_rule_id(&last_token, expr_buffer); break; default: error("Syntactic error: Failed to parse the expression", ERROR_SYN); } vector_push(stack, S_EXPR); break; case TAB_END: if (vector_pop(stack) != S_EXPR) { error("Syntactic error: Failed to parse the expression", ERROR_SYN); } parsed_expr = vector_top(expr_buffer); break; case TAB_ERR: default: error("Syntactic error: Failed to parse the expression", ERROR_SYN); } } while (top != S_END || next != S_END); ifj15_free(stack); ifj15_free(token_buffer); ifj15_free(expr_buffer); return parsed_expr; }
//constructs a SatState from an input cnf file SatState* sat_state_new(const char* file_name) { FILE *file; if (!(file = fopen(file_name, "r"))) return NULL; SatState *sat_state = malloc(sizeof(SatState)); while (!feof(file)) { if (fgetc(file) == 'p') break; while (fgetc(file) != '\n') continue; } fscanf(file, " cnf %lu %lu", &sat_state->varnum, &sat_state->clausenum); vector_init(&sat_state->vars); vector_init(&sat_state->plits); vector_init(&sat_state->nlits); vector_init(&sat_state->kb); vector_init(&sat_state->lc); vector_init(&sat_state->ds); vector_init(&sat_state->il); vector_init(&sat_state->q); vector_init(&sat_state->s); sat_state->ac = NULL; for (c2dSize i = 1; i <= sat_var_count(sat_state); i++) { Var* var = malloc(sizeof(Var)); var->index = i; var->mark = 0; vector_init(&var->mentions); vector_init(&var->mentions_lc); Lit* plit = malloc(sizeof(Lit)); plit->index = i; plit->implied = 0; plit->var = var; Lit* nlit = malloc(sizeof(Lit)); nlit->index = -i; nlit->implied = 0; nlit->var = var; vector_push(&sat_state->plits, plit); vector_push(&sat_state->nlits, nlit); var->plit = plit; var->nlit = nlit; vector_push(&sat_state->vars, var); } for (c2dSize i = 1; i <= sat_clause_count(sat_state); i++) { Clause* clause = malloc(sizeof(Clause)); clause->index = i; clause->subsumed = 0; clause->mark = 0; vector_init(&clause->lits); while (1) { c2dLiteral index; while (!fscanf(file, "%ld", &index) || (index == 0 && vector_size(&clause->lits) == 0)) { while (fgetc(file) != '\n') continue; } if (index == 0) break; vector_push(&clause->lits, sat_index2literal(index, sat_state)); } vector_push(&sat_state->kb, clause); vector_push(&sat_state->q, clause); } for (c2dSize i = 1; i <= sat_clause_count(sat_state); i++) { Clause* clause = sat_index2clause(i, sat_state); for (c2dSize j = 0; j < sat_clause_size(clause); j++) { Lit* lit = vector_get(&clause->lits, j); Var* var = sat_literal_var(lit); if (vector_size(&var->mentions) == 0 || vector_top(&var->mentions) != clause) vector_push(&var->mentions, clause); } } fclose(file); return sat_state; }