예제 #1
0
파일: sat.cpp 프로젝트: Totofufu/parpar
// input form of SAT expression: 2,1 -2,3,-4
int main(int argc, char** argv) {
  int* num_vars_ptr = new int;
  std::vector <std::vector<int> > expr = parse(argc, argv, num_vars_ptr); // assume this is initialized
  int num_vars = *num_vars_ptr;

  // contains current clause true/false values
  std::vector<int> sat_vals;
  for (int i = 0; i < num_vars; i++) {
    sat_vals.push_back(-1);
  }

  for (int rep_num = 0; rep_num < pow(2, num_vars); rep_num++) {
    int rep_temp = rep_num;
    // fill in the SAT expr with a brute force attempt
    for (int i = 0; i < num_vars; i++) {
      int bit = rep_temp & 0x1;
      sat_vals.at(i) = bit;
      rep_temp >>= 1;
    }

    // check to see if the current SAT expression is satisfiable
    if (is_satisfiable(expr, sat_vals)) {
      printf("Solution found!\n");
      print_solution(sat_vals);
      delete num_vars_ptr;
      return 0;
    }
  }

  printf("No solution found.\n");
  delete num_vars_ptr;
  return 1;
}
예제 #2
0
int main(int argc, char** argv)
{
  timeout = 0;
  timeout_time = time(0) + 180;
  int err3 = 0;
  // Parse the formula and verify it is correct
  formula3 f3 = verify3(argc, argv, &err3);
  if(err3)    
    printf("ERROR\n");    
  else
    {
      // Fill the formula with indexes
      fill_formula3(&f3);
      strip_units_and_pures3(&f3);

      int result = is_satisfiable3(&f3, 0);
      if(!timeout)
	{
	  if(result)
	    {
	      printf("SATISFIABLE\n");
	      // Free the formula's memory
	      annhialate_formula3(f3);  
	    }
	  else
	    {
	      printf("UNSATISFIABLE\n");
	      // Free the formula's memory
	      annhialate_formula3(f3);  
	    }
	}
      else
	{
	  int err = 0;
	  // Parse the formula and verify it is correct
	  formula f = verify(argc, argv, &err);
	  if(err)    
	    printf("ERROR");    
	  else
	    {
	      // Fill the formula with indexes
	      fill_formula(&f);

	      if(is_satisfiable(&f, 0))
		printf("SATISFIABLE\n");
	      else
		printf("UNSATISFIABLE\n");
	    }
  
	  // Free the formula's memory
	  annhialate_formula(f);
	}
    } 

}
예제 #3
0
bool simulator_symext::check_full_trace(
    const abstract_counterexamplet &abstract_counterexample,
    prefixt &prefix,
    goto_symex_statet &state,
    concrete_counterexamplet &concrete_counterexample,
    fail_infot &fail_info)
{
  assert(!prefix.equation.SSA_steps.empty());  
  assert(prefix.equation.SSA_steps.back().is_assert());

  status("Prefix of size "+i2string(prefix.equation.SSA_steps.size()));

  symex_target_equationt::SSA_stepst::const_iterator c_it=
    --prefix.equation.SSA_steps.end();

  simulator_sat_dect satcheck(concrete_model.ns);
  prefix.equation.convert(satcheck);

  if(is_satisfiable(satcheck))
  {
    // grab counterexample!
    build_goto_trace(
        prefix.equation,
        satcheck,
        concrete_model.ns,
        concrete_counterexample.goto_trace);

    return false;
  }

  get_fail_info(
      abstract_counterexample,
      satcheck,
      prefix,
      c_it,
      fail_info);

  // cannot be simulated, its spurious
  status("Spurious counterexample.");

  return true;
}
예제 #4
0
파일: solver.cpp 프로젝트: olivo/BP
bool simulator_baset::is_satisfiable(formulat formula)
{
  satcheckt satcheck;

  #ifdef DEBUG  
  std::cout << "simulator_baset::is_satisfiable1\n";
  std::cout << "F: " << formula << std::endl;
  #endif

  formula_container.reset_prop();  

  #ifdef DEBUG
  std::cout << "simulator_baset::is_satisfiable2\n";
  #endif

  literalt l=formula.convert(satcheck);
  satcheck.l_set_to(l, true);
  
  return is_satisfiable(satcheck);
}
예제 #5
0
void simulator_ctt::execute_assert(
  statet &state,
  const program_formulat::formula_goto_programt::instructiont &instruction)
{
  std::cout << "CHECKING ASSERTION\n";

  formulat condition=
    instantiate(state, 0, instruction.guard);
    
  formulat property=
    formula_container.gen_and(
      state.data().guard,
      formula_container.gen_not(condition));

  // see if it is reachable
  if(!property.is_false() &&
     is_satisfiable(property))
  {
    tracet trace;

    compute_trace(state, trace, true);
    dump_trace(trace, instruction);
    std::cout << "Assertion violated" << std::endl;
    std::cout << std::endl;

    error_state_found=true;
  }
  
  #if 0
  else
  {
    // otherwise, treat this like an assumption
    state.data_w().guard=
      formula_container.gen_and(state.data().guard, condition);
  }
  #endif
}
예제 #6
0
bool simulator_loop_detectiont::check_phase_I_equation(
    symex_target_equationt &equation,
    goto_symex_statet &state,
    const abstract_counterexamplet &abstract_counterexample,
    concrete_counterexamplet &phase_I_counterexample,
    prefixt::step_mapt &step_map,
    fail_infot &fail_info
    )
{
  minimization_listt symbols;

  // run SAT
  symex_target_equationt::SSA_stepst::iterator c_it;

  for(c_it=equation.SSA_steps.begin();
      c_it!=equation.SSA_steps.end();
      c_it++)
  {
    if(c_it->is_assignment())
    {
      const exprt &rhs=c_it->ssa_rhs;
      recurrence_solver::referenced_parameters(state, rhs, symbols);
      continue;
    }

    if(c_it->is_location() ||
        (c_it->is_assume() && c_it->cond_expr.is_true()))
      continue;

    bv_minimizing_dect satcheck(concrete_model.ns);

    symex_target_equationt::SSA_stepst SSA_steps;
    SSA_steps.splice(SSA_steps.end(),
        equation.SSA_steps, equation.SSA_steps.begin(), ++c_it);
    equation.SSA_steps.swap(SSA_steps);
    equation.convert(satcheck);
    equation.SSA_steps.splice(equation.SSA_steps.end(),
        SSA_steps, SSA_steps.begin(), SSA_steps.end());
    --c_it;

    // solve it
    if(!is_satisfiable(satcheck))
      break; // spurious!

    if(c_it->is_assert()) // we reached the assertion
    {
      for (minimization_listt::const_iterator m_it = symbols.begin();
          m_it!=symbols.end(); m_it++)
        std::cout << from_expr (concrete_model.ns, "", *m_it) << ", ";
      std::cout << std::endl;

      satcheck.minimize(symbols);

      build_goto_trace(
          equation,
          satcheck,
          concrete_model.ns,
          phase_I_counterexample.goto_trace);

      return false;
    }
  }

  assert(c_it !=equation.SSA_steps.end());

  // cannot be simulated, its spurious
  status("Phase I Counterexample is spurious");

  // fill fail_info
  fail_info.all_steps = abstract_counterexample.steps;

  assert(c_it->source.pc->is_assert() ||
      c_it->source.pc->is_assume() ||
      c_it->source.pc->is_goto());

  // get the corresponding abstract step
  prefixt::step_mapt::const_iterator s_it=step_map.find(c_it);
  assert (s_it!=step_map.end());
  abstract_counterexamplet::stepst::const_iterator a_it = s_it->second;

  // and fill the steps
  fail_info.steps.clear();

  for(abstract_counterexamplet::stepst::const_iterator
      it=abstract_counterexample.steps.begin();
      it!=abstract_counterexample.steps.end();
      it++)
  {
    fail_info.steps.push_back(*it);
    if(it==a_it) 
      break;
  }

  fail_info.guard=c_it->source.pc->guard;

  // we might need to negate it
  if (c_it->source.pc->is_goto())
    if (c_it->guard_expr.is_false())
      fail_info.guard.make_not();

  return true;
}
예제 #7
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;
}
예제 #8
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;
}
예제 #9
0
bool simulator_symext::check_prefix_equation(
    const abstract_counterexamplet &abstract_counterexample,
    prefixt &prefix,
    goto_symex_statet &state,
    concrete_counterexamplet &concrete_counterexample,
    fail_infot &fail_info)
{
  unsigned int left = 0;     /* leftmost index of search interval  */
  unsigned int right = 0;    /* rightmost index of search interval */
  unsigned int step = 1;     /* the current step size              */
  unsigned int index = 0;    /* the current index into the array   */

  // first of all, that should end with an assertion
  // if not, it's spurious for sure

  assert(!prefix.equation.SSA_steps.empty());  
  assert(prefix.equation.SSA_steps.back().is_assert());

  status("Unprocessed prefix of size "+ i2string (prefix.equation.SSA_steps.size ()));

  symex_target_equationt::SSA_stepst::iterator c_it;

  /* construct an array of iterators (for binary search) */
  std::vector<symex_target_equationt::SSA_stepst::iterator> state_array;

  for(c_it=prefix.equation.SSA_steps.begin();
      c_it!=prefix.equation.SSA_steps.end(); 
      c_it++)
  {
    /* assignments and locations don't make a path infeasible */
    if(!(c_it->is_assignment() ||
          c_it->is_location()))
    {
      if(!(c_it->is_assume() && c_it->cond_expr.is_true()))
      {
        state_array.push_back(c_it);

        // this must be an assumption, an assertion or a goto
        assert(c_it->source.pc->is_assert() ||
            c_it->source.pc->is_assume() ||
            c_it->source.pc->is_goto());
      }
    }
  }

  assert(!state_array.empty()); // we expect at least one element!

  status("Processed prefix of size "+ i2string (state_array.size ()));

  right=state_array.size();

  do
  {
    assert(index<state_array.size());
    assert(index>=left);
    assert(index<right);

    status("Simulating prefix of size "+i2string(index+1));

    c_it=state_array[index];

    simulator_sat_dect satcheck(concrete_model.ns);
    symex_target_equationt::SSA_stepst SSA_steps;
    SSA_steps.splice(SSA_steps.end(),
        prefix.equation.SSA_steps, prefix.equation.SSA_steps.begin(), ++c_it);
    prefix.equation.SSA_steps.swap(SSA_steps);
    prefix.equation.convert(satcheck);
    prefix.equation.SSA_steps.splice(prefix.equation.SSA_steps.end(),
        SSA_steps, SSA_steps.begin(), SSA_steps.end());
    --c_it;

    if(is_satisfiable(satcheck))
    {
      // it's the assertion? grab counterexample!
      if(c_it->is_assert())
      {
        build_goto_trace(
            prefix.equation,
            satcheck,
            concrete_model.ns,
            concrete_counterexample.goto_trace);

        return false;
      }

      // otherwise decrease the search interval size
      left=index;       /* feasible element      */
    }
    else // unsatisfiable
    {
      right = index;      /* infeasible element    */
      step  = 1;          /* reset the step size   */
      index = left;       /* and restart from left */

      get_fail_info(
          abstract_counterexample,
          satcheck,
          prefix,
          c_it,
          fail_info);
    }

    /* now increase the index and the step interval */
    index = 
      (left + step < right)? (left + step) : (right - 1); 

    step = 2 * step;
  }
  while(left+1<right);

  // cannot be simulated, its spurious
  status("Spurious counterexample");

  // report the location
  status("Simulation failed at "+
      fail_info.last_step().pc->location.as_string());

  return true;
}