Example #1
0
    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))
Example #2
0
    def test_smv_incorrect_file(self):

        car = nsnode.car
        cdr = nsnode.cdr

        f = "tests/pynusmv/models/counter-syntax-error.smv"
        nsopt.set_input_file(nsopt.OptsHandler_get_instance(), f)
        ret = nsparser.Parser_ReadSMVFromFile(f)

        # When parsing a model with parser_is_lax enabled, the parser gets
        # as many correct parts of the model as possible and build a partial
        # model with it.
        # In this example, a partial model is built, this is why the command
        # returns 0.

        self.assertEqual(ret, 0)

        errors = nsparser.Parser_get_syntax_errors_list()
        self.assertIsNotNone(errors)

        while errors is not None:
            error = car(errors)
            err = nsparser.Parser_get_syntax_error(error)
            self.assertIsNotNone(err)
            self.assertEqual(len(err), 4)

            errors = cdr(errors)
Example #3
0
def flatten_hierarchy(keep_single_enum=False):
    """
    Flatten the read model and store it in global data structures.

    :param keep_single_enum: whether or not enumerations with single values
                             should be converted into defines
    :type keep_single_enum: bool

    :raise: a :exc:`NuSMVNoReadModelError
            <pynusmv.exception.NuSMVNoReadModelError>` if no model is read yet
    :raise: a :exc:`NuSMVCannotFlattenError
            <pynusmv.exception.NuSMVCannotFlattenError>` if an error occurred
            during flattening
    :raise: a :exc:`NuSMVModelAlreadyFlattenedError
            <pynusmv.exception.NuSMVModelAlreadyFlattenedError>` if the model
            is already flattened

    .. warning:: In case of type checking errors, a message is printed at
       stderr and a :exc:`NuSMVCannotFlattenError
       <pynusmv.exception.NuSMVCannotFlattenError>` is raised.

    """

    # Check cmps
    if not nscompile.cmp_struct_get_read_model(global_compile_cmps()):
        raise NuSMVNoReadModelError("Cannot flatten; no read model.")

    if nscompile.cmp_struct_get_flatten_hrc(global_compile_cmps()):
        raise NuSMVModelAlreadyFlattenedError("Model already flattened.")

    # Update options to reflect keep_single_enum
    if keep_single_enum:
        nsopt.set_keep_single_value_vars(nsopt.OptsHandler_get_instance())
    else:
        nsopt.unset_keep_single_value_vars(nsopt.OptsHandler_get_instance())

    # Flatten hierarchy
    ret = nscompile.flatten_hierarchy()
    if ret != 0:
        raise NuSMVCannotFlattenError("Cannot flatten the model.")

    global __symb_table
    __symb_table = SymbTable(nscompile.Compile_get_global_symb_table())
Example #4
0
def is_cone_of_influence_enabled():
    """
    This function returns true iff the cone of influence (coi)  option is
    enabled.

    :return: true iff the cone of influence (coi) option is enabled
    """
    opthandler = nsopt.OptsHandler_get_instance()
    is_coi_enabled = nsopt.OptsHandler_get_bool_option_value(
        opthandler, "cone_of_influence")
    return is_coi_enabled
Example #5
0
File: mc.py Project: yyaan/pynusmv
def check_ltl_spec(spec):
    """
    Return whether the loaded SMV model satisfies or not the LTL given `spec`.
    That is, return whether all initial states of le model satisfies `spec` or
    not.

    :param spec: a specification
    :type spec: :class:`Spec <pynusmv.prop.Spec>`
    :rtype: bool

    """
    # Check that a model has been compiled
    assert(glob.prop_database().master is not None)
    
    # Create a property from the given spec
    prop = nsprop.Prop_create_partial(spec._ptr, propTypes["LTL"])
    
    # Save settings
    o = nsopt.OptsHandler_get_enum_option_value(
            nsopt.OptsHandler_get_instance(),
            "oreg_justice_emptiness_bdd_algorithm")
    if (nscompile.
            FlatHierarchy_get_compassion(glob.
                                         global_compile_flathierarchy())
            is None and
            o == nsfsmbdd.BDD_OREG_JUSTICE_EMPTINESS_BDD_ALGORITHM_EL_FWD):
        
        saved_options = nsfsmbdd.Bdd_elfwd_check_set_and_save_options(
                            nsfsmbdd.BDD_ELFWD_OPT_ALL)
    else:
        saved_options = None
    
    # Create, build and check the structure for LTL model checking
    ltl_struct = nsltl.Ltl_StructCheckLtlSpec_create(prop)
    nsltl.Ltl_StructCheckLtlSpec_build(ltl_struct)
    nsltl.Ltl_StructCheckLtlSpec_check(ltl_struct)
    
    # Get the result
    result = nsprop.Prop_get_status(prop) == nsprop.Prop_True
    
    # Destroy the intermediate structure
    nsltl.Ltl_StructCheckLtlSpec_destroy(ltl_struct)
    
    # Restore settings
    if saved_options is not None:
        nsfsmbdd.Bdd_elfwd_restore_options(nsfsmbdd.BDD_ELFWD_OPT_ALL,
                                           saved_options)
    
    # Destroy prop
    nsprop.Prop_destroy(prop)
    
    return result
Example #6
0
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 test_namecheR1(self):
        # activate bdd dynamic reordering
        nsopt.set_dynamic_reorder(nsopt.OptsHandler_get_instance())

        fsm = self.nameche_model()

        # AG (T_04BM.st = o & TRP_CM.krc = s -> AX (!R1.L_CS))
        to = prop.atom("T_04BM.st = o")
        trps = prop.atom("TRP_CM.krc = s")
        nr1lcs = prop.atom("!R1.L_CS")
        p = prop.imply(to & trps, prop.ax(nr1lcs))
        self.assertTrue(fsm.reachable_states <= eval_ctl(fsm, p))

        # AG (EF R1.L_CS)
        r1lcs = prop.atom("R1.L_CS")
        p = prop.ef(r1lcs)
        self.assertTrue(fsm.reachable_states <= eval_ctl(fsm, p))
Example #8
0
File: dd.py Project: yyaan/pynusmv
def enable_dynamic_reordering(DDmanager=None, method="sift"):
    """
    Enable dynamic reordering of BDD variables under control of `DDmanager`
    with the given `method`.

    :param DDmanager: the concerned DD manager; if None, the global DD manager
                      is used instead.
    :type DDmanager: :class:`DDManager`
    :param method: the method to use for reordering:
                   `sift (default method)`,
                   `random`,
                   `random_pivot`,
                   `sift_converge`,
                   `symmetry_sift`,
                   `symmetry_sift_converge`,
                   `window{2, 3, 4}`,
                   `window{2, 3, 4}_converge`,
                   `group_sift`,
                   `group_sift_converge`,
                   `annealing`,
                   `genetic`,
                   `exact`,
                   `linear`,
                   `linear_converge`,
                   `same` (the previously chosen method)
    :type method: :class:`str`

    :raise: a :exc:`MissingManagerError
            <pynusmv.exception.MissingManagerError>` if the manager is missing

    .. note:: For more information on reordering methods, see NuSMV manual.

    """
    if DDmanager is None:
        DDmanager_ptr = nscinit.cvar.dd_manager
    else:
        DDmanager_ptr = DDmanager._ptr
    if DDmanager_ptr is None:
        raise MissingManagerError("Missing manager")

    method = nsdd.StringConvertToDynOrderType(method)
    if method == nsdd.CUDD_REORDER_NONE:
        method = nsdd.CUDD_REORDER_SIFT
    nsopt.set_dynamic_reorder(nsopt.OptsHandler_get_instance())
    nsdd.dd_autodyn_enable(DDmanager_ptr, method)
Example #9
0
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())
Example #10
0
File: dd.py Project: yyaan/pynusmv
def disable_dynamic_reordering(DDmanager=None):
    """
    Disable dynamic reordering of BDD variables under control of `DDmanager`.

    :param DDmanager: the concerned DD manager; if None, the global DD manager
                      is used instead.
    :type DDmanager: :class:`DDManager`

    :raise: a :exc:`MissingManagerError
            <pynusmv.exception.MissingManagerError>` if the manager is missing

    """
    if DDmanager is None:
        DDmanager_ptr = nscinit.cvar.dd_manager
    else:
        DDmanager_ptr = DDmanager._ptr
    if DDmanager_ptr is None:
        raise MissingManagerError("Missing manager")
    nsopt.unset_dynamic_reorder(nsopt.OptsHandler_get_instance())
    nsdd.dd_autodyn_disable(DDmanager_ptr)
Example #11
0
def load_from_file(filepath):
    """
    Load a model from an SMV file and store it in global data structures.

    :param filepath: the path to the SMV file
    :type filepath: str

    """
    # Check file
    if not os.path.exists(filepath):
        raise IOError("File {} does not exist".format(filepath))

    # Check cmps. Need reset_nusmv if a model is already read
    if nscompile.cmp_struct_get_read_model(global_compile_cmps()):
        raise NuSMVModelAlreadyReadError("A model is already read.")

    # Set the input file
    nsopt.set_input_file(nsopt.OptsHandler_get_instance(), filepath)

    # Call the parser
    # ret = 0 => OK
    # ret = 1 => syntax error (and there are registered syntax errors)
    # ret = 2 => lexer error
    ret = nsparser.Parser_ReadSMVFromFile(filepath)
    if ret == 2:
        # ret = 2 means lexer error
        raise NuSMVLexerError("An error with NuSMV lexer occured.")

    # When parsing a model with parser_is_lax enabled (this is the case
    # since this is enabled in init_nusmv), the parser gets
    # as many correct parts of the model as possible and build a partial
    # model with it.

    # Raise exceptions if needed
    errors = nsparser.Parser_get_syntax_errors_list()
    if errors is not None:
        raise NuSMVParsingError.from_nusmv_errors_list(errors)

    # Update cmps
    nscompile.cmp_struct_set_read_model(global_compile_cmps())
Example #12
0
File: mc.py Project: yyaan/pynusmv
def check_explain_ltl_spec(spec):
    """
    Return whether the loaded SMV model satisfies or not the LTL given `spec`,
    that is, whether all initial states of le model satisfies `spec` or not.
    Return also an explanation for why the model does not satisfy `spec`,
    if it is the case, or `None` otherwise.
    
    The result is a tuple where the first element is a boolean telling whether
    `spec` is satisfied, and the second element is either `None` if the first
    element is `True`, or a path of the SMV model violating `spec` otherwise.
    
    The explanation is a tuple of alternating states and inputs, starting and
    ennding with a state. The path is looping if the last state is somewhere
    else in the sequence. States and inputs are represented by dictionaries
    where keys are state and inputs variable of the loaded SMV model, and
    values are their value.

    :param spec: a specification
    :type spec: :class:`Spec <pynusmv.prop.Spec>`
    :rtype: tuple

    """
    # Check that a model has been compiled
    assert(glob.prop_database().master is not None)
    
    # Create a property from the given spec
    prop = nsprop.Prop_create_partial(spec._ptr, propTypes["LTL"])
    
    # Save settings
    o = nsopt.OptsHandler_get_enum_option_value(
            nsopt.OptsHandler_get_instance(),
            "oreg_justice_emptiness_bdd_algorithm")
    if (nscompile.
            FlatHierarchy_get_compassion(glob.
                                         global_compile_flathierarchy())
            is None and
            o == nsfsmbdd.BDD_OREG_JUSTICE_EMPTINESS_BDD_ALGORITHM_EL_FWD):
        
        saved_options = nsfsmbdd.Bdd_elfwd_check_set_and_save_options(
                            nsfsmbdd.BDD_ELFWD_OPT_ALL)
    else:
        saved_options = None
    
    # Create, build and check the structure for LTL model checking
    ltl_struct = nsltl.Ltl_StructCheckLtlSpec_create(prop)
    nsltl.Ltl_StructCheckLtlSpec_build(ltl_struct)
    nsltl.Ltl_StructCheckLtlSpec_check(ltl_struct)
    
    # Get the result
    result = nsprop.Prop_get_status(prop) == nsprop.Prop_True
    
    # explain
    if not result:
        # Extract explanation
        bdd_fsm = BddFsm(ltl_struct.fsm)
        
        full_fairness = (not nsfsmbdd.FairnessList_is_empty(
                             nsfsmbdd.compassionList2fairnessList(
                             nsfsmbdd.BddFsm_get_compassion(bdd_fsm._ptr))))
        
        # Counterexample construction for forward Emerson-Lei not yet
        # implemented
        assert(full_fairness or not o)

        tmp = BDD(nsencbdd.BddEnc_pick_one_state(ltl_struct.bdd_enc,
                                                 ltl_struct.s0),
                  dd_manager=DDManager(nsencbdd.BddEnc_get_dd_manager(
                                       ltl_struct.bdd_enc)))
        
        if full_fairness:
            exp = BDDList(nsltl.witness(bdd_fsm._ptr,
                                        ltl_struct.bdd_enc,
                                        tmp._ptr),
                          ddmanager=tmp._manager)
        else:
            path = nsnode.cons(nsnode.bdd2node(nsdd.bdd_dup(tmp._ptr)), None)
            exp = BDDList(nsnode.reverse(
                          nsmc.explain(bdd_fsm._ptr,
                                       ltl_struct.bdd_enc,
                                       path,
                                       ltl_struct.spec_formula,
                                       None)),
                          ddmanager=tmp._manager)
        
        if exp is None: # The counterexample consists of one initial state
            exp = BDDList(nsnode.cons(nsnode.bdd2node(nsdd.bdd_dup(tmp._ptr)),
                                      None),
                          ddmanager=tmp._manager)
        exp = exp.to_tuple()

        # removes all the tableau variables from the result before
        # building the resulting trace. This will make simulation
        # working, but may show unexistent loops in the shown trace
        def clean(bdd):
            tableau_cube = Cube(nsencbdd.BddEnc_get_layer_vars_cube(
                                    ltl_struct.bdd_enc,
                                    ltl_struct.tableau_layer,
                                    nssymb_table.VFT_ALL),
                                dd_manager=bdd._manager)
            return bdd.forsome(tableau_cube)
        
        # exp has at least one element
        explanation = [bdd_fsm.pick_one_state(clean(exp[0])).get_str_values()]
        for inputs_bdd, state_bdd in zip(exp[1::2], exp[2::2]):
            explanation.append(bdd_fsm.pick_one_inputs(
                               clean(inputs_bdd))
                               .get_str_values())
            explanation.append(bdd_fsm.pick_one_state(
                               clean(state_bdd))
                               .get_str_values())
    else:
        explanation = None
    
    # Destroy the intermediate structure
    nsltl.Ltl_StructCheckLtlSpec_destroy(ltl_struct)
    
    # Restore settings
    if saved_options is not None:
        nsfsmbdd.Bdd_elfwd_restore_options(nsfsmbdd.BDD_ELFWD_OPT_ALL,
                                           saved_options)
    
    # Destroy prop
    nsprop.Prop_destroy(prop)
    
    return (result, explanation if explanation is None else tuple(explanation))