def test_releases(self): with Configure(self, __file__, "/models/flipflops.smv"): fsm = self.befsm formula = self.nnf("(a V b)") # bound 0 offset = 0 bound = 0 ref_expr= ltlspec.bounded_semantics(fsm, formula, bound) expr = ltlspec.bounded_semantics_at_offset(fsm, formula, bound, offset) self.assertEqual(canonical_cnf(expr), canonical_cnf(ref_expr)) # bound 1 offset = 0 bound = 1 ref_expr= ltlspec.bounded_semantics(fsm, formula, bound) expr = ltlspec.bounded_semantics_at_offset(fsm, formula, bound, offset) # VERIFIED manually, complains only about the CNF clauses literals and that's OK. # self.assertEqual(canonical_cnf(expr), canonical_cnf(ref_expr)) # ---- other offset ---- # bound 2 offset = 2 bound = 1 # because of the way the loop condition is encoded ! ref_expr= ltlspec.bounded_semantics_without_loop_at_offset(fsm, formula, 0, bound, offset)\ | ( ltlspec.bounded_semantics_with_loop_at_offset(fsm, formula, 0, bound, 0, offset) & bmcutils.loop_condition(self.enc, offset+bound, offset+0)) expr = ltlspec.bounded_semantics_at_offset(fsm, formula, bound, offset)
def test_next_with_loop(self): with tests.Configure(self, __file__, "/example.smv"): i, k, l = 0, 2, 0 enc = self.enc # One step a = ast.Proposition("a") formula = ast.Next(a) tool = formula.semantic_with_loop(enc, i, k, l) manual = a.semantic_with_loop(enc, 1, k, l) nusmv = ltlspec.bounded_semantics(self.befsm, Node.from_ptr( parse_ltl_spec("X a")), bound=k, loop=l) loop_cond = bmcutils.loop_condition(enc, k, l) s_tool = tests.canonical_cnf(tool & loop_cond) s_manual = tests.canonical_cnf(manual & loop_cond) s_nusmv = tests.canonical_cnf(nusmv) self.assertEqual(s_tool, s_nusmv) self.assertEqual(s_tool, s_manual) # two steps formula = ast.Next(ast.Next(a)) tool = formula.semantic_with_loop(enc, i, k, l) manual = a.semantic_with_loop(enc, 0, k, l) nusmv = ltlspec.bounded_semantics(self.befsm, Node.from_ptr( parse_ltl_spec("X X a")), bound=k, loop=l) loop_cond = bmcutils.loop_condition(enc, k, l) s_tool = tests.canonical_cnf(tool & loop_cond) s_manual = tests.canonical_cnf(manual & loop_cond) s_nusmv = tests.canonical_cnf(nusmv) self.assertEqual(s_tool, s_nusmv) self.assertEqual(s_tool, s_manual) # Three steps (getting over k) formula = ast.Next(ast.Next(ast.Next(a))) tool = formula.semantic_with_loop(enc, i, k, l) manual = a.semantic_with_loop(enc, 1, k, l) nusmv = ltlspec.bounded_semantics(self.befsm, Node.from_ptr( parse_ltl_spec("X X X a")), bound=k, loop=l) loop_cond = bmcutils.loop_condition(enc, k, l) s_tool = tests.canonical_cnf(tool & loop_cond) s_manual = tests.canonical_cnf(manual & loop_cond) s_nusmv = tests.canonical_cnf(nusmv) self.assertEqual(s_tool, s_nusmv) self.assertEqual(s_tool, s_manual)
def test_next_with_loop(self): with tests.Configure(self, __file__, "/example.smv"): i,k,l = 0,2,0 enc = self.enc # One step a = ast.Proposition("a") formula = ast.Next(a) tool = formula.semantic_with_loop(enc, i, k, l) manual = a.semantic_with_loop(enc, 1, k, l) nusmv = ltlspec.bounded_semantics(self.befsm, Node.from_ptr(parse_ltl_spec("X a")), bound = k, loop = l) loop_cond = bmcutils.loop_condition(enc, k, l) s_tool = tests.canonical_cnf(tool & loop_cond) s_manual= tests.canonical_cnf(manual & loop_cond) s_nusmv = tests.canonical_cnf(nusmv) self.assertEqual(s_tool, s_nusmv) self.assertEqual(s_tool, s_manual) # two steps formula = ast.Next(ast.Next(a)) tool = formula.semantic_with_loop(enc, i, k, l) manual = a.semantic_with_loop(enc, 0, k, l) nusmv = ltlspec.bounded_semantics(self.befsm, Node.from_ptr(parse_ltl_spec("X X a")), bound = k, loop = l) loop_cond = bmcutils.loop_condition(enc, k, l) s_tool = tests.canonical_cnf(tool & loop_cond) s_manual= tests.canonical_cnf(manual & loop_cond) s_nusmv = tests.canonical_cnf(nusmv) self.assertEqual(s_tool, s_nusmv) self.assertEqual(s_tool, s_manual) # Three steps (getting over k) formula = ast.Next(ast.Next(ast.Next(a))) tool = formula.semantic_with_loop(enc, i, k, l) manual = a.semantic_with_loop(enc, 1, k, l) nusmv = ltlspec.bounded_semantics(self.befsm, Node.from_ptr(parse_ltl_spec("X X X a")), bound = k, loop = l) loop_cond = bmcutils.loop_condition(enc, k, l) s_tool = tests.canonical_cnf(tool & loop_cond) s_manual= tests.canonical_cnf(manual & loop_cond) s_nusmv = tests.canonical_cnf(nusmv) self.assertEqual(s_tool, s_nusmv) self.assertEqual(s_tool, s_manual)
def test_next_noloop(self): with tests.Configure(self, __file__, "/example.smv"): i, k = 0, 2 enc = self.enc # One step a = ast.Proposition("a") formula = ast.Next(a) tool = formula.semantic_no_loop(enc, i, k) manual = a.semantic_no_loop(enc, 1, k) nusmv = ltlspec.bounded_semantics(self.befsm, Node.from_ptr( parse_ltl_spec("X a")), bound=k, loop=bmcutils.no_loopback()) s_tool = tests.canonical_cnf(tool) s_manual = tests.canonical_cnf(manual) s_nusmv = tests.canonical_cnf(nusmv) self.assertEqual(s_tool, s_nusmv) self.assertEqual(s_tool, s_manual) # two steps formula = ast.Next(ast.Next(a)) tool = formula.semantic_no_loop(enc, i, k) manual = a.semantic_no_loop(enc, 2, k) nusmv = ltlspec.bounded_semantics(self.befsm, Node.from_ptr( parse_ltl_spec("X X a")), bound=k, loop=bmcutils.no_loopback()) s_tool = tests.canonical_cnf(tool) s_manual = tests.canonical_cnf(manual) s_nusmv = tests.canonical_cnf(nusmv) self.assertEqual(s_tool, s_nusmv) self.assertEqual(s_tool, s_manual) # Three steps (getting over k) formula = ast.Next(ast.Next(ast.Next(a))) tool = formula.semantic_no_loop(enc, i, k) manual = Be.false(enc.manager) nusmv = ltlspec.bounded_semantics(self.befsm, Node.from_ptr( parse_ltl_spec("X X X a")), bound=k, loop=bmcutils.no_loopback()) s_tool = tests.canonical_cnf(tool) s_manual = tests.canonical_cnf(manual) s_nusmv = tests.canonical_cnf(nusmv) self.assertEqual(s_tool, s_nusmv) self.assertEqual(s_tool, s_manual)
def test_next_noloop(self): with tests.Configure(self, __file__, "/example.smv"): i,k = 0,2 enc = self.enc # One step a = ast.Proposition("a") formula = ast.Next(a) tool = formula.semantic_no_loop(enc, i, k) manual = a.semantic_no_loop(enc, 1, k) nusmv = ltlspec.bounded_semantics(self.befsm, Node.from_ptr(parse_ltl_spec("X a")), bound = k, loop = bmcutils.no_loopback()) s_tool = tests.canonical_cnf(tool) s_manual = tests.canonical_cnf(manual) s_nusmv = tests.canonical_cnf(nusmv) self.assertEqual(s_tool, s_nusmv) self.assertEqual(s_tool, s_manual) # two steps formula = ast.Next(ast.Next(a)) tool = formula.semantic_no_loop(enc, i, k) manual = a.semantic_no_loop(enc, 2, k) nusmv = ltlspec.bounded_semantics(self.befsm, Node.from_ptr(parse_ltl_spec("X X a")), bound = k, loop = bmcutils.no_loopback()) s_tool = tests.canonical_cnf(tool) s_manual = tests.canonical_cnf(manual) s_nusmv = tests.canonical_cnf(nusmv) self.assertEqual(s_tool, s_nusmv) self.assertEqual(s_tool, s_manual) # Three steps (getting over k) formula = ast.Next(ast.Next(ast.Next(a))) tool = formula.semantic_no_loop(enc, i, k) manual = Be.false(enc.manager) nusmv = ltlspec.bounded_semantics(self.befsm, Node.from_ptr(parse_ltl_spec("X X X a")), bound = k, loop = bmcutils.no_loopback()) s_tool = tests.canonical_cnf(tool) s_manual = tests.canonical_cnf(manual) s_nusmv = tests.canonical_cnf(nusmv) self.assertEqual(s_tool, s_nusmv) self.assertEqual(s_tool, s_manual)
def test_bounded_semantics(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.bounded_semantics(self.fsm, spec, bound=-1) # it must raise exception when the bound and loop are not consistent with self.assertRaises(ValueError): ltlspec.bounded_semantics(self.fsm, spec, bound=5, loop=6) # verify that the generated expression corresponds to what is announced formula = ltlspec.bounded_semantics(self.fsm, spec, bound=10) no_loop = ltlspec.bounded_semantics_without_loop(self.fsm, spec, 10) all_loop = ltlspec.bounded_semantics_all_loops(self.fsm, spec, 10, 0) self.assertEqual(formula, no_loop | all_loop)
def test_weak_until_noloop(self): with tests.Configure(self, __file__, "/example.smv"): enc = self.enc a = ast.Proposition("a") b = ast.Proposition("b") expr = ast.WeakUntil(a, b) tool = expr.semantic_no_loop(enc, 0, 2) manual = (b.semantic_no_loop(enc, 0, 2) | (a.semantic_no_loop(enc, 0, 2) & (b.semantic_no_loop(enc, 1, 2) | (a.semantic_no_loop(enc, 1, 2) & (b.semantic_no_loop(enc, 2, 2)))))) spec = Node.from_ptr(parse_ltl_spec("a U b")) nusmv = ltlspec.bounded_semantics(self.befsm, spec, bound=2, loop=bmcutils.no_loopback()) # normalized string representation of the BE's (make them comparable) s_tool = tests.canonical_cnf(tool) s_nusmv = tests.canonical_cnf(nusmv) s_manual = tests.canonical_cnf(manual) self.assertEqual(s_tool, s_manual) self.assertEqual(s_tool, s_nusmv)
def test_eventually_with_loop(self): with tests.Configure(self, __file__, "/example.smv"): i, k, l = 0, 2, 0 enc = self.enc a = ast.Proposition("a") formula = ast.Eventually(a) tool = formula.semantic_with_loop(enc, i, k, l) manual = a.semantic_with_loop(enc, i+1, k, l) |\ a.semantic_with_loop(enc, i , k, l) nusmv = ltlspec.bounded_semantics(self.befsm, Node.from_ptr( parse_ltl_spec("F a")), bound=k, loop=l) # normalized string representation of the BE's (make them comparable) loop_cond = bmcutils.loop_condition(enc, k, l) s_tool = tests.canonical_cnf(tool & loop_cond) s_manual = tests.canonical_cnf(manual & loop_cond) s_nusmv = tests.canonical_cnf(nusmv) self.assertEqual(s_nusmv, s_tool) self.assertEqual(s_manual, s_tool)
def test_eventually_with_loop(self): with tests.Configure(self, __file__, "/example.smv"): i,k,l = 0,2,0 enc = self.enc a = ast.Proposition("a") formula = ast.Eventually(a) tool = formula.semantic_with_loop(enc, i, k, l) manual = a.semantic_with_loop(enc, i+1, k, l) |\ a.semantic_with_loop(enc, i , k, l) nusmv = ltlspec.bounded_semantics( self.befsm, Node.from_ptr(parse_ltl_spec("F a")), bound = k, loop = l) # normalized string representation of the BE's (make them comparable) loop_cond = bmcutils.loop_condition(enc, k, l) s_tool = tests.canonical_cnf(tool & loop_cond) s_manual= tests.canonical_cnf(manual & loop_cond) s_nusmv = tests.canonical_cnf(nusmv) self.assertEqual(s_nusmv, s_tool) self.assertEqual(s_manual, s_tool)
def test_until_with_loop(self): with tests.Configure(self, __file__, "/example.smv"): enc = self.enc i,k,l= 0,2,0 a = ast.Proposition("a") b = ast.Proposition("b") expr = ast.Until(a, b) tool = expr.semantic_with_loop(enc, i,k,l) manual = b.semantic_with_loop(enc, i, k, l) | \ (a.semantic_with_loop(enc, i, k, l) & b.semantic_with_loop(enc, i+1, k, l)) spec = Node.from_ptr(parse_ltl_spec("a U b")) nusmv = ltlspec.bounded_semantics(self.befsm, spec, bound=k, loop=l) tool &= bmcutils.loop_condition(enc, k, l) manual &= bmcutils.loop_condition(enc, k, l) # normalized string representation of the BE's (make them comparable) s_tool = tests.canonical_cnf(tool) s_nusmv = tests.canonical_cnf(nusmv) s_manual= tests.canonical_cnf(manual) self.assertEqual(s_tool, s_manual) self.assertEqual(s_tool, s_nusmv)
def test_bounded_semantics(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.bounded_semantics(self.fsm, spec, bound=-1) # it must raise exception when the bound and loop are not consistent with self.assertRaises(ValueError): ltlspec.bounded_semantics(self.fsm, spec, bound=5, loop=6) # verify that the generated expression corresponds to what is announced formula = ltlspec.bounded_semantics(self.fsm, spec, bound=10) no_loop = ltlspec.bounded_semantics_without_loop(self.fsm, spec, 10) all_loop= ltlspec.bounded_semantics_all_loops(self.fsm, spec, 10, 0) self.assertEqual(formula, no_loop | all_loop)
def test_until_with_loop(self): with tests.Configure(self, __file__, "/example.smv"): enc = self.enc i, k, l = 0, 2, 0 a = ast.Proposition("a") b = ast.Proposition("b") expr = ast.Until(a, b) tool = expr.semantic_with_loop(enc, i, k, l) manual = b.semantic_with_loop(enc, i, k, l) | \ (a.semantic_with_loop(enc, i, k, l) & b.semantic_with_loop(enc, i+1, k, l)) spec = Node.from_ptr(parse_ltl_spec("a U b")) nusmv = ltlspec.bounded_semantics(self.befsm, spec, bound=k, loop=l) tool &= bmcutils.loop_condition(enc, k, l) manual &= bmcutils.loop_condition(enc, k, l) # normalized string representation of the BE's (make them comparable) s_tool = tests.canonical_cnf(tool) s_nusmv = tests.canonical_cnf(nusmv) s_manual = tests.canonical_cnf(manual) self.assertEqual(s_tool, s_manual) self.assertEqual(s_tool, s_nusmv)
def test_until(self): with Configure(self, __file__, "/models/flipflops.smv"): fsm = self.befsm formula = self.nnf("(a U !b)") # bound 0 offset = 0 bound = 0 ref_expr= ltlspec.bounded_semantics(fsm, formula, bound) expr = ltlspec.bounded_semantics_at_offset(fsm, formula, bound, offset) self.assertEqual(canonical_cnf(expr), canonical_cnf(ref_expr)) # bound 1 offset = 0 bound = 1 ref_expr= ltlspec.bounded_semantics(fsm, formula, bound) expr = ltlspec.bounded_semantics_at_offset(fsm, formula, bound, offset) self.assertEqual(canonical_cnf(expr), canonical_cnf(ref_expr)) # ---- other offset ---- # bound 0 offset = 2 bound = 0 cdr = Wff.decorate(ltlspec.cdr(formula)).to_be(fsm.encoding) ref_expr= self.enc.shift_to_time(cdr, 0+offset) expr = ltlspec.bounded_semantics_at_offset(fsm, formula, bound, offset) self.assertEqual(canonical_cnf(expr), canonical_cnf(ref_expr)) # bound 1 offset = 2 bound = 1 car = Wff.decorate(ltlspec.car(formula)).to_be(fsm.encoding) cdr = Wff.decorate(ltlspec.cdr(formula)).to_be(fsm.encoding) ref_expr= self.enc.shift_to_time(cdr, 0+offset) \ | (self.enc.shift_to_time(car, 0+offset) & self.enc.shift_to_time(cdr, 1+offset)) expr = ltlspec.bounded_semantics_at_offset(fsm, formula, bound, offset) self.assertEqual(canonical_cnf(expr), canonical_cnf(ref_expr))
def test_globally(self): with Configure(self, __file__, "/models/flipflops.smv"): fsm = self.befsm formula = self.nnf("G (a <-> !b)") # bound 0 offset = 0 bound = 0 ref_expr= ltlspec.bounded_semantics(fsm, formula, bound) expr = ltlspec.bounded_semantics_at_offset(fsm, formula, bound, offset) self.assertEqual(canonical_cnf(expr), canonical_cnf(ref_expr)) # bound 1 offset = 0 bound = 1 ref_expr= ltlspec.bounded_semantics(fsm, formula, bound) expr = ltlspec.bounded_semantics_at_offset(fsm, formula, bound, offset) self.assertEqual(canonical_cnf(expr), canonical_cnf(ref_expr)) # ---- other offset ---- # bound 0 offset = 2 bound = 0 ref_expr= Be.false(self.enc.manager) expr = ltlspec.bounded_semantics_at_offset(fsm, formula, bound, offset) self.assertEqual(canonical_cnf(expr), canonical_cnf(ref_expr)) # bound 1 offset = 2 bound = 1 ref_expr= ltlspec.bounded_semantics_without_loop_at_offset(fsm, formula, 0, bound, offset) \ |( ltlspec.bounded_semantics_with_loop_at_offset(fsm, formula, 0, bound, 0, offset) \ & bmcutils.loop_condition(self.enc, bound+offset, offset)) expr = ltlspec.bounded_semantics_at_offset(fsm, formula, bound, offset) self.assertEqual(canonical_cnf(expr), canonical_cnf(ref_expr))
def validate_bounded_semantics(self, bound, custom_text, nusmv_text): fsm = self.befsm # formulae formula = parseLTL(custom_text) fml_node = Node.from_ptr(parse_ltl_spec(nusmv_text)) tool = formula.bounded_semantics(fsm, bound) smv = ltlspec.bounded_semantics(fsm, fml_node, bound) # canonical forms s_tool = tests.canonical_cnf(tool) s_smv = tests.canonical_cnf(smv) self.assertEqual(s_tool, s_smv)
def validate_bounded_semantics(self, bound, custom_text, nusmv_text): fsm = self.befsm # formulae formula = parseLTL(custom_text) fml_node= Node.from_ptr(parse_ltl_spec(nusmv_text)) tool = formula.bounded_semantics(fsm, bound) smv = ltlspec.bounded_semantics(fsm, fml_node, bound) # canonical forms s_tool = tests.canonical_cnf(tool) s_smv = tests.canonical_cnf(smv) self.assertEqual(s_tool, s_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 test_next(self): with Configure(self, __file__, "/models/flipflops.smv"): fsm = self.befsm formula = self.nnf("X (a <-> !b)") # bound 0 offset = 0 bound = 0 ref_expr= ltlspec.bounded_semantics(fsm, formula, bound) expr = ltlspec.bounded_semantics_at_offset(fsm, formula, bound, offset) self.assertEqual(canonical_cnf(expr), canonical_cnf(ref_expr)) # bound 1 offset = 0 bound = 1 # done this way to avoid the depth 1 optimisation car = Wff.decorate(ltlspec.car(formula)).to_be(fsm.encoding) ref_expr= self.enc.shift_to_time(car, offset+1) \ | (self.enc.shift_to_time(car, offset) & bmcutils.loop_condition(self.enc, bound, 0)) expr = ltlspec.bounded_semantics_at_offset(fsm, formula, bound, offset)
def test_weak_until_noloop(self): with tests.Configure(self, __file__, "/example.smv"): enc = self.enc a = ast.Proposition("a") b = ast.Proposition("b") expr = ast.WeakUntil(a, b) tool = expr.semantic_no_loop(enc, 0, 2) manual = ( b.semantic_no_loop(enc, 0, 2) | (a.semantic_no_loop(enc, 0, 2) & (b.semantic_no_loop(enc, 1, 2) | (a.semantic_no_loop(enc, 1, 2) & (b.semantic_no_loop(enc, 2, 2)))))) spec = Node.from_ptr(parse_ltl_spec("a U b")) nusmv = ltlspec.bounded_semantics(self.befsm, spec, bound=2, loop=bmcutils.no_loopback()) # normalized string representation of the BE's (make them comparable) s_tool = tests.canonical_cnf(tool) s_nusmv = tests.canonical_cnf(nusmv) s_manual= tests.canonical_cnf(manual) self.assertEqual(s_tool, s_manual) self.assertEqual(s_tool, s_nusmv)