def check_ltl_incrementally( ltl_prop, bound=10, loop=utils.all_loopbacks(), one_problem=False, ): """ Performs the same end to end LTL property verification as `check_ltl` but generates the problem /incrementally/ instead of doing it all at once. Concretely, this means that it does not compute the complete unrolling of the transition relation :math:`[[M]]_{k}` up front but computes each unrolling step separately and adds it to a group of the incremental sat solver. The bounded semantics conversion of `ltl_prop` is done the exact same way as in `check_ltl`. So the real gain of calling this function resides in the avoidance of the regeneration of the formula representing the unrolled transition relation for lengths < bound. (and thus in the reduction of the size of the generated formula that needs to be solved). :param ltl_prop: the LTL property to be verified. This should be an instance of Prop similar to what you obtain querying PropDb (:func:`pynusmv.glob.prop_database()`) :param bound: the bound of the problem, that is to say the maximum number of times the problem will be unrolled. This parameter corresponds to the value `k` used in the formal definitions of a bmc problem. :param loop: a loop definition. This is an integer value corresponding to the moment in time where the loop might be starting (the parameter `l` in the formal definitions). However, this value is not as 'crude' as an absolute moment in time since it may indicate: - an absolute moment in time (obviously) when the value is positive - indicate a relative moment in time (when it is a negative number (for instance value -2 indicates that the loops are supposed to start 2 states ago) - that NO loop at all must be considered (ignore infinite behaviors) when this parameter takes the special value defined in :func:`pynusmv.bmc.utils.no_loopback()` - that ALL possible loops in the model must be taken into account when this parameter takes the special value defined in :func:`pynusmv.bmc.utils.all_loopback()` (this is the default) :param one_problem: a flag indicating whether the problem should be verified for all possible execution lengths UP TO `bound` or if it should be evaluated only for executions that have the exact length `bound`. By default this flag is OFF and all problem lengths up to `bound` are verified. :raises NuSmvSatSolverError: when the verification could not be performed because of a problem related to the sat solver (solver could not be created) :raises ValueError: when the bound is infeasible (negative value) or when the loop and bound values are inconsistent (loop is greater than the bound but none of the special values described above) """ utils.check_consistency(bound, loop) result = _bmc.Bmc_GenSolveLtlInc(ltl_prop._ptr, bound, loop, not one_problem) if result == 1: raise NuSmvSatSolverError("The sat solver could not be created")
def check_ltl_incrementally(ltl_prop, bound=10, loop=utils.all_loopbacks(), one_problem=False, ): """ Performs the same end to end LTL property verification as `check_ltl` but generates the problem /incrementally/ instead of doing it all at once. Concretely, this means that it does not compute the complete unrolling of the transition relation [[M]]_{k} up front but computes each unrolling step separately and adds it to a group of the incremental sat solver. The bounded semantics conversion of `ltl_prop` is done the exact same way as in `check_ltl`. So the real gain of calling this function resides in the avoidance of the regeneration of the formula representing the unrolled transition relation for lengths < bound. (and thus in the reduction of the size of the generated formula that needs to be solved). :param ltl_prop: the LTL property to be verified. This should be an instance of Prop similar to what you obtain querying PropDb (:see:`pynusmv.glob.prop_database())s :param bound: the bound of the problem, that is to say the maximum number of times the problem will be unrolled. This parameter corresponds to the value `k` used in the formal definitions of a bmc problem. :param loop: a loop definition. This is an integer value corresponding to the moment in time where the loop might be starting (the parameter `l` in the formal definitions). However, this value is not as 'crude' as an absolute moment in time since it may indicate:: - an absolute moment in time (obviously) when the value is positive - indicate a relative moment in time (when it is a negative number (for instance value -2 indicates that the loops are supposed to start 2 states ago) - that NO loop at all must be considered (ignore infinite behaviors) when this parameter takes the special value defined in :see:`pynusmv.bmc.utils.no_loopback()` - that ALL possible loops in the model must be taken into account when this parameter takes the special value defined in :see:`pynusmv.bmc.utils.all_loopback()` (this is the default) :param one_problem: a flag indicating whether the problem should be verified for all possible execution lengths UP TO `bound` or if it should be evaluated only for executions that have the exact length `bound`. By default this flag is OFF and all problem lengths up to `bound` are verified. :raises NuSmvSatSolverError: when the verification could not be performed because of a problem related to the sat solver (solver could not be created) :raises ValueError: when the bound is infeasible (negative value) or when the loop and bound values are inconsistent (loop is greater than the bound but none of the special values described above) """ utils.check_consistency(bound, loop) result = _bmc.Bmc_GenSolveLtlInc(ltl_prop._ptr,bound, loop, not one_problem) if result == 1: raise NuSmvSatSolverError("The sat solver could not be created")
def bounded_semantics_all_loops(fsm, prop_node, bound, loop, optimized=True): """ Generates a Be expression corresponding to the bounded semantics of the given LTL formula in the case where the formula is evaluated against a path that contains a loop at any of the positions in the range [loop; bound] In the literature, the resulting formula would be denoted as .. math:: \\bigvee_{j=l}^{k} {}_{j}L_{k} \\wedge {}_{j}[[f]]_{k}^{0} where l is used to denote `loop`, f for `prop_node` and k for the `bound`. .. note:: Fairness is taken into account in the generation of the resulting expression :param fsm: the fsm against which the formula will be evaluated. It is not directly relevant to the generation of the formula for `prop_node` but is used to determine to generate fairness constraints for this model which are combined with `prop_node` constraint. :param prop_node: the property for which to generate a verification problem represented in a 'node' format (subclass of :class:`pynusmv.node.Node`) which corresponds to the format obtained from the ast.(remark: if you need to manipulate [ie negate] the formula before passing it, it is perfectly valid to pass a node decorated by `Wff.decorate`). :param bound: the bound of the problem, that is to say the maximum number of times the problem will be unrolled. This parameter corresponds to the value `k` used in the formal definitions of a bmc problem. :param optimized: a flag indicating whether or not the use of the optimisation for formulas of depth 1 is desired. :return: a boolean expression corresponding to the bounded semantics of `prop_node` in the case where there is may be a loop anywhere on the path between the positions `loop` and `bound` :raises ValueError: when the bound is infeasible (negative value) or when the loop and bound values are inconsistent (loop is greater than the bound but none of the special values described above) """ utils.check_consistency(bound, loop) ltl_wff = utils.make_nnf_boolean_wff(prop_node) if optimized and ltl_wff.depth == 1 and len(fsm.fairness_list) == 0: return bounded_semantics_all_loops_optimisation_depth1( fsm, prop_node, bound) else: be_ptr = _bmc.Bmc_Tableau_GetAllLoops(fsm._ptr, ltl_wff._ptr, bound, loop) return Be(be_ptr, fsm.encoding.manager)
def generate_ltl_problem(fsm, prop_node, bound=10, loop=utils.all_loopbacks()): """ Generates a (non-incremental) Be expression corresponding to the SAT problem denoted by :math:`[[fsm, prop\\_node]]_{bound}^{loop}` That is to say it generates the problem that combines both the formula and and the model to perform the verification. Put another way, this problem can be read as: .. math:: [[fsm]]_{bound} \\wedge \\neg ( (\\neg L_k \\wedge [[ \\neg prop\\_node]]_{k}) \\vee {}_{l}[[ \\neg prop\\_node]]_{k}^{l} ) :param fsm: the BeFsm object that represents the model against which the property will be verified. (if in doubt, it can be obtained via :func:`pynusmv.bmc.glob.master_be_fsm()` ) :param prop_node: the property for which to generate a verification problem represented in a 'node' format (subclass of :class:`pynusmv.node.Node`) which corresponds to the format obtained from the ast. (remark: if you need to manipulate [ie negate] the formula before passing it, it is perfectly valid to pass a node decorated by `Wff.decorate`). :param bound: the bound of the problem, that is to say the maximum number of times the problem will be unrolled. This parameter corresponds to the value `k` used in the formal definitions of a bmc problem. :param loop: a loop definition. This is an integer value corresponding to the moment in time where the loop might be starting (the parameter `l` in the formal definitions). However, this value is not as 'crude' as an absolute moment in time since it may indicate: - an absolute moment in time (obviously) when the value is positive - indicate a relative moment in time (when it is a negative number (for instance value -2 indicates that the loops are supposed to start 2 states ago) - that NO loop at all must be considered (ignore infinite behaviors) when this parameter takes the special value defined in :func:`pynusmv.bmc.utils.no_loopback()` - that ALL possible loops in the model must be taken into account when this parameter takes the special value defined in :func:`pynusmv.bmc.utils.all_loopback()` (this is the default) :return: a Be boolean expression representing the satisfiability problem of for the verification of this property. :raises ValueError: when the bound is infeasible (negative value) or when the loop and bound values are inconsistent (loop is greater than the bound but none of the special values described above) """ utils.check_consistency(bound, loop) ltl_wff = utils.make_negated_nnf_boolean_wff(prop_node) be_ptr = _bmc.Bmc_Gen_LtlProblem(fsm._ptr, ltl_wff._ptr, bound, loop) return Be(be_ptr, fsm.encoding.manager)
def bounded_semantics_all_loops(fsm, prop_node, bound, loop, optimized=True): """ Generates a Be expression corresponding to the bounded semantics of the given LTL formula in the case where the formula is evaluated against a path that contains a loop at any of the positions in the range [loop; bound] In the literature, the resulting formula would be denoted as .. math:: \bigvee_{j=l}^{k} _{j}L_{k} \wedge _{j}[[f]]_{k}^{0} where l is used to denote `loop`, f for `prop_node` and k for the `bound`. .. note:: Fairness is taken into account in the generation of the resulting expression :param fsm: the fsm against which the formula will be evaluated. It is not directly relevant to the generation of the formula for `prop_node` but is used to determine to generate fairness constraints for this model which are combined with `prop_node` constraint. :param prop_node: the property for which to generate a verification problem represented in a 'node' format (subclass of :see::class:`pynusmv.node.Node`) which corresponds to the format obtained from the ast.(remark: if you need to manipulate [ie negate] the formula before passing it, it is perfectly valid to pass a node decorated by `Wff.decorate`). :param bound: the bound of the problem, that is to say the maximum number of times the problem will be unrolled. This parameter corresponds to the value `k` used in the formal definitions of a bmc problem. :param optimized: a flag indicating whether or not the use of the optimisation for formulas of depth 1 is desired. :return: a boolean expression corresponding to the bounded semantics of `prop_node` in the case where there is may be a loop anywhere on the path between the positions `loop` and `bound` :raises ValueError: when the bound is infeasible (negative value) or when the loop and bound values are inconsistent (loop is greater than the bound but none of the special values described above) """ utils.check_consistency(bound, loop) ltl_wff= utils.make_nnf_boolean_wff(prop_node) if optimized and ltl_wff.depth == 1 and len(fsm.fairness_list) == 0: return bounded_semantics_all_loops_optimisation_depth1(fsm, prop_node, bound) else: be_ptr = _bmc.Bmc_Tableau_GetAllLoops(fsm._ptr, ltl_wff._ptr, bound, loop) return Be(be_ptr, fsm.encoding.manager)
def generate_ltl_problem(fsm, prop_node, bound=10, loop=utils.all_loopbacks()): """ Generates a (non-incremental) Be expression corresponding to the SAT problem denoted by [[fsm, prop_node]]_{bound}^{loop} That is to say it generates the problem that combines both the formula and and the model to perform the verification. Put another way, this problem can be read as:: [[fsm]]_{bound} & ! ( (!Lk & [[ ! prop_node]]_{k}) | _{l}[[ ! prop_node]]_{k}^{l} ) :param fsm: the BeFsm object that represents the model against which the property will be verified. (if in doubt, it can be obtained via :see:`pynusmv.bmc.glob.master_be_fsm()` ) :param prop_node: the property for which to generate a verification problem represented in a 'node' format (subclass of :see::class:`pynusmv.node.Node`) which corresponds to the format obtained from the ast. (remark: if you need to manipulate [ie negate] the formula before passing it, it is perfectly valid to pass a node decorated by `Wff.decorate`). :param bound: the bound of the problem, that is to say the maximum number of times the problem will be unrolled. This parameter corresponds to the value `k` used in the formal definitions of a bmc problem. :param loop: a loop definition. This is an integer value corresponding to the moment in time where the loop might be starting (the parameter `l` in the formal definitions). However, this value is not as 'crude' as an absolute moment in time since it may indicate:: - an absolute moment in time (obviously) when the value is positive - indicate a relative moment in time (when it is a negative number (for instance value -2 indicates that the loops are supposed to start 2 states ago) - that NO loop at all must be considered (ignore infinite behaviors) when this parameter takes the special value defined in :see:`pynusmv.bmc.utils.no_loopback()` - that ALL possible loops in the model must be taken into account when this parameter takes the special value defined in :see:`pynusmv.bmc.utils.all_loopback()` (this is the default) :return: a Be boolean expression representing the satisfiability problem of for the verification of this property. :raises ValueError: when the bound is infeasible (negative value) or when the loop and bound values are inconsistent (loop is greater than the bound but none of the special values described above) """ utils.check_consistency(bound, loop) ltl_wff = utils.make_negated_nnf_boolean_wff(prop_node) be_ptr = _bmc.Bmc_Gen_LtlProblem(fsm._ptr, ltl_wff._ptr, bound, loop) return Be(be_ptr, fsm.encoding.manager)
def bounded_semantics_single_loop(fsm, prop_node, bound, loop): """ Generates a Be expression corresponding to the bounded semantics of the given LTL formula in the case where the formula is evaluated against a path that contains one single loop starting at position `loop`. In the literature, the resulting formula would be denoted as .. math:: _{l}L_{k} \wedge _{l}[[f]]_{k}^{0} where l is used to denote `loop`, f for `prop_node` and k for the `bound`. In other words, the generated boolean expression is the conjunction of the constraint imposing that there be a k-l loop from `bound` to `loop` and that the formula is evaluated at time 0 out of `bound`. .. note:: Fairness is taken into account in the generation of the resulting expression :param fsm: the fsm against which the formula will be evaluated. It is not directly relevant to the generation of the formula for `prop_node` but is used to determine to generate fairness constraints for this model which are combined with `prop_node` constraint. :param prop_node: the property for which to generate a verification problem represented in a 'node' format (subclass of :see::class:`pynusmv.node.Node`) which corresponds to the format obtained from the ast.(remark: if you need to manipulate [ie negate] the formula before passing it, it is perfectly valid to pass a node decorated by `Wff.decorate`). :param bound: the bound of the problem, that is to say the maximum number of times the problem will be unrolled. This parameter corresponds to the value `k` used in the formal definitions of a bmc problem. :return: a boolean expression corresponding to the bounded semantics of `prop_node` in the case where there is a loop from bound to loop :raises ValueError: when the bound is infeasible (negative value) or when the loop and bound values are inconsistent (loop is greater than the bound but none of the special values described above) """ utils.check_consistency(bound, loop) ltl_wff= utils.make_nnf_boolean_wff(prop_node) be_ptr = _bmc.Bmc_Tableau_GetSingleLoop(fsm._ptr, ltl_wff._ptr, bound, loop) return Be(be_ptr, fsm.encoding.manager)
def bounded_semantics_single_loop(fsm, prop_node, bound, loop): """ Generates a Be expression corresponding to the bounded semantics of the given LTL formula in the case where the formula is evaluated against a path that contains one single loop starting at position `loop`. In the literature, the resulting formula would be denoted as :math:`{}_{l}L_{k} \\wedge {}_{l}[[f]]_{k}^{0}` where l is used to denote `loop`, f for `prop_node` and k for the `bound`. In other words, the generated boolean expression is the conjunction of the constraint imposing that there be a k-l loop from `bound` to `loop` and that the formula is evaluated at time 0 out of `bound`. .. note:: Fairness is taken into account in the generation of the resulting expression :param fsm: the fsm against which the formula will be evaluated. It is not directly relevant to the generation of the formula for `prop_node` but is used to determine to generate fairness constraints for this model which are combined with `prop_node` constraint. :param prop_node: the property for which to generate a verification problem represented in a 'node' format (subclass of :class:`pynusmv.node.Node`) which corresponds to the format obtained from the ast.(remark: if you need to manipulate [ie negate] the formula before passing it, it is perfectly valid to pass a node decorated by `Wff.decorate`). :param bound: the bound of the problem, that is to say the maximum number of times the problem will be unrolled. This parameter corresponds to the value `k` used in the formal definitions of a bmc problem. :return: a boolean expression corresponding to the bounded semantics of `prop_node` in the case where there is a loop from bound to loop :raises ValueError: when the bound is infeasible (negative value) or when the loop and bound values are inconsistent (loop is greater than the bound but none of the special values described above) """ utils.check_consistency(bound, loop) ltl_wff = utils.make_nnf_boolean_wff(prop_node) be_ptr = _bmc.Bmc_Tableau_GetSingleLoop(fsm._ptr, ltl_wff._ptr, bound, loop) return Be(be_ptr, fsm.encoding.manager)
def test_check_consistency(self): # when the bound is not meaningful with self.assertRaises(ValueError): bmcutils.check_consistency(-1, 2) # when the loop is greater than the bound with self.assertRaises(ValueError): bmcutils.check_consistency(1, 2) # unless it is a special value bmcutils.check_consistency(4, bmcutils.all_loopbacks()) bmcutils.check_consistency(4, bmcutils.no_loopback())
def check_ltl(ltl_prop, bound=10, loop=utils.all_loopbacks(), one_problem=False, solve=True, dump_type=utils.DumpType.NONE, fname_template=None): """ High level function that performs the verification of an LTL property (LTLSPEC property as obtained from the :class:`pynusmv.prop.PropDb`). This function performs an end to end verification of the given LTL property and prints the outcome (satisfaction or violation result) to standard output Formally, it tries to determine if the problem [[M,f]]_{k} is satisfiable. This problem is generated as [[M]]_{k} & ! ( (!Lk & [[ltl_prop]]_{k}) | _{l}[[ltl_prop]]_{k}^{l} ) :param ltl_prop: the LTL property to be verified. This should be an instance of Prop similar to what you obtain querying PropDb (:see:`pynusmv.glob.prop_database())s :param bound: the bound of the problem, that is to say the maximum number of times the problem will be unrolled. This parameter corresponds to the value `k` used in the formal definitions of a bmc problem. :param loop: a loop definition. This is an integer value corresponding to the moment in time where the loop might be starting (the parameter `l` in the formal definitions). However, this value is not as 'crude' as an absolute moment in time since it may indicate:: - an absolute moment in time (obviously) when the value is positive - indicate a relative moment in time (when it is a negative number (for instance value -2 indicates that the loops are supposed to start 2 states ago) - that NO loop at all must be considered (ignore infinite behaviors) when this parameter takes the special value defined in :see:`pynusmv.bmc.utils.no_loopback()` - that ALL possible loops in the model must be taken into account when this parameter takes the special value defined in :see:`pynusmv.bmc.utils.all_loopback()` (this is the default) :param one_problem: a flag indicating whether the problem should be verified for all possible execution lengths UP TO `bound` or if it should be evaluated only for executions that have the exact length `bound`. By default this flag is OFF and all problem lengths up to `bound` are verified. :param solve: a flag indicating whether or not the verification should actually be performed. (when this flag is turned off, no sat solver is not used to perform the bmc verification and the function can serve to simply dump the ltl problem to files). :param dump_type: the format in which to perform a dump of the generated sat problem (ie dimacs). By default, this parameter takes the value :see:`pynusmv.bmc.utils.DumpType.NONE` which means that the problem is not dumped to file. Should you want to change this behavior, then this parameter is used to specify a file format in conjunction with `fname_template` which is used to specify the name of the location where the file will be output. :param fname_template: the file name template of the location where to output the dump file. :raises NuSmvSatSolverError: when the verification could not be performed because of a problem related to the sat solver (solver could not be created) :raises ValueError: when the bound is infeasible (negative value) or when the loop and bound values are inconsistent (loop is greater than the bound but none of the special values described above) """ utils.check_consistency(bound, loop) if dump_type is not utils.DumpType.NONE and fname_template is None: raise ValueError("a filename must be specified when dump_type is set") if fname_template is not None and dump_type is utils.DumpType.NONE: raise ValueError("a filename is specified but dump_type is not set") result = _bmc.Bmc_GenSolveLtl(ltl_prop._ptr, bound, loop, not one_problem, solve, dump_type, fname_template) if result == 1: raise NuSmvSatSolverError("The sat solver could not be created")
def check_ltl(ltl_prop, bound=10, loop=utils.all_loopbacks(), one_problem=False, solve=True, dump_type=utils.DumpType.NONE, fname_template=None): """ High level function that performs the verification of an LTL property (LTLSPEC property as obtained from the :class:`pynusmv.prop.PropDb`). This function performs an end to end verification of the given LTL property and prints the outcome (satisfaction or violation result) to standard output Formally, it tries to determine if the problem :math:`[[M,f]]_{k}` is satisfiable. This problem is generated as .. math:: [[M]]_{k} \\wedge \\neg ( (\\neg L_{k} \\wedge [[ltl\\_prop]]_{k}) \\vee {}_{l}[[ltl\\_prop]]_{k}^{l} ) :param ltl_prop: the LTL property to be verified. This should be an instance of Prop similar to what you obtain querying PropDb (:func:`pynusmv.glob.prop_database()`) :param bound: the bound of the problem, that is to say the maximum number of times the problem will be unrolled. This parameter corresponds to the value `k` used in the formal definitions of a bmc problem. :param loop: a loop definition. This is an integer value corresponding to the moment in time where the loop might be starting (the parameter `l` in the formal definitions). However, this value is not as 'crude' as an absolute moment in time since it may indicate: - an absolute moment in time (obviously) when the value is positive - indicate a relative moment in time (when it is a negative number (for instance value -2 indicates that the loops are supposed to start 2 states ago) - that NO loop at all must be considered (ignore infinite behaviors) when this parameter takes the special value defined in :func:`pynusmv.bmc.utils.no_loopback()` - that ALL possible loops in the model must be taken into account when this parameter takes the special value defined in :func:`pynusmv.bmc.utils.all_loopback()` (this is the default) :param one_problem: a flag indicating whether the problem should be verified for all possible execution lengths UP TO `bound` or if it should be evaluated only for executions that have the exact length `bound`. By default this flag is OFF and all problem lengths up to `bound` are verified. :param solve: a flag indicating whether or not the verification should actually be performed. (when this flag is turned off, no sat solver is not used to perform the bmc verification and the function can serve to simply dump the ltl problem to files). :param dump_type: the format in which to perform a dump of the generated sat problem (ie dimacs). By default, this parameter takes the value :data:`pynusmv.bmc.utils.DumpType.NONE` which means that the problem is not dumped to file. Should you want to change this behavior, then this parameter is used to specify a file format in conjunction with `fname_template` which is used to specify the name of the location where the file will be output. :param fname_template: the file name template of the location where to output the dump file. :raises NuSmvSatSolverError: when the verification could not be performed because of a problem related to the sat solver (solver could not be created) :raises ValueError: when the bound is infeasible (negative value) or when the loop and bound values are inconsistent (loop is greater than the bound but none of the special values described above) """ utils.check_consistency(bound, loop) if dump_type is not utils.DumpType.NONE and fname_template is None: raise ValueError("a filename must be specified when dump_type is set") if fname_template is not None and dump_type is utils.DumpType.NONE: raise ValueError("a filename is specified but dump_type is not set") result = _bmc.Bmc_GenSolveLtl(ltl_prop._ptr, bound, loop, not one_problem, solve, dump_type, fname_template) if result == 1: raise NuSmvSatSolverError("The sat solver could not be created")