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_bounded_semantics_without_loop(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_without_loop(self.fsm, spec, bound=-1) # verify that the generated expression corresponds to what is announced no_loop = ltlspec.bounded_semantics_without_loop(self.fsm, spec, 10) # globally w/o loop is false (this is just a test) self.assertEqual(no_loop, Be.false(self.fsm.encoding.manager)) # an other more complex generation spec = Node.from_ptr(parse_ltl_spec("F (y <= 7)")) no_loop = ltlspec.bounded_semantics_without_loop(self.fsm, spec, 10) # # The generated expression is [[f]]^{0}_{k} so (! L_{k}) is not taken # care of. And actually, NuSMV does not generate that part of the # formula: it only enforce the loop condition when the semantics with # loop is used # handcrafted = Be.false(self.fsm.encoding.manager) y_le_seven = Wff(parse_ltl_spec("y <= 7")).to_boolean_wff().to_be(self.fsm.encoding) for time_x in reversed(range(11)): # 11 because range 'eats' up the last step handcrafted |= self.fsm.encoding.shift_to_time(y_le_seven, time_x) #### debuging info ##### #print("noloop = {}".format(no_loop.to_cnf())) #print("hancraft= {}".format(handcrafted.to_cnf())) #print(self.fsm.encoding) self.assertEqual(no_loop, handcrafted)
def test_is_loopback_when_frozen(self): with BmcSupport(): sexp_fsm = master_bool_sexp_fsm() be_fsm = master_be_fsm() # empty trace trace = Trace.create("Dummy example", TraceType.COUNTER_EXAMPLE, sexp_fsm.symbol_table, sexp_fsm.symbols_list, is_volatile=True) step1 = trace.steps[1] step2 = trace.append_step() yes = Node.from_ptr(parse_simple_expression("TRUE")) no = Node.from_ptr(parse_simple_expression("FALSE")) v = be_fsm.encoding.by_name['v'].name step1 += (v, yes) step2 += (v, no) trace.freeze() step1.force_loopback() self.assertTrue(step1.is_loopback) self.assertFalse(step2.is_loopback) step2.force_loopback() self.assertTrue(step1.is_loopback) # last step is never a loopback self.assertFalse(step2.is_loopback) trace.thaw() self.assertFalse(step1.is_loopback) self.assertFalse(step2.is_loopback)
def test_assign_value__magicmethod__(self): """tests the behavior of assign and value""" with BmcSupport(): sexp_fsm = master_bool_sexp_fsm() be_fsm = master_be_fsm() # empty trace trace = Trace.create( "Dummy example", TraceType.COUNTER_EXAMPLE, sexp_fsm.symbol_table, sexp_fsm.symbols_list, is_volatile=True, ) step1 = trace.steps[1] yes = Node.from_ptr(parse_simple_expression("TRUE")) no = Node.from_ptr(parse_simple_expression("FALSE")) v = be_fsm.encoding.by_name["v"].name self.assertIsNone(step1.value[v]) step1 += (v, yes) self.assertEqual(yes, step1.value[v]) step1 += (v, no) self.assertEqual(no, step1.value[v])
def test_iter(self): """tests the behavior of assign and value""" with BmcSupport(): sexp_fsm = master_bool_sexp_fsm() be_fsm = master_be_fsm() # empty trace trace = Trace.create( "Dummy example", TraceType.COUNTER_EXAMPLE, sexp_fsm.symbol_table, sexp_fsm.symbols_list, is_volatile=True, ) step1 = trace.steps[1] yes = Node.from_ptr(parse_simple_expression("TRUE")) no = Node.from_ptr(parse_simple_expression("FALSE")) v = be_fsm.encoding.by_name["v"].name self.assertEqual([], list(step1)) step1 += v, yes self.assertEqual([(v, yes)], list(step1)) # += really ASSIGNS a value, not append step1 += v, no self.assertEqual([(v, no)], list(step1))
def test_bounded_semantics_with_loop_optimized_depth1(self): spec = Node.from_ptr(parse_ltl_spec("G ( y <= 7 )")) # depth == 1 # it must raise exception when the bound is not feasible with self.assertRaises(ValueError): ltlspec.bounded_semantics_all_loops_optimisation_depth1( self.fsm, spec, -1) # should yield the same result (w/ opt) as regular all loops when depth is one optimized = ltlspec.bounded_semantics_all_loops_optimisation_depth1( self.fsm, spec, 5) regular = ltlspec.bounded_semantics_all_loops(self.fsm, spec, bound=5, loop=0) self.assertEqual(regular, optimized) # but not when the optim is turned off on 'all loops' regular = ltlspec.bounded_semantics_all_loops(self.fsm, spec, bound=5, loop=0, optimized=False) self.assertNotEqual(regular, optimized) # and it should only be applied when the depth is equal to one spec = Node.from_ptr(parse_ltl_spec("F G ( y <= 7 )")) # depth == 2 self.assertEqual(2, Wff.decorate(spec).depth) optimized = ltlspec.bounded_semantics_all_loops_optimisation_depth1( self.fsm, spec, 5) regular = ltlspec.bounded_semantics_all_loops(self.fsm, spec, bound=5, loop=0) self.assertNotEqual(regular, optimized)
def test_iter(self): """tests the behavior of assign and value""" with BmcSupport(): sexp_fsm = master_bool_sexp_fsm() be_fsm = master_be_fsm() # empty trace trace = Trace.create("Dummy example", TraceType.COUNTER_EXAMPLE, sexp_fsm.symbol_table, sexp_fsm.symbols_list, is_volatile=True) step1 = trace.steps[1] yes = Node.from_ptr(parse_simple_expression("TRUE")) no = Node.from_ptr(parse_simple_expression("FALSE")) v = be_fsm.encoding.by_name['v'].name self.assertEqual([], list(step1)) step1 += v, yes self.assertEqual([(v, yes)], list(step1)) # += really ASSIGNS a value, not append step1 += v, no self.assertEqual([(v, no)], list(step1))
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_is_constant_expr(self): expr = Node.from_ptr(parse_ltl_spec("F G ( w <-> v )")) self.assertFalse(bmcutils.is_constant_expr(expr)) expr = Node.from_ptr(parse_ltl_spec("some_variable")) self.assertFalse(bmcutils.is_constant_expr(expr)) expr = Node.from_ptr(parse_ltl_spec("TRUE")) self.assertTrue(bmcutils.is_constant_expr(expr)) expr = Node.from_ptr(parse_ltl_spec("FALSE")) self.assertTrue(bmcutils.is_constant_expr(expr))
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_is_variable(self): expr = Node.from_ptr(parse_ltl_spec("F G ( w <-> v )")) self.assertFalse(bmcutils.is_variable(expr)) expr = Node.from_ptr(parse_ltl_spec("some_variable")) expr.type = _parser.DOT # just to make sure it is seen as a variable, not an atom self.assertTrue(bmcutils.is_variable(expr)) expr = Node.from_ptr(parse_ltl_spec("TRUE")) self.assertFalse(bmcutils.is_variable(expr)) expr = Node.from_ptr(parse_ltl_spec("FALSE")) self.assertFalse(bmcutils.is_variable(expr))
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_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_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_copy(self): """Tests the copy behavior""" h = Assoc(_u.new_assoc(), freeit=True) a = Node.from_ptr(parse_simple_expression("a.car = 3"), freeit=False) h[a] = a h2 = h.copy() self.assertTrue(a in h2)
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 decode_value(self, list_of_bits_and_value): """ Returns a node (:class:`pynusmv.node.Node`) corresponding to the value of the variable encoded by the list of bits and values. :param list_of_bits_and_value: a sequence of tuples (BeVar, BooleanValue) which represent a bit and its value. :return: an intelligible value node corresponding to what these bits means when interpreted in the context of the SMV model. """ if not list_of_bits_and_value: raise ValueError("The given list of bits and values must at least "+ "contain one bit") # if the variable to be decoded is boolean in the model if not list_of_bits_and_value[0][0].is_bit: return list_of_bits_and_value[0][1] # otherwise decode the bits bool_enc = self._bool_enc scalar = list_of_bits_and_value[0][0].scalar bv = _bool.BitValues_create(bool_enc, scalar._ptr) for bit,val in list_of_bits_and_value: bit_index = _bool.BoolEnc_get_index_from_bit(bool_enc, bit.name._ptr) _bool.BitValues_set(bv, bit_index, val) result_ptr = _bool.BoolEnc_get_value_from_var_bits(bool_enc, bv) _bool.BitValues_destroy(bv) return Node.from_ptr(result_ptr)
def test_clear(self): """Verifies that clear works as expected""" h = Assoc(_u.new_assoc(), freeit=True) a = Node.from_ptr(parse_simple_expression("a.car = 3"), freeit=False) h[a] = a h.clear() self.assertFalse(a in h)
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))
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_language_contains(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, ) v = be_fsm.encoding.by_name["v"] w = be_fsm.encoding.by_name["w"] f = be_fsm.encoding.by_name["f"] i = be_fsm.encoding.by_name["i"] self.assertTrue(v.name in trace) self.assertTrue(w.name in trace) self.assertTrue(f.name in trace) self.assertTrue(i.name in trace) x = parse_simple_expression("x") self.assertFalse(Node.from_ptr(x) in trace)
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 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_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 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_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_copy(self): """Tests the copy behavior""" h = Assoc(_u.new_assoc(), freeit=True) a = Node.from_ptr(parse_simple_expression("a.car = 3"), freeit=False) h[a] = a h2= h.copy() self.assertTrue(a in h2)
def decode_value(self, list_of_bits_and_value): """ Returns a node (:see:`pynusmv.node.Node`) corresponding to the value of the variable encoded by the list of bits and values. :param list_of_bits_and_value: a sequence of tuples (BeVar, BooleanValue) which represent a bit and its value. :return: an intelligible value node corresponding to what these bits means when interpreted in the context of the SMV model. """ if not list_of_bits_and_value: raise ValueError("The given list of bits and values must at least "+ "contain one bit") # if the variable to be decoded is boolean in the model if not list_of_bits_and_value[0][0].is_bit: return list_of_bits_and_value[0][1] # otherwise decode the bits bool_enc = self._bool_enc scalar = list_of_bits_and_value[0][0].scalar bv = _bool.BitValues_create(bool_enc, scalar._ptr) for bit,val in list_of_bits_and_value: bit_index = _bool.BoolEnc_get_index_from_bit(bool_enc, bit.name._ptr) _bool.BitValues_set(bv, bit_index, val) result_ptr = _bool.BoolEnc_get_value_from_var_bits(bool_enc, bv) _bool.BitValues_destroy(bv) return Node.from_ptr(result_ptr)
def test_bounded_semantics_with_loop(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_single_loop(self.fsm, spec, -1, -2) # it must raise exception when the bound and loop are not consistent with self.assertRaises(ValueError): ltlspec.bounded_semantics_single_loop(self.fsm, spec, 5, 6) # verify that the generated problem corresponds to what is announced # without optimisation, the all loops is built as the conjunction of all # the possible 'single_loops' all_loops = ltlspec.bounded_semantics_all_loops(self.fsm, spec, 10, 0, optimized=False) acc_loops = Be.false(self.fsm.encoding.manager) for time_t in range(10): acc_loops |= ltlspec.bounded_semantics_single_loop( self.fsm, spec, 10, time_t) self.assertEqual(acc_loops, all_loops) # with optimisation, it's different all_loops = ltlspec.bounded_semantics_all_loops(self.fsm, spec, 10, 0, optimized=True) self.assertNotEqual(acc_loops, all_loops)
def test_empty(self): """Tests the empty factory""" a = Node.from_ptr(parse_simple_expression("a.car = 3"), freeit=False) h = Assoc.empty(freeit=True) self.assertFalse(a in h) hh = Assoc.empty(initial_capa=1, freeit=True) hh[a] = a self.assertTrue(a in hh)
def name(self): """ Returns the name of this BOOLEAN variable. If this variable was not declared boolean in the SMV text, this is going to be the name of one of the bits composing that variable. :return: the name node corresponding to this boolean variable. """ ptr = _be.BeEnc_index_to_name(self.encoding._ptr, self.untimed.index) return Node.from_ptr(ptr)
def test_associative_array(self): """ This function tests the basic functions of the associative array proto """ h = Assoc(_u.new_assoc(), freeit=True) a = Node.from_ptr(parse_simple_expression("a.car = 3"), freeit=False) b = Node.from_ptr(parse_simple_expression("b.car = 3"), freeit=False) # __contains__ self.assertFalse(a in h) # __setitem__ h[a] = a self.assertTrue(a in h) # __getitem__ self.assertEqual(h[a], a) with self.assertRaises(KeyError): h[b] # __delitem__ del h[a] self.assertFalse(a in h)
def cdr(this_node): """ Returns the rhs branch of this node. .. note:: This is a simple workaround of `Node.cdr` which does not behave as expected. :param this_node: the node whose rhs (cdr) is wanted. :return: the rhs member of this node. """ return Node.from_ptr(_node.cdr(this_node._ptr))
def __next__(self): """ Performs the iteration :return: the next node :raise: StopIteration when the iteration is over """ if self._ptr is None: raise StopIteration else: ret = Node.from_ptr(self._ptr) self._ptr = _node.cdr(self._ptr) return ret
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_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 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_bounded_semantics_with_loop_optimized_depth1(self): spec = Node.from_ptr(parse_ltl_spec("G ( y <= 7 )")) # depth == 1 # it must raise exception when the bound is not feasible with self.assertRaises(ValueError): ltlspec.bounded_semantics_all_loops_optimisation_depth1(self.fsm, spec, -1) # should yield the same result (w/ opt) as regular all loops when depth is one optimized = ltlspec.bounded_semantics_all_loops_optimisation_depth1(self.fsm, spec, 5) regular = ltlspec.bounded_semantics_all_loops(self.fsm, spec, bound=5, loop=0) self.assertEqual(regular, optimized) # but not when the optim is turned off on 'all loops' regular = ltlspec.bounded_semantics_all_loops(self.fsm, spec, bound=5, loop=0, optimized=False) self.assertNotEqual(regular, optimized) # and it should only be applied when the depth is equal to one spec = Node.from_ptr(parse_ltl_spec("F G ( y <= 7 )")) # depth == 2 self.assertEqual(2, Wff.decorate(spec).depth) optimized = ltlspec.bounded_semantics_all_loops_optimisation_depth1(self.fsm, spec, 5) regular = ltlspec.bounded_semantics_all_loops(self.fsm, spec, bound=5, loop=0) self.assertNotEqual(regular, optimized)
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)
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 value(self, symbol_node): """ Retrieves the value that was assigned to `symbol_node` in the current trace step. :param symbol_node: a Node (:class:`pynusmv.node.Node`) representing the symbol to which a value is assigned :return: a value_node, that is to say a Node (:class:`pynusmv.node.Node`) representing the value being assigned to the requested symbol. """ return Node.from_ptr( _trace.Trace_step_get_value(self.trace._ptr, self._ptr, symbol_node._ptr))
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)
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))
def scalar(self): """ Returns the name node of this variable as it was declared in the SMV text (hence not the name of the bit, but the name of the variable). .. seealso:: `is_bit` :return: the name node corresponding to scalar using this variable. """ bool_enc = self.encoding._bool_enc if self.is_bit: scalar = _bool.BoolEnc_get_scalar_var_from_bit(bool_enc, self.name._ptr) return Node.from_ptr(scalar) else: return self.name
def value(self, symbol_node): """ Retrieves the value that was assigned to `symbol_node` in the current trace step. :param symbol_node: a Node (:see: :class: `pynusmv.node.Node`) representing the symbol to which a value is assigned :return: a value_node, that is to say a Node (:see: :class: `pynusmv.node.Node`) representing the value being assigned to the requested symbol. """ return Node.from_ptr(_trace.Trace_step_get_value( self.trace._ptr, self._ptr, symbol_node._ptr))
def scalar(self): """ Returns the name node of this variable as it was declared in the SMV text (hence not the name of the bit, but the name of the variable). :see:`is_bit` :return: the name node corresponding to scalar using this variable. """ bool_enc = self.encoding._bool_enc if self.is_bit: scalar = _bool.BoolEnc_get_scalar_var_from_bit(bool_enc, self.name._ptr) return Node.from_ptr(scalar) else: return self.name
def test_make_negated_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_negated_nnf_boolean_wff(expr) self.assertEquals(" F ( G (w <-> v))", str(expr)) # Via De Morgan Laws self.assertEquals(" G ( F ((v & !w) | (!v & w)))", str(wff))
def test_is_loopback_when_frozen(self): with BmcSupport(): sexp_fsm = master_bool_sexp_fsm() be_fsm = master_be_fsm() # empty trace trace = Trace.create( "Dummy example", TraceType.COUNTER_EXAMPLE, sexp_fsm.symbol_table, sexp_fsm.symbols_list, is_volatile=True, ) step1 = trace.steps[1] step2 = trace.append_step() yes = Node.from_ptr(parse_simple_expression("TRUE")) no = Node.from_ptr(parse_simple_expression("FALSE")) v = be_fsm.encoding.by_name["v"].name step1 += (v, yes) step2 += (v, no) trace.freeze() step1.force_loopback() self.assertTrue(step1.is_loopback) self.assertFalse(step2.is_loopback) step2.force_loopback() self.assertTrue(step1.is_loopback) # last step is never a loopback self.assertFalse(step2.is_loopback) trace.thaw() self.assertFalse(step1.is_loopback) self.assertFalse(step2.is_loopback)
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 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_associative_array(self): """ This function tests the basic functions of the associative array proto """ h = Assoc(_u.new_assoc(), freeit=True) a = Node.from_ptr(parse_simple_expression("a.car = 3"), freeit=False) # __contains__ self.assertFalse(a in h) # __setitem__ h[a] = a self.assertTrue(a in h) # __getitem__ self.assertEqual(h[a], a) # __delitem__ del h[a] self.assertFalse(a in h)
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_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)