Esempio n. 1
0
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;
}
Esempio n. 2
0
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]);
    }
  }
Esempio n. 4
0
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;
}
Esempio n. 5
0
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);
}
Esempio n. 6
0
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);
}
Esempio n. 7
0
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);
      }
    }
Esempio n. 8
0
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;
}
Esempio n. 9
0
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;
}
Esempio n. 10
0
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;
}
Esempio n. 11
0
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;
}
Esempio n. 12
0
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;
}
Esempio n. 13
0
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;
}