def test_generate_problem_with_fairness(self): ''' This test clearly shows the difference in validating a property with or without fairness constraint ''' with tests.Configure(self, __file__, "/philo.smv"): # length 0 # nusmv has fairness always on. fml_node= Node.from_ptr(parse_ltl_spec("G (p1.waiting -> F !p1.waiting)")) smv = ltlspec.generate_ltl_problem(self.befsm, fml_node, 0) self.assertEqual(SatSolverResult.UNSATISFIABLE, self.satisfiability(smv)) formula = parseLTL("[](p1.waiting => <>!p1.waiting)") unfair = gen.generate_problem(formula, self.befsm, 0, no_fairness=True) self.assertEqual(SatSolverResult.UNSATISFIABLE, self.satisfiability(unfair)) fair = gen.generate_problem(formula, self.befsm, 0, no_fairness=False) self.assertEqual(SatSolverResult.UNSATISFIABLE, self.satisfiability(fair)) # length 1 fml_node= Node.from_ptr(parse_ltl_spec("G (p1.waiting -> F !p1.waiting)")) smv = ltlspec.generate_ltl_problem(self.befsm, fml_node, 1) self.assertEqual(SatSolverResult.UNSATISFIABLE, self.satisfiability(smv)) formula = parseLTL("[](p1.waiting => <>!p1.waiting)") unfair = gen.generate_problem(formula, self.befsm, 1, no_fairness=True) self.assertEqual(SatSolverResult.SATISFIABLE, self.satisfiability(unfair)) fair = gen.generate_problem(formula, self.befsm, 1, no_fairness=False) self.assertEqual(SatSolverResult.UNSATISFIABLE, self.satisfiability(fair))
def test_generate_problem_with_fairness(self): ''' This test clearly shows the difference in validating a property with or without fairness constraint ''' with tests.Configure(self, __file__, "/philo.smv"): # length 0 # nusmv has fairness always on. fml_node = Node.from_ptr( parse_ltl_spec("G (p1.waiting -> F !p1.waiting)")) smv = ltlspec.generate_ltl_problem(self.befsm, fml_node, 0) self.assertEqual(SatSolverResult.UNSATISFIABLE, self.satisfiability(smv)) formula = parseLTL("[](p1.waiting => <>!p1.waiting)") unfair = gen.generate_problem(formula, self.befsm, 0, no_fairness=True) self.assertEqual(SatSolverResult.UNSATISFIABLE, self.satisfiability(unfair)) fair = gen.generate_problem(formula, self.befsm, 0, no_fairness=False) self.assertEqual(SatSolverResult.UNSATISFIABLE, self.satisfiability(fair)) # length 1 fml_node = Node.from_ptr( parse_ltl_spec("G (p1.waiting -> F !p1.waiting)")) smv = ltlspec.generate_ltl_problem(self.befsm, fml_node, 1) self.assertEqual(SatSolverResult.UNSATISFIABLE, self.satisfiability(smv)) formula = parseLTL("[](p1.waiting => <>!p1.waiting)") unfair = gen.generate_problem(formula, self.befsm, 1, no_fairness=True) self.assertEqual(SatSolverResult.SATISFIABLE, self.satisfiability(unfair)) fair = gen.generate_problem(formula, self.befsm, 1, no_fairness=False) self.assertEqual(SatSolverResult.UNSATISFIABLE, self.satisfiability(fair))
def validate_generate_problem(self, bound, custom_text, nusmv_text): fsm = self.befsm # formulae formula = parseLTL(custom_text) fml_node = Node.from_ptr(parse_ltl_spec(nusmv_text)) # IMPORTANT NOTE: each instantiation of the problem creates new CNF # literal which appears in the clauses list (even in canonical form) # hence, the canonical forms of the different instantiations cannot # simply be compared as there is no a priori way to know what CNF # literal reconcile with what other. # However, the different expressions should all have the exact same # satisfiability. So, that's how this test proceeds. smv = ltlspec.generate_ltl_problem(fsm, fml_node, bound) tool = gen.generate_problem(formula, fsm, bound) manual = gen.model_problem(fsm, bound) &\ formula.nnf(True).bounded_semantics(fsm, bound) sat_smv = self.satisfiability(smv) sat_tool = self.satisfiability(tool) sat_man = self.satisfiability(manual) self.assertEqual(sat_tool, sat_man) self.assertEqual(sat_tool, sat_smv)
def test_fill_counter_example(self): load_from_string(""" MODULE main VAR v : boolean; w : boolean; ASSIGN init(v) := TRUE; next(v) := !v; init(w) := FALSE; next(w) := !w; """) with BmcSupport(): bound = 2 fsm = master_be_fsm() sexpfsm = master_bool_sexp_fsm() expr = Node.from_ptr(parse_ltl_spec("F ( w <-> v )")) pb = generate_ltl_problem(fsm, expr, bound=bound) cnf = pb.inline(True).to_cnf() solver = SatSolverFactory.create() solver += cnf solver.polarity(cnf, Polarity.POSITIVE) self.assertEqual(SatSolverResult.SATISFIABLE, solver.solve()) trace = Trace.create("FILLED", TraceType.COUNTER_EXAMPLE, sexpfsm.symbol_table, sexpfsm.symbols_list, True) bmcutils.fill_counter_example(fsm, solver, bound, trace) self.assertIsNotNone(trace) self.assertEqual(2, len(trace)) print(trace)
def test_concat(self): with BmcSupport(): sexp_fsm = master_bool_sexp_fsm() be_fsm = master_be_fsm() trace = Trace.create("Dummy example", TraceType.COUNTER_EXAMPLE, sexp_fsm.symbol_table, sexp_fsm.symbols_list, is_volatile=True) spec = Node.from_ptr(parse_ltl_spec("F (w <-> v)")) bound = 2 problem = generate_ltl_problem(be_fsm, spec, bound=bound) #.inline(True) cnf = problem.to_cnf() solver = SatSolverFactory.create() solver += cnf solver.polarity(cnf, Polarity.POSITIVE) solver.solve() other = generate_counter_example(be_fsm, problem, solver, bound) trace.concat(other) self.assertEquals(-1, trace.id) self.assertFalse(trace.is_registered) self.assertEquals("Dummy example", trace.description) self.assertEquals(TraceType.COUNTER_EXAMPLE, trace.type) self.assertTrue(trace.is_volatile) self.assertEquals(2, trace.length) self.assertEquals(2, len(trace)) self.assertFalse(trace.is_empty) self.assertFalse(trace.is_frozen) self.assertTrue(trace.is_thawed)
def validate_generate_problem(self, bound, custom_text, nusmv_text): fsm = self.befsm # formulae formula = parseLTL(custom_text) fml_node= Node.from_ptr(parse_ltl_spec(nusmv_text)) # IMPORTANT NOTE: each instantiation of the problem creates new CNF # literal which appears in the clauses list (even in canonical form) # hence, the canonical forms of the different instantiations cannot # simply be compared as there is no a priori way to know what CNF # literal reconcile with what other. # However, the different expressions should all have the exact same # satisfiability. So, that's how this test proceeds. smv = ltlspec.generate_ltl_problem(fsm, fml_node, bound) tool = gen.generate_problem(formula, fsm, bound) manual = gen.model_problem(fsm, bound) &\ formula.nnf(True).bounded_semantics(fsm, bound) sat_smv = self.satisfiability(smv) sat_tool= self.satisfiability(tool) sat_man = self.satisfiability(manual) self.assertEqual(sat_tool, sat_man) self.assertEqual(sat_tool, sat_smv)
def test_generate_ltl_problem(self): # parse the ltl property spec = Node.from_ptr(parse_ltl_spec("G ( y <= 7 )")) # it must raise exception when the bound is not feasible with self.assertRaises(ValueError): ltlspec.generate_ltl_problem(self.fsm, spec, bound=-1) # it must raise exception when the bound and loop are not consistent with self.assertRaises(ValueError): ltlspec.generate_ltl_problem(self.fsm, spec, bound=5, loop=6) problem = ltlspec.generate_ltl_problem(self.fsm, spec, bound=10) self.assertEqual("No counter example", self.do_verify(problem)) # verify that the generated problem corresponds to what is announced model = BmcModel().path(10) negspec = utils.make_negated_nnf_boolean_wff(spec) formula = ltlspec.bounded_semantics(self.fsm, negspec, bound=10) self.assertEqual(problem, model & formula)
def mk_cnf_with_formula(formula, bound): ''' :return: a `BeCnf` expression representing the verification of `formula` on the loaded model for a `bound` time steps ''' import pynusmv.node as _node import pynusmv.parser as _parser import pynusmv.bmc.glob as _bmc import pynusmv.bmc.ltlspec as _ltlspec prop = _node.Node.from_ptr( _parser.parse_ltl_spec(formula) ) fsm = _bmc.master_be_fsm() problem = _ltlspec.generate_ltl_problem(fsm, prop, bound).to_cnf() return problem
def test_dump_problem(self): load_from_string(""" MODULE main VAR v : boolean; w : boolean; ASSIGN init(v) := TRUE; next(v) := !v; LTLSPEC F G ( w <-> v ) """) with BmcSupport(): fsm = master_be_fsm() for prop in prop_database(): pb = generate_ltl_problem(fsm, prop.expr) bmcutils.dump_problem(fsm.encoding, pb.to_cnf(), prop, 10, 0, bmcutils.DumpType.DIMACS, "dimacs_dump")
def check_ltl(fml, bound, dry_run): import time fsm = master_be_fsm() for i in range(bound + 1): start = time.time() problem = ltlspec.generate_ltl_problem(fsm, fml, i) end = time.time() if not dry_run: status, trace = check_problem(problem, i) if status != "Ok": return (status, i, trace) else: print("-- No problem at length {}".format(i)) else: print(" 'Problem {}' ; {}".format(i, end - start)) return ("Ok", bound, None)
def check_ltl(fml, bound, dry_run): import time fsm = master_be_fsm() for i in range(bound+1): start = time.time() problem = ltlspec.generate_ltl_problem(fsm, fml, i) end = time.time() if not dry_run: status, trace = check_problem(problem, i) if status != "Ok": return (status, i, trace) else: print("-- No problem at length {}".format(i)) else: print(" 'Problem {}' ; {}".format(i, end-start)) return ("Ok", bound, None)
def test_concat(self): with BmcSupport(): sexp_fsm = master_bool_sexp_fsm() be_fsm = master_be_fsm() trace = Trace.create( "Dummy example", TraceType.COUNTER_EXAMPLE, sexp_fsm.symbol_table, sexp_fsm.symbols_list, is_volatile=True, ) spec = Node.from_ptr(parse_ltl_spec("F (w <-> v)")) bound = 2 problem = generate_ltl_problem(be_fsm, spec, bound=bound) # .inline(True) cnf = problem.to_cnf() solver = SatSolverFactory.create() solver += cnf solver.polarity(cnf, Polarity.POSITIVE) solver.solve() other = generate_counter_example(be_fsm, problem, solver, bound) trace.concat(other) self.assertEquals(-1, trace.id) self.assertFalse(trace.is_registered) self.assertEquals("Dummy example", trace.description) self.assertEquals(TraceType.COUNTER_EXAMPLE, trace.type) self.assertTrue(trace.is_volatile) self.assertEquals(2, trace.length) self.assertEquals(2, len(trace)) self.assertFalse(trace.is_empty) self.assertFalse(trace.is_frozen) self.assertTrue(trace.is_thawed)
def test_dump_dimacs_filename(self): # parse the ltl property spec = Node.from_ptr(parse_ltl_spec("G ( y <= 7 )")) problem = ltlspec.generate_ltl_problem(self.fsm, spec, bound=10) ltlspec.dump_dimacs_filename(self.fsm.encoding, problem.to_cnf(), 10, "test.dimacs")