Exemplo n.º 1
0
/**Function********************************************************************

  Synopsis           [Performs a simulation from the current selected state]

  SideEffects        [Generated referenced states traces are stored to be
  analyzed by the user in a second time]

  SeeAlso            [pick_state goto_state]

  CommandName        [simulate]

  CommandSynopsis    [Performs a simulation from the current selected state]

  CommandArguments   [\[-h\] \[-p | -v\] \[-r | -i \[-a\]\]
  [\[-c "constraints"\] | \[-t "constraints"\] ] \[-k steps\]
  ]

  CommandDescription [
  Generates a sequence of at most <tt>steps</tt> states (representing a
  possible execution of the model), starting from the <em>current state</em>.
  The current state must be set via the <em>pick_state</em> or
  <em>goto_state</em> commands.<p>
  It is possible to run the simulation in three ways (according to different
  command line policies):
  deterministic (the default mode), random and interactive.<p>
  The resulting sequence is stored in a trace indexed with an integer number
  taking into account the total number of traces stored in the system. There is
  a different behavior in the way traces are built, according to how
  <em>current state</em> is set: <em>current state</em> is always put at
  the beginning of a new trace (so it will contain at most <it>steps + 1</it>
  states) except when it is the last state of an existent old trace.
  In this case the old trace is lengthened by at most <it>steps</it> states.
  <p>
  Command Options:<p>
  <dl>
    <dt> <tt>-p</tt>
       <dd> Prints current generated trace (only those variables whose value
       changed from the previous state).
    <dt> <tt>-v</tt>
       <dd> Verbosely prints current generated trace (changed and unchanged
       state variables).
    <dt> <tt>-r</tt>
       <dd> Picks a state from a set of possible future states in a random way.
    <dt> <tt>-i</tt>
       <dd> Enables the user to interactively choose every state of the trace,
       step by step. If the number of possible states is too high, then
       the user has to specify some constraints as simple expression.
       These constraints are used only for a single simulation step and
       are <em>forgotten</em> in the following ones. They are to be intended
       in an opposite way with respect to those constraints eventually entered
       with the pick_state command, or during an interactive simulation
       session (when the number of future states to be displayed is too high),
       that are <em>local</em> only to a single step of the simulation and
       are <em>forgotten</em> in the next one.
    <dt> <tt>-a</tt>
       <dd> Displays all the state variables (changed and unchanged) during
       every step of an interactive session. This option works only if the
       <tt>-i</tt> option has been specified.
    <dt> <tt>-c "constraints"</tt>
       <dd> Performs a simulation in which computation is restricted
       to states satisfying those <tt>constraints</tt>. The desired
       sequence of states could not exist if such constraints were too
       strong or it may happen that at some point of the simulation a
       future state satisfying those constraints doesn't exist: in
       that case a trace with a number of states less than
       <tt>steps</tt> trace is obtained. The expression cannot contain
       next operators, and is automatically shifted by one state in
       order to constraint only the next steps
    <dt> <tt>-t "constraints"</tt>
       <dd> Performs a simulation in which computation is restricted
       to states satisfying those <tt>constraints</tt>. The desired
       sequence of states could not exist if such constraints were too
       strong or it may happen that at some point of the simulation a
       future state satisfying those constraints doesn't exist: in
       that case a trace with a number of states less than
       <tt>steps</tt> trace is obtained.  The expression can contain
       next operators, and is NOT automatically shifted by one state
       as done with option -c
    <dt> <tt>-k steps</tt>
       <dd> Maximum length of the path according to the constraints.
       The length of a trace could contain less than <tt>steps</tt> states:
       this is the case in which simulation stops in an intermediate
       step because it may not exist any future state satisfying those
       constraints.
    </dl> ]

******************************************************************************/
int CommandSimulate(int argc, char **argv)
{
  BddEnc_ptr enc;
  DdManager* dd;
  bdd_ptr bdd_constraints = (bdd_ptr) NULL;
  boolean isconstraint = false;
  boolean printrace = false;
  int display_all = 0;
  int c = 0;
  boolean only_changes = 1;
  boolean time_shift = false;
  int steps = get_default_simulation_steps(OptsHandler_get_instance());
  Simulation_Mode mode = Deterministic;
  boolean k_specified = false;

  /* the string of constraint to parsificate */
  char* strConstr = NIL(char);

  util_getopt_reset();
  while((c = util_getopt(argc,argv,"t:c:hpvriak:")) != EOF){
    switch(c){
    case 'h': return UsageSimulate();
    case 'p':
      if (printrace == true) return UsageSimulate();
      printrace = true;
      only_changes = true;
      break;
    case 'v':
      if (printrace == true) return UsageSimulate();
      printrace = true;
      only_changes = false;
      break;
    case 'r':
      if (mode == Interactive) return UsageSimulate();
      mode = Random;
      break;
    case 'i':
      if (mode == Random) return UsageSimulate();
      mode = Interactive;
      break;
    case 'a':
      display_all = 1;
      break;
    case 'c':
      if (NIL(char) != strConstr) return UsageSimulate();
      strConstr = util_strsav(util_optarg);
      isconstraint = true;
      time_shift = true;
      break;
    case 't':
      if (NIL(char) != strConstr) return UsageSimulate();
      strConstr = util_strsav(util_optarg);
      isconstraint = true;
      time_shift = false;
      break;

    case 'k':
      {
        char* strNumber;

        if (k_specified) {
          fprintf(nusmv_stderr,
                  "Option -k cannot be specified more than once.\n");
          return 1;
        }

        strNumber = util_strsav(util_optarg);

        if (util_str2int(strNumber, &steps) != 0) {
          error_invalid_number(strNumber);
          FREE(strNumber);
          return 1;
        }

        if (steps < 0) {
           error_invalid_number(strNumber);
           FREE(strNumber);
          return 1;
        }

        FREE(strNumber);
        k_specified = true;
        break;
      }

    default:
      return UsageSimulate();
    }
  }

  if ((mode != Interactive) && (display_all == 1)) return UsageSimulate();

  if (argc == util_optind + 1) {
    char* strNumber;

    fprintf(nusmv_stderr, "*** Warning: Parameter \"steps\" is deprecated. "
            "Use option \"-k\" instead\n");

    if (k_specified) {
      fprintf(nusmv_stderr, "Error: Parameter \"steps\" conflicts with option -k\n");
      return 1;
    }

    strNumber = util_strsav(argv[util_optind]);

    if (util_str2int(strNumber, &steps) != 0) {
      error_invalid_number(strNumber);
      FREE(strNumber);
      return 1;
    }

    if (steps < 0) {
      error_invalid_number(strNumber);
      FREE(strNumber);
      return 1;
    }

    FREE(strNumber);
    k_specified = true;
  }
  else if (argc != util_optind) {
    return UsageSimulate();
  }

  /* pre-conditions */
  if (Compile_check_if_model_was_built(nusmv_stderr, true)) return 1;

  if (!(current_state_exist())) {
    fprintf(nusmv_stderr,
            "No current state set. Use the \"pick_state\" command.\n");
    return 1;
  }

  enc = Enc_get_bdd_encoding();
  dd = BddEnc_get_dd_manager(enc);

  if (isconstraint == true) {
    bdd_constraints = simulate_get_constraints_from_string(strConstr, enc,
                                                           !time_shift,
                                                           true /*inputs*/);
    FREE(strConstr);
    if (bdd_constraints == (bdd_ptr) NULL) return 1; /* error */
  }
  else bdd_constraints = bdd_true(dd);

  {
    SexpFsm_ptr sexp_fsm; /* needed for trace lanugage */
    sexp_fsm = \
        PropDb_master_get_scalar_sexp_fsm(PropPkg_get_prop_database());

    node_ptr current_trace = Nil;
    BddFsm_ptr fsm;
    TraceLabel curr_lbl;

    fsm = PropDb_master_get_bdd_fsm(PropPkg_get_prop_database());

    curr_lbl = current_state_label_get();
    nusmv_assert(curr_lbl != TRACE_LABEL_INVALID);

    fprintf( nusmv_stdout, "********  Simulation Starting From State %d.%d "
             "  ********\n",
             TraceLabel_get_trace(curr_lbl) + 1,
             TraceLabel_get_state(curr_lbl) + 1);

    /* Important: the simulation ALWAYS starts from the current selected state */
    current_trace = Simulate_MultipleSteps(fsm, bdd_constraints, time_shift,
                                           mode, steps, display_all);
    if (current_trace == Nil) {
      bdd_free(dd, bdd_constraints);
      return 1;
    }

    /* extends and prints the current simulation trace */
    simulate_extend_print_curr_trace(enc, current_trace, printrace,
                                     only_changes,
                                     SexpFsm_get_symbols_list(sexp_fsm));

    /* Update the current state. */
    {
      int trace_id;
      Trace_ptr curr_trace;
      BddStates curr_state;
      TraceLabel new_label;

      trace_id = TraceManager_get_current_trace_number(global_trace_manager);

      curr_trace = TraceManager_get_trace_at_index(global_trace_manager,
                                                   trace_id);

      new_label = TraceLabel_create(trace_id, Trace_get_length(curr_trace));

      curr_state = TraceUtils_fetch_as_bdd(curr_trace,
                                           Trace_last_iter(curr_trace),
                                           TRACE_ITER_SF_VARS, enc);

      current_state_set(curr_state, new_label);

      bdd_free(BddEnc_get_dd_manager(enc),curr_state);
    }

    walk_dd(dd, bdd_free, current_trace);
    bdd_free(dd, bdd_constraints);
  }
  return 0;
} /* Command Simulate */
Exemplo n.º 2
0
/**Function********************************************************************

  Synopsis [Executes a trace on the fsm given at construction time
  using BDDs]

  Description [The trace is executed using BDDs, that is a proof that
  the fsm is compatible with the trace is built (if such proof
  exists). Incomplete traces are filled-in with compatible values for
  state and input variables.

  Given trace can be either complete or incomplete.

  The number of performed steps (transitions) is returned in *n_steps,
  if a non-NULL pointer is given. If the initial state is not
  compatible -1 is written.]

  SideEffects [None]

  SeeAlso     []

******************************************************************************/
static Trace_ptr
bdd_partial_trace_executor_execute
(const PartialTraceExecutor_ptr partial_executor, const Trace_ptr trace,
 const NodeList_ptr language, int* n_steps)
{
  /* local references to self */
  const BDDPartialTraceExecutor_ptr self = \
    BDD_PARTIAL_TRACE_EXECUTOR(partial_executor);

  const BaseTraceExecutor_ptr executor = \
    BASE_TRACE_EXECUTOR(partial_executor);

  Trace_ptr res = TRACE(NULL); /* failure */

  int count = -1;
  boolean success = true;

  DdManager* dd;
  BddStates trace_states;
  TraceIter step = TRACE_END_ITER;

  BddStates fwd_image = (BddStates) NULL;
  node_ptr path = Nil; /* forward constrained images will be used
                          later to compute the complete trace */

  const char* trace_description = "BDD Execution";

  /* 0- Check prerequisites */
  BDD_PARTIAL_TRACE_EXECUTOR_CHECK_INSTANCE(self);
  TRACE_CHECK_INSTANCE(trace);
  BDD_FSM_CHECK_INSTANCE(self->fsm);
  BDD_ENC_CHECK_INSTANCE(self->enc);

  dd = BddEnc_get_dd_manager(self->enc);

  step = trace_first_iter(trace);
  nusmv_assert(TRACE_END_ITER != step);

  trace_states = TraceUtils_fetch_as_bdd(trace, step,
                                         TRACE_ITER_SF_SYMBOLS, self->enc);

  /* 1- Check Start State */
  {
    bdd_ptr init_bdd = BddFsm_get_init(self->fsm);
    bdd_ptr invar_bdd = BddFsm_get_state_constraints(self->fsm);
    BddStates source_states; /* last known states */

    source_states = bdd_and(dd, init_bdd, invar_bdd);
    bdd_and_accumulate(dd, &source_states, trace_states);

    bdd_free(dd, invar_bdd);
    bdd_free(dd, init_bdd);
    bdd_free(dd, trace_states);

    if (!bdd_is_false(dd, source_states)) {

      boolean terminate = false;
      path = cons(NODE_PTR(bdd_dup(source_states)), Nil);

      ++ count;

      /* 2- Check Consecutive States are related by transition relation */
      do {
        BddStates last_state; /* (unshifted) next state */
        BddStates next_state; /* next state constraints */

        BddInputs next_input; /* next input constraints */
        BddStatesInputsNexts next_combo; /* state-input-next constraints */

        BddStatesInputsNexts constraints;

        step = TraceIter_get_next(step);
        if (TRACE_END_ITER != step) {

          next_input = \
            TraceUtils_fetch_as_bdd(trace, step, TRACE_ITER_I_SYMBOLS,
                                    self->enc);
          next_combo = \
            TraceUtils_fetch_as_bdd(trace, step, TRACE_ITER_COMBINATORIAL,
                                    self->enc);
          last_state = \
            TraceUtils_fetch_as_bdd(trace, step, TRACE_ITER_SF_SYMBOLS,
                                    self->enc);

          next_state = BddEnc_state_var_to_next_state_var(self->enc, last_state);

          if (0 < BaseTraceExecutor_get_verbosity(executor)) {
            fprintf(BaseTraceExecutor_get_output_stream(executor),
                    "-- executing step %d ... ", 1 + count);
            fflush(BaseTraceExecutor_get_output_stream(executor));
          }

          /* building constrained fwd image */
          constraints = bdd_and(dd, next_input, next_combo);
          bdd_and_accumulate(dd, &constraints, next_state);

          fwd_image =
            BddFsm_get_sins_constrained_forward_image(self->fsm, source_states,
                                                      constraints);

           /* test whether the constrained fwd image is not empty */
          if (!bdd_is_false(dd, fwd_image)) {
            if (0 < BaseTraceExecutor_get_verbosity(executor)) {
              fprintf(BaseTraceExecutor_get_output_stream(executor), "done\n");
            }
            path = cons(NODE_PTR(fwd_image), path);
            ++ count;
          }
          else {
            if (0 < BaseTraceExecutor_get_verbosity(executor)) {
              fprintf(BaseTraceExecutor_get_output_stream(executor),
                      "failed!\n");
            }
            terminate = true;
            success = false;
          }

          /* no longer used bdd refs */
          bdd_free(dd, next_input);
          bdd_free(dd, next_combo);
          bdd_free(dd, last_state);
          bdd_free(dd, next_state);

          bdd_free(dd, source_states);
          source_states = bdd_dup(fwd_image);
        }

        else {
          if (0 == count) {
            fprintf(BaseTraceExecutor_get_error_stream(executor),
                    "Warning: trace has no transitions.\n");
          }
          terminate = true;
        }
      } while (!terminate); /* loop on state/input pairs */
    } /* if has initial state */

    else {
      fprintf(BaseTraceExecutor_get_error_stream(executor),
              "Error: starting state is not initial state.\n");
      success = false;
    }

    /* 3- If last state could be reached a complete trace exists */
    if (success) {
      if (0 < count) {
        res = \
          bdd_partial_trace_executor_generate(self, fwd_image, path,
                                              count, language,
                                              trace_description);
      }

      else { /* generates a complete state of trace of length 0 */
        res = \
          bdd_partial_trace_executor_generate(self, source_states,
                                              Nil, 0, language,
                                              trace_description);
      }

      nusmv_assert(TRACE(NULL) != res);

      /* cleanup */
      walk_dd(dd, bdd_free, path);
      free_list(path);
    }

    bdd_free(dd, source_states);
  }

  /* as a final stage, verify loopbacks consistency using internal
     service. The incomplete trace is compatible (that is, a valid
     completion exists) iff exactly len(Trace) steps have been
     performed *and* loopback data for the incomplete trace applies to
     the complete one as well. */
  if (TRACE(NULL) != res) {
    if (Trace_get_length(trace) == count &&
        partial_trace_executor_check_loopbacks(partial_executor, trace, res)) {

      fprintf(BaseTraceExecutor_get_output_stream(executor),
              "-- Trace was successfully completed.\n");
    }

    else {
      Trace_destroy(res);
      res = TRACE(NULL);
    }
  }

  if (TRACE(NULL) == res) {
    fprintf(BaseTraceExecutor_get_output_stream(executor),
            "-- Trace could not be completed.\n");
  }

  if (NIL(int) != n_steps) { *n_steps = count; }
  return res;
}
Exemplo n.º 3
0
/**Function********************************************************************


  Synopsis    [Generates a complete trace]

  Description [This function is a private service of
  bdd_partial_trace_executor_execute]

  SideEffects [None]

******************************************************************************/
static Trace_ptr
bdd_partial_trace_executor_generate(const BDDPartialTraceExecutor_ptr self,
                                    const BddStates goal_states,
                                    node_ptr reachable, int length,
                                    const NodeList_ptr language,
                                    const char* trace_name)
{
  Trace_ptr res;
  DdManager* dd;
  node_ptr path;
  bdd_ptr target;

  NODE_LIST_CHECK_INSTANCE(language);

  dd = BddEnc_get_dd_manager(self->enc);

  target = BddEnc_pick_one_state_rand(self->enc, goal_states);
  path = cons((node_ptr) target, Nil);

  if (Nil != reachable) {
    reachable = cdr(reachable);
    while (0 != length) {
      bdd_ptr source;
      bdd_ptr input;
      bdd_ptr inputs;
      bdd_ptr bwd_image;
      bdd_ptr intersect;

      /* pick source state */
      bwd_image = BddFsm_get_backward_image(self->fsm, target);
      intersect = bdd_and(dd, bwd_image, (bdd_ptr) car(reachable));
      nusmv_assert(!bdd_is_false(dd, intersect));
      source = BddEnc_pick_one_state(self->enc, intersect);
      bdd_free(dd, intersect);
      bdd_free(dd, bwd_image);

      /* pick one input s.t. source -> (input) -> target */
      inputs = BddFsm_states_to_states_get_inputs(self->fsm, source, target);
      input = BddEnc_pick_one_input(self->enc, inputs);
      nusmv_assert(!bdd_is_false(dd, input));
      bdd_free(dd, inputs);

      /* prepend input and source state */
      path = cons((node_ptr) input, path);
      path = cons((node_ptr) source, path);

      -- length;
      target = source;
      reachable = cdr(reachable);
    }
  }
  /* make sure the trace length is correct */
  nusmv_assert(0 == length &&  Nil == reachable);

  res = \
    Mc_create_trace_from_bdd_state_input_list(self->enc, language, trace_name,
                                              TRACE_TYPE_EXECUTION, path);
  /* cleanup */
  walk_dd(dd, bdd_free, path);
  free_list(path);

  return res;
}
Exemplo n.º 4
0
int Compass_write_sigref(NuSMVEnv_ptr env,
                         BddFsm_ptr fsm,
                         FILE* sigref_file,
                         FILE* prob_file, /* can be NULL */
                         FILE* ap_file, /* can be NULL */
                         Expr_ptr tau, /* can be NULL */
                         boolean do_indent /* Beautify the XML output */
                         )
{
  BddEnc_ptr enc = BddFsm_get_bdd_encoding(fsm);
  DDMgr_ptr dd = BddEnc_get_dd_manager(enc);
  const NodeMgr_ptr nodemgr =
    NODE_MGR(NuSMVEnv_get_value(env, ENV_NODE_MGR));
  const TypeChecker_ptr tc = BaseEnc_get_type_checker(BASE_ENC(enc));

  NodeList_ptr ap_list_add = NODE_LIST(NULL);
  NodeList_ptr probs_list = NULL;
  NodeList_ptr ap_list = NULL;
  int retval = 0;

  add_ptr prob_add;
  add_ptr init_add;
  add_ptr trans_add;
  add_ptr tau_add;
  bdd_ptr bdd_trans;
  bdd_ptr state_mask = NULL;
  bdd_ptr input_mask = NULL;
  bdd_ptr next_state_mask = NULL;
  bdd_ptr next_and_curr_state_mask = NULL;

  /* preprocessing of the parameters */
  /* tau */
  if (EXPR(NULL) != tau) {
    tau = Compile_FlattenSexp(BaseEnc_get_symb_table(BASE_ENC(enc)),
                              car(tau) /* gets rid of SIMPWFF */,
                              Nil);
  }

  /* prob_file */
  if (NULL != prob_file) {
    ParserProb_ptr pl_parser = NULL;

    pl_parser = ParserProb_create(env);
    ParserProb_parse_from_file(pl_parser, prob_file);
    probs_list = ParserProb_get_prob_list(pl_parser);

    if (NODE_LIST(NULL) != probs_list) {
      Compass_check_prob_list(tc, probs_list);
    }

    ParserProb_destroy(pl_parser);
  }

  /* ap_file */
  if (NULL != ap_file) {
    ParserAp_ptr ap_parser = NULL;

    ap_parser = ParserAp_create(env);
    ParserAp_parse_from_file(ap_parser, ap_file);

    ap_list = ParserAp_get_ap_list(ap_parser);

    if (NODE_LIST(NULL) != ap_list) {
      Compass_check_ap_list(tc, ap_list);
    }

    ParserAp_destroy(ap_parser);
  }

  /* collects all required pieces */

  state_mask = BddEnc_get_state_frozen_vars_mask_bdd(enc);
  input_mask = BddEnc_get_input_vars_mask_bdd(enc);
  next_state_mask = BddEnc_state_var_to_next_state_var(enc, state_mask);
  next_and_curr_state_mask = bdd_and(dd, state_mask, next_state_mask);

  { /* calculates the initial states */
    bdd_ptr bdd_init = BddFsm_get_init(fsm);
    bdd_ptr bdd_sinvar = BddFsm_get_state_constraints(fsm);
    bdd_ptr bdd_iinvar = BddFsm_get_input_constraints(fsm);
    bdd_and_accumulate(dd, &bdd_init, bdd_sinvar);
    bdd_and_accumulate(dd, &bdd_init, bdd_iinvar);
    bdd_and_accumulate(dd, &bdd_init, state_mask);

    init_add = bdd_to_add(dd, bdd_init);

    bdd_free(dd, bdd_iinvar);
    bdd_free(dd, bdd_sinvar);
    bdd_free(dd, bdd_init);
  }


  { /* to control dynamic reordering */
    dd_reorderingtype method;
    int dd_reord_status;

    /* Dynamic reordering during monolithic trans can improve performances */
    dd_reord_status = dd_reordering_status(dd, &method);
    dd_autodyn_enable(dd, method);

    { /* calculates the transition relation */
      bdd_ptr bdd_sinvar = BddFsm_get_state_constraints(fsm);
      bdd_ptr bdd_nsinvar = BddEnc_state_var_to_next_state_var(enc, bdd_sinvar);
      bdd_ptr bdd_iinvar = BddFsm_get_input_constraints(fsm);

      bdd_trans = BddFsm_get_monolithic_trans_bdd(fsm);
      bdd_and_accumulate(dd, &bdd_trans, bdd_sinvar);
      bdd_and_accumulate(dd, &bdd_trans, bdd_nsinvar);
      bdd_and_accumulate(dd, &bdd_trans, bdd_iinvar);
      bdd_and_accumulate(dd, &bdd_trans, next_and_curr_state_mask);
      bdd_and_accumulate(dd, &bdd_trans, input_mask);

/* #define DEBUG_TRANS */
#ifdef DEBUG_TRANS
      FILE * p = stdout; // fopen("TRANS.txt", "w");
      fprintf(p, "==================================================\n");
      fprintf(p, "TRANS\n");
      fprintf(p, "==================================================\n");
      // print_trans(enc, bdd_trans, p);
      dd_printminterm(dd, bdd_trans);
      fprintf(p, "==================================================\n");
      dd_printminterm(dd, input_mask);
      fprintf(p, "==================================================\n");
      // fclose(p);
#endif

      trans_add = bdd_to_add(dd, bdd_trans);

      bdd_free(dd, bdd_iinvar);
      bdd_free(dd, bdd_nsinvar);
      bdd_free(dd, bdd_sinvar);
    }

    /* Dynamic reordering is disabled after monolitic
       construction. Later it will be re-enabled if it was enable
       before entering this block */
    dd_autodyn_disable(dd);

    /* probability and tau are optional */
    if (probs_list != NODE_LIST(NULL)) {
      prob_add = Compass_process_prob_list(enc, probs_list, bdd_trans);
    }
    else prob_add = (add_ptr) NULL;

    bdd_free(dd, bdd_trans);

    if (tau != (Expr_ptr) NULL) {
      tau_add = BddEnc_expr_to_add(enc, tau, Nil);

      /* [RC]: This code was disable because it seems masks for input
       * var do not work */
      /* mask_tau_add = BddEnc_apply_input_vars_mask_add(enc, tau_add); */
      /* add_free(dd, tau_add); */
      /* tau_add = mask_tau_add; */
    }
    else
      tau_add = (add_ptr) NULL;

    if (NODE_LIST(NULL) != ap_list) {
      add_ptr expr_add, expr_add_mask;
      ListIter_ptr iter;
      ap_list_add = NodeList_create();

      NODE_LIST_FOREACH(ap_list, iter) {
        node_ptr ap_el = (node_ptr)NodeList_get_elem_at(ap_list, iter);
        node_ptr lab = car(ap_el);
        node_ptr expr = cdr(ap_el);

        expr_add = BddEnc_expr_to_add(enc, expr, Nil);
        expr_add_mask = BddEnc_apply_state_frozen_vars_mask_add(enc, expr_add);
        NodeList_append(ap_list_add, cons(nodemgr, lab, (node_ptr)expr_add_mask));
        add_free(dd, expr_add);
        /* The expr_add_mask will be freed later when the ap_list_add
           will be destroyed */
      }
    }