bool state_projectiont::is_new(const statet &state, bool use_cache) { // get the right map assert(!state.data().previous.is_null()); state_listt &state_list= state_map[state.data().previous_PC]; // first try syntactically for(state_listt::const_iterator it=state_list.begin(); it!=state_list.end(); it++) if(is_syntactically_equal(*it, state)) return false; // not new // now try expensive comparison for(state_listt::const_iterator it=state_list.begin(); it!=state_list.end(); it++) if(is_equal(*it, state, use_cache)) { // put into list anyways state_list.push_back(state); return false; // not new } // not found, it's new state_list.push_back(state); return true; }
void simulator_ctt::compute_goto_successors( const statet &state, queuet &queue) { const instructiont &instruction=*state.data().threads.front().PC; unsigned count=0; // must have target assert(!instruction.targets.empty()); formulat instantiated_guard= instantiate(state, 0, instruction.guard); formulat new_guard_taken; if(instantiated_guard.is_true()) new_guard_taken=state.data().guard; else { new_guard_taken=formula_container.gen_and( instantiated_guard, state.data().guard); formulat new_guard_not_taken=formula_container.gen_and( formula_container.gen_not(instantiated_guard), state.data().guard); // do "guard is false" case statet new_state=state; new_state.data_w().threads.front().PC++; new_state.data_w().guard=new_guard_not_taken; new_state.data_w().taken=false; new_state.set_previous(state, 0); queue.add(new_state); count++; } for(program_formulat::formula_goto_programt:: instructiont::targetst::const_iterator t_it=instruction.targets.begin(); t_it!=instruction.targets.end(); t_it++) { statet new_state=state; new_state.data_w().threads.front().PC=*t_it; new_state.data_w().guard=new_guard_taken; new_state.data_w().taken=true; new_state.set_previous(state, 0); queue.add(new_state); count++; } if(count>=2) path_counter+=count-1; }
void simulatort::explore( const statet &state, queuet &queue) { #ifdef DEBUG std::cout << "simulatort::explore1\n"; #endif #if 0 std::cout << "/////////////////////////////////////////////// " << "\n"; for(unsigned thread=0; thread<program_formula.threads.size(); thread++) { std::cout << "Thread " << thread << " Location: "; if(state.data().PCs[thread]== program_formula.threads[thread].formula_goto_program.instructions.end()) std::cout << "END" << std::endl; else { instructiont &instruction=*state.data().PCs[thread]; std::cout << location_string(instruction.location) << std::endl; } } std::cout << std::endl; #endif // dump it if the guard is false if(state.data().guard.is_false()) return; #ifdef DEBUG std::cout << "simulatort::explore2\n"; #endif if(history.check_history( state, enable_qbf_cache, enable_small_history)) { // we have seen it already #ifdef DEBUG std::cout << ">>>>>>>>>>>>>>>>>>>>>>>> SEEN ALREADY\n"; #endif return; } #ifdef DEBUG std::cout << "simulatort::explore3\n"; #endif compute_successor_states(state, true, queue); #ifdef DEBUG std::cout << "simulatort::explore4\n"; #endif }
bool state_projectiont::is_syntactically_equal( const statet &old_state, const statet &new_state) { if(old_state.data().guard!=new_state.data().guard) return false; unsigned v=0; for(program_formulat::variablest::const_iterator it=program_formula.variables.begin(); it!=program_formula.variables.end(); it++, v++) { if(it->is_global) { assert(v<old_state.data().globals.size()); assert(v<new_state.data().globals.size()); if(old_state.data().globals[v]!= new_state.data().globals[v]) return false; } } return true; }
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 }
void simulator_ctt::execute_functioncall( const statet &state, edget &edge) { const program_formulat::formula_goto_programt::instructiont &instruction=*state.data().threads.front().PC; const irep_idt &function_id=instruction.code.function; // find in program formula program_formulat::function_mapt::const_iterator f_it=program_formula.function_map.find(function_id); assert(f_it!=program_formula.function_map.end()); const program_formulat::functiont &f=f_it->second; // produce a start state statet start_state(state); statet::threadt &thread=start_state.data_w().threads.back(); // adjust PC thread.program=&(f.body); thread.PC=thread.start_pc(); // assign args assert(instruction.code.function_args.size()==f.args.size()); for(unsigned i=0; i<f.args.size(); i++) { formulat formula=instruction.code.function_args[i]; formula=instantiate(state, 0, formula); start_state.data_w().set_var(f.args[i], 0, formula); } std::cout << "Adding edge for " << function_id << std::endl; // add edge edget &f_edge=new_edge(function_id, start_state); f_edge.calls.push_back(conft(edge, state)); }
void simulator_ctt::execute_return(const statet &state, edget &edge) { // compute vector of return values std::vector<formulat> return_values; bool have_return=!state.data().threads.front().is_at_end(); if(have_return) { const program_formulat::formula_goto_programt::instructiont &return_instruction=*state.data().threads.front().PC; return_values.resize(return_instruction.code.assigns.size()); for(unsigned i=0; i<return_values.size(); i++) { formulat f1=return_instruction.code.assigns[i].value; formulat f2=instantiate(state, 0, f1); return_values[i]=f2; } } // propagate to all call sites for(callst::const_iterator it=edge.calls.begin(); it!=edge.calls.end(); it++) { const conft &conf=*it; // save PC const_targett PC=conf.state.data().threads.front().PC; const program_formulat::formula_goto_programt::instructiont &call_instruction=*PC; // get return PC PC++; statet new_state=state; // set PC to return location new_state.data_w().threads.front().PC=PC; new_state.data_w().threads.front().program= conf.state.data().threads.front().program; if(!call_instruction.code.function_lhs.empty()) { if(have_return) { assert(call_instruction.code.function_lhs.size()== return_values.size()); // do return value for(unsigned i=0; i<return_values.size(); i++) { if(call_instruction.code.function_lhs[i].in_use) { unsigned lhs=call_instruction.code.function_lhs[i].variable; new_state.data_w().set_var(lhs, 0, return_values[i]); } } } } std::cout << "Adding to queue of " << conf.edge->function << std::endl; // put it into the right queue conf.edge->queue.add(new_state); // make sure this is noticed active_edges.insert(conf.edge); } }
bool match( formula_containert &container, const statet &state, const std::map<vart, bool> &values) { // do the reset container.reset_prop(); // build the SAT instance satcheckt satcheck; // 1st, the guard must hold { literalt l=state.data().guard.convert(satcheck); satcheck.l_set_to(l, true); } #if 0 std::cout << "G: "; state.data().guard.output(std::cout); std::cout << std::endl; #endif // 2nd, the values must match for(std::map<vart, bool>::const_iterator it=values.begin(); it!=values.end(); it++) { const vart &var=it->first; formulat f=state.data().get_var(var.var_nr, var.thread_nr); literalt l=f.convert(satcheck); satcheck.l_set_to(l, it->second); #if 0 std::cout << "V: "; state.data().values[v].output(std::cout); std::cout << std::endl; #endif } std::cout << "Running " << satcheck.solver_text() << ", " << satcheck.no_variables() << " variables, " << satcheck.no_clauses() << " clauses" << std::endl; switch(satcheck.prop_solve()) { case propt::P_SATISFIABLE: // oh! match! return true; case propt::P_UNSATISFIABLE: // nah, no match return false; default:; assert(false); } assert(false); return false; }