def test_verify_exactly(self):
     theta = Node.from_ptr(parse_simple_expression("TRUE"))
     theta = bmcutils.make_nnf_boolean_wff(theta)
     
     sigma_12= Node.from_ptr(parse_ltl_spec("TRUE"))
     sigma_12= bmcutils.make_nnf_boolean_wff(sigma_12).to_node()
     
     obs_names = ["mouse"]
     obs_vars  = diagnosability.mk_observable_vars(obs_names)
     f1 = Node.from_ptr(parse_simple_expression("status = active"))
     f2 = Node.from_ptr(parse_simple_expression("status = inactive"))
     
     for i in range(5):
         res = diagnosability.verify_for_size_exactly_k(obs_names, obs_vars, (f1, f2), i, theta, sigma_12, sigma_12)
         self.assertEqual("No Violation", res)
     
     f1 = Node.from_ptr(parse_simple_expression("status = active"))
     f2 = Node.from_ptr(parse_simple_expression("status = highlight"))
     
     res = diagnosability.verify_for_size_exactly_k(obs_names, obs_vars, (f1, f2), 0, theta, sigma_12, sigma_12)
     self.assertEqual("No Violation", res)
     
     res = diagnosability.verify_for_size_exactly_k(obs_names, obs_vars, (f1, f2), 1, theta, sigma_12, sigma_12)
     self.assertTrue(res.startswith("############### DIAGNOSABILITY VIOLATION"))
     
     res = diagnosability.verify_for_size_exactly_k(obs_names, obs_vars, (f1, f2), 2, theta, sigma_12, sigma_12)
     self.assertTrue(res.startswith("############### DIAGNOSABILITY VIOLATION"))
     
     res = diagnosability.verify_for_size_exactly_k(obs_names, obs_vars, (f1, f2), 3, theta, sigma_12, sigma_12)
     self.assertTrue(res.startswith("############### DIAGNOSABILITY VIOLATION"))
    def test_generate_sat_problem(self):
        theta = Node.from_ptr(parse_simple_expression("TRUE"))
        theta = bmcutils.make_nnf_boolean_wff(theta)

        sigma_12 = Node.from_ptr(parse_ltl_spec("TRUE"))
        sigma_12 = bmcutils.make_nnf_boolean_wff(sigma_12).to_node()

        observable = diagnosability.mk_observable_vars(["mouse"])
        f1 = Node.from_ptr(parse_simple_expression("status = active"))
        f2 = Node.from_ptr(parse_simple_expression("status = inactive"))

        for i in range(5):
            problem = diagnosability.generate_sat_problem(
                observable, (f1, f2), i, theta, sigma_12, sigma_12)
            solver = SatSolverFactory.create()
            cnf = problem.to_cnf()
            solver += cnf
            solver.polarity(cnf, Polarity.POSITIVE)
            self.assertEqual(SatSolverResult.UNSATISFIABLE, solver.solve())

        f1 = Node.from_ptr(parse_simple_expression("status = active"))
        f2 = Node.from_ptr(parse_simple_expression("status = highlight"))

        for i in range(1, 4):
            # length zero has no input => only an initial state and the
            # diagnosability condition is not checked
            problem = diagnosability.generate_sat_problem(
                observable, (f1, f2), i, theta, sigma_12, sigma_12)
            solver = SatSolverFactory.create()
            cnf = problem.to_cnf()
            solver += cnf
            solver.polarity(cnf, Polarity.POSITIVE)
            self.assertEqual(SatSolverResult.SATISFIABLE, solver.solve())
 def test_generate_sat_problem(self):
     theta = Node.from_ptr(parse_simple_expression("TRUE"))
     theta = bmcutils.make_nnf_boolean_wff(theta)
     
     sigma_12= Node.from_ptr(parse_ltl_spec("TRUE"))
     sigma_12= bmcutils.make_nnf_boolean_wff(sigma_12).to_node()
     
     observable = diagnosability.mk_observable_vars(["mouse"])
     f1 = Node.from_ptr(parse_simple_expression("status = active"))
     f2 = Node.from_ptr(parse_simple_expression("status = inactive"))
      
     for i in range(5):
         problem = diagnosability.generate_sat_problem(observable, (f1, f2), i, theta, sigma_12, sigma_12)
         solver  = SatSolverFactory.create()
         cnf     = problem.to_cnf()
         solver += cnf
         solver.polarity(cnf, Polarity.POSITIVE)
         self.assertEqual(SatSolverResult.UNSATISFIABLE, solver.solve())
          
     f1 = Node.from_ptr(parse_simple_expression("status = active"))
     f2 = Node.from_ptr(parse_simple_expression("status = highlight"))
      
     for i in range(1, 4): 
         # length zero has no input => only an initial state and the 
         # diagnosability condition is not checked
         problem = diagnosability.generate_sat_problem(observable, (f1, f2), i, theta, sigma_12, sigma_12)
         solver  = SatSolverFactory.create()
         cnf     = problem.to_cnf()
         solver += cnf
         solver.polarity(cnf, Polarity.POSITIVE)
         self.assertEqual(SatSolverResult.SATISFIABLE, solver.solve())
 def test_constraint_context_sigma(self):
     fsm   = master_be_fsm()
     
     _true = Node.from_ptr(parse_ltl_spec("TRUE"))
     _true = bmcutils.make_nnf_boolean_wff(_true)
     _truen= _true.to_node()
     
     cond  = Wff(parse_ltl_spec("G !(mouse = hover)"))\
                 .to_boolean_wff()\
                 .to_negation_normal_form()
     off_1 = 0
     off_2 = 2
     length= 1
      
     # sigma1
     problem = diagnosability.generate_sat_problem([], (_truen, _truen), length, _true, cond.to_node(), _truen)
     tm_cond = ltlspec.bounded_semantics_at_offset(fsm, cond.to_node(), length, off_1)
     
     canonical_p = tests.canonical_cnf(problem)
     canonical_f = tests.canonical_cnf(tm_cond)
     
     self.assertTrue(all(clause in canonical_p for clause in canonical_f))
     
     # sigma2
     problem = diagnosability.generate_sat_problem([], (_truen, _truen), length, _true, _truen, cond.to_node())
     tm_cond = ltlspec.bounded_semantics_at_offset(fsm, cond.to_node(), length, off_2)
     
     canonical_p = tests.canonical_cnf(problem)
     canonical_f = tests.canonical_cnf(tm_cond)
     
     self.assertTrue(all(clause in canonical_p for clause in canonical_f))
     
Exemple #5
0
 def test_generate_invar_problem(self):
     # PROBLEM = BASE STEP & INDUCTION
     for prop in prop_database():
         expr    = utils.make_nnf_boolean_wff(prop.expr)
         problem = invarspec.generate_invar_problem(self.fsm, expr)
     
         manual  = (invarspec.generate_base_step(self.fsm, expr) & 
                    invarspec.generate_inductive_step(self.fsm, expr))
        
         self.assertEqual(problem.to_cnf().vars_list, manual.to_cnf().vars_list)
    def test_verify_exactly(self):
        theta = Node.from_ptr(parse_simple_expression("TRUE"))
        theta = bmcutils.make_nnf_boolean_wff(theta)

        sigma_12 = Node.from_ptr(parse_ltl_spec("TRUE"))
        sigma_12 = bmcutils.make_nnf_boolean_wff(sigma_12).to_node()

        obs_names = ["mouse"]
        obs_vars = diagnosability.mk_observable_vars(obs_names)
        f1 = Node.from_ptr(parse_simple_expression("status = active"))
        f2 = Node.from_ptr(parse_simple_expression("status = inactive"))

        for i in range(5):
            res = diagnosability.verify_for_size_exactly_k(
                obs_names, obs_vars, (f1, f2), i, theta, sigma_12, sigma_12)
            self.assertEqual("No Violation", res)

        f1 = Node.from_ptr(parse_simple_expression("status = active"))
        f2 = Node.from_ptr(parse_simple_expression("status = highlight"))

        res = diagnosability.verify_for_size_exactly_k(obs_names, obs_vars,
                                                       (f1, f2), 0, theta,
                                                       sigma_12, sigma_12)
        self.assertEqual("No Violation", res)

        res = diagnosability.verify_for_size_exactly_k(obs_names, obs_vars,
                                                       (f1, f2), 1, theta,
                                                       sigma_12, sigma_12)
        self.assertTrue(
            res.startswith("############### DIAGNOSABILITY VIOLATION"))

        res = diagnosability.verify_for_size_exactly_k(obs_names, obs_vars,
                                                       (f1, f2), 2, theta,
                                                       sigma_12, sigma_12)
        self.assertTrue(
            res.startswith("############### DIAGNOSABILITY VIOLATION"))

        res = diagnosability.verify_for_size_exactly_k(obs_names, obs_vars,
                                                       (f1, f2), 3, theta,
                                                       sigma_12, sigma_12)
        self.assertTrue(
            res.startswith("############### DIAGNOSABILITY VIOLATION"))
Exemple #7
0
    def test_generate_invar_problem(self):
        # PROBLEM = BASE STEP & INDUCTION
        for prop in prop_database():
            expr = utils.make_nnf_boolean_wff(prop.expr)
            problem = invarspec.generate_invar_problem(self.fsm, expr)

            manual = (invarspec.generate_base_step(self.fsm, expr)
                      & invarspec.generate_inductive_step(self.fsm, expr))

            self.assertEqual(problem.to_cnf().vars_list,
                             manual.to_cnf().vars_list)
Exemple #8
0
def constraint_eventually_critical_pair(formula_nodes, offset_path1, offset_path2, length):
    """
    Generates a boolean expression representing the critical pair condition.
    That is to say, it generates a condition that verifies if it is possible that
    the two belief states are inconsistent wrt `formula`.
    
    :param formula_nodes: the formula whose diagnosability is verified.
    :param offset_path1: the offset at which path 1 is supposed to start (should be 0)
    :param offset_path2: the offset at which path 2 is supposed to start (must not intersect with path1)
    :param length: the length of the path
    :return: an expression describing the 'critical pair' condition.
    """
    enc = master_be_fsm().encoding
    c1 = make_nnf_boolean_wff(formula_nodes[0]).to_be(enc)
    c2 = make_nnf_boolean_wff(formula_nodes[1]).to_be(enc)

    constraint = Be.false(enc.manager)
    for time_ in range(length + 1):
        constraint |= enc.shift_to_time(c1, time_ + offset_path1) & enc.shift_to_time(c2, time_ + offset_path2)
    return constraint
def constraint_eventually_critical_pair(formula_nodes, offset_path1, offset_path2, length):
    """
    Generates a boolean expression representing the critical pair condition.
    That is to say, it generates a condition that verifies if it is possible that
    the two belief states are inconsistent wrt `formula`.

    :param formula_nodes: the formula whose diagnosability is verified.
    :param offset_path1: the offset at which path 1 is supposed to start (should be 0)
    :param offset_path2: the offset at which path 2 is supposed to start (must not intersect with path1)
    :param length: the length of the path
    :return: an expression describing the 'critical pair' condition.
    """
    enc = master_be_fsm().encoding
    c1  = make_nnf_boolean_wff(formula_nodes[0]).to_be(enc)
    c2  = make_nnf_boolean_wff(formula_nodes[1]).to_be(enc)

    constraint = Be.false(enc.manager)
    for time_ in range(length+1):
        constraint |= ( enc.shift_to_time(c1, time_ + offset_path1)
                      & enc.shift_to_time(c2 , time_ + offset_path2) )
    return constraint
Exemple #10
0
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 test_eventually_critical_pair(self):
        enc = master_be_fsm().encoding
        f1 = Node.from_ptr(parse_simple_expression("status = active"))
        f2 = Node.from_ptr(parse_simple_expression("status = highlight"))

        constraint = diagnosability.constraint_eventually_critical_pair(
            (f1, f2), 0, 5, 5)

        nnf1 = bmcutils.make_nnf_boolean_wff(f1).to_be(enc)
        nnf2 = bmcutils.make_nnf_boolean_wff(f2).to_be(enc)
        manual = Be.false(enc.manager)

        for i in range(6):  # again, from 0 to 5
            manual |= (enc.shift_to_time(nnf1, i)
                       & enc.shift_to_time(nnf2, 5 + i))

        # observing the clauses generated in both cases, one observes that
        # the generated clauses are the same except that the number of the cnf
        # literals do not match, example:
        #                        [-59, -24, 58]
        #                        [-65, -24, 64]
        # This is due to the fact that some 'fresh' cnf literals are used in the
        # generation of the epxression. Therefore, a comparison (even on the
        # canonical form of the CNF) is not feasible.
        #
        # Satisfiability is just an indication but at least that is .. something
        solver_c = SatSolverFactory.create()
        cnf = constraint.to_cnf()
        solver_c += cnf
        solver_c.polarity(cnf, Polarity.POSITIVE)
        result_c = solver_c.solve()

        solver_m = SatSolverFactory.create()
        cnf = manual.to_cnf()
        solver_m += cnf
        solver_m.polarity(cnf, Polarity.POSITIVE)
        result_m = solver_m.solve()

        self.assertEqual(result_c, result_m)
Exemple #12
0
 def test_generate_base_step(self):
     # BASE STEP = (I0 -> P0 )  
     for prop in prop_database():
         expr  = utils.make_nnf_boolean_wff(prop.expr)
         gen   = invarspec.generate_base_step(self.fsm, expr)
     
         # 
         model = BmcModel()
         i0    = model.init[0] & model.invar[0]
         # recall: the prop has to be shifted to time 0
         p0    = self.fsm.encoding.shift_to_time(expr.to_be(self.fsm.encoding), 0)
         manual= i0.imply(p0)
         self.assertEqual(gen.to_cnf().vars_list, manual.to_cnf().vars_list)
 def test_eventually_critical_pair(self):
     enc= master_be_fsm().encoding
     f1 = Node.from_ptr(parse_simple_expression("status = active"))
     f2 = Node.from_ptr(parse_simple_expression("status = highlight"))
     
     constraint = diagnosability.constraint_eventually_critical_pair((f1, f2), 0, 5, 5)
     
     nnf1   = bmcutils.make_nnf_boolean_wff(f1).to_be(enc)
     nnf2   = bmcutils.make_nnf_boolean_wff(f2).to_be(enc)
     manual = Be.false(enc.manager)
     
     for i in range(6): # again, from 0 to 5
         manual |= ( enc.shift_to_time(nnf1 , i)
                   & enc.shift_to_time(nnf2 , 5+i))
     
     # observing the clauses generated in both cases, one observes that 
     # the generated clauses are the same except that the number of the cnf
     # literals do not match, example:
     #                        [-59, -24, 58]
     #                        [-65, -24, 64]
     # This is due to the fact that some 'fresh' cnf literals are used in the
     # generation of the epxression. Therefore, a comparison (even on the 
     # canonical form of the CNF) is not feasible.
     #
     # Satisfiability is just an indication but at least that is .. something
     solver_c = SatSolverFactory.create()
     cnf      = constraint.to_cnf()
     solver_c+= cnf
     solver_c.polarity(cnf, Polarity.POSITIVE)
     result_c = solver_c.solve()
     
     solver_m = SatSolverFactory.create()
     cnf      = manual.to_cnf()
     solver_m+= cnf
     solver_m.polarity(cnf, Polarity.POSITIVE)
     result_m = solver_m.solve()
     
     self.assertEqual(result_c, result_m)
Exemple #14
0
    def test_generate_base_step(self):
        # BASE STEP = (I0 -> P0 )
        for prop in prop_database():
            expr = utils.make_nnf_boolean_wff(prop.expr)
            gen = invarspec.generate_base_step(self.fsm, expr)

            #
            model = BmcModel()
            i0 = model.init[0] & model.invar[0]
            # recall: the prop has to be shifted to time 0
            p0 = self.fsm.encoding.shift_to_time(expr.to_be(self.fsm.encoding),
                                                 0)
            manual = i0.imply(p0)
            self.assertEqual(gen.to_cnf().vars_list, manual.to_cnf().vars_list)
Exemple #15
0
 def test_make_nnf_boolean_wff(self):
     load_from_string("""
         MODULE main
         VAR     v : boolean;
                 w : boolean;
         ASSIGN  init(v) := TRUE; 
                 next(v) := !v;
         """)
     with BmcSupport():
         expr = Node.from_ptr(parse_ltl_spec("F G ( w <-> v )"))
         wff = bmcutils.make_nnf_boolean_wff(expr)
         self.assertEquals(" F ( G (w <-> v))", str(expr))
         self.assertEquals(" F ( G ((!v | w) & (v | !w)))", str(wff))
         self.assertEquals(Wff, type(wff))
Exemple #16
0
def check(args, condition_text, observable):
    """
    Performs the verification of the diagnosability of the condition represented
    by `condition_text` and print its result to stdout.
    
    :param args: the arguments that were given on the command line
    :param condition_text: a string representing the diagnosability condition to
        be verified in the format 'c1 ; c2'.
    :param observable: the set of symbols considered observable in the context
        of this diagnosability test
    """
    try:
        observable_vars = mk_observable_vars(observable)
        diagnosability_condition = mk_specs_nodes(condition_text)

        theta = Node.from_ptr(parse_simple_expression(args.initial_condition))
        theta = make_nnf_boolean_wff(theta)

        sigma1 = Node.from_ptr(parse_ltl_spec(args.sigma1))
        sigma1 = make_nnf_boolean_wff(sigma1).to_node()

        sigma2 = Node.from_ptr(parse_ltl_spec(args.sigma2))
        sigma2 = make_nnf_boolean_wff(sigma2).to_node()

        for k in range(args.bound + 1):
            result = verify_for_size_exactly_k(
                observable, observable_vars, diagnosability_condition, k, theta, sigma1, sigma2
            )
            if "No Violation" != str(result):
                print("-- {} is *NOT* diagnosable for length {}".format(diagnosability_condition, k))
                print(result)
                return
        print("-- No counter example found for executions of length <= {}".format(k))

    except Exception as e:
        print("The specified condition contains a syntax error")
        print(e)
def check(args, condition_text, observable):
    """
    Performs the verification of the diagnosability of the condition represented
    by `condition_text` and print its result to stdout.

    :param args: the arguments that were given on the command line
    :param condition_text: a string representing the diagnosability condition to
        be verified in the format 'c1 ; c2'.
    :param observable: the set of symbols considered observable in the context
        of this diagnosability test
    """
    try:
        observable_vars          = mk_observable_vars(observable)
        diagnosability_condition = mk_specs_nodes(condition_text)

        theta = Node.from_ptr(parse_simple_expression(args.initial_condition))
        theta = make_nnf_boolean_wff(theta)

        sigma1= Node.from_ptr(parse_ltl_spec(args.sigma1))
        sigma1= make_nnf_boolean_wff(sigma1).to_node()

        sigma2= Node.from_ptr(parse_ltl_spec(args.sigma2))
        sigma2= make_nnf_boolean_wff(sigma2).to_node()

        for k in range(args.bound+1):
            result = verify_for_size_exactly_k(observable, observable_vars, diagnosability_condition, k, theta, sigma1, sigma2)
            if "No Violation" != str(result):
                print("-- {} is *NOT* diagnosable for length {}".format(diagnosability_condition, k))
                print(result)
                return
            else:
                print("-- No counter example at length {}".format(k))
        print("-- No counter example found for executions of length <= {}".format(args.bound))

    except Exception as e:
        print("The specified condition contains a syntax error")
        print(e)
Exemple #18
0
 def test_generate_inductive_step(self):
     # INDUCT = (P0 and R01) -> P1
     for prop in prop_database():
         expr  = utils.make_nnf_boolean_wff(prop.expr)
         gen   = invarspec.generate_inductive_step(self.fsm, expr)
     
         # 
         model = BmcModel()
         r01   = model.unrolling(0, 1)
         # recall: the prop has to be shifted to time 0
         p     = expr.to_be(self.fsm.encoding)
         p0    = self.fsm.encoding.shift_to_time(p, 0)
         p1    = self.fsm.encoding.shift_to_time(p, 1)
         manual= (p0 & r01).imply(p1)
         self.assertEqual(gen.to_cnf().vars_list, manual.to_cnf().vars_list)
Exemple #19
0
    def test_generate_inductive_step(self):
        # INDUCT = (P0 and R01) -> P1
        for prop in prop_database():
            expr = utils.make_nnf_boolean_wff(prop.expr)
            gen = invarspec.generate_inductive_step(self.fsm, expr)

            #
            model = BmcModel()
            r01 = model.unrolling(0, 1)
            # recall: the prop has to be shifted to time 0
            p = expr.to_be(self.fsm.encoding)
            p0 = self.fsm.encoding.shift_to_time(p, 0)
            p1 = self.fsm.encoding.shift_to_time(p, 1)
            manual = (p0 & r01).imply(p1)
            self.assertEqual(gen.to_cnf().vars_list, manual.to_cnf().vars_list)
Exemple #20
0
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)
Exemple #21
0
def bounded_semantics_without_loop(fsm, prop_node, bound):
    """
    Generates a Be expression corresponding to the bounded semantics of the
    given LTL formula in the case where the formula is evaluated against paths 
    that contain no loop and have a maximal length of `bound`.
    
    .. note::
    
        This function proves to be very useful since the bounded semantics of
        LTL depends on two cases: (a) when the encountered path contains loops
        (in that case the unbounded semantics of LTL can be maintained since
        there exists infinite paths) and (b) the case where there are no 
        possible loops (and the semantics has to be altered slightly).
        
        In the literature, the expression generated by this function is denoted
        .. math:: 
            
            [[f]]^{0}_{k} 
        
        With f used to represent the formula `prop_node`, and k for `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 no loop on the path.
    :raises ValueError: when the specified problem bound is negative
    """
    if bound < 0:
        raise ValueError("The problem bound may not be negative")
    ltl_wff = utils.make_nnf_boolean_wff(prop_node)
    be_ptr  = _bmc.Bmc_Tableau_GetNoLoop(fsm._ptr, ltl_wff._ptr, bound)
    return Be(be_ptr, fsm.encoding.manager)
Exemple #22
0
def bounded_semantics_without_loop(fsm, prop_node, bound):
    """
    Generates a Be expression corresponding to the bounded semantics of the
    given LTL formula in the case where the formula is evaluated against paths 
    that contain no loop and have a maximal length of `bound`.
    
    .. note::
    
        This function proves to be very useful since the bounded semantics of
        LTL depends on two cases: (a) when the encountered path contains loops
        (in that case the unbounded semantics of LTL can be maintained since
        there exists infinite paths) and (b) the case where there are no 
        possible loops (and the semantics has to be altered slightly).
        
        In the literature, the expression generated by this function is denoted
        :math:`[[f]]^{0}_{k}`
        
        With f used to represent the formula `prop_node`, and k for `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 no loop on the path.
    :raises ValueError: when the specified problem bound is negative
    """
    if bound < 0:
        raise ValueError("The problem bound may not be negative")
    ltl_wff = utils.make_nnf_boolean_wff(prop_node)
    be_ptr = _bmc.Bmc_Tableau_GetNoLoop(fsm._ptr, ltl_wff._ptr, bound)
    return Be(be_ptr, fsm.encoding.manager)
Exemple #23
0
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)
Exemple #24
0
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)
Exemple #25
0
def bounded_semantics_all_loops_optimisation_depth1(fsm, prop_node, bound):
    """
    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 [0; bound] and 
    *the 'depth'(:see:`Wff.depth`) of the formula is 1 and no fairness 
    constraint comes into play*.
    
    .. note::
    
        Unless you know precisely why you are using this function, it is 
        probably safer to just use bounded_semantics_all_loops with the 
        optimized flag turned on.
        
    This optimized generation scheme was proposed by R. Sebastiani in 
    
            
    :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 may be a loop anywhere on the 
        path between the positions `loop` and `bound` and the formula has a 
        depth of exactly one.
    :raises ValueError: when the specified propblem bound is negative
    """
    if bound < 0:
        raise ValueError("The problem bound may not be negative")
    ltl_wff= utils.make_nnf_boolean_wff(prop_node)
    be_ptr = _bmc.Bmc_Tableau_GetAllLoopsDepth1(fsm._ptr, ltl_wff._ptr, bound)
    return Be(be_ptr, fsm.encoding.manager)
Exemple #26
0
def bounded_semantics_all_loops_optimisation_depth1(fsm, prop_node, bound):
    """
    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 [0; bound] and 
    *the 'depth'(:attr:`pynusmv.wff.Wff.depth`) of the formula is 1 and no fairness 
    constraint comes into play*.
    
    .. note::
    
        Unless you know precisely why you are using this function, it is 
        probably safer to just use bounded_semantics_all_loops with the 
        optimized flag turned on.
            
    :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 may be a loop anywhere on the 
        path between the positions `loop` and `bound` and the formula has a 
        depth of exactly one.
    :raises ValueError: when the specified propblem bound is negative
    """
    if bound < 0:
        raise ValueError("The problem bound may not be negative")
    ltl_wff = utils.make_nnf_boolean_wff(prop_node)
    be_ptr = _bmc.Bmc_Tableau_GetAllLoopsDepth1(fsm._ptr, ltl_wff._ptr, bound)
    return Be(be_ptr, fsm.encoding.manager)
    def test_constraint_context_sigma(self):
        fsm = master_be_fsm()

        _true = Node.from_ptr(parse_ltl_spec("TRUE"))
        _true = bmcutils.make_nnf_boolean_wff(_true)
        _truen = _true.to_node()

        cond  = Wff(parse_ltl_spec("G !(mouse = hover)"))\
                    .to_boolean_wff()\
                    .to_negation_normal_form()
        off_1 = 0
        off_2 = 2
        length = 1

        # sigma1
        problem = diagnosability.generate_sat_problem([], (_truen, _truen),
                                                      length, _true,
                                                      cond.to_node(), _truen)
        tm_cond = ltlspec.bounded_semantics_at_offset(fsm, cond.to_node(),
                                                      length, off_1)

        canonical_p = tests.canonical_cnf(problem)
        canonical_f = tests.canonical_cnf(tm_cond)

        self.assertTrue(all(clause in canonical_p for clause in canonical_f))

        # sigma2
        problem = diagnosability.generate_sat_problem([], (_truen, _truen),
                                                      length, _true, _truen,
                                                      cond.to_node())
        tm_cond = ltlspec.bounded_semantics_at_offset(fsm, cond.to_node(),
                                                      length, off_2)

        canonical_p = tests.canonical_cnf(problem)
        canonical_f = tests.canonical_cnf(tm_cond)

        self.assertTrue(all(clause in canonical_p for clause in canonical_f))
Exemple #28
0
 def test_dump_dimacs_filename(self):
     for prop in prop_database():
         expr    = utils.make_nnf_boolean_wff(prop.expr)
         problem = invarspec.generate_invar_problem(self.fsm, expr)
         invarspec.dump_dimacs_filename(self.fsm.encoding, problem.to_cnf(), "testit")
Exemple #29
0
 def test_dump_dimacs_filename(self):
     for prop in prop_database():
         expr = utils.make_nnf_boolean_wff(prop.expr)
         problem = invarspec.generate_invar_problem(self.fsm, expr)
         invarspec.dump_dimacs_filename(self.fsm.encoding, problem.to_cnf(),
                                        "testit")