Example #1
0
std::pair<exprt,exprt> ranking_synthesis_qbf_bitwiset::duplicate(
   const std::pair<exprt,exprt> pp,
   unsigned bits)
{
  if(bits<=1) return pp;

  std::pair<exprt,exprt> res;
  res.first.id(ID_concatenation); res.first.type() = unsignedbv_typet(bits);
  res.second.id(ID_concatenation); res.second.type() = unsignedbv_typet(bits);

  std::vector<replace_mapt> replace_maps(bits);

  for(coefficient_mapt::const_iterator it=coefficient_map.begin();
      it!=coefficient_map.end();
      it++)
  {
    const exprt *sym=&it->second;
    while(sym->id()==ID_typecast)
      sym=&sym->op0();

    assert(sym->id()==ID_symbol);
    exprt nsym(*sym);
    std::string original_id=sym->get_string(ID_identifier);

    for(unsigned i=1; i<bits; i++)
    {
      nsym.set(ID_identifier, original_id + "@" + i2string(i));
      replace_maps[i][*sym] = nsym;
    }
  }

  for(int i=bits-1; i>0; i--)
  {
    exprt pre=pp.first;
    exprt post=pp.second;

    replace_expr(replace_maps[i], pre);
    replace_expr(replace_maps[i], post);

    res.first.move_to_operands(pre);
    res.second.move_to_operands(post);
  }

  res.first.copy_to_operands(pp.first); // 0-bit is not renamed!
  res.second.copy_to_operands(pp.second);

  return res;
}
Example #2
0
/* this function does the transformation involved in replacing an
 * expression */
static void replace_expression(expr_t* expr,mloop_t* mloop) {
  symboltable_t *new_temp;
  expr_t *new_expr;
  char *new_id = (char *)malloc(10);
  statement_t *body=T_MLOOP_BODY(mloop);

  /* drop out if replacement expr already exists */
  if (find_replacement(mloop, expr)) return;

  /* create a new temporary variable */
  sprintf(new_id,"__temp%d",idnum);
  new_temp = alloc_loc_st (S_VARIABLE,new_id);
  S_DTYPE(new_temp) = T_TYPEINFO(expr);
  S_VAR_INIT(new_temp) = NULL;
  S_INIT(new_temp) = build_init(expr,NULL);
  S_PROHIBITIONS(new_temp) |= TILED_OUTER_MLOOP_FLAG;
  new_expr = build_0ary_op(VARIABLE,new_temp);
  idnum++;

  /* replace the variable */
  T_ADD_MLOOP_VAR (mloop, new_temp, T_MLOOP_ORDER(mloop, T_MLOOP_RANK(mloop)-1));
  replace_expr(expr, copy_expr(new_expr));
  /*add_replacement(mloop,copy_expr(expr),copy_expr(new_expr));*/

  /* if necessary, reassign the variable */
  if (is_written(new_expr,body)) {
    statement_t* post;
    expr_t* reassign;
    reassign=build_binary_op(BIASSIGNMENT,copy_expr(new_expr),copy_expr(expr));
    post=build_expr_statement(reassign,T_LINENO(body),T_FILENAME(body));
    T_PROHIBITIONS(post) |= TILED_OUTER_MLOOP_FLAG;
    T_ADD_MLOOP_POST(mloop,post,T_MLOOP_ORDER(mloop, T_MLOOP_RANK(mloop)-1));
  }
} /* replace_expression(expr,mloop) */
Example #3
0
bool ranking_synthesis_seneschalt::write_constraints(
  std::ostream &f,
  replace_mapt &rmap,
  exprt e)
{
  expr2seneschalt expr2seneschal(ns);
  f << " \\transition {" << std::endl;

  bool first=true;
  forall_operands(it, e)
  {
    exprt t = *it;
    replace_expr(rmap, t);

    {
      if(!first) f << " & " << std::endl;

      try {
        f << "  " << expr2seneschal(t, false, true);
      }
      catch (const expr2seneschalt::UnhandledException &ex)
      {
        status("Seneschal unsuitable: " + ex.reason.id_string());
        status("In: " + from_expr(ns, "", t));
        return false;
      }

      first=false;
    }
  }
Example #4
0
std::pair<exprt,exprt> ranking_synthesis_qbf_bitwiset::ite_template()
{
  exprt function;
  replace_mapt pre_replace_map;
    
  unsigned state_size = get_state_size();
  unsigned bits=log((double)state_size)/log(2.0) + 1;  
  
  symbol_exprt const_sym(CONSTANT_COEFFICIENT_ID, unsignedbv_typet(bits));
  const_coefficient=coefficient(const_sym);
    
  unsigned cnt=0;
  for(bodyt::variable_mapt::const_iterator it=body.variable_map.begin();
      it!=body.variable_map.end();
      it++)
  {
    if(used_variables.find(it->first)==used_variables.end())
      continue;
    
    exprt postsym=symbol_exprt(it->first, ns.lookup(it->first).type);
    exprt presym=symbol_exprt(it->second, ns.lookup(it->second).type);
        
    pre_replace_map[postsym] = presym; // save the corresponding pre-var
    exprt var=postsym;
    adjust_type(var.type());

    unsigned vwidth = safe_width(var, ns);
    for(unsigned i=0; i<vwidth; i++)
    {
      exprt t(ID_extractbit, bool_typet());
      t.copy_to_operands(var);
      t.copy_to_operands(from_integer(i, typet(ID_natural)));
      
      if(it==body.variable_map.begin() && i==0)
        function = t;
      else
      {
        function =           
          if_exprt(equal_exprt(const_coefficient, 
                                  from_integer(cnt, const_coefficient.type())),
                   t,
                   function);        
      }      
      
      cnt++;
    }
  }
  
  exprt pre_function=function;
  replace_expr(pre_replace_map, pre_function);
  
  return std::pair<exprt,exprt>(pre_function, function);
}
Example #5
0
bool ranking_synthesis_satt::generate_functions(void)
{
  exprt templ = instantiate();

  if(body.variable_map.size()==0 || templ.is_false())
    return false;

  // some coefficient values
  c_valuest c_values;

  debug("Template:" + from_expr(ns, "", templ));

  satcheckt::resultt result=satcheckt::P_SATISFIABLE;

  while(result==satcheckt::P_SATISFIABLE)
  {
    if(c_values.size()==0)
      initialize_coefficients(c_values);
    else
    {
      if(increase_coefficients(c_values))
        break;
    }

    result=check_for_counterexample(templ, c_values,
                                    conversion_time, solver_time);
  }

  if(result==satcheckt::P_ERROR)
    throw ("Solver error.");
  else if(result==satcheckt::P_UNSATISFIABLE) // no counter-example
  {
    debug("Found ranking functions");

    // put the coefficient values in the rank relation
    replace_mapt replace_map;

    for(c_valuest::const_iterator it=c_values.begin();
        it!=c_values.end();
        it++)
    {
      replace_map[it->first] = from_integer(it->second, it->first.type());
    }

    replace_expr(replace_map, rank_relation);
    simplify(rank_relation, ns);

    return true;
  }
  else
    return false;
}
Example #6
0
bool ranking_synthesis_qbf_bitwiset::extract_ranking_relation(boolbvt &converter)
{
  replace_mapt replace_map;

  for(coefficient_mapt::const_iterator it=coefficient_map.begin();
      it!=coefficient_map.end();
      it++)
  {
    const exprt *sym=&it->second;
    while(sym->id()==ID_typecast)
      sym=&sym->op0();

    if(bitwise_width<=1)
    {
      exprt value;      
      value=converter.get(*sym); // this returns a constant.      
      
      replace_map[*sym] = value;
      std::cout << from_expr(ns, "", it->second) << " = " << from_expr(ns, "", value) << std::endl;
    }
    else
    {
      assert(sym->id()==ID_symbol);
      exprt nsym(*sym);
      std::string original_id=sym->get_string(ID_identifier);

      for(unsigned i=0; i<bitwise_width; i++)
      {
        if(i!=0) nsym.set(ID_identifier, original_id + "@" + i2string(i));
        exprt value = converter.get(nsym);
        replace_map[nsym] = value; // bit i
        std::cout << from_expr(ns, "", nsym) << " = " << from_expr(ns, "", value) << std::endl;
      }
    }
  }

  if(const_coefficient.id()!=ID_nil)
  {
    exprt value=converter.get(const_coefficient);
    std::cout << from_expr(ns, "", const_coefficient) << " = " << from_expr(ns, "", value) << std::endl;
    replace_map[const_coefficient]=value;
  }

  replace_expr(replace_map, rank_relation);
  simplify(rank_relation, ns);

  return false;
}
Example #7
0
void boolbvt::post_process_quantifiers()
{
  std::set<exprt> instances;
  
  if(quantifier_list.empty()) return;
  
  for(quantifier_listt::const_iterator q_it=quantifier_list.begin();
      q_it!=quantifier_list.end();
      q_it++)
    forall_operands(o_it, q_it->expr.op1())
      instances.insert(*o_it);

  if(instances.empty())
    throw "post_process_quantifiers: no instances";

  for(quantifier_listt::const_iterator q_it=quantifier_list.begin();
      q_it!=quantifier_list.end();
      q_it++)
  {
    const exprt &expr=q_it->expr;
    
    bvt inst_bv;
    inst_bv.reserve(instances.size());
    
    for(std::set<exprt>::const_iterator it=instances.begin();
        it!=instances.end();
        it++)
    {
      exprt dest(expr.op2());

      exprt by(*it);
      if(expr.op0().type()!=by.type())
        by.make_typecast(expr.op0().type());

      replace_expr(expr.op0(), by, dest);
      inst_bv.push_back(convert(dest));
    }

    if(expr.id()=="forall")
      prop.set_equal(prop.land(inst_bv), q_it->l);
    else if(expr.id()=="exists")
      prop.set_equal(prop.lor(inst_bv), q_it->l);
    else
      assert(false);
  }
}
Example #8
0
bool ranking_synthesis_seneschalt::extract_ranking_relation(exprt &rf)
{
  exprt function = rf;
  replace_mapt post_replace_map;

  for(bodyt::variable_mapt::const_iterator it=body.variable_map.begin();
      it!=body.variable_map.end();
      it++)
  {
    if(used_variables.find(it->first)==used_variables.end())
      continue;
    
    exprt postsym=symbol_exprt(it->first, ns.lookup(it->first).type);
    exprt presym=symbol_exprt(it->second, ns.lookup(it->second).type);
    
    post_replace_map[presym] = postsym;
  }

  for(intermediate_statet::const_iterator it=intermediate_state.begin();
      it!=intermediate_state.end();
      it++)
  {
    const exprt e=symbol_exprt(*it);

    // Get rid of SSA-numbers
    const std::string &str = id2string(*it);
    exprt ne=e;
    ne.set("identifier", str.substr(0, str.find('#')));
    ne.type()=ns.lookup(ne.get("identifier")).type;
  }

  simplify(function, ns);

  exprt post_function = function;
  replace_expr(post_replace_map, post_function);

  rank_relation = binary_relation_exprt(post_function, "<", function);

  return true;
}
Example #9
0
exprt polynomial_acceleratort::precondition(patht &path) {
  exprt ret = false_exprt();

  for (patht::reverse_iterator r_it = path.rbegin();
       r_it != path.rend();
       ++r_it) {
    goto_programt::const_targett t = r_it->loc;

    if (t->is_assign()) {
      // XXX Need to check for aliasing...
      const code_assignt &assignment = to_code_assign(t->code);
      const exprt &lhs = assignment.lhs();
      const exprt &rhs = assignment.rhs();

      if (lhs.id() == ID_symbol) {
        replace_expr(lhs, rhs, ret);
      } else if (lhs.id() == ID_index ||
                 lhs.id() == ID_dereference) {
        continue;
      } else {
        throw "Couldn't take WP of " + expr2c(lhs, ns) + " = " + expr2c(rhs, ns);
      }
    } else if (t->is_assume() || t->is_assert()) {
      ret = implies_exprt(t->guard, ret);
    } else {
      // Ignore.
    }

    if (!r_it->guard.is_true() && !r_it->guard.is_nil()) {
      // The guard isn't constant true, so we need to accumulate that too.
      ret = implies_exprt(r_it->guard, ret);
    }
  }

  simplify(ret, ns);

  return ret;
}
Example #10
0
bool polynomial_acceleratort::accelerate(patht &loop,
    path_acceleratort &accelerator) {
  goto_programt::instructionst body;
  accelerator.clear();

  for (patht::iterator it = loop.begin();
       it != loop.end();
       ++it) {
    body.push_back(*(it->loc));
  }

  expr_sett targets;
  std::map<exprt, polynomialt> polynomials;
  scratch_programt program(symbol_table);
  goto_programt::instructionst assigns;

  utils.find_modified(body, targets);

#ifdef DEBUG
  std::cout << "Polynomial accelerating program:" << std::endl;

  for (goto_programt::instructionst::iterator it = body.begin();
       it != body.end();
       ++it) {
    program.output_instruction(ns, "scratch", std::cout, it);
  }

  std::cout << "Modified:" << std::endl;

  for (expr_sett::iterator it = targets.begin();
       it != targets.end();
       ++it) {
    std::cout << expr2c(*it, ns) << std::endl;
  }
#endif

  for (goto_programt::instructionst::iterator it = body.begin();
       it != body.end();
       ++it) {
    if (it->is_assign() || it->is_decl()) {
      assigns.push_back(*it);
    }
  }

  if (loop_counter.is_nil()) {
    symbolt loop_sym = utils.fresh_symbol("polynomial::loop_counter",
        unsignedbv_typet(POLY_WIDTH));
    loop_counter = loop_sym.symbol_expr();
  }

  for (expr_sett::iterator it = targets.begin();
       it != targets.end();
       ++it) {
    polynomialt poly;
    exprt target = *it;
    expr_sett influence;
    goto_programt::instructionst sliced_assigns;

    if (target.type() == bool_typet()) {
      // Hack: don't accelerate booleans.
      continue;
    }

    cone_of_influence(assigns, target, sliced_assigns, influence);

    if (influence.find(target) == influence.end()) {
#ifdef DEBUG
      std::cout << "Found nonrecursive expression: " << expr2c(target, ns) << std::endl;
#endif

      nonrecursive.insert(target);
      continue;
    }

    if (target.id() == ID_index ||
        target.id() == ID_dereference) {
      // We can't accelerate a recursive indirect access...
      accelerator.dirty_vars.insert(target);
      continue;
    }

    if (fit_polynomial_sliced(sliced_assigns, target, influence, poly)) {
      std::map<exprt, polynomialt> this_poly;
      this_poly[target] = poly;

      if (check_inductive(this_poly, assigns)) {
        polynomials.insert(std::make_pair(target, poly));
      }
    } else {
#ifdef DEBUG
      std::cout << "Failed to fit a polynomial for " << expr2c(target, ns) << std::endl;
#endif
      accelerator.dirty_vars.insert(*it);
    }
  }

  if (polynomials.empty()) {
    //return false;
  }

  /*
  if (!utils.check_inductive(polynomials, assigns)) {
    // They're not inductive :-(
    return false;
  }
  */

  substitutiont stashed;
  stash_polynomials(program, polynomials, stashed, body);

  exprt guard;
  exprt guard_last;

  bool path_is_monotone;
  
  try {
    path_is_monotone = utils.do_assumptions(polynomials, loop, guard);
  } catch (std::string s) {
    // Couldn't do WP.
    std::cout << "Assumptions error: " << s << std::endl;
    return false;
  }

  guard_last = guard;

  for (std::map<exprt, polynomialt>::iterator it = polynomials.begin();
       it != polynomials.end();
       ++it) {
    replace_expr(it->first, it->second.to_expr(), guard_last);
  }

  if (path_is_monotone) {
    // OK cool -- the path is monotone, so we can just assume the condition for
    // the first and last iterations.
    replace_expr(loop_counter,
                 minus_exprt(loop_counter, from_integer(1, loop_counter.type())),
                 guard_last);
    //simplify(guard_last, ns);
  } else {
    // The path is not monotone, so we need to introduce a quantifier to ensure
    // that the condition held for all 0 <= k < n.
    symbolt k_sym = utils.fresh_symbol("polynomial::k", unsignedbv_typet(POLY_WIDTH));
    exprt k = k_sym.symbol_expr();

    exprt k_bound = and_exprt(binary_relation_exprt(from_integer(0, k.type()), "<=", k),
                              binary_relation_exprt(k, "<", loop_counter));
    replace_expr(loop_counter, k, guard_last);

    implies_exprt implies(k_bound, guard_last);
    //simplify(implies, ns);

    exprt forall(ID_forall);
    forall.type() = bool_typet();
    forall.copy_to_operands(k);
    forall.copy_to_operands(implies);

    guard_last = forall;
  }

  // All our conditions are met -- we can finally build the accelerator!
  // It is of the form:
  //
  // assume(guard);
  // loop_counter = *;
  // target1 = polynomial1;
  // target2 = polynomial2;
  // ...
  // assume(guard);
  // assume(no overflows in previous code);

  program.add_instruction(ASSUME)->guard = guard;

  program.assign(loop_counter, side_effect_expr_nondett(loop_counter.type()));

  for (std::map<exprt, polynomialt>::iterator it = polynomials.begin();
       it != polynomials.end();
       ++it) {
    program.assign(it->first, it->second.to_expr());
  }

  // Add in any array assignments we can do now.
  if (!utils.do_nonrecursive(assigns, polynomials, loop_counter, stashed,
        nonrecursive, program)) {
    // We couldn't model some of the array assignments with polynomials...
    // Unfortunately that means we just have to bail out.
#ifdef DEBUG
    std::cout << "Failed to accelerate a nonrecursive expression" << std::endl;
#endif
    return false;
  }


  program.add_instruction(ASSUME)->guard = guard_last;
  program.fix_types();

  if (path_is_monotone) {
    utils.ensure_no_overflows(program);
  }

  accelerator.pure_accelerator.instructions.swap(program.instructions);

  return true;
}
Example #11
0
std::pair<exprt,exprt> ranking_synthesis_qbf_bitwiset::affine_template(
  const irep_idt &termOp,
  const irep_idt &coefOp)
{
  exprt function;
  replace_mapt pre_replace_map;

  for(bodyt::variable_mapt::const_iterator it=body.variable_map.begin();
      it!=body.variable_map.end();
      it++)
  {
    if(used_variables.find(it->first)==used_variables.end())
      continue;
    
    exprt postsym=symbol_exprt(it->first, ns.lookup(it->first).type);
    exprt presym=symbol_exprt(it->second, ns.lookup(it->second).type);
        
    pre_replace_map[postsym] = presym; // save the corresponding pre-var
    exprt var=postsym;
    adjust_type(var.type());

    exprt co = coefficient(var);
    irep_idt bitop = (coefOp==ID_and)      ? ID_bitand :
                     (coefOp==ID_or)       ? ID_bitor  :
                     (coefOp==ID_notequal) ? ID_bitxor : 
                                             "";

    exprt varblock(bitop, var.type());
    varblock.copy_to_operands(var, co);

    exprt bchain = bitwise_chain(termOp, varblock);

    if(it==body.variable_map.begin()) // first one
      function=bchain;
    else
    {
      if(termOp==ID_notequal)
      {
        exprt t(ID_equal, bool_typet());
        t.move_to_operands(function);
        t.move_to_operands(bchain);
        function=not_exprt(t);
      }
      else
      {
        exprt t(termOp, bool_typet());
        t.move_to_operands(function);
        t.move_to_operands(bchain);
        function=t;
      }
    }
  }

  // ... and a constant coefficient
  symbol_exprt const_sym(CONSTANT_COEFFICIENT_ID, bool_typet());
  const_coefficient=coefficient(const_sym);

  
  if(termOp==ID_notequal)
  {
    exprt t(ID_equal, bool_typet());
    t.move_to_operands(function);
    t.copy_to_operands(const_coefficient);
    function = not_exprt(t);
  }
  else
  {
    exprt t(termOp, bool_typet());
    t.move_to_operands(function);
    t.copy_to_operands(const_coefficient);
    function = t;
  }

  exprt pre_function=function;
  replace_expr(pre_replace_map, pre_function);

  return std::pair<exprt,exprt>(pre_function, function);
}
bool disjunctive_polynomial_accelerationt::accelerate(
    path_acceleratort &accelerator) {
  std::map<exprt, polynomialt> polynomials;
  scratch_programt program(symbol_table);

  accelerator.clear();

#ifdef DEBUG
  std::cout << "Polynomial accelerating program:" << std::endl;

  for (goto_programt::instructionst::iterator it = goto_program.instructions.begin();
       it != goto_program.instructions.end();
       ++it) {
    if (loop.find(it) != loop.end()) {
      goto_program.output_instruction(ns, "scratch", std::cout, it);
    }
  }

  std::cout << "Modified:" << std::endl;

  for (expr_sett::iterator it = modified.begin();
       it != modified.end();
       ++it) {
    std::cout << expr2c(*it, ns) << std::endl;
  }
#endif

  if (loop_counter.is_nil()) {
    symbolt loop_sym = utils.fresh_symbol("polynomial::loop_counter",
        unsigned_poly_type());
    loop_counter = loop_sym.symbol_expr();
  }

  patht &path = accelerator.path;
  path.clear();

  if (!find_path(path)) {
    // No more paths!
    return false;
  }

#if 0
  for (expr_sett::iterator it = modified.begin();
       it != modified.end();
       ++it) {
    polynomialt poly;
    exprt target = *it;

    if (it->type().id() == ID_bool) {
      // Hack: don't try to accelerate booleans.
      continue;
    }

    if (target.id() == ID_index ||
        target.id() == ID_dereference) {
      // We'll handle this later.
      continue;
    }

    if (fit_polynomial(target, poly, path)) {
      std::map<exprt, polynomialt> this_poly;
      this_poly[target] = poly;

      if (utils.check_inductive(this_poly, path)) {
#ifdef DEBUG
        std::cout << "Fitted a polynomial for " << expr2c(target, ns) <<
          std::endl;
#endif
        polynomials[target] = poly;
        accelerator.changed_vars.insert(target);
        break;
      }
    }
  }

  if (polynomials.empty()) {
    return false;
  }
#endif

  // Fit polynomials for the other variables.
  expr_sett dirty;
  utils.find_modified(accelerator.path, dirty);
  polynomial_acceleratort path_acceleration(symbol_table, goto_functions,
      loop_counter);
  goto_programt::instructionst assigns;

  for (patht::iterator it = accelerator.path.begin();
       it != accelerator.path.end();
       ++it) {
    if (it->loc->is_assign() || it->loc->is_decl()) {
      assigns.push_back(*(it->loc));
    }
  }

  for (expr_sett::iterator it = dirty.begin();
       it != dirty.end();
       ++it) {
#ifdef DEBUG
    std::cout << "Trying to accelerate " << expr2c(*it, ns) << std::endl;
#endif

    if (it->type().id() == ID_bool) {
      // Hack: don't try to accelerate booleans.
      accelerator.dirty_vars.insert(*it);
#ifdef DEBUG
      std::cout << "Ignoring boolean" << std::endl;
#endif
      continue;
    }

    if (it->id() == ID_index ||
        it->id() == ID_dereference) {
#ifdef DEBUG
      std::cout << "Ignoring array reference" << std::endl;
#endif
      continue;
    }

    if (accelerator.changed_vars.find(*it) != accelerator.changed_vars.end()) {
      // We've accelerated variable this already.
#ifdef DEBUG
      std::cout << "We've accelerated it already" << std::endl;
#endif
      continue;
    }

    // Hack: ignore variables that depend on array values..
    exprt array_rhs;

    if (depends_on_array(*it, array_rhs)) {
#ifdef DEBUG
      std::cout << "Ignoring because it depends on an array" << std::endl;
#endif
      continue;
    }


    polynomialt poly;
    exprt target(*it);

    if (path_acceleration.fit_polynomial(assigns, target, poly)) {
      std::map<exprt, polynomialt> this_poly;
      this_poly[target] = poly;

      if (utils.check_inductive(this_poly, accelerator.path)) {
        polynomials[target] = poly;
        accelerator.changed_vars.insert(target);
        continue;
      }
    }

#ifdef DEBUG
    std::cout << "Failed to accelerate " << expr2c(*it, ns) << std::endl;
#endif

    // We weren't able to accelerate this target...
    accelerator.dirty_vars.insert(target);
  }


  /*
  if (!utils.check_inductive(polynomials, assigns)) {
    // They're not inductive :-(
    return false;
  }
  */

  substitutiont stashed;
  utils.stash_polynomials(program, polynomials, stashed, path);

  exprt guard;
  bool path_is_monotone;

  try {
    path_is_monotone = utils.do_assumptions(polynomials, path, guard);
  } catch (std::string s) {
    // Couldn't do WP.
    std::cout << "Assumptions error: " << s << std::endl;
    return false;
  }

  exprt pre_guard(guard);

  for (std::map<exprt, polynomialt>::iterator it = polynomials.begin();
       it != polynomials.end();
       ++it) {
    replace_expr(it->first, it->second.to_expr(), guard);
  }

  if (path_is_monotone) {
    // OK cool -- the path is monotone, so we can just assume the condition for
    // the last iteration.
    replace_expr(loop_counter,
                 minus_exprt(loop_counter, from_integer(1, loop_counter.type())),
                 guard);
  } else {
    // The path is not monotone, so we need to introduce a quantifier to ensure
    // that the condition held for all 0 <= k < n.
    symbolt k_sym = utils.fresh_symbol("polynomial::k", unsigned_poly_type());
    exprt k = k_sym.symbol_expr();

    exprt k_bound = and_exprt(binary_relation_exprt(from_integer(0, k.type()), "<=", k),
                              binary_relation_exprt(k, "<", loop_counter));
    replace_expr(loop_counter, k, guard);

    simplify(guard, ns);

    implies_exprt implies(k_bound, guard);

    exprt forall(ID_forall);
    forall.type() = bool_typet();
    forall.copy_to_operands(k);
    forall.copy_to_operands(implies);

    guard = forall;
  }

  // All our conditions are met -- we can finally build the accelerator!
  // It is of the form:
  //
  // loop_counter = *;
  // target1 = polynomial1;
  // target2 = polynomial2;
  // ...
  // assume(guard);
  // assume(no overflows in previous code);

  program.add_instruction(ASSUME)->guard = pre_guard;
  program.assign(loop_counter, side_effect_expr_nondett(loop_counter.type()));

  for (std::map<exprt, polynomialt>::iterator it = polynomials.begin();
       it != polynomials.end();
       ++it) {
    program.assign(it->first, it->second.to_expr());
    accelerator.changed_vars.insert(it->first);
  }

  // Add in any array assignments we can do now.
  if (!utils.do_arrays(assigns, polynomials, loop_counter, stashed, program)) {
    // We couldn't model some of the array assignments with polynomials...
    // Unfortunately that means we just have to bail out.
    return false;
  }

  program.add_instruction(ASSUME)->guard = guard;
  program.fix_types();

  if (path_is_monotone) {
    utils.ensure_no_overflows(program);
  }

  accelerator.pure_accelerator.instructions.swap(program.instructions);

  return true;
}
Example #13
0
bool ranking_synthesis_seneschalt::read_output(exprt &rf)
{
  // Check if there is a result at all...
  std::ifstream err("seneschal.err");
  bool result_found=false;
  while(err)
  {
    std::string line;
    std::getline(err, line);

    if(line=="Solving ... no solution" ||
       line=="Solving ... found a solution")
    {
      result_found = true;
      break;
    }
  }
  err.close();

  if(!result_found) return false;

  // There is a result!
  std::ifstream in("seneschal.out");

  std::string rank_string;
  std::string bound_string;

  while(in)
  {
    std::string line;

    std::getline(in, line);

    if(line.substr(0,7)=="Ranking")
    {
      std::vector<std::string> tokens;
      tokenize(line, tokens, " =[],\tr");

      bool work=false;
      for(std::vector<std::string>::const_iterator it=tokens.begin();
          it!=tokens.end();
          it++)
      {
        // std::cout << "TOKEN: " << *it << std::endl;

        if(*it=="Ranking")
        {
          result_found=true;
          work=true;
        }
        else if(*it=="function:") /* SKIP */ ;
        else if(work)
        {
          rank_string += " " + *it;
        }
      }
    }
    else if(line.substr(0,25)=="Lower bound (post-state):")
    {
      std::vector<std::string> tokens;
      tokenize(line, tokens, " =[],\t");

      std::vector<std::string>::const_iterator it=tokens.begin();
      it++; it++; it++;
      if(it!=tokens.end())
      {
        //std::cout << "TOKEN: " << *it << std::endl;

        bound_string = *it;
      }
    };
  }

  if(rank_string!="")
  {
    bound = string2integer(bound_string);

    if(bound!=0)
      rank_string = "(" + rank_string + ") - (" + bound_string + ")";

    exprt rfl;

    if(parse_rank_function(rank_string, trans_context, ns, *message_handler, rfl))
      throw ("RF EXTRACTION ERROR");

    replace_expr(variable_map, rfl);
    std::cout << "FOUND FUNCTION: " << from_expr(ns, "", rfl) << std::endl;

    rf.swap(rfl);

    std::cout << "BOUND: " << bound << std::endl;
  }
    
  return true;
}
Example #14
0
bool simplify_exprt::simplify_index(exprt &expr)
{
  bool result=true;

  // extra arithmetic optimizations
  const exprt &index=to_index_expr(expr).index();
  const exprt &array=to_index_expr(expr).array();

  if(index.id()==ID_div &&
     index.operands().size()==2)
  {
    if(index.op0().id()==ID_mult &&
       index.op0().operands().size()==2 &&
       index.op0().op1()==index.op1())
    {
      exprt tmp=index.op0().op0();
      expr.op1()=tmp;
      result=false;
    }
    else if(index.op0().id()==ID_mult &&
            index.op0().operands().size()==2 &&
            index.op0().op0()==index.op1())
    {
      exprt tmp=index.op0().op1();
      expr.op1()=tmp;
      result=false;
    }
  }

  if(array.id()==ID_lambda)
  {
    // simplify (lambda i: e)(x) to e[i/x]

    const exprt &lambda_expr=array;

    if(lambda_expr.operands().size()!=2)
      return true;

    if(expr.op1().type()==lambda_expr.op0().type())
    {
      exprt tmp=lambda_expr.op1();
      replace_expr(lambda_expr.op0(), expr.op1(), tmp);
      expr.swap(tmp);
      return false;
    }
  }
  else if(array.id()==ID_with)
  {
    // we have (a WITH [i:=e])[j]

    const exprt &with_expr=array;

    if(with_expr.operands().size()!=3)
      return true;

    if(with_expr.op1()==expr.op1())
    {
      // simplify (e with [i:=v])[i] to v
      exprt tmp=with_expr.op2();
      expr.swap(tmp);
      return false;
    }
    else
    {
      // Turn (a with i:=x)[j] into (i==j)?x:a[j].
      // watch out that the type of i and j might be different.
      equal_exprt equality_expr(expr.op1(), with_expr.op1());

      if(equality_expr.lhs().type()!=equality_expr.rhs().type())
        equality_expr.rhs().make_typecast(equality_expr.lhs().type());

      simplify_inequality(equality_expr);

      index_exprt new_index_expr;
      new_index_expr.type()=expr.type();
      new_index_expr.array()=with_expr.op0();
      new_index_expr.index()=expr.op1();

      simplify_index(new_index_expr); // recursive call

      if(equality_expr.is_true())
      {
        expr=with_expr.op2();
        return false;
      }
      else if(equality_expr.is_false())
      {
        expr.swap(new_index_expr);
        return false;
      }

      if_exprt if_expr(equality_expr, with_expr.op2(), new_index_expr);
      simplify_if(if_expr);

      expr.swap(if_expr);

      return false;
    }
  }
  else if(array.id()==ID_constant ||
          array.id()==ID_array)
  {
    mp_integer i;

    if(to_integer(expr.op1(), i))
    {
    }
    else if(i<0 || i>=array.operands().size())
    {
      // out of bounds
    }
    else
    {
      // ok
      exprt tmp=array.operands()[integer2size_t(i)];
      expr.swap(tmp);
      return false;
    }
  }
  else if(array.id()==ID_string_constant)
  {
    mp_integer i;

    const irep_idt &value=array.get(ID_value);

    if(to_integer(expr.op1(), i))
    {
    }
    else if(i<0 || i>value.size())
    {
      // out of bounds
    }
    else
    {
      // terminating zero?
      char v=(i==value.size())?0:value[integer2size_t(i)];
      exprt tmp=from_integer(v, expr.type());
      expr.swap(tmp);
      return false;
    }
  }
  else if(array.id()==ID_array_of)
  {
    if(array.operands().size()==1)
    {
      exprt tmp=array.op0();
      expr.swap(tmp);
      return false;
    }
  }
  else if(array.id()=="array-list")
  {
    // These are index/value pairs, alternating.
    for(size_t i=0; i<array.operands().size()/2; i++)
    {
      exprt tmp_index=array.operands()[i*2];
      tmp_index.make_typecast(index.type());
      simplify(tmp_index);
      if(tmp_index==index)
      {
        exprt tmp=array.operands()[i*2+1];
        expr.swap(tmp);
        return false;
      }
    }
  }
  else if(array.id()==ID_byte_extract_little_endian ||
          array.id()==ID_byte_extract_big_endian)
  {
    const typet &array_type=ns.follow(array.type());

    if(array_type.id()==ID_array)
    {
      // This rewrites byte_extract(s, o, array_type)[i]
      // to byte_extract(s, o+offset, sub_type)

      mp_integer sub_size=pointer_offset_size(array_type.subtype(), ns);
      if(sub_size==-1)
        return true;

      // add offset to index
      mult_exprt offset(from_integer(sub_size, array.op1().type()), index);
      plus_exprt final_offset(array.op1(), offset);
      simplify_node(final_offset);

      exprt result(array.id(), expr.type());
      result.copy_to_operands(array.op0(), final_offset);
      expr.swap(result);

      simplify_rec(expr);

      return false;
    }
  }
  else if(array.id()==ID_if)
  {
    const if_exprt &if_expr=to_if_expr(array);
    exprt cond=if_expr.cond();

    index_exprt idx_false=to_index_expr(expr);
    idx_false.array()=if_expr.false_case();

    to_index_expr(expr).array()=if_expr.true_case();

    expr=if_exprt(cond, expr, idx_false, expr.type());
    simplify_rec(expr);

    return false;
  }

  return result;
}
Example #15
0
exprt ranking_synthesis_satt::instantiate(void)
{
  find_largest_constant(body.body_relation);

  binary_relation_exprt toplevel_and("and");

  toplevel_and.lhs() = body.body_relation; // that's R(x,x')

  exprt function;
  replace_mapt pre_replace_map;
      
  bool first=true;
  
  for(bodyt::variable_mapt::const_iterator it=body.variable_map.begin();
      it!=body.variable_map.end();
      it++)
  {
    if(used_variables.find(it->first)==used_variables.end())
      continue;
    
    exprt var=symbol_exprt(it->first, ns.lookup(it->first).type);
    pre_replace_map[var] = // save the corresponding pre-var
            symbol_exprt(it->second, ns.lookup(it->second).type);
    
    adjust_type(var.type());
    const typet type=var.type();

    exprt coef=coefficient(var);    

    unsigned width=safe_width(var, ns);
    assert(width!=0);

    exprt term("*", typet(""));
    term.copy_to_operands(coef, var);

    if(first)
    {
      function=term;
      first=false;
    }
    else
    {
//      cast_up(function, term);
      exprt t("+", typet(""));
      t.move_to_operands(function, term);
      function = t;
    }
  }
  
  if(first) // non of the interesting variables was used - bail out!
  {
    debug("Completely non-deterministic template; "
           "this loop does not terminate.");
    return false_exprt();
  }

//  if(!largest_constant.is_zero())
//  {
//    // add the largest constant
//    symbol_exprt lc_sym("termination::LC", largest_constant.type());
//    exprt lc=largest_constant;
//    exprt lcc=coefficient(lc_sym);
////    cast_up(lc, lcc);
//    exprt m("*", typet(""));
//    m.move_to_operands(lcc, lc);
//
////    cast_up(function, m);
//    exprt t("+", typet(""));
//    t.move_to_operands(function, m);
//    function = t;
//  }

  // add a constant term
  symbol_exprt const_sym("termination::constant", signedbv_typet(2));
  exprt cc=coefficient(const_sym);

//  cast_up(function, cc);
  exprt t2("+", typet(""));
  t2.move_to_operands(function, cc);
  function=t2;
      
  contextt context;
  ansi_c_parse_treet pt;
  rankfunction_typecheckt typecheck(pt, context, ns, *message_handler);

  try
  {
    typecheck.typecheck_expr(function);
  }
  catch (...)
  {
    throw "TC ERROR";
  }
  

  exprt pre_function = function;
  replace_expr(pre_replace_map, pre_function);

  // save the relation for later
  rank_relation = binary_relation_exprt(function, "<", pre_function);
  
  // base_type(rank_relation, ns);

  toplevel_and.rhs()=not_exprt(rank_relation);

  return toplevel_and;
}
Example #16
0
void bv_cbmct::convert_waitfor(const exprt &expr, bvt &bv)
{
  if(expr.operands().size()!=4)
    throw "waitfor expected to have four operands";

  exprt new_cycle;
  const exprt &old_cycle=expr.op0();
  const exprt &cycle_var=expr.op1();
  const exprt &bound=expr.op2();
  const exprt &predicate=expr.op3();

  make_free_bv_expr(expr.type(), new_cycle);

  mp_integer bound_value;
  if(to_integer(bound, bound_value))
    throw "waitfor bound must be a constant";

  {
    // constraint: new_cycle>=old_cycle

    exprt rel_expr(ID_ge, bool_typet());
    rel_expr.copy_to_operands(new_cycle, old_cycle);
    set_to_true(rel_expr);
  }

  {
    // constraint: new_cycle<=bound+1

    exprt one=from_integer(1, bound.type());

    exprt bound_plus1(ID_plus, bound.type());
    bound_plus1.reserve_operands(2);
    bound_plus1.copy_to_operands(bound);
    bound_plus1.move_to_operands(one);

    exprt rel_expr(ID_le, bool_typet());
    rel_expr.copy_to_operands(new_cycle, bound_plus1);
    set_to_true(rel_expr);
  }

  for(mp_integer i=0; i<=bound_value; i=i+1)
  {
    // replace cycle_var by old_cycle+i;

    exprt old_cycle_plus_i(ID_plus, old_cycle.type());
    old_cycle_plus_i.operands().resize(2);
    old_cycle_plus_i.op0()=old_cycle;
    old_cycle_plus_i.op1()=from_integer(i, old_cycle.type());

    exprt tmp_predicate=predicate;
    replace_expr(cycle_var, old_cycle_plus_i, tmp_predicate);

    // CONSTRAINT:
    // if((cycle)<=bound) {
    //   if((cycle)<new_cycle)
    //     assume(!property);
    //   else if((cycle)==new_cycle)
    //     assume(property);

    {
      exprt cycle_le_bound(ID_le, bool_typet());
      cycle_le_bound.operands().resize(2);
      cycle_le_bound.op0()=old_cycle_plus_i;
      cycle_le_bound.op1()=bound;

      exprt cycle_lt_new_cycle(ID_lt, bool_typet());
      cycle_lt_new_cycle.operands().resize(2);
      cycle_lt_new_cycle.op0()=old_cycle_plus_i;
      cycle_lt_new_cycle.op1()=new_cycle;

      exprt and_expr(ID_and, bool_typet());
      and_expr.operands().resize(2);
      and_expr.op0().swap(cycle_le_bound);
      and_expr.op1().swap(cycle_lt_new_cycle);

      exprt top_impl(ID_implies, bool_typet());
      top_impl.reserve_operands(2);
      top_impl.move_to_operands(and_expr);
      top_impl.copy_to_operands(tmp_predicate);
      top_impl.op1().make_not();

      set_to_true(top_impl);
    }

    {
      exprt cycle_le_bound(ID_le, bool_typet());
      cycle_le_bound.operands().resize(2);
      cycle_le_bound.op0()=old_cycle_plus_i;
      cycle_le_bound.op1()=bound;

      exprt cycle_eq_new_cycle(ID_equal, bool_typet());
      cycle_eq_new_cycle.operands().resize(2);
      cycle_eq_new_cycle.op0()=old_cycle_plus_i;
      cycle_eq_new_cycle.op1()=new_cycle;

      exprt and_expr(ID_and, bool_typet());
      and_expr.operands().resize(2);
      and_expr.op0().swap(cycle_le_bound);
      and_expr.op1().swap(cycle_eq_new_cycle);

      exprt top_impl(ID_implies, bool_typet());
      top_impl.reserve_operands(2);
      top_impl.move_to_operands(and_expr);
      top_impl.copy_to_operands(tmp_predicate);

      set_to_true(top_impl);
    }
  }

  // result: new_cycle
  return convert_bitvector(new_cycle, bv);
}