Example #1
0
/*!
  \brief auxiliary part of bmc_tableauGetUntilAtTime

  
*/
static be_ptr
bmc_tableauGetUntilAtTime_aux(const BeEnc_ptr be_enc,
                              const node_ptr p, const node_ptr q,
                              const int time, const int k, const int l,
                              const int steps)
{
  Be_Manager_ptr be_mgr;
  be_ptr tableau_temp; /* for increasing of performances */
  be_ptr tableau_following; /* to increase readability */

  nusmv_assert((time < k) || (time==k && Bmc_Utils_IsNoLoopback(l)) );
  nusmv_assert (steps >= 1);

  be_mgr = BeEnc_get_be_manager(be_enc);
  tableau_temp = BmcInt_Tableau_GetAtTime(be_enc, q, time, k, l);

  if (steps > 1) {
    tableau_following =
      bmc_tableauGetUntilAtTime_aux(be_enc, p, q,
                                    Bmc_Utils_GetSuccTime(time, k, l),
                                    k, l, steps - 1);

    tableau_temp =
      Be_Or( be_mgr,
             tableau_temp,
             Be_And(be_mgr,
                    BmcInt_Tableau_GetAtTime(be_enc, p, time, k, l),
                    tableau_following) );
  }
  return tableau_temp;
}
Example #2
0
/*!
  \brief auxiliary part of bmc_tableauGetReleasesAtTime

  Builds the release operator expression
*/
static be_ptr
bmc_tableauGetReleasesAtTime_aux(const BeEnc_ptr be_enc,
                                 const node_ptr p, const node_ptr q,
                                 const int time, const int k, const int l,
                                 const int steps)
{
  be_ptr tableau_p;
  be_ptr tableau_q;
  be_ptr tableau_result;

  nusmv_assert((time < k) || (time==k && Bmc_Utils_IsNoLoopback(l)) );
  nusmv_assert (steps >= 1);

  tableau_p = BmcInt_Tableau_GetAtTime(be_enc, p, time, k, l);
  tableau_q = BmcInt_Tableau_GetAtTime(be_enc, q, time, k, l);

  if (steps == 1) {
    if (Bmc_Utils_IsNoLoopback(l)) { /* q & p */
      tableau_result = Be_And(BeEnc_get_be_manager(be_enc),
                              tableau_p, tableau_q);
    } else { /* q */
      tableau_result = tableau_q;
    }
  }
  else { /* q & ( p | X(p R q) ) */
    be_ptr tableau_following =
      bmc_tableauGetReleasesAtTime_aux(be_enc, p, q,
                                       Bmc_Utils_GetSuccTime(time, k, l),
                                       k, l, steps - 1);
    tableau_result =
      Be_And(BeEnc_get_be_manager(be_enc),
             tableau_q,
             Be_Or(BeEnc_get_be_manager(be_enc),
                   tableau_p, tableau_following));
  }

  return tableau_result;
}
Example #3
0
be_ptr
bmc_tableauGetEventuallyAtTime(const BeEnc_ptr be_enc,
                               const node_ptr ltl_wff,
                               const int intime, const int k, const int l)
{
  Be_Manager_ptr be_mgr;
  int time;
  be_ptr tableau;
  int stop_time;
  int start_time;

  nusmv_assert((intime < k) || (intime==k && Bmc_Utils_IsNoLoopback(l)) );

  /* checks out the validity of [l, k] only if a loop exists: */
  nusmv_assert(Bmc_Utils_IsNoLoopback(l) || (k > l));

  be_mgr = BeEnc_get_be_manager(be_enc);
  tableau = Be_Falsity(be_mgr);

  /* there exist three cases:
     1) no loop: iterates from k downto intime;
     2) loop, (intime < l): iterates from k-1 downto intime;
     3) loop, (l <= intime < k) : iterates from k-1 downto l */

  if (Bmc_Utils_IsNoLoopback(l)) {
    /* The first case */
    start_time = k;
    stop_time  = intime;
  }
  else {
    /* The second and third case*/
    start_time = k-1;
    stop_time  = min(intime,l);
  }

  for (time = start_time; time>=stop_time; --time) {
    /* lazy evaluation: */
    be_ptr tableau_at_time = BmcInt_Tableau_GetAtTime(be_enc, ltl_wff,
                                                      time, k, l);

    if ( Be_IsTrue(be_mgr, tableau_at_time) ) {
      tableau = tableau_at_time;
      break;
    }
    tableau = Be_Or(be_mgr,
           tableau_at_time, tableau);
  } /* loop */

  return tableau;
}
Example #4
0
be_ptr
bmc_tableauGetGloballyAtTime(const BeEnc_ptr be_enc,
                             const node_ptr ltl_wff,
                             const int intime, const int k, const int l)
{
  Be_Manager_ptr be_mgr;
  int time;
  be_ptr tableau;
  int stop_time;

  nusmv_assert((intime < k) || (intime==k && Bmc_Utils_IsNoLoopback(l)) );

  /* checks out the validity of [l, k] only if a loop exists: */
  nusmv_assert(Bmc_Utils_IsNoLoopback(l) || (k > l));

  be_mgr = BeEnc_get_be_manager(be_enc);

  /* there exist three cases:
     1) no loop: cannot assure nothing, so return falsity;
     2) loop, (intime < l): iterates from intime to k-1;
     3) loop, (l <= intime < k) : iterates from intime to k-1, and then from
        l to intime-1 (so more efficiently from l to k-1.)  */
  if (Bmc_Utils_IsNoLoopback(l)) {
    tableau = Be_Falsity(be_mgr);
  }
  else {
    /* second and third cases */
    tableau = Be_Truth(be_mgr);

    stop_time = min(intime, l);
    for (time=k-1; time >= stop_time; --time) {
      /* lazy evaluation: */
      be_ptr tableau_at_time = BmcInt_Tableau_GetAtTime(be_enc, ltl_wff,
                                                        time, k, l);
      if ( Be_IsFalse(be_mgr, tableau_at_time) ) {
        tableau = tableau_at_time;
        break;
      }
      tableau = Be_And(be_mgr,
                       tableau_at_time, tableau);
    }
  }

  return tableau;
}
Example #5
0
be_ptr
bmc_tableauGetNextAtTime(const BeEnc_ptr be_enc, const node_ptr ltl_wff,
                         const int time, const int k, const int l)
{
  int succtime;
  be_ptr tableau;

  nusmv_assert((time < k) || (time==k && Bmc_Utils_IsNoLoopback(l)) );

  /* checks out the validity of [l, k] only if a loop exists: */
  nusmv_assert(Bmc_Utils_IsNoLoopback(l) || (k > l) );

  succtime = Bmc_Utils_GetSuccTime(time, k, l);

  if (!Bmc_Utils_IsNoLoopback(succtime)) {
    tableau = BmcInt_Tableau_GetAtTime(be_enc, ltl_wff, succtime, k, l);
  }
  else {
    tableau = Be_Falsity(BeEnc_get_be_manager(be_enc));
  }

  return tableau;
}
Example #6
0
Trace_ptr
Bmc_fill_trace_from_cnf_model(const BeEnc_ptr be_enc,
                              const Slist_ptr cnf_model,
                              int k, Trace_ptr trace)
{
  TraceIter first;
  /* local refs */
  const NuSMVEnv_ptr env = EnvObject_get_environment(ENV_OBJECT(be_enc));
  const ExprMgr_ptr exprs = EXPR_MGR(NuSMVEnv_get_value(env, ENV_EXPR_MANAGER));
  const BoolEnc_ptr bool_enc = \
    BoolEncClient_get_bool_enc(BOOL_ENC_CLIENT(be_enc));
  const NodeMgr_ptr nodemgr =
    NODE_MGR(NuSMVEnv_get_value(env, ENV_NODE_MGR));

  const Be_Manager_ptr be_mgr = BeEnc_get_be_manager(be_enc);
  const SymbTable_ptr st = BaseEnc_get_symb_table(BASE_ENC(be_enc));

  hash_ptr tvar_2_bval = new_assoc();
  hash_ptr time_2_step = new_assoc();

  Siter genLiteral;
  nusmv_ptrint cnfLiteral;
  nusmv_ptrint beLiteral;

  int i;

  TRACE_CHECK_INSTANCE(trace);
  nusmv_assert(Trace_is_empty(trace));

  first = Trace_first_iter(trace);

  /* phase 0: setup trace iterators for all times */
  insert_assoc(time_2_step, NODE_FROM_INT(0), (node_ptr)(first));
  for (i = 1; i <= k; ++ i) {
    TraceIter step = Trace_append_step(trace);
    insert_assoc(time_2_step, NODE_FROM_INT(i), (node_ptr)(step));
  }

  /* phase 1: we consider only the cnf variables corresponding to BE
     variables in the range [0, k].

     Thus we ignore the cnf variables that are not corresponding to
     the encoding of the:
     - model variables;
     - encoding variables (sub formulas, loop variables, ...)
  */
  SLIST_FOREACH(cnf_model, genLiteral) {
    int var_idx, ut_index, vtime;
    node_ptr var, key;

    cnfLiteral = (nusmv_ptrint) Siter_element(genLiteral);
    beLiteral = (nusmv_ptrint) Be_CnfLiteral2BeLiteral(be_mgr, cnfLiteral);

    /* if there is no corresponding rbc variable skip this */
    if (0 == beLiteral) continue;

    /* get timed var */
    var_idx = Be_BeLiteral2BeIndex(be_mgr, beLiteral);
    ut_index = BeEnc_index_to_untimed_index(be_enc, var_idx);
    vtime = BeEnc_index_to_time(be_enc, var_idx);
    var = BeEnc_index_to_name(be_enc, ut_index);

    /* needed to adapt to new trace timing format, input is stored
     in the next step */
    if (SymbTable_is_symbol_input_var(st, var)) { ++ vtime; }

    if (vtime > k) continue;

    /* if it's a bit get/create a BitValues structure for
       the scalar variable which this bit belongs */
    if (BoolEnc_is_var_bit(bool_enc, var)) {
      node_ptr scalar_var = BoolEnc_get_scalar_var_from_bit(bool_enc, var);
      BitValues_ptr bv;
      key = find_node(nodemgr, ATTIME, scalar_var, NODE_FROM_INT(vtime));

      bv = BIT_VALUES(find_assoc(tvar_2_bval, key));
      if (BIT_VALUES(NULL) == bv) {
        bv = BitValues_create(bool_enc, scalar_var);
        insert_assoc(tvar_2_bval, key, (node_ptr)(bv));
      }

      /* set the bit value */
      BitValues_set(bv, BoolEnc_get_index_from_bit(bool_enc, var),
                    (beLiteral >= 0) ? BIT_VALUE_TRUE : BIT_VALUE_FALSE);

    }
    else { /* boolean variables do not require any further processing */

      TraceIter timed_step = (-1 != vtime) /* frozenvars */
        ? TRACE_ITER(find_assoc(time_2_step, NODE_FROM_INT(vtime)))
        : first ;

      nusmv_assert(TRACE_END_ITER != timed_step);
      Trace_step_put_value(trace, timed_step, var, beLiteral >= 0
                           ? ExprMgr_true(exprs) : ExprMgr_false(exprs));
    }

  } /* SLIST_FOREACH (phase 1) */
Example #7
0
be_ptr
BmcInt_Tableau_GetAtTime(const BeEnc_ptr be_enc, const node_ptr ltl_wff,
                         const int time, const int k, const int l)
{
  const NuSMVEnv_ptr env = EnvObject_get_environment(ENV_OBJECT(be_enc));
  const StreamMgr_ptr streams =
    STREAM_MGR(NuSMVEnv_get_value(env, ENV_STREAM_MANAGER));
  const ErrorMgr_ptr errmgr =
    ERROR_MGR(NuSMVEnv_get_value(env, ENV_ERROR_MANAGER));
  const MasterPrinter_ptr wffprint =
    MASTER_PRINTER(NuSMVEnv_get_value(env, ENV_WFF_PRINTER));
  const NodeMgr_ptr nodemgr =
    NODE_MGR(NuSMVEnv_get_value(env, ENV_NODE_MGR));

  be_ptr result = (be_ptr)NULL;
  SymbTable_ptr st;
  Be_Manager_ptr be_mgr;
  node_ptr key;
  hash_ptr tableau_ltl_hash;

  /* checks out the validity of [l, k] only if a loop exists: */
  nusmv_assert(Bmc_Utils_IsNoLoopback(l) || (k > l));
  nusmv_assert((time < k) || (time==k && Bmc_Utils_IsNoLoopback(l)) );

  st = BaseEnc_get_symb_table(BASE_ENC(be_enc));
  be_mgr = BeEnc_get_be_manager(be_enc);

  tableau_ltl_hash = Bmc_Tableau_get_handled_hash(st, ST_BMC_TABLEAU_LTL_HASH);

  key = bmc_tableau_memoization_get_key(nodemgr, ltl_wff, time, k, l);
  result = bmc_tableau_memoization_lookup(tableau_ltl_hash, key);
  if (result != (be_ptr) NULL) return result;

  switch (node_get_type(ltl_wff)) {
  case TRUEEXP:
    return Be_Truth(be_mgr); /* not memoized */

  case FALSEEXP:
    return Be_Falsity(be_mgr); /* not memoized */

  case BIT:
  case DOT:
    if ((time == k) &&
        BeEnc_is_index_input_var(be_enc,
                                 BeEnc_name_to_index(be_enc, ltl_wff))) {
      /* input vars when time == max_time evaluate to false: */
      return Be_Falsity(be_mgr); /* not memoized */
    }

    return BeEnc_name_to_timed(be_enc, ltl_wff, time); /* not memoized */

  case ARRAY:
    if (!SymbTable_is_symbol_declared(st, ltl_wff)) {
      ErrorMgr_internal_error(errmgr, "Unexpected array node\n");
    }

    if (!SymbTable_is_symbol_bool_var(st, ltl_wff)) {
      StreamMgr_print_error(streams,  "Detected scalar array variable '");
      StreamMgr_nprint_error(streams, wffprint, "%N", ltl_wff);
      StreamMgr_print_error(streams,  "'");
      ErrorMgr_internal_error(errmgr, "Scalar array variable has been found where a boolean "
                     "variable had to be used instead.\n"
                     "This might be due to a bug on your model.");
    }

    if ((time == k) &&
        BeEnc_is_index_input_var(be_enc,
                                 BeEnc_name_to_index(be_enc, ltl_wff))) {
      /* input vars when time == max_time evaluate to false: */
      return Be_Falsity(be_mgr); /* not memoized */
    }

    return BeEnc_name_to_timed(be_enc, ltl_wff, time); /* not memoized */

  case NOT:
    /* checks out that argument of NOT operator is actually a variable: */
    nusmv_assert( node_get_type(car(ltl_wff)) == DOT ||
                  node_get_type(car(ltl_wff)) == BIT ||
                  node_get_type(car(ltl_wff)) == ARRAY);

    if (!SymbTable_is_symbol_declared(st, car(ltl_wff))) {
      ErrorMgr_internal_error(errmgr, "Unexpected scalar or undefined node\n");
    }

    if ((node_get_type(car(ltl_wff)) == ARRAY) &&
        ! SymbTable_is_symbol_bool_var(st, car(ltl_wff))) {
      StreamMgr_print_error(streams,  "Detected scalar array variable '");
      StreamMgr_nprint_error(streams, wffprint, "%N", car(ltl_wff));
      StreamMgr_print_error(streams,  "'");
      ErrorMgr_internal_error(errmgr, "Scalar array variable has been found where a boolean "
                     "variable had to be used instead.\n"
                     "This might be due to a bug on your model.");
    }

    if ((time == k) &&
        BeEnc_is_index_input_var(be_enc,
                                 BeEnc_name_to_index(be_enc, car(ltl_wff)))) {
      /* input vars when time == max_time evaluate to false: */
      result = Be_Falsity(be_mgr);
      break;
    }

    result = Be_Not(be_mgr, BeEnc_name_to_timed(be_enc, car(ltl_wff), time));
    break;

  case AND:
    result = Be_And(be_mgr,
                    BmcInt_Tableau_GetAtTime(be_enc,car(ltl_wff), time, k, l),
                    BmcInt_Tableau_GetAtTime(be_enc,cdr(ltl_wff), time, k, l));
    break;

  case OR:
    result = Be_Or(be_mgr,
                   BmcInt_Tableau_GetAtTime(be_enc,car(ltl_wff), time, k, l),
                   BmcInt_Tableau_GetAtTime(be_enc,cdr(ltl_wff), time, k, l));
    break;

  case IFF:
    result = Be_Iff(be_mgr,
                    BmcInt_Tableau_GetAtTime(be_enc,car(ltl_wff),time,k,l),
                    BmcInt_Tableau_GetAtTime(be_enc,cdr(ltl_wff),time,k,l));
    break;

  case OP_NEXT:
    result = bmc_tableauGetNextAtTime(be_enc, car(ltl_wff), time, k, l);
    break;

  case OP_GLOBAL:
    result = bmc_tableauGetGloballyAtTime(be_enc, car(ltl_wff), time, k, l);
    break;

  case OP_FUTURE: /* EVENTUALLY */
    result = bmc_tableauGetEventuallyAtTime(be_enc, car(ltl_wff), time, k, l);

    break;

  case UNTIL:
    result = bmc_tableauGetUntilAtTime(be_enc, car(ltl_wff), cdr(ltl_wff),
                                       time, k, l);
    break;

  case RELEASES:
    result = bmc_tableauGetReleasesAtTime(be_enc, car(ltl_wff), cdr(ltl_wff),
                                          time, k, l );
    break;

  case IMPLIES:
    ErrorMgr_internal_error(errmgr, "'Implies' should had been nnf-ed away!\n");

  case ATOM:
  case EX:
  case AX:
  case EF:
  case AF:
  case EG:
  case AG:
  case EBF:
  case EBG:
  case ABF:
  case ABG:
    ErrorMgr_internal_error(errmgr,  "Unexpected CTL operator, node type %d\n",
                    node_get_type(ltl_wff) );

  default:
    /* no other type are available here: */
    error_unreachable_code();
  }

  nusmv_assert(result != NULL); /*it must be assigned! */
  bmc_tableau_memoization_insert(tableau_ltl_hash, key, result);
  return result;
}
Example #8
0
/**Function********************************************************************

  Synopsis           [Checks the truth value of a list of constraints on the
                      current state, transitions and next states,
                      from given starting state. This can be used
                      in guided interactive simulation to propose
                      the set of transitions which are allowed to
                      occur in the interactive simulation.]

  Description        [Given a list of constraints (next-expressions as be_ptr),
                      checks which (flattened) constraints are
                      satisfiable from a given state. Iff
                      from_state is NULL (and not TRUE), the
                      initial state of the fsm is
                      considered. Returned list contains values in
                      {0,1}, and has to be freed.]

  SideEffects        [None]

  SeeAlso            []

******************************************************************************/
Olist_ptr
Bmc_simulate_check_feasible_constraints(BeFsm_ptr be_fsm,
                                        BddEnc_ptr bdd_enc,
                                        Olist_ptr constraints,
                                        be_ptr from_state)
{
  Olist_ptr res = Olist_create();
#if NUSMV_HAVE_INCREMENTAL_SAT
  BeEnc_ptr be_enc = BeFsm_get_be_encoding(be_fsm);
  Be_Manager_ptr be_mgr = BeEnc_get_be_manager(be_enc);

  SatIncSolver_ptr solver;
  be_ptr be_init, be_trans, be_prob;

  /* Create the SAT solver instance */
  solver = Sat_CreateIncSolver(get_sat_solver(OptsHandler_get_instance()));
  if (SAT_INC_SOLVER(NULL) == solver) {
    internal_error("Incremental sat solver '%s' is not available.\n",
                   get_sat_solver(OptsHandler_get_instance()));
  }

  be_init = (from_state == (be_ptr) NULL) ? BeFsm_get_init(be_fsm) : from_state;
  be_init = Be_And(be_mgr, be_init, BeFsm_get_invar(be_fsm));

  be_trans = Be_And(be_mgr,
                    BeFsm_get_trans(be_fsm),
                    BeEnc_shift_curr_to_next(be_enc, BeFsm_get_invar(be_fsm)));

  be_prob = Be_And(be_mgr, be_init, be_trans);
  be_prob = BeEnc_untimed_expr_to_timed(be_enc, be_prob, 0);

  /* pushes the transition relation */
  bmc_simulate_add_be_into_inc_solver_positively(SAT_INC_SOLVER(solver),
                            SatSolver_get_permanent_group(SAT_SOLVER(solver)),
                            be_prob, be_enc);

  { /* loops over the constraints list */
    Oiter iter;
    OLIST_FOREACH(constraints, iter) {
      be_ptr be_constr = (be_ptr) Oiter_element(iter);
      boolean constr_truth;
      SatSolverGroup satGrp;
      SatSolverResult sat_res;

      be_constr = BeEnc_untimed_expr_to_timed(be_enc, be_constr, 0);

      /* pushes the constraint */
      satGrp = SatIncSolver_create_group(solver);
      bmc_simulate_add_be_into_inc_solver_positively(SAT_INC_SOLVER(solver),
                                                     satGrp, be_constr,
                                                     be_enc);

      /* solves */
      sat_res = SatSolver_solve_all_groups(SAT_SOLVER(solver));
      switch (sat_res) {
      case SAT_SOLVER_SATISFIABLE_PROBLEM:
        constr_truth = true; break;

      case SAT_SOLVER_UNSATISFIABLE_PROBLEM:
        constr_truth = false; break;

      default:
        error_unreachable_code(); /* no other options handled! */
      }

      Olist_append(res, (void*) constr_truth);
      SatIncSolver_destroy_group(solver, satGrp);
    } /* constr loop */
  }
Example #9
0
/**Function********************************************************************

  Synopsis           [SAT Based Incremental simulation]

  Description        [This function performs incremental sat based
  simulation up to <tt>target_steps</tt>.

  Simulation starts from an initial state internally selected.

  It accepts a constraint to direct the simulation to paths satisfying
  such constraints. The constraints is assumed to be over state, input
  and next state variables. Thus, please carefully consider this
  information while providing constraints to this routine.

  The simulation stops if either the <tt>target_steps</tt> steps of
  simulation have been performed, or the simulation bumped in a
  deadlock (that might be due to the constraints that are too strong).

  Parameters:

  'print_trace'  : shows the generated trace
  'changes_only' : shows only variables that actually change value
  between one step and it's next one]

  SideEffects        [The possibly partial generated simulaiton trace
  is added to the trace manager for possible reuse.]

  SeeAlso            [optional]

******************************************************************************/
int Bmc_StepWiseSimulation(BeFsm_ptr be_fsm,
                           BddEnc_ptr bdd_enc,
                           TraceManager_ptr trace_manager,
                           int target_steps,
                           be_ptr constraints,
                           boolean time_shift,
                           boolean print_trace,
                           boolean changes_only,
                           Simulation_Mode mode,
                           boolean display_all)
{
#if NUSMV_HAVE_INCREMENTAL_SAT
  int steps;
  boolean no_deadlock;
  BeEnc_ptr be_enc = BE_ENC(NULL);
  Be_Manager_ptr be_mgr = (Be_Manager_ptr)NULL;
  SatIncSolver_ptr solver = SAT_INC_SOLVER(NULL);
  SatSolverGroup satGrp = (SatSolverGroup)-1;
  SatSolverResult satResult = SAT_SOLVER_UNAVAILABLE;
  Trace_ptr trace = bmc_simulate_get_curr_sim_trace();
  int tr_num = bmc_simulate_get_curr_sim_trace_index();
  be_ptr be_trans = (be_ptr)NULL;
  long time_statistics = util_cpu_time();

  TRACE_CHECK_INSTANCE(trace); /* a trace was picked */

  if (target_steps <= 0) return -1;

  /* Create the SAT solver instance */
  solver  = Sat_CreateIncSolver(get_sat_solver(OptsHandler_get_instance()));
  if (SAT_INC_SOLVER(NULL) == solver) {
    fprintf(nusmv_stderr,
            "Incremental sat solver '%s' is not available.\n",
            get_sat_solver(OptsHandler_get_instance()));
    return -1;
  }

  switch (mode) {
  case Random:
    bmc_simulate_enable_random_mode(SAT_SOLVER(solver));
    break;
  case Interactive:
    /* Do nothing */
    break;
  case Deterministic:
    /* Do nothing */
    break;
  default:
    internal_error("%s: Invalid mode given", __func__);
  }

  no_deadlock = true;

  be_enc = BeFsm_get_be_encoding(be_fsm);
  be_mgr = BeEnc_get_be_manager(be_enc);

  /* 1. Add the transition relation into the solver permanently */
  be_trans = BeFsm_get_invar(be_fsm);
  be_trans = Be_And(be_mgr,
                    be_trans,
                    BeEnc_shift_curr_to_next(be_enc, be_trans));
  be_trans = Be_And(be_mgr, BeFsm_get_trans(be_fsm), be_trans);

  /* We force the constraints that can be over starting states, or
     over next states, or over the input. If the constraint is over
     the current state variables, then it might be the case the chosen
     next statre does not satisfy the constraint. */
  if (time_shift) {
    constraints = BeEnc_shift_curr_to_next(be_enc, constraints);
  }

  be_trans = Be_And(be_mgr, be_trans, constraints);

  /* Necessary to re-use the routines for extracting the model */
  be_trans = BeEnc_untimed_expr_to_timed(be_enc, be_trans, 0);
  bmc_simulate_add_be_into_inc_solver_positively(SAT_INC_SOLVER(solver),
                      SatSolver_get_permanent_group(SAT_SOLVER(solver)),
                      be_trans, be_enc);

  /* 2. Iteration adding last computed state as src state and
        extracting the pair (input,next_state), adding the pair to the
        computed trace, and then iterating from the so far computed
        next_state */
  {
    for (steps = 0; ((steps < target_steps) && no_deadlock) ; steps++) {
      be_ptr be_src_state = (be_ptr)NULL;

      if (opt_verbose_level_gt(OptsHandler_get_instance(), 1)) {
        fprintf(nusmv_stderr, "Performing simulation step %d ...", steps+1);
      }

      /* 2.0. Extraction from the so far compute trace the last
         state. */
      be_src_state = BeEnc_untimed_expr_to_timed(be_enc,
                         TraceUtils_fetch_as_be(trace, Trace_last_iter(trace),
                                        TRACE_ITER_SF_VARS, be_enc, bdd_enc), 0);

      /* 2.2 Create the group to store the last state and, add the
           last state to the solver */
      satGrp = SatIncSolver_create_group(solver);
      bmc_simulate_add_be_into_inc_solver_positively(SAT_INC_SOLVER(solver),
                                                     satGrp,
                                                     be_src_state, be_enc);

      /* 2.3. Call the solver on the instantiated problem */
      satResult = SatSolver_solve_all_groups(SAT_SOLVER(solver));

      switch (satResult) {
      case SAT_SOLVER_SATISFIABLE_PROBLEM:
        if (Interactive == mode) {
          Trace_ptr iTrace =
            bmc_simulate_interactive_step(SAT_SOLVER(solver), be_enc,
                                          bdd_enc, Trace_get_symbols(trace),
                                          true, display_all);
          Trace_concat(trace, &iTrace);
        }
        else {
          /* Append current computed state to the trace */
          bmc_trace_utils_append_input_state(trace, be_enc,
                                   SatSolver_get_model(SAT_SOLVER(solver)));
        }

        break;

      case SAT_SOLVER_UNSATISFIABLE_PROBLEM:
        fprintf(nusmv_stderr,
            "The model reached a deadlock state: iteration %d.\n", steps);
        if (!Be_IsTrue(be_mgr, constraints)) {
          fprintf(nusmv_stderr,
            "This might be due to the constraints that are too strong.\n");
        }
        no_deadlock = false;
        break;

      default:
        fprintf(nusmv_stderr,
            "At iteration %d, the solver returned an unexpected value: %d\n",
                steps, satResult);
        no_deadlock = false;
        break;
      }

      /* 2.4. Remove and destroy the group containing the last
              computed state */
      SatIncSolver_destroy_group(solver, satGrp);

      if (opt_verbose_level_gt(OptsHandler_get_instance(), 1)) {
        fprintf(nusmv_stderr, "... done\n");
      }

      if (opt_verbose_level_gt(OptsHandler_get_instance(), 0)) {
        fprintf(nusmv_stdout,
                " -- simulation of step %d has finished in %2.1f seconds\n",
                steps, (util_cpu_time() - time_statistics) / 1000.0);
        time_statistics = util_cpu_time();
      }
    } /* (steps < target_steps) && no_deadlock) */

  } /* iteration block */

  /* 3. We clean the memory and we return */
  SatIncSolver_destroy(solver);

  if (no_deadlock && print_trace) {
    TraceManager_execute_plugin(trace_manager, TRACE_OPT(NULL),
                                (changes_only) ? 0 : 1, tr_num);
  }

  return steps;

#else
  fprintf(nusmv_stderr,
          "%s: Relies on Incremental solving. "
          "No incremental SAT solver is available now\n", __func__);
  return -1;
#endif
}
Example #10
0
/**Function********************************************************************

   Synopsis           [Performs simulation]

   Description [Generate a problem with no property, and search for a
   solution, appending it to the current simulation trace.
   Returns 1 if solver could not be created, 0 if everything went smooth]

   SideEffects        [None]

   SeeAlso            []

******************************************************************************/
int Bmc_Simulate(const BeFsm_ptr be_fsm, BddEnc_ptr bdd_enc,
                 be_ptr be_constraints, boolean time_shift,
                 const int k, const boolean print_trace,
                 const boolean changes_only,
                 const Simulation_Mode mode)
{
  be_ptr init, prob; /* The problem in BE format */
  SatSolver_ptr solver;
  SatSolverResult sat_res;
  BeEnc_ptr be_enc;
  Be_Manager_ptr be_mgr;
  Be_Cnf_ptr cnf;

  Trace_ptr trace = bmc_simulate_get_curr_sim_trace();
  int tr_num = bmc_simulate_get_curr_sim_trace_index();

  TRACE_CHECK_INSTANCE(trace); /* curr trace was picked */

  be_enc = BeFsm_get_be_encoding(be_fsm);
  be_mgr = BeEnc_get_be_manager(be_enc);

  if (opt_verbose_level_gt(OptsHandler_get_instance(), 0)) {
    fprintf(nusmv_stderr, "Simulation of length %d (no loopback)\n", k);
  }

  solver = Sat_CreateNonIncSolver(get_sat_solver(OptsHandler_get_instance()));
  if (solver == SAT_SOLVER(NULL)) {
    fprintf(nusmv_stderr,
            "Non-incremental sat solver '%s' is not available.\n",
            get_sat_solver(OptsHandler_get_instance()));
    return 1;
  }

  switch (mode) {
  case Random:
    bmc_simulate_enable_random_mode(SAT_SOLVER(solver));
    break;
  case Interactive:
    internal_error("%s: Interactive mode not supported yet", __func__);
    break;
  case Deterministic:
    /* Do nothing */
    break;
  default:
    internal_error("%s: Invalid mode given", __func__);
  }

  /* starting state taken from the last node of the current sim trace */
  init = BeEnc_untimed_expr_to_timed(be_enc,
               TraceUtils_fetch_as_be(trace, Trace_last_iter(trace),
                                      TRACE_ITER_SF_VARS, be_enc, bdd_enc), 0);

  prob = Be_And(be_mgr, Bmc_Model_GetPathNoInit(be_fsm, k), init);

  /* Use constraints only if actually necessary */
  if (!Be_IsTrue(be_mgr, be_constraints)) {
    int i;
    for (i = 0; i <= k; ++i) {
      be_ptr be_timed = be_constraints;

      if (time_shift) {
        be_timed = BeEnc_shift_curr_to_next(be_enc, be_timed);
      }

      be_timed = BeEnc_untimed_expr_to_timed(be_enc, be_timed, i);

      prob = Be_And(be_mgr, prob, be_timed);
    }
  }

  prob = Bmc_Utils_apply_inlining(be_mgr, prob);
  cnf = Be_ConvertToCnf(be_mgr, prob, 1);

  SatSolver_add(solver, cnf, SatSolver_get_permanent_group(solver));
  SatSolver_set_polarity(solver, cnf, 1,
                         SatSolver_get_permanent_group(solver));
  sat_res = SatSolver_solve_all_groups(solver);

  /* Processes the result: */
  switch (sat_res) {

  case SAT_SOLVER_UNSATISFIABLE_PROBLEM:
    fprintf(nusmv_stdout,
            "The model deadlocks before requested length %d!\n", k);
    break;

  case SAT_SOLVER_SATISFIABLE_PROBLEM:
    {
      BoolSexpFsm_ptr bsexp_fsm; /* needed for trace language */
      bsexp_fsm =  \
        PropDb_master_get_bool_sexp_fsm(PropPkg_get_prop_database());
      BOOL_SEXP_FSM_CHECK_INSTANCE(bsexp_fsm);

      Trace_ptr extension = \
        Bmc_create_trace_from_cnf_model(be_enc,
             SexpFsm_get_symbols_list(SEXP_FSM(bsexp_fsm)), NIL(char),
                                      TRACE_TYPE_UNSPECIFIED,
                                      SatSolver_get_model(solver), k);

      trace = Trace_concat(trace, &extension);
      nusmv_assert(TRACE(NULL) == extension);

      if (print_trace) {
        TraceManager_execute_plugin(global_trace_manager, TRACE_OPT(NULL),
                                    (changes_only) ? 0 : 1, tr_num);
      }

      break;
    } /* SAT */

  case SAT_SOLVER_INTERNAL_ERROR:
    internal_error("Sorry, solver answered with a fatal Internal "
                   "Failure during problem solving.\n");

  case SAT_SOLVER_TIMEOUT:
  case SAT_SOLVER_MEMOUT:
    internal_error("Sorry, solver ran out of resources and aborted "
                   "the execution.\n");

  default:
    internal_error(" Bmc_Simulate: Unexpected value in sat result");
  } /* switch */

  /* cleanup */
  SatSolver_destroy(solver);
  Be_Cnf_Delete(cnf);

  return 0;
}