// input form of SAT expression: 2,1 -2,3,-4 int main(int argc, char** argv) { int* num_vars_ptr = new int; std::vector <std::vector<int> > expr = parse(argc, argv, num_vars_ptr); // assume this is initialized int num_vars = *num_vars_ptr; // contains current clause true/false values std::vector<int> sat_vals; for (int i = 0; i < num_vars; i++) { sat_vals.push_back(-1); } for (int rep_num = 0; rep_num < pow(2, num_vars); rep_num++) { int rep_temp = rep_num; // fill in the SAT expr with a brute force attempt for (int i = 0; i < num_vars; i++) { int bit = rep_temp & 0x1; sat_vals.at(i) = bit; rep_temp >>= 1; } // check to see if the current SAT expression is satisfiable if (is_satisfiable(expr, sat_vals)) { printf("Solution found!\n"); print_solution(sat_vals); delete num_vars_ptr; return 0; } } printf("No solution found.\n"); delete num_vars_ptr; return 1; }
int main(int argc, char** argv) { timeout = 0; timeout_time = time(0) + 180; int err3 = 0; // Parse the formula and verify it is correct formula3 f3 = verify3(argc, argv, &err3); if(err3) printf("ERROR\n"); else { // Fill the formula with indexes fill_formula3(&f3); strip_units_and_pures3(&f3); int result = is_satisfiable3(&f3, 0); if(!timeout) { if(result) { printf("SATISFIABLE\n"); // Free the formula's memory annhialate_formula3(f3); } else { printf("UNSATISFIABLE\n"); // Free the formula's memory annhialate_formula3(f3); } } else { int err = 0; // Parse the formula and verify it is correct formula f = verify(argc, argv, &err); if(err) printf("ERROR"); else { // Fill the formula with indexes fill_formula(&f); if(is_satisfiable(&f, 0)) printf("SATISFIABLE\n"); else printf("UNSATISFIABLE\n"); } // Free the formula's memory annhialate_formula(f); } } }
bool simulator_symext::check_full_trace( const abstract_counterexamplet &abstract_counterexample, prefixt &prefix, goto_symex_statet &state, concrete_counterexamplet &concrete_counterexample, fail_infot &fail_info) { assert(!prefix.equation.SSA_steps.empty()); assert(prefix.equation.SSA_steps.back().is_assert()); status("Prefix of size "+i2string(prefix.equation.SSA_steps.size())); symex_target_equationt::SSA_stepst::const_iterator c_it= --prefix.equation.SSA_steps.end(); simulator_sat_dect satcheck(concrete_model.ns); prefix.equation.convert(satcheck); if(is_satisfiable(satcheck)) { // grab counterexample! build_goto_trace( prefix.equation, satcheck, concrete_model.ns, concrete_counterexample.goto_trace); return false; } get_fail_info( abstract_counterexample, satcheck, prefix, c_it, fail_info); // cannot be simulated, its spurious status("Spurious counterexample."); return true; }
bool simulator_baset::is_satisfiable(formulat formula) { satcheckt satcheck; #ifdef DEBUG std::cout << "simulator_baset::is_satisfiable1\n"; std::cout << "F: " << formula << std::endl; #endif formula_container.reset_prop(); #ifdef DEBUG std::cout << "simulator_baset::is_satisfiable2\n"; #endif literalt l=formula.convert(satcheck); satcheck.l_set_to(l, true); return is_satisfiable(satcheck); }
void simulator_ctt::execute_assert( statet &state, const program_formulat::formula_goto_programt::instructiont &instruction) { std::cout << "CHECKING ASSERTION\n"; formulat condition= instantiate(state, 0, instruction.guard); formulat property= formula_container.gen_and( state.data().guard, formula_container.gen_not(condition)); // see if it is reachable if(!property.is_false() && is_satisfiable(property)) { tracet trace; compute_trace(state, trace, true); dump_trace(trace, instruction); std::cout << "Assertion violated" << std::endl; std::cout << std::endl; error_state_found=true; } #if 0 else { // otherwise, treat this like an assumption state.data_w().guard= formula_container.gen_and(state.data().guard, condition); } #endif }
bool simulator_loop_detectiont::check_phase_I_equation( symex_target_equationt &equation, goto_symex_statet &state, const abstract_counterexamplet &abstract_counterexample, concrete_counterexamplet &phase_I_counterexample, prefixt::step_mapt &step_map, fail_infot &fail_info ) { minimization_listt symbols; // run SAT symex_target_equationt::SSA_stepst::iterator c_it; for(c_it=equation.SSA_steps.begin(); c_it!=equation.SSA_steps.end(); c_it++) { if(c_it->is_assignment()) { const exprt &rhs=c_it->ssa_rhs; recurrence_solver::referenced_parameters(state, rhs, symbols); continue; } if(c_it->is_location() || (c_it->is_assume() && c_it->cond_expr.is_true())) continue; bv_minimizing_dect satcheck(concrete_model.ns); symex_target_equationt::SSA_stepst SSA_steps; SSA_steps.splice(SSA_steps.end(), equation.SSA_steps, equation.SSA_steps.begin(), ++c_it); equation.SSA_steps.swap(SSA_steps); equation.convert(satcheck); equation.SSA_steps.splice(equation.SSA_steps.end(), SSA_steps, SSA_steps.begin(), SSA_steps.end()); --c_it; // solve it if(!is_satisfiable(satcheck)) break; // spurious! if(c_it->is_assert()) // we reached the assertion { for (minimization_listt::const_iterator m_it = symbols.begin(); m_it!=symbols.end(); m_it++) std::cout << from_expr (concrete_model.ns, "", *m_it) << ", "; std::cout << std::endl; satcheck.minimize(symbols); build_goto_trace( equation, satcheck, concrete_model.ns, phase_I_counterexample.goto_trace); return false; } } assert(c_it !=equation.SSA_steps.end()); // cannot be simulated, its spurious status("Phase I Counterexample is spurious"); // fill fail_info fail_info.all_steps = abstract_counterexample.steps; assert(c_it->source.pc->is_assert() || c_it->source.pc->is_assume() || c_it->source.pc->is_goto()); // get the corresponding abstract step prefixt::step_mapt::const_iterator s_it=step_map.find(c_it); assert (s_it!=step_map.end()); abstract_counterexamplet::stepst::const_iterator a_it = s_it->second; // and fill the steps fail_info.steps.clear(); for(abstract_counterexamplet::stepst::const_iterator it=abstract_counterexample.steps.begin(); it!=abstract_counterexample.steps.end(); it++) { fail_info.steps.push_back(*it); if(it==a_it) break; } fail_info.guard=c_it->source.pc->guard; // we might need to negate it if (c_it->source.pc->is_goto()) if (c_it->guard_expr.is_false()) fail_info.guard.make_not(); return true; }
bool transition_refinert::check_guarded_transition( const predicatest &predicates, const abstract_stept &abstract_state_from, unsigned passive_id, bool &inconsistent_initial_state) { // get the concrete basic block const goto_programt::instructiont &c_instruction= *abstract_state_from.pc->code.concrete_pc; if (!c_instruction.is_goto() && !c_instruction.is_assume()) return false; // whatever // this is the original guard exprt guard=c_instruction.guard; if(guard.is_true()) // boring return false; // we might need to negate it if the branch was not taken if (c_instruction.is_goto() && !abstract_state_from.branch_taken) guard.make_not(); abstract_transition_relationt &abstract_transition_relation= abstract_state_from.pc->code.get_transition_relation(); #ifdef SATCHECK_MINISAT2 satcheck_minisat_no_simplifiert satcheck; #else satcheckt satcheck; #endif bv_pointerst solver(concrete_model.ns, satcheck); solver.unbounded_array=boolbvt::U_NONE; // Note that we take "thread_nr" from "abstract_state_from", not from "abstract_state_to", as the "from" state determines which thread is executing const unsigned active_id=abstract_state_from.thread_nr; const unsigned num_threads=abstract_state_from.thread_states.size(); std::vector<predicatest> active_passive_preds(num_threads, predicatest()); for(unsigned int t=0; t < num_threads; ++t) { if(active_id!=t && passive_id < num_threads && t!=passive_id) continue; for(unsigned int i = 0; i < predicates.size(); i++) { active_passive_preds[t].lookup(active_id==t? predicates[i] : predicatest::make_expr_passive(predicates[i], concrete_model.ns, t)); } assert(active_passive_preds[t].size() == predicates.size()); } std::vector<std::vector<literalt> > predicate_variables_from(num_threads, std::vector<literalt>(predicates.size(), literalt())); bvt assumptions; std::vector<abstract_stept::thread_to_predicate_valuest::const_iterator> from_predicates(num_threads, abstract_state_from.thread_states.end()); for(unsigned int t=0; t < num_threads; ++t) { from_predicates[t]=abstract_state_from.thread_states.find(t); assert(abstract_state_from.thread_states.end() != from_predicates[t]); } // we use all predicates in order to also find constraints over invalid // from states for(unsigned i=0; i < predicates.size(); ++i) { for(unsigned int t=0; t < num_threads; ++t) { if(active_id!=t && passive_id < num_threads && t!=passive_id) continue; // not sure whether we really want the following check if(active_id!=t && active_passive_preds[t][i]==predicates[i]) continue; literalt li=make_pos(concrete_model.ns, solver, active_passive_preds[t][i]); predicate_variables_from[t][i]=li; assumptions.push_back(li.cond_negation( !from_predicates[t]->second[i])); #ifdef DEBUG const std::string predname= (active_id==t?"P#":"PP"+i2string(t)+"#")+i2string(i); std::cerr << "G-F: " << predname << ": " << (from_predicates[t]->second[i]?"":"!") << "(" << from_expr(concrete_model.ns, "", active_passive_preds[t][i]) << ")" << std::endl; #endif } } satcheck.set_assumptions(assumptions); if(!is_satisfiable(solver)) { if(passive_id >= num_threads) { const std::string opt="Invalid states requiring more than 1 passive thread"; assert(stats.find(opt)!=stats.end()); ++(stats[opt].val); } inconsistent_initial_state = true; print(9, "Guarded transition spurious due to invalid abstract state"); return false; // this has to be fixed in the respective assignment } // now add the guard solver.set_to_true(guard); // solve it incrementally if(is_satisfiable(solver)) { print(9, "Transition is OK"); #ifdef DEBUG std::cout << "********\n"; solver.print_assignment(std::cout); std::cout << "********\n"; #endif return false; // ok } if(passive_id >= num_threads) { const std::string opt="Spurious guard transitions requiring more than 1 passive thread"; assert(stats.find(opt)!=stats.end()); ++(stats[opt].val); return false; // can't do anything } print(9, "Guarded transition is spurious, refining"); exprt condition; for(unsigned i=0; i < predicates.size(); ++i) { if(satcheck.is_in_conflict(predicate_variables_from[active_id][i])) { condition.operands().push_back(exprt()); exprt &e=condition.operands().back(); e=exprt(ID_predicate_symbol, bool_typet()); e.set(ID_identifier, i); if(!from_predicates[active_id]->second[i]) e.make_not(); #ifdef DEBUG std::cout << "G-C: " << from_expr(concrete_model.ns, "", e) << std::endl; #endif } if(passive_id!=active_id && satcheck.is_in_conflict(predicate_variables_from[passive_id][i])) { condition.operands().push_back(exprt()); exprt &e=condition.operands().back(); e=exprt(ID_predicate_passive_symbol, bool_typet()); e.set(ID_identifier, i); if(!from_predicates[passive_id]->second[i]) e.make_not(); #ifdef DEBUG std::cout << "G-C-F: " << from_expr(concrete_model.ns, "", e) << std::endl; #endif } } gen_and(condition); if(c_instruction.is_goto()) { bool neg=abstract_state_from.branch_taken; constrain_goto_transition(abstract_transition_relation, condition, neg); } else { assert(c_instruction.is_assume()); constrain_assume_transition(abstract_transition_relation, condition); } // spurious return true; }
bool transition_refinert::check_assignment_transition( const predicatest &predicates, const abstract_stept &abstract_state_from, const abstract_stept &abstract_state_to, unsigned passive_id) { // Note that we take "thread_nr" from "abstract_state_from", not from "abstract_state_to", as the "from" state determines which thread is executing const unsigned active_id=abstract_state_from.thread_nr; const unsigned num_threads=abstract_state_from.thread_states.size(); std::vector<predicatest> active_passive_preds(num_threads, predicatest()); std::vector<std::vector<exprt> > predicates_wp(num_threads, std::vector<exprt>()); std::list<exprt> constraints; for(unsigned int t=0; t < num_threads; ++t) { if(active_id!=t && passive_id < num_threads && t!=passive_id) continue; for(unsigned int i = 0; i < predicates.size(); i++) { active_passive_preds[t].lookup(active_id==t? predicates[i] : predicatest::make_expr_passive(predicates[i], concrete_model.ns, t)); } assert(active_passive_preds[t].size() == predicates.size()); std::list<exprt> constraints_t; build_equation( concrete_model.ns, active_passive_preds[t], abstract_state_from.pc->code.concrete_pc, constraints_t, predicates_wp[t]); constraints.splice(constraints.end(), constraints_t); } // create SAT solver object satcheckt satcheck; bv_pointerst solver(concrete_model.ns, satcheck); solver.unbounded_array=boolbvt::U_NONE; // convert constraints for(std::list<exprt>::const_iterator it=constraints.begin(); it!=constraints.end(); it++) { exprt tmp(*it); solver.set_to_true(tmp); } abstract_transition_relationt &abstract_transition_relation= abstract_state_from.pc->code.get_transition_relation(); std::vector<std::vector<literalt> > predicate_variables_from(num_threads, std::vector<literalt>(predicates.size(), literalt())), predicate_variables_to(num_threads, std::vector<literalt>(predicates.size(), literalt())); bvt assumptions; std::vector<abstract_stept::thread_to_predicate_valuest::const_iterator> from_predicates(num_threads, abstract_state_from.thread_states.end()), to_predicates(num_threads, abstract_state_to.thread_states.end()); for(unsigned int t=0; t < num_threads; ++t) { from_predicates[t]=abstract_state_from.thread_states.find(t); assert(abstract_state_from.thread_states.end() != from_predicates[t]); to_predicates[t]=abstract_state_to.thread_states.find(t); assert(abstract_state_to.thread_states.end() != to_predicates[t]); } // we use all predicates in order to also find constraints over invalid // from/to states for(unsigned i=0; i < predicates.size(); ++i) { assert(abstract_transition_relation.to_predicates.find(i) != abstract_transition_relation.to_predicates.end() || abstract_transition_relation.from_predicates.find(i) != abstract_transition_relation.from_predicates.end() || (from_predicates[active_id]->second[i] == to_predicates[active_id]->second[i] && (passive_id >= num_threads || from_predicates[passive_id]->second[i] == to_predicates[passive_id]->second[i]))); for(unsigned int t=0; t < num_threads; ++t) { if(active_id!=t && passive_id < num_threads && t!=passive_id) continue; // not sure whether we really want the following check if(active_id!=t && active_passive_preds[t][i]==predicates[i]) continue; literalt li=make_pos(concrete_model.ns, solver, active_passive_preds[t][i]); predicate_variables_from[t][i]=li; assumptions.push_back(li.cond_negation( !from_predicates[t]->second[i])); #ifdef DEBUG const std::string predname= (active_id==t?"P#":"PP"+i2string(t)+"#")+i2string(i); std::cerr << "F: " << predname << ": " << (from_predicates[t]->second[i]?"":"!") << "(" << from_expr(concrete_model.ns, "", active_passive_preds[t][i]) << ")" << std::endl; #endif literalt lo=make_pos(concrete_model.ns, solver, predicates_wp[t][i]); predicate_variables_to[t][i]=lo; assumptions.push_back(lo.cond_negation( !to_predicates[t]->second[i])); #ifdef DEBUG std::cerr << "T: " << predname << ": " << (to_predicates[t]->second[i]?"":"!") << "(" << from_expr(concrete_model.ns, "", predicates_wp[t][i]) << ")" << std::endl; #endif } } satcheck.set_assumptions(assumptions); // solve it if(is_satisfiable(solver)) { print(9, "Transition is OK"); #ifdef DEBUG std::cout << "********\n"; solver.print_assignment(std::cout); std::cout << "********\n"; #endif return false; // ok } if(passive_id >= num_threads) { const std::string opt="Spurious assignment transitions requiring more than 1 passive thread"; assert(stats.find(opt)!=stats.end()); ++(stats[opt].val); return false; // can't do anything } print(9, "Assignment transition is spurious, refining"); exprt constraint; for(unsigned i=0; i < predicates.size(); ++i) { if(satcheck.is_in_conflict(predicate_variables_from[active_id][i])) { constraint.operands().push_back(exprt()); exprt &e=constraint.operands().back(); e=exprt(ID_predicate_symbol, bool_typet()); e.set(ID_identifier, i); if(from_predicates[active_id]->second[i]) e.make_not(); #ifdef DEBUG std::cout << "C-F: " << from_expr(concrete_model.ns, "", e) << std::endl; #endif } if(passive_id!=active_id && satcheck.is_in_conflict(predicate_variables_from[passive_id][i])) { constraint.operands().push_back(exprt()); exprt &e=constraint.operands().back(); e=exprt(ID_predicate_passive_symbol, bool_typet()); e.set(ID_identifier, i); if(from_predicates[passive_id]->second[i]) e.make_not(); #ifdef DEBUG std::cout << "C-F: " << from_expr(concrete_model.ns, "", e) << std::endl; #endif } if(satcheck.is_in_conflict(predicate_variables_to[active_id][i])) { constraint.operands().push_back(exprt()); exprt &e=constraint.operands().back(); e=exprt(ID_predicate_next_symbol, bool_typet()); e.set(ID_identifier, i); if(to_predicates[active_id]->second[i]) e.make_not(); #ifdef DEBUG std::cout << "C-T: " << from_expr(concrete_model.ns, "", e) << std::endl; #endif } if(passive_id!=active_id && satcheck.is_in_conflict(predicate_variables_to[passive_id][i])) { constraint.operands().push_back(exprt()); exprt &e=constraint.operands().back(); e=exprt(ID_next_symbol, bool_typet()); e.operands().resize(1); e.op0()=exprt(ID_predicate_passive_symbol, bool_typet()); e.op0().set(ID_identifier, i); if(to_predicates[passive_id]->second[i]) e.make_not(); #ifdef DEBUG std::cout << "C-T: " << from_expr(concrete_model.ns, "", e) << std::endl; #endif } } #ifdef DEBUG ::std::cerr << "Spurious in thread " << passive_id << " (active: " << abstract_state_from.thread_nr << "): " << ::std::endl; ::std::cerr << abstract_state_from << ::std::endl; goto_programt tmp; tmp.output_instruction(concrete_model.ns, "", std::cerr, abstract_state_from.pc->code.concrete_pc); ::std::cerr << abstract_state_to << ::std::endl; #endif if(constraint.operands().empty()) constraint.make_false(); // this can happen if else // the invariants are inconsistent gen_or(constraint); abstract_transition_relation.constraints.push_back(constraint); // spurious! return true; }
bool simulator_symext::check_prefix_equation( const abstract_counterexamplet &abstract_counterexample, prefixt &prefix, goto_symex_statet &state, concrete_counterexamplet &concrete_counterexample, fail_infot &fail_info) { unsigned int left = 0; /* leftmost index of search interval */ unsigned int right = 0; /* rightmost index of search interval */ unsigned int step = 1; /* the current step size */ unsigned int index = 0; /* the current index into the array */ // first of all, that should end with an assertion // if not, it's spurious for sure assert(!prefix.equation.SSA_steps.empty()); assert(prefix.equation.SSA_steps.back().is_assert()); status("Unprocessed prefix of size "+ i2string (prefix.equation.SSA_steps.size ())); symex_target_equationt::SSA_stepst::iterator c_it; /* construct an array of iterators (for binary search) */ std::vector<symex_target_equationt::SSA_stepst::iterator> state_array; for(c_it=prefix.equation.SSA_steps.begin(); c_it!=prefix.equation.SSA_steps.end(); c_it++) { /* assignments and locations don't make a path infeasible */ if(!(c_it->is_assignment() || c_it->is_location())) { if(!(c_it->is_assume() && c_it->cond_expr.is_true())) { state_array.push_back(c_it); // this must be an assumption, an assertion or a goto assert(c_it->source.pc->is_assert() || c_it->source.pc->is_assume() || c_it->source.pc->is_goto()); } } } assert(!state_array.empty()); // we expect at least one element! status("Processed prefix of size "+ i2string (state_array.size ())); right=state_array.size(); do { assert(index<state_array.size()); assert(index>=left); assert(index<right); status("Simulating prefix of size "+i2string(index+1)); c_it=state_array[index]; simulator_sat_dect satcheck(concrete_model.ns); symex_target_equationt::SSA_stepst SSA_steps; SSA_steps.splice(SSA_steps.end(), prefix.equation.SSA_steps, prefix.equation.SSA_steps.begin(), ++c_it); prefix.equation.SSA_steps.swap(SSA_steps); prefix.equation.convert(satcheck); prefix.equation.SSA_steps.splice(prefix.equation.SSA_steps.end(), SSA_steps, SSA_steps.begin(), SSA_steps.end()); --c_it; if(is_satisfiable(satcheck)) { // it's the assertion? grab counterexample! if(c_it->is_assert()) { build_goto_trace( prefix.equation, satcheck, concrete_model.ns, concrete_counterexample.goto_trace); return false; } // otherwise decrease the search interval size left=index; /* feasible element */ } else // unsatisfiable { right = index; /* infeasible element */ step = 1; /* reset the step size */ index = left; /* and restart from left */ get_fail_info( abstract_counterexample, satcheck, prefix, c_it, fail_info); } /* now increase the index and the step interval */ index = (left + step < right)? (left + step) : (right - 1); step = 2 * step; } while(left+1<right); // cannot be simulated, its spurious status("Spurious counterexample"); // report the location status("Simulation failed at "+ fail_info.last_step().pc->location.as_string()); return true; }