def encode_variables_for_layers(layers=None, init=False): """ Encode the BDD variables of the given layers and store them in global data structures. :param layers: the set of layers variables to encode :type layers: :class:`set` :param bool init: whether or not initialize the global encodings .. warning: Global encodings should be initialized only once, otherwise, NuSMV quits unexpectingly. Note that :func:`encode_variables` initializes them, and should be called before any call to this function. """ if init: nsenc.Enc_init_bool_encoding() # See to understand why setting a default set value is not a good idea # http://pylint-messages.wikidot.com/messages:w0102 layers = layers or {"model"} bool_enc = nsenc.Enc_get_bool_encoding() base_enc = nsboolenc.boolenc2baseenc(bool_enc) for layer in layers: nsbaseenc.BaseEnc_commit_layer(base_enc, layer) if init: nsenc.Enc_init_bdd_encoding() bdd_enc = nsenc.Enc_get_bdd_encoding() base_enc = nsbddenc.bddenc2baseenc(bdd_enc) for layer in layers: nsbaseenc.BaseEnc_commit_layer(base_enc, layer)
def test_create_trans_counters_assign(self): fsm = self.model("tests/pynusmv/models/counters-assign.smv") c1c0bdd = evalSexp(fsm, "c1.c = 0") c2c0bdd = evalSexp(fsm, "c2.c = 0") c1c1bdd = evalSexp(fsm, "c1.c = 1") c2c1bdd = evalSexp(fsm, "c2.c = 1") self.assertEqual(c1c0bdd & c2c0bdd, fsm.init) self.assertEqual(c1c0bdd & c2c1bdd | c1c1bdd & c2c0bdd, fsm.post(fsm.init)) fsmbuilder = nscompile.Compile_get_global_fsm_builder() enc = nsenc.Enc_get_bdd_encoding() ddmanager = nsbddenc.BddEnc_get_dd_manager(enc) base_enc = nsbddenc.bddenc2baseenc(enc) symb_table = nsbaseenc.BaseEnc_get_symb_table(base_enc) propDb = glob.prop_database() master = propDb.master sexpfsm_ptr = nsprop.Prop_get_scalar_sexp_fsm(master._ptr) # Create a new expr trans c2c = self.get_variable_from_string(sexpfsm_ptr, "c2.c") self.assertIsNotNone(c2c) # trans = next(c2c) = (c2.c + 1) % 4 nextc2c = nssexp.Expr_next(c2c, symb_table) one = nsnode.create_node(parser.NUMBER, None, None) one.left.nodetype = nsnode.int2node(1) self.assertEqual(nsnode.sprint_node(one), "1") four = nsnode.create_node(parser.NUMBER, None, None) four.left.nodetype = nsnode.int2node(4) self.assertEqual(nsnode.sprint_node(four), "4") c2cp1 = nssexp.Expr_plus(c2c, one) c2cp1m4 = nssexp.Expr_mod(c2cp1, four) trans = nssexp.Expr_equal(nextc2c, c2cp1m4, symb_table) clusters = nsfsm.FsmBuilder_clusterize_expr(fsmbuilder, enc, trans) cluster_options = nsbddtrans.ClusterOptions_create( nsopt.OptsHandler_get_instance()) bddTrans = BddTrans( nsbddtrans.BddTrans_create( ddmanager, clusters, nsbddenc.BddEnc_get_state_vars_cube(enc), nsbddenc.BddEnc_get_input_vars_cube(enc), nsbddenc.BddEnc_get_next_state_vars_cube(enc), nsopt.get_partition_method(nsopt.OptsHandler_get_instance()), cluster_options)) fsm.trans = bddTrans self.assertEqual(c1c0bdd & c2c0bdd, fsm.init) self.assertEqual(c2c1bdd, fsm.post(fsm.init))
def build_model(): """ Build the BDD FSM of the current model and store it in global data structures. :raise: a :exc:`NuSMVNeedFlatModelError <pynusmv.exception.NuSMVNeedFlatModelError>` if the Sexp FSM of the model is not built yet :raise: a :exc:`NuSMVNeedVariablesEncodedError <pynusmv.exception.NuSMVNeedVariablesEncodedError>` if the variables of the model are not encoded yet :raise: a :exc:`NuSMVModelAlreadyBuiltError <pynusmv.exception.NuSMVModelAlreadyBuiltError>` if the BDD FSM of the model is already built """ # Check cmps if not nscompile.cmp_struct_get_build_flat_model(global_compile_cmps()): raise NuSMVNeedFlatModelError("Need flat model.") if not nscompile.cmp_struct_get_encode_variables(global_compile_cmps()): raise NuSMVNeedVariablesEncodedError("Need variables encoded.") if nscompile.cmp_struct_get_build_model(global_compile_cmps()): raise NuSMVModelAlreadyBuiltError("The model is already built.") # Build the model pd = nsprop.PropPkg_get_prop_database() sexp_fsm = nsprop.PropDb_master_get_scalar_sexp_fsm(pd) bdd_fsm = nsfsm.FsmBuilder_create_bdd_fsm( nscompile.Compile_get_global_fsm_builder(), nsenc.Enc_get_bdd_encoding(), sexp_fsm, nsopt.get_partition_method(nsopt.OptsHandler_get_instance())) nsprop.PropDb_master_set_bdd_fsm(pd, bdd_fsm) # Register executors enc = nsbddfsm.BddFsm_get_bdd_encoding(bdd_fsm) nstrace.TraceManager_register_complete_trace_executor( nstrace.TracePkg_get_global_trace_manager(), "bdd", "BDD partial trace execution", nstraceexec.bddCompleteTraceExecutor2completeTraceExecutor( nstraceexec.BDDCompleteTraceExecutor_create(bdd_fsm, enc))) nstrace.TraceManager_register_partial_trace_executor( nstrace.TracePkg_get_global_trace_manager(), "bdd", "BDD complete trace execution", nstraceexec.bddPartialTraceExecutor2partialTraceExecutor( nstraceexec.BDDPartialTraceExecutor_create(bdd_fsm, enc))) # Update cmps nscompile.cmp_struct_set_build_model(global_compile_cmps())
def bdd_encoding(): """ Return the main bdd encoding of the current model. :rtype: :class:`BddEnc <pynusmv.dd.BddEnc>` """ # Encode variables if needed global __bdd_encoding if __bdd_encoding is None: if nscompile.cmp_struct_get_encode_variables(global_compile_cmps()): __bdd_encoding = BddEnc(nsenc.Enc_get_bdd_encoding()) else: encode_variables() return __bdd_encoding
def encode_variables(layers=None, variables_ordering=None): """ Encode the BDD variables of the current model and store it in global data structures. If variables_ordering is provided, use this ordering to encode the variables; otherwise, the default ordering method is used. :param layers: the set of layers variables to encode :type layers: :class:`set` :param variables_ordering: the file containing a custom ordering :type variables_ordering: path to file :raise: a :exc:`NuSMVNeedFlatHierarchyError <pynusmv.exception.NuSMVNeedFlatHierarchyError>` if the model is not flattened :raise: a :exc:`NuSMVModelAlreadyEncodedError <pynusmv.exception.NuSMVModelAlreadyEncodedError>` if the variables are already encoded """ # Check cmps if not nscompile.cmp_struct_get_flatten_hrc(global_compile_cmps()): raise NuSMVNeedFlatHierarchyError("Need flat hierarchy.") if nscompile.cmp_struct_get_encode_variables(global_compile_cmps()): raise NuSMVModelAlreadyEncodedError( "The variables are already encoded.") # See to understand why setting a default set value is not a good idea # http://pylint-messages.wikidot.com/messages:w0102 layers = layers or {"model"} if variables_ordering is not None: nsopt.set_input_order_file(nsopt.OptsHandler_get_instance(), variables_ordering) encode_variables_for_layers(layers, init=True) # Update cmps nscompile.cmp_struct_set_encode_variables(global_compile_cmps()) # Get global encoding global __bdd_encoding __bdd_encoding = BddEnc(nsenc.Enc_get_bdd_encoding())
def build_boolean_model(force=False): """ Compiles the flattened hierarchy into a boolean model (SEXP) and stores it it a global variable. .. note:: This function is subject to the following requirements: - hierarchy must already be flattened (:func:`flatten_hierarchy`) - encoding must be already built (:func:`encode_variables`) - boolean model must not exist yet (or the force flag must be on) :param force: a flag telling whether or not the boolean model must be built even though the cone of influence option is turned on. :raises NuSMVNeedFlatHierarchyError: if the hierarchy wasn't flattened yet. :raises NuSMVNeedVariablesEncodedError: if the variables are not yet encoded :raises NuSMVModelAlreadyBuiltError: if the boolean model is already built and force=False """ global __bool_sexp_fsm # check the preconditions if not nscompile.cmp_struct_get_encode_variables(global_compile_cmps()): raise NuSMVNeedVariablesEncodedError("Need variables encoded.") if nscompile.cmp_struct_get_build_bool_model( global_compile_cmps()) and not force: raise NuSMVModelAlreadyBuiltError( "The boolean model is already built and the force flag is off") # create the flat model if need be. if not nscompile.cmp_struct_get_build_flat_model(global_compile_cmps()): build_flat_model() # Create the boolean model proper (CompileCmd.c/compile_create_boolean_model) propdb = nsprop.PropPkg_get_prop_database() bool_sexp_fsm = nsprop.PropDb_master_get_bool_sexp_fsm(propdb) # even though the force flag is on, a call to this method will have no effect # if the bool sexp_fsm already exists in the propdb (reproduces the behavior # of CompileCmd.c/compile_create_boolean_model() ) if bool_sexp_fsm is None: benc = __bdd_encoding symb = benc.symbTable mgr = benc.DDmanager # Temporarily disable reordering (if needed) reord = nsdd.wrap_dd_reordering_status(mgr._ptr) if reord.status == 1: nsdd.dd_autodyn_disable(mgr._ptr) # add 'determ' to the default and Artifact classes determ = symb.create_layer("determ", nssymb_table.SYMB_LAYER_POS_BOTTOM) nssymb_table.SymbTable_layer_add_to_class(symb._ptr, "determ", None) nssymb_table.SymbTable_layer_add_to_class(symb._ptr, "determ", "Artifacts Class") # THIS IS THE REAL CREATION !! scalar_sexp_fsm = nsprop.PropDb_master_get_scalar_sexp_fsm(propdb) bool_sexp_fsm = nssexp.BoolSexpFsm_create_from_scalar_fsm( scalar_sexp_fsm, benc._ptr, determ) __bool_sexp_fsm = BoolSexpFsm(bool_sexp_fsm, freeit=False) nsprop.PropDb_master_set_bool_sexp_fsm(propdb, bool_sexp_fsm) # unfortunately, if the C malloc fails, the C assertion will also fail # and result in a program crash. boolenc = nsboolenc.boolenc2baseenc(nsenc.Enc_get_bool_encoding()) nsbaseenc.BaseEnc_commit_layer(boolenc, "determ") bddenc = nsbddenc.bddenc2baseenc(nsenc.Enc_get_bdd_encoding()) nsbaseenc.BaseEnc_commit_layer(bddenc, "determ") # Re-enable reordering if it had been disabled if reord.status == 1: nsdd.dd_autodyn_enable(mgr._ptr, reord.method) # Tell NuSMV that the boolean model was built nscompile.cmp_struct_set_build_bool_model(global_compile_cmps())