/**Function******************************************************************** Synopsis [The BoolEncClient class private deinitializer] Description [The BoolEncClient class private deinitializer] SideEffects [] SeeAlso [BoolEncClient_destroy] ******************************************************************************/ void bool_enc_client_deinit(BoolEncClient_ptr self) { /* members deinitialization */ /* base class deinitialization */ base_enc_deinit(BASE_ENC(self)); }
/**Function******************************************************************** Synopsis [Prints statistical information of a formula.] Description [Prints statistical information about a given formula. It is computed taking care of the encoding and of the indifferent variables in the encoding.] SideEffects [] SeeAlso [] ******************************************************************************/ void BddEnc_print_formula_info(BddEnc_ptr self, Expr_ptr formula, boolean print_models, boolean print_formula, FILE* out) { bdd_ptr phi; double cardinality; phi = BddEnc_expr_to_bdd(self, formula, Nil); cardinality = BddEnc_get_minterms_of_bdd(self, phi); fprintf(out, "formula models: %g (2^%g)\n", cardinality, log(cardinality)/log(2.0)); /* one of these flags can be enabled, not both */ nusmv_assert(!print_models || !print_formula); if (print_models) { BddEnc_print_set_of_trans_models(self, phi, /* false, */ out); } else if (print_formula) { BoolEnc_ptr benc = BoolEncClient_get_bool_enc(BOOL_ENC_CLIENT(self)); const array_t* layer_names = BaseEnc_get_committed_layer_names(BASE_ENC(self)); SymbTable_ptr st = BaseEnc_get_symb_table(BASE_ENC(self)); NodeList_ptr all_vars = SymbTable_get_layers_sf_vars(st, layer_names); NodeList_ptr scalar_vars = NodeList_create(); ListIter_ptr iter; /* encoding variables are not allowed in the wff printer */ NODE_LIST_FOREACH(all_vars, iter) { node_ptr v = NodeList_get_elem_at(all_vars, iter); if (BoolEnc_is_var_bit(benc, v)) continue; NodeList_append(scalar_vars, v); } NodeList_destroy(all_vars); fprintf(nusmv_stdout, "\nFORMULA = \n"); BddEnc_print_bdd_wff(self, phi, scalar_vars, true, false, 0, out); NodeList_destroy(scalar_vars); }
/**Function******************************************************************** Synopsis [Checks that the given layer occurs within the used bool encoder, and then adds this layer to the set of committed layers. ] Description [This method must always be called by derived classes] SideEffects [] SeeAlso [BoolEncClient_destroy] ******************************************************************************/ void bool_enc_client_commit_layer(BaseEnc_ptr base_enc, const char* layer_name) { BoolEncClient_ptr self; self = BOOL_ENC_CLIENT(base_enc); nusmv_assert(BaseEnc_layer_occurs(BASE_ENC(self->bool_enc), layer_name)); base_enc_commit_layer(base_enc, layer_name); }
Trace_ptr Bmc_create_trace_from_cnf_model(const BeEnc_ptr be_enc, const NodeList_ptr symbols, const char* desc, const TraceType type, const Slist_ptr cnf_model, int k) { Trace_ptr trace = Trace_create(BaseEnc_get_symb_table(BASE_ENC(be_enc)), desc, type, symbols, false); return Bmc_fill_trace_from_cnf_model(be_enc, cnf_model, k, trace); }
/**Function******************************************************************** Synopsis [The BoolEncClient class private initializer] Description [The BoolEncClient class private initializer] SideEffects [] SeeAlso [BoolEncClient_create] ******************************************************************************/ void bool_enc_client_init(BoolEncClient_ptr self, SymbTable_ptr symb_table, BoolEnc_ptr bool_enc) { /* base class initialization */ base_enc_init(BASE_ENC(self), symb_table); /* members initialization */ self->bool_enc = bool_enc; /* virtual methods settings */ OVERRIDE(Object, finalize) = bool_enc_client_finalize; OVERRIDE(BaseEnc, commit_layer) = bool_enc_client_commit_layer; OVERRIDE(BaseEnc, remove_layer) = bool_enc_client_remove_layer; }
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) */
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; }
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 */ } }