decision_proceduret::resultt smt1_dect::read_result_z3(std::istream &in) { std::string line; decision_proceduret::resultt res = D_ERROR; smt1_prop.reset_assignment(); typedef hash_map_cont<std::string, std::string, string_hash> valuest; valuest values; while(str_getline(in, line)) { if(line=="sat") res = D_SATISFIABLE; else if(line=="unsat") res = D_UNSATISFIABLE; else { std::size_t pos=line.find(" -> "); if(pos!=std::string::npos) values[std::string(line, 0, pos)]= std::string(line, pos+4, std::string::npos); } } for(identifier_mapt::iterator it=identifier_map.begin(); it!=identifier_map.end(); it++) { it->second.value.make_nil(); std::string conv_id=convert_identifier(it->first); std::string value=values[conv_id]; if(value=="") continue; // std::cout << it->first << " := " << value << std::endl; exprt e; if(string_to_expr_z3(it->second.type, value, e)) { // std::cout << "E: " << e << std::endl; it->second.value=e; } else set_value(it->second, value); } // Booleans for(unsigned v=0; v<smt1_prop.no_variables(); v++) { std::string value=values["B"+i2string(v)]; if(value=="") continue; smt1_prop.set_assignment(literalt(v, false), value=="true"); } return res; }
decision_proceduret::resultt smt1_dect::read_result_boolector(std::istream &in) { std::string line; str_getline(in, line); if(line=="sat") { smt1_prop.reset_assignment(); typedef hash_map_cont<std::string, std::string, string_hash> valuest; valuest values; while(str_getline(in, line)) { std::size_t pos=line.find(' '); if(pos!=std::string::npos) values[std::string(line, 0, pos)]= std::string(line, pos+1, std::string::npos); } // Theory variables for(identifier_mapt::iterator it=identifier_map.begin(); it!=identifier_map.end(); it++) { it->second.value.make_nil(); std::string conv_id=convert_identifier(it->first); std::string value=values[conv_id]; if(value=="") continue; set_value(it->second, value); } // Booleans for(unsigned v=0; v<smt1_prop.no_variables(); v++) { std::string value=values["B"+i2string(v)]; if(value=="") continue; smt1_prop.set_assignment(literalt(v, false), value=="1"); } return D_SATISFIABLE; } else if(line=="unsat") return D_UNSATISFIABLE; else error("Unexpected result from SMT-Solver: "+line); return D_ERROR; }
virtual void root(const vec<Lit> &c) { resolution_proof.clauses.push_back(clauset()); resolution_proof.clauses.back().is_root=true; resolution_proof.clauses.back().root_clause.resize(c.size()); // resolution_proof.clauses.back().pid = resolution_proof.partition_id; for(int i=0; i<c.size(); i++) { resolution_proof.clauses.back().root_clause[i]= literalt(var(c[i]), sign(c[i])); // if(var(c[i]) > resolution_proof.no_vars) // resolution_proof.no_vars = var(c[i]); } }
literalt prop_convt::get_literal(const irep_idt &identifier) { std::pair<symbolst::iterator, bool> result= symbols.insert(std::pair<irep_idt, literalt>(identifier, literalt())); if(!result.second) return result.first->second; // produce new variable literalt literal=prop.new_variable(); // set the name of the new variable prop.set_variable_name(literal, id2string(identifier)); // insert result.first->second=literal; return literal; }
const exprt qbf_squolem_coret::f_get_dnf(WitnessStack *wsp) { Clause *p=wsp->posWits; if(!p) return exprt(ID_false, typet(ID_bool)); exprt::operandst operands; while(p!=NULL) { exprt cube=and_exprt(); for(unsigned i=0; i<p->size; i++) { const Literal &lit=p->literals[i]; exprt subf = f_get(literalt(var(lit), !isPositive(lit))); if(find(cube.operands().begin(), cube.operands().end(), subf)== cube.operands().end()) cube.move_to_operands(subf); simplify_extractbits(cube); } if(cube.operands().empty()) cube=true_exprt(); else if(cube.operands().size()==1) { const exprt tmp=cube.op0(); cube=tmp; } #if 0 std::cout << "CUBE: " << cube << std::endl; #endif operands.push_back(cube); p=p->next; } return or_exprt(operands); }
const exprt qbf_squolem_coret::f_get_cnf(WitnessStack *wsp) { Clause *p=wsp->negWits; if(!p) return exprt(ID_true, typet(ID_bool)); exprt::operandst operands; while(p!=NULL) { exprt clause=or_exprt(); for(unsigned i=0; i<p->size; i++) { const Literal &lit=p->literals[i]; exprt subf = f_get(literalt(var(lit), isPositive(lit))); // negated! if(find(clause.operands().begin(), clause.operands().end(), subf)== clause.operands().end()) clause.move_to_operands(subf); } if(clause.operands().empty()) clause=false_exprt(); else if(clause.operands().size()==1) { const exprt tmp=clause.op0(); clause=tmp; } #if 0 std::cout << "CLAUSE: " << clause << std::endl; #endif operands.push_back(clause); p=p->next; } return and_exprt(operands); }
void aig_prop_solvert::convert_node( unsigned n, const aigt::nodet &node, bool n_pos, bool n_neg, std::vector<unsigned> &p_usage_count, std::vector<unsigned> &n_usage_count) { if (p_usage_count[n] > 0 || n_usage_count[n] > 0) { literalt o=literalt(n, false); bvt body(2); body[0]=node.a; body[1]=node.b; #ifdef USE_AIG_COMPACT // Inline positive literals // This should remove the overhead introduced by land and lor for bvt for (bvt::size_type i = 0; i < body.size(); i++) { literalt l = body[i]; if (!l.sign() && // Used positively... aig.nodes[l.var_no()].is_and() && // ... is a gate ... p_usage_count[l.var_no()] == 1 && // ... only used here. n_usage_count[l.var_no()] == 0) { const aigt::nodet &rep = aig.nodes[l.var_no()]; body[i] = rep.a; body.push_back(rep.b); --i; // Repeat the process --p_usage_count[l.var_no()]; // Supress generation of inlined node } } // TODO : Could check the array for duplicates / complementary literals // but this should be found by the SAT preprocessor. // TODO : Likewise could find things that are constrained, esp the output // and backwards constant propagate. Again may not be worth it. // lxor and lselect et al. are difficult to express in AIGs. // Doing so introduces quite a bit of overhead. // This should recognise the AIGs they produce and // handle them in a more efficient way. // Recognise something of the form: // // neg(o) = lor(land(a,b), land(neg(a),c)) // o = land(lneg(land(a,b)), lneg(land(neg(a),c))) // // Note that lxor and lselect generate the negation of this // but will still be recognised because the negation is // recorded where it is used if(body.size() == 2 && body[0].sign() && body[1].sign()) { const aigt::nodet &left = aig.nodes[body[0].var_no()]; const aigt::nodet &right = aig.nodes[body[1].var_no()]; if(left.is_and() && right.is_and()) { if(left.a == neg(right.a)) { if (p_usage_count[body[0].var_no()] == 0 && n_usage_count[body[0].var_no()] == 1 && p_usage_count[body[1].var_no()] == 0 && n_usage_count[body[1].var_no()] == 1) { bvt lits(3); if (n_neg) { lits[0] = left.a; lits[1] = right.b; lits[2] = o; solver.lcnf(lits); lits[0] = neg(left.a); lits[1] = left.b; lits[2] = o; solver.lcnf(lits); } if (n_pos) { lits[0] = left.a; lits[1] = neg(right.b); lits[2] = neg(o); solver.lcnf(lits); lits[0] = neg(left.a); lits[1] = neg(left.b); lits[2] = neg(o); solver.lcnf(lits); } // Supress generation --n_usage_count[body[0].var_no()]; --n_usage_count[body[1].var_no()]; return; } } } } // Likewise, carry has an improved encoding which is generated // by the CNF encoding if (body.size() == 3 && body[0].sign() && body[1].sign() && body[2].sign()) { const aigt::nodet &left = aig.nodes[body[0].var_no()]; const aigt::nodet &mid = aig.nodes[body[1].var_no()]; const aigt::nodet &right = aig.nodes[body[2].var_no()]; if (left.is_and() && mid.is_and() && right.is_and()) { if (p_usage_count[body[0].var_no()] == 0 && n_usage_count[body[0].var_no()] == 1 && p_usage_count[body[1].var_no()] == 0 && n_usage_count[body[1].var_no()] == 1 && p_usage_count[body[2].var_no()] == 0 && n_usage_count[body[2].var_no()] == 1) { literalt a = left.a; literalt b = left.b; literalt c = mid.a; if (a == right.b && b == mid.b && c == right.a) { // A (negative) carry -- 1 if at most one input is 1 bvt lits(3); if (n_neg) { lits[0] = a; lits[1] = b; lits[2] = o; solver.lcnf(lits); lits[0] = a; lits[1] = c; lits[2] = o; solver.lcnf(lits); lits[0] = b; lits[1] = c; lits[2] = o; solver.lcnf(lits); } if (n_pos) { lits[0] = neg(a); lits[1] = neg(b); lits[2] = neg(o); solver.lcnf(lits); lits[0] = neg(a); lits[1] = neg(c); lits[2] = neg(o); solver.lcnf(lits); lits[0] = neg(b); lits[1] = neg(c); lits[2] = neg(o); solver.lcnf(lits); } // Supress generation --n_usage_count[body[0].var_no()]; --n_usage_count[body[1].var_no()]; --n_usage_count[body[2].var_no()]; return; } } } } // TODO : these special cases are fragile and could be improved. // They don't handle cases where the construction is partially constant // folded. Also the usage constraints are sufficient for improvement // but reductions may still be possible with looser restrictions. #endif if(n_pos) { bvt lits(2); lits[1]=neg(o); forall_literals(it, body) { lits[0]=pos(*it); solver.lcnf(lits); } }
decision_proceduret::resultt smt1_dect::read_result_cvc3(std::istream &in) { std::string line; decision_proceduret::resultt res = D_ERROR; smt1_prop.reset_assignment(); typedef hash_map_cont<std::string, std::string, string_hash> valuest; valuest values; while(str_getline(in, line)) { if(line=="sat") res = D_SATISFIABLE; else if(line=="unsat") res = D_UNSATISFIABLE; else if(line.find("Current scope level")!=std::string::npos || line.find("Variable Assignment")!=std::string::npos) ; //ignore else { assert(line.substr(0,13)==" :assumption"); std::size_t pos=line.find('('); if(pos!=std::string::npos) { std::string var; std::string val; if(line[pos+1]=='=') { std::string ops = line.substr(pos+3, line.length()-pos-4); std::size_t blank=ops.find(' '); var = ops.substr(0, blank); val = ops.substr(blank+1, ops.length()-blank); if((var.length()>=4 && var.substr(0,4)=="cvc3") || (val.length()>=4 && val.substr(0,4)=="cvc3") || var==val) continue; else if((var.substr(0,9)=="array_of'") || (var.substr(0,2)=="bv" && val.substr(0,2)!="bv")) { std::string t=var; var=val; val=t; } } else if(line.substr(pos+1,3)=="not") { var = line.substr(pos+5, line.length()-pos-6); val = "false"; } else { var = line.substr(pos+1, line.length()-pos-2); assert(var.find(' ')==std::string::npos); val = "true"; } values[var]=val; } } } for(identifier_mapt::iterator it=identifier_map.begin(); it!=identifier_map.end(); it++) { it->second.value.make_nil(); std::string conv_id=convert_identifier(it->first); std::string value=values[conv_id]; if(value=="") continue; if(value.substr(0,2)=="bv") { std::string v=value.substr(2, value.find('[')-2); size_t p = value.find('[')+1; std::string w=value.substr(p, value.find(']')-p); std::string binary=integer2binary(string2integer(v,10), string2integer(w,10).to_ulong()); set_value(it->second, "", binary); } else if(value=="false") it->second.value.make_false(); else if(value=="true") it->second.value.make_true(); else if(value.substr(0,8)=="array_of") { // We assume that array_of has only concrete arguments... irep_idt id(value); array_of_mapt::const_iterator fit=array_of_map.begin(); while(fit!=array_of_map.end() && fit->second!=id) fit++; if(fit!=array_of_map.end()) it->second.value = fit->first; } else set_value(it->second, "", value); } // Booleans for(unsigned v=0; v<smt1_prop.no_variables(); v++) { std::string value=values["B"+i2string(v)]; if(value=="") continue; smt1_prop.set_assignment(literalt(v, false), value=="true"); } return res; }
decision_proceduret::resultt smt1_dect::read_result_mathsat(std::istream &in) { std::string line; decision_proceduret::resultt res = D_ERROR; smt1_prop.reset_assignment(); typedef hash_map_cont<std::string, valuet, string_hash> valuest; valuest values; while(str_getline(in, line)) { if(line=="sat") res=D_SATISFIABLE; else if(line=="unsat") res=D_UNSATISFIABLE; else if(line.size()>=1 && line[0]=='(') { // (= c_h39__h39___CPROVER_malloc_size_h39_35_h39_1 bv0[64]) // (= (select __h64_0 bv0[32]) bv5[8]) std::size_t pos1=line.find(' '); std::size_t pos2=line.rfind(' '); if(pos1!=std::string::npos && pos2!=std::string::npos && pos1!=pos2) { std::string id=std::string(line, pos1+1, pos2-pos1-1); std::string value=std::string(line, pos2+1, line.size()-pos2-2); if(has_prefix(id, "(select ")) { #if 0 std::size_t pos3=id.rfind(' '); std::string index=std::string(pos3+1, id.size()-pos3-1); id=std::string(id, 8, pos3-8); #endif } else values[id].value=value; } } } for(identifier_mapt::iterator it=identifier_map.begin(); it!=identifier_map.end(); it++) { it->second.value.make_nil(); std::string conv_id=convert_identifier(it->first); std::string value=mathsat_value(values[conv_id].value); if(value!="") set_value(it->second, "", value); } // Booleans for(unsigned v=0; v<smt1_prop.no_variables(); v++) { std::string value=values["B"+i2string(v)].value; if(value=="") continue; smt1_prop.set_assignment(literalt(v, false), value=="true"); } return res; }
decision_proceduret::resultt smt1_dect::read_result_boolector(std::istream &in) { std::string line; str_getline(in, line); if(line=="sat") { smt1_prop.reset_assignment(); typedef hash_map_cont<std::string, valuet, string_hash> valuest; valuest values; while(str_getline(in, line)) { std::size_t pos=line.find(' '); if(pos!=std::string::npos && pos!=0) { std::string id=std::string(line, 0, pos); std::string value=std::string(line, pos+1, std::string::npos); // Boolector offers array values as follows: // // ID[INDEX] VALUE // // There may be more than one line per ID if(id!="" && id[id.size()-1]==']') // array? { std::size_t pos2=id.find('['); if(pos2!=std::string::npos) { std::string new_id=std::string(id, 0, pos2); std::string index=std::string(id, pos2+1, id.size()-pos2-2); values[new_id].index_value_map[index]=value; } } else values[id].value=value; } } // Theory variables for(identifier_mapt::iterator it=identifier_map.begin(); it!=identifier_map.end(); it++) { it->second.value.make_nil(); std::string conv_id=convert_identifier(it->first); const valuet &v=values[conv_id]; for(valuet::index_value_mapt::const_iterator i_it=v.index_value_map.begin(); i_it!=v.index_value_map.end(); i_it++) set_value(it->second, i_it->first, i_it->second); if(v.value!="") set_value(it->second, "", v.value); } // Booleans for(unsigned v=0; v<smt1_prop.no_variables(); v++) { std::string value=values["B"+i2string(v)].value; if(value=="") continue; smt1_prop.set_assignment(literalt(v, false), value=="1"); } return D_SATISFIABLE; } else if(line=="unsat") return D_UNSATISFIABLE; else error("Unexpected result from SMT-Solver: "+line); return D_ERROR; }
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; }
decision_proceduret::resultt smt2_dect::read_result_mathsat(std::istream &in) { std::string line; decision_proceduret::resultt res=D_ERROR; smt2_prop.reset_assignment(); typedef hash_map_cont<std::string, std::string, string_hash> valuest; valuest values; while(str_getline(in, line)) { if(line=="sat") res=D_SATISFIABLE; else if(line=="unsat") res=D_UNSATISFIABLE; else if(line.size()>=2 && line[0]=='(') { // ( (B0 true) ) std::size_t pos1=line.find('(', 1); std::size_t pos2=line.find(' ', pos1); std::size_t pos3=line.find(')', pos2); if(pos1!=std::string::npos && pos2!=std::string::npos && pos3!=std::string::npos) { std::string id=std::string(line, pos1+1, pos2-pos1-1); std::string value=std::string(line, pos2+1, pos3-pos2-1); values[id]=value; } } } for(identifier_mapt::iterator it=identifier_map.begin(); it!=identifier_map.end(); it++) { it->second.value.make_nil(); std::string conv_id=convert_identifier(it->first); std::string value=values[conv_id]; if(value=="") continue; if (value.substr(0, 5) == "(_ bv") { // value is "(_ bvDECIMAL_VALUE SIZE" // convert to binary value = value.substr(5); size_t pos = value.find(' '); std::string v = value.substr(0, pos); std::string w = value.substr(pos+1); value = integer2binary(string2integer(v, 10), string2integer(w, 10).to_ulong()); } set_value(it->second, value); } // Booleans for(unsigned v=0; v<smt2_prop.no_variables(); v++) { std::string value=values["B"+i2string(v)]; if(value=="") continue; smt2_prop.set_assignment(literalt(v, false), value=="true"); } return res; }