def test_constraint_context_theta(self): enc = master_be_fsm().encoding cond = Wff(parse_simple_expression("mouse = down")).to_boolean_wff() theta = diagnosability.constraint_context_theta_initial(cond, 0, 1) manual= enc.shift_to_time(cond.to_be(enc), 0) \ & enc.shift_to_time(cond.to_be(enc), 1) \ self.assertEqual(theta, manual)
def nnf(self, text): """ Utility function to convert text into an equivalent Node form in NNF :return: an NNF node version of the text """ return Wff(parse_ltl_spec(text)).to_boolean_wff()\ .to_negation_normal_form()\ .to_node()
def _booleanize(self): """ Returns a boolean expression (Be) corresponding to this simple boolean expression (text). .. note:: Albeit feasible, working directly with variables as offered by the encoding is a little bit limiting as it de facto rejects any symbol which is not a variable. As a consequence, the DEFINES, or arithmetic expressions are not usable. The use of this function palliates that limitation and makes the use of any simple boolean expression possible. :return: a be expression (Be) corresponding to `self` """ if not self._booleanized: befsm = master_be_fsm() node = parse_simple_expression(self.id) self._booleanized = Wff(node).to_boolean_wff().to_be( befsm.encoding) return self._booleanized
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_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)