def test_negation_normal_form(self): queries = [ "~?", "~(~?)", "~('a' & ?)", "~(~'a' & ~?)", "~(? | 'a')", "~(~? | ~'a')", "'a' -> ?", "~'a' -> ~?", "~('a' -> ?)", "~(~'a' -> ~?)", "? <-> 'a'", "~? <-> ~'a'", "~(? <-> 'a')", "~(~? <-> ~'a')", "~EX ?", "~EX ~?", "~AX ?", "~AX ~?", "~EF ?", "~EF ~?", "~AF ?", "~AF ~?", "~EG ?", "~EG ~?", "~AG ?", "~AG ~?", "~E['a' U ?]", "~E[~'a' U ~?]", "~A['a' U ?]", "~A[~'a' U ~?]", "~E[? W 'a']", "~E[~? W ~'a']", "~A[? W 'a']", "~A[~? W ~'a']", "~E['a' oU ?]", "~E[~'a' oU ~?]", "~A['a' oU ?]", "~A[~'a' oU ~?]", "~E[? oW 'a']", "~E[~? oW ~'a']", "~A[? oW 'a']", "~A[~? oW ~'a']", "~E['a' dU ?]", "~E[~'a' dU ~?]", "~A['a' dU ?]", "~A[~'a' dU ~?]", "~E[? dW 'a']", "~E[~? dW ~'a']", "~A[? dW 'a']", "~A[~? dW ~'a']", "? -> ~(AF 'a')", "~(EG ? <-> 'a')" ] nnfs = [ "~?", "?", "~'a' | ~?", "'a' | ?", "~? & ~'a'", "? & 'a'", "~'a' | ?", "'a' | ~?", "'a' & ~?", "~'a' & ?", "(~? | 'a') & (? | ~'a')", "(? | ~'a') & (~? | 'a')", "(? & ~'a') | (~? & 'a')", "(~? & 'a') | (? & ~'a')", "AX ~?", "AX ?", "EX ~?", "EX ?", "AG ~?", "AG ?", "EG ~?", "EG ?", "AF ~?", "AF ?", "EF ~?", "EF ?", "A[~? oW ~'a']", "A[? oW 'a']", "E[~? oW ~'a']", "E[? oW 'a']", "A[~'a' oU ~?]", "A['a' oU ?]", "E[~'a' oU ~?]", "E['a' oU ?]", "A[~? W ~'a']", "A[? W 'a']", "E[~? W ~'a']", "E[? W 'a']", "A[~'a' U ~?]", "A['a' U ?]", "E[~'a' U ~?]", "E['a' U ?]", "A[('a' | ~?) oW ~'a']", "A[(~'a' | ?) oW 'a']", "E[('a' | ~?) oW ~'a']", "E[(~'a' | ?) oW 'a']", "A[(? | ~'a') oU ~?]", "A[(~? | 'a') oU ?]", "E[(? | ~'a') oU ~?]", "E[(~? | 'a') oU ?]", "~? | EG ~'a'", "(EG ? & ~'a') | (AF ~? & 'a')" ] for (query, nnf) in zip(queries, nnfs): self.assertEqual(negation(parse_ctlq(query)), parse_ctlq(nnf))
def test_and(self): ast = negation_normal_form(parse_ctlq("AX AG (? & False)")) ast2 = negation_normal_form(parse_ctlq("AX AG ?")) self.assertTrue(check_ctlqx(ast)) self.assertTrue(check_ctlqx(ast2)) fsm = self.init_model() self.assertEqual(solve_ctlqx(fsm, ast), solve_ctlqx(fsm, ast2))
def test_replace_placeholder(self): query1 = "? | 'a'" query2 = "True -> AG ('a' & ?)" query3 = "A [? U AG ('b' -> False & AX ?)]" self.assertEqual(count(replace(parse_ctlq(query1), TrueExp())), 0) self.assertEqual(count(replace(parse_ctlq(query2), TrueExp())), 0) self.assertEqual(count(replace(parse_ctlq(query3), TrueExp())), 0)
def test_count_placeholders(self): query1 = "? | 'a'" query2 = "? -> AG ('a' & ?)" query3 = "A [? U AG (? -> 'a' & AX ?)]" self.assertEqual(count(parse_ctlq(query1)), 1) self.assertEqual(count(parse_ctlq(query2)), 2) self.assertEqual(count(parse_ctlq(query3)), 3)
def test_negation_normal_form(self): queries = ["~?", "~(~?)", "~('a' & ?)", "~(~'a' & ~?)", "~(? | 'a')", "~(~? | ~'a')", "'a' -> ?", "~'a' -> ~?", "~('a' -> ?)", "~(~'a' -> ~?)", "? <-> 'a'", "~? <-> ~'a'", "~(? <-> 'a')", "~(~? <-> ~'a')", "~EX ?", "~EX ~?", "~AX ?", "~AX ~?", "~EF ?", "~EF ~?", "~AF ?", "~AF ~?", "~EG ?", "~EG ~?", "~AG ?", "~AG ~?", "~E['a' U ?]", "~E[~'a' U ~?]", "~A['a' U ?]", "~A[~'a' U ~?]", "~E[? W 'a']", "~E[~? W ~'a']", "~A[? W 'a']", "~A[~? W ~'a']", "~E['a' oU ?]", "~E[~'a' oU ~?]", "~A['a' oU ?]", "~A[~'a' oU ~?]", "~E[? oW 'a']", "~E[~? oW ~'a']", "~A[? oW 'a']", "~A[~? oW ~'a']", "~E['a' dU ?]", "~E[~'a' dU ~?]", "~A['a' dU ?]", "~A[~'a' dU ~?]", "~E[? dW 'a']", "~E[~? dW ~'a']", "~A[? dW 'a']", "~A[~? dW ~'a']", "? -> ~(AF 'a')", "~(EG ? <-> 'a')"] nnfs = ["~?", "?", "~'a' | ~?", "'a' | ?", "~? & ~'a'", "? & 'a'", "~'a' | ?", "'a' | ~?", "'a' & ~?", "~'a' & ?", "(~? | 'a') & (? | ~'a')", "(? | ~'a') & (~? | 'a')", "(? & ~'a') | (~? & 'a')", "(~? & 'a') | (? & ~'a')", "AX ~?", "AX ?", "EX ~?", "EX ?", "AG ~?", "AG ?", "EG ~?", "EG ?", "AF ~?", "AF ?", "EF ~?", "EF ?", "A[~? oW ~'a']", "A[? oW 'a']", "E[~? oW ~'a']", "E[? oW 'a']", "A[~'a' oU ~?]", "A['a' oU ?]", "E[~'a' oU ~?]", "E['a' oU ?]", "A[~? W ~'a']", "A[? W 'a']", "E[~? W ~'a']", "E[? W 'a']", "A[~'a' U ~?]", "A['a' U ?]", "E[~'a' U ~?]", "E['a' U ?]", "A[('a' | ~?) oW ~'a']", "A[(~'a' | ?) oW 'a']", "E[('a' | ~?) oW ~'a']", "E[(~'a' | ?) oW 'a']", "A[(? | ~'a') oU ~?]", "A[(~? | 'a') oU ?]", "E[(? | ~'a') oU ~?]", "E[(~? | 'a') oU ?]", "~? | EG ~'a'", "(EG ? & ~'a') | (AF ~? & 'a')"] for (query, nnf) in zip(queries, nnfs): self.assertEqual(negation(parse_ctlq(query)), parse_ctlq(nnf))
def test_path_to_placeholder(self): query1 = "? | 'a'" query2 = "True -> AG ('a' & ?)" query3 = "A ['a' U AG (AX ? & 'b' -> A[False U True])]" self.assertEqual(path(parse_ctlq(query1)), ['_Or', 'Placeholder']) self.assertEqual(path(parse_ctlq(query2)), ['Imply_', 'AG', 'And_', 'Placeholder']) self.assertEqual(path(parse_ctlq(query3)), ['AU_', 'AG', '_Imply', '_And', 'AX', 'Placeholder'])
def test_fail_no_placeholder(self): kos = ["False", "~'a'", "EF True", "'a = 3' & 'b = 2'", "A['b' U 'a']"] for ko in kos: with self.assertRaises(NoPlaceholderError): parse_ctlq(ko)
def test_associativity(self): list1 = ["'a' & 'b' & ?", "'a' | 'b' | ?", "'a' <-> 'b' <-> ?", "'a' -> 'b' -> ?"] list2 = ["('a' & 'b') & ?", "('a' | 'b') | ?", "('a' <-> 'b') <-> ?", "'a' -> ('b' -> ?)"] for (elem1, elem2) in zip(list1, list2): self.assertEqual(parse_ctlq(elem1), parse_ctlq(elem2))
def test_parentheses(self): list1 = ["?", "'a' & 'b' | ?", "A['a' U ?]", "~ EF ?"] list2 = ["((((?))))", "(('a') & ('b')) | (?)", "(A[(('a')) U (?)])", "((~EF ((?))))"] for (elem1, elem2) in zip(list1, list2): self.assertEqual(parse_ctlq(elem1), parse_ctlq(elem2))
def test_commutativity(self): list1 = ["?", "? & 'a'", "? | 'a'", "? <-> 'a'", "? | 'a' & ~True"] list2 = ["?", "'a' & ?", "'a' | ?", "'a' <-> ?", "~True & 'a' | ?"] for (elem1, elem2) in zip(list1, list2): self.assertEqual(parse_ctlq(elem1), parse_ctlq(elem2))
def test_fail_parsing(self): kos = ["", "'test", "AG true", "EX ? True", "A(? U 'a')", "A[& U ~]", "(EF ?", "'a' (&) ?", "E['a' (U) ?]", "E AF [? oW False]"] for ko in kos: with self.assertRaises(pyparsing.ParseException): parse_ctlq(ko)
def test_ko_not_nnf(self): kos = [ "~AX ?", "~EX ?", "~EF ?", "? -> 'a'", "'a' -> ?", "~(? -> AF 'a')" ] for ko in kos: self.assertFalse(check_ctlqx(parse_ctlq(ko)))
def test_false(self): ast = negation_normal_form( parse_ctlq("A['admin = bob' oW A['admin = alice' oU AG ?]]")) self.assertTrue(check_ctlqx(ast)) fsm = self.init_model() self.assertEqual(solve_ctlqx(fsm, ast), BDD.false(fsm.bddEnc.DDmanager))
def test_imply(self): ast = parse_ctlq("? -> 'a = 42'") self.assertEqual(type(ast), Imply) self.assertEqual(type(ast.left), Placeholder) self.assertEqual(type(ast.right), Atom) self.assertEqual(ast.right.value, 'a = 42')
def test_ast_to_spec(self): queries = ["?", "~?", "'request' & ?", "? | 'state = ready'", "? -> '!request'", "'state = busy' <-> ?", "AX ?", "AF ?", "AG ?", "EX ?", "EF ?", "EG ?", "A[True U ?]", "A[? W False]", "E[? U True]", "E[False W ?]", "A[False oU ?]", "A[? oW True]", "A[True dU ?]", "A[? dW False]", "E[False oU ?]", "E[? oW True]", "E[True dU ?]", "E[? dW False]"] for query in queries: init_nusmv() self.init_model() self.assertIsInstance(ast_to_spec(replace(parse_ctlq(query), TrueExp())), Spec) deinit_nusmv()
def test_or(self): ast = negation_normal_form(parse_ctlq("AF ('admin = bob' | AG ?)")) self.assertTrue(check_ctlqx(ast)) fsm = self.init_model() solution = {HashableDict({'admin': 'alice', 'state': 'waiting'}), HashableDict({'admin': 'alice', 'state': 'processing'})} self.assertCountEqual(bdd_to_set(fsm, solve_ctlqx(fsm, ast)), solution)
def test_aou(self): ast = parse_ctlq("A[? oU 'a']") self.assertEqual(type(ast), AoU) self.assertEqual(type(ast.left), Placeholder) self.assertEqual(type(ast.right), Atom) self.assertEqual(ast.right.value, 'a')
def test_edu(self): ast = parse_ctlq("E[? dU 'a']") self.assertEqual(type(ast), EdU) self.assertEqual(type(ast.left), Placeholder) self.assertEqual(type(ast.right), Atom) self.assertEqual(ast.right.value, 'a')
def test_edw(self): ast = parse_ctlq("E['a' dW ?]") self.assertEqual(type(ast), EdW) self.assertEqual(type(ast.left), Atom) self.assertEqual(ast.left.value, 'a') self.assertEqual(type(ast.right), Placeholder)
def test_aow(self): ast = parse_ctlq("A['a' oW ?]") self.assertEqual(type(ast), AoW) self.assertEqual(type(ast.left), Atom) self.assertEqual(ast.left.value, 'a') self.assertEqual(type(ast.right), Placeholder)
def test_iff(self): ast = parse_ctlq("'a = 42' <-> ?") self.assertEqual(type(ast), Iff) self.assertEqual(type(ast.left), Atom) self.assertEqual(ast.left.value, 'a = 42') self.assertEqual(type(ast.right), Placeholder)
def test_false(self): ast = negation_normal_form( parse_ctlq("A['admin = bob' oW A['admin = alice' oU AG ?]]") ) self.assertTrue(check_ctlqx(ast)) fsm = self.init_model() self.assertEqual(solve_ctlqx(fsm, ast), BDD.false(fsm.bddEnc.DDmanager))
def test_str(self): logical = parse_ctlq("~? & True | False -> 'a' <-> 'b'") unary = parse_ctlq("AX EX AG EG AF EF ?") binary = parse_ctlq("A[True U A[True W E[True U E[True W ?]]]]") binary2 = parse_ctlq("A[True oU A[True oW E[True oU E[True oW ?]]]]") binary3 = parse_ctlq("A[True dU A[True dW E[True dU E[True dW ?]]]]") self.assertEqual(str(logical), "((((~(?) & True) | False) -> 'a') <-> 'b')") self.assertEqual(str(unary), "AX (EX (AG (EG (AF (EF (?))))))") self.assertEqual(str(binary), "A[True U A[True W E[True U E[True W ?]]]]") self.assertEqual(str(binary2), "A[True oU A[True oW E[True oU E[True oW ?]]]]") self.assertEqual(str(binary3), "A[True dU A[True dW E[True dU E[True dW ?]]]]")
def test_precedence(self): list1 = ["? | 'a' & ~True", "'a' & 'b' -> ~'c' | ?", "AG ~? | 'a'", "AF ~(? & 'a') & 'b'", "AX ~AG 'a' & ? | 'b'", "E[~'a' & ? dW ~AX 'b']", "EX AX 'a' & EX AX ?"] list2 = ["((?) | (('a') & (~(True))))", "((('a') & ('b')) -> ((~('c')) | (?)))", "((AG (~(?))) | ('a'))", "((AF ~((?) & ('a'))) & ('b'))", "(((AX (~(AG ('a')))) & (?)) | ('b'))", "(E[((~('a')) & (?)) dW (~(AX ('b')))])", "((EX (AX ('a'))) & (EX (AX (?))))"] for (elem1, elem2) in zip(list1, list2): self.assertEqual(parse_ctlq(elem1), parse_ctlq(elem2))
def test_au(self): ast = negation_normal_form(parse_ctlq("A[? U 'state = processing']")) self.assertTrue(check_ctlqx(ast)) fsm = self.init_model() solution = {HashableDict({'admin': 'none', 'state': 'starting'}), HashableDict({'admin': 'none', 'state': 'choosing'}), HashableDict({'admin': 'alice', 'state': 'waiting'}), HashableDict({'admin': 'bob', 'state': 'waiting'})} self.assertCountEqual(bdd_to_set(fsm, solve_ctlqx(fsm, ast)), solution)
def test_simplify_conjunction(self): ast = negation_normal_form(parse_ctlq("AG (? -> AF 'heat')")) self.assertTrue(check_ctlqx(ast)) fsm = self.init_model('examples/microwave.smv') simplification = simplify(fsm, solve_ctlqx(fsm, ast), 2) self.assertCountEqual('(error = FALSE)\n& (close = TRUE)\n&' ' ((heat = FALSE & start = TRUE) |' ' (heat = TRUE & start = TRUE) |' ' (heat = TRUE & start = FALSE))', simplification)
def test_simplify_fail(self): ast = negation_normal_form(parse_ctlq("?")) self.assertTrue(check_ctlqx(ast)) fsm = self.init_model('examples/microwave.smv') with self.assertRaises(VariableNotInModelError): simplify(fsm, solve_ctlqx(fsm, ast), 1, ['a']) with self.assertRaises(ValueOutOfBoundsError): simplify(fsm, solve_ctlqx(fsm, ast), 0) with self.assertRaises(ValueOutOfBoundsError): simplify(fsm, solve_ctlqx(fsm, ast), 10)
def test_not_equal(self): list1 = ["?", "AX ?", "AF ?", "EG (True & ?)", "E[? U True]", "A[False W ?]", "A['a' W ?]", "A['a' oU ?]"] list2 = ["~?", "EX ?", "AF ~?", "EG (False & ?)", "A[? U True]", "A[False U ?]", "A[? W 'a']", "A['b' oU ?]"] for (elem1, elem2) in zip(list1, list2): self.assertNotEqual(parse_ctlq(elem1), parse_ctlq(elem2))
def test_or(self): ast = negation_normal_form(parse_ctlq("AF ('admin = bob' | AG ?)")) self.assertTrue(check_ctlqx(ast)) fsm = self.init_model() solution = { HashableDict({ 'admin': 'alice', 'state': 'waiting' }), HashableDict({ 'admin': 'alice', 'state': 'processing' }) } self.assertCountEqual(bdd_to_set(fsm, solve_ctlqx(fsm, ast)), solution)
def test_ast_to_spec(self): queries = [ "?", "~?", "'request' & ?", "? | 'state = ready'", "? -> '!request'", "'state = busy' <-> ?", "AX ?", "AF ?", "AG ?", "EX ?", "EF ?", "EG ?", "A[True U ?]", "A[? W False]", "E[? U True]", "E[False W ?]", "A[False oU ?]", "A[? oW True]", "A[True dU ?]", "A[? dW False]", "E[False oU ?]", "E[? oW True]", "E[True dU ?]", "E[? dW False]" ] for query in queries: init_nusmv() self.init_model() self.assertIsInstance( ast_to_spec(replace(parse_ctlq(query), TrueExp())), Spec) deinit_nusmv()
def test_ko(self): kos = [ "? <-> 'a'", "'a' <-> ?", "AF ?", "A['a' U ?]", "A['a' W ?]", "A['a' oU ?]", "A['a' oW ?]", "A[? dU 'a']", "A[? dW 'a']", "EX ?", "EF ?", "EG ?", "~AX ?", "~AF ?", "~AG ?", "E['a' U ?]", "E[? U 'a']", "E['a' W ?]", "E[? W 'a']", "E['a' oU ?]", "E[? oU 'a']", "E['a' oW ?]", "E[? oW 'a']", "E['a' dU ?]", "E[? dU 'a']", "E['a' dW ?]", "E[? dW 'a']", "~('a' -> AF ?)", "AF ('a' & AF ('b' | AG ?))", "AX ((AF A[? dU 'b']) | 'a')", "AF A[True oU A[? U 'a']]", "A['a' U A[True oU A[? U 'b']]]", "A['a' W A[True oU A[? U 'b']]]", "A['a' oU A[True oU A[? U 'b']]]", "A['a' oW A[True oU A[? U 'b']]]", "AF AX (A['a' W A[? U 'b']] | False)", "AF A['a' dW A['b' W A[? U 'c']]]", "AF A['a' oW A['b' W A[? U 'c']]]", "AF A[A['a' W A[? U 'b']] oW 'c']", "AF A['a' dU A['b' W A[? U 'c']]]", "AF A['a' oU A['b' W A[? U 'c']]]", "AF A[A['a' W A[? U 'b']] oU 'c']", "AF AX A[AF AX (AG ? & True) U False]", "A['a' U A['b' oU A[A[A['c' dW AG ?] W 'e'] oW 'f']]]", "AF AX ('a' & (('b' & A['c' oW AG ?]) | 'd'))", "AF AX ('a' & (('b' & ('c' | A['d' oW AG ?])) | 'e'))", "AF ('a' & A['b' oW (A['c' oW AG ?] | 'd')])", "AF AX A['b' oW (A['c' oW AG ?] | 'd')]", "AF AX (('a' | A[AG ? U 'b']) & 'c')", "AF ('a' & (A['b' oW (A['c' oW AG ?] | 'd')] | 'e'))", "A['a' U A['b' dW A['c' oU A[AG (AG ? | 'd') U 'e']]]]", "A['a' U A['b' oU A['c' oU A[AG (AG ? | 'd') U 'e']]]]", "A['a' U A[A['b' oU A[AG (AG ? | 'c') U 'd']] oU 'e']]", "A['a' U A['b' dU A['c' oU A[AG (AG ? | 'd') U 'e']]]]", "A['a' U A[A['b' oU A[AG (AG ? | 'c') U 'd']] oW 'e']]", "A['a' U A['b' oW A['c' oU A[AG (AG ? | 'd') U 'e']]]]", "AF A['a' oU A['b' oW A[AG A[AG ? U 'c'] U 'd']]]", "A['a' U AX A['b' U A[AG ? U 'c']]]", "A['a' U AX A['b' W A[AG ? U 'c']]]", "A['a' U AX A['b' dU A[AG ? U 'c']]]", "A['a' U AX A['b' dW A[AG ? U 'c']]]", "A['a' U AX A[A[AG ? U 'b'] U 'c']]", "A['a' U AX A[A[AG ? U 'b'] W 'c']]", "A['a' U AX A[A[AG ? U 'b'] oU 'c']]", "A['a' U AX A[A[AG ? U 'b'] oW 'c']]" ] for ko in kos: self.assertFalse(check_ctlqx(negation_normal_form(parse_ctlq(ko))))
def test_ko(self): kos = ["? <-> 'a'", "'a' <-> ?", "AF ?", "A['a' U ?]", "A['a' W ?]", "A['a' oU ?]", "A['a' oW ?]", "A[? dU 'a']", "A[? dW 'a']", "EX ?", "EF ?", "EG ?", "~AX ?", "~AF ?", "~AG ?", "E['a' U ?]", "E[? U 'a']", "E['a' W ?]", "E[? W 'a']", "E['a' oU ?]", "E[? oU 'a']", "E['a' oW ?]", "E[? oW 'a']", "E['a' dU ?]", "E[? dU 'a']", "E['a' dW ?]", "E[? dW 'a']", "~('a' -> AF ?)", "AF ('a' & AF ('b' | AG ?))", "AX ((AF A[? dU 'b']) | 'a')", "AF A[True oU A[? U 'a']]", "A['a' U A[True oU A[? U 'b']]]", "A['a' W A[True oU A[? U 'b']]]", "A['a' oU A[True oU A[? U 'b']]]", "A['a' oW A[True oU A[? U 'b']]]", "AF AX (A['a' W A[? U 'b']] | False)", "AF A['a' dW A['b' W A[? U 'c']]]", "AF A['a' oW A['b' W A[? U 'c']]]", "AF A[A['a' W A[? U 'b']] oW 'c']", "AF A['a' dU A['b' W A[? U 'c']]]", "AF A['a' oU A['b' W A[? U 'c']]]", "AF A[A['a' W A[? U 'b']] oU 'c']", "AF AX A[AF AX (AG ? & True) U False]", "A['a' U A['b' oU A[A[A['c' dW AG ?] W 'e'] oW 'f']]]", "AF AX ('a' & (('b' & A['c' oW AG ?]) | 'd'))", "AF AX ('a' & (('b' & ('c' | A['d' oW AG ?])) | 'e'))", "AF ('a' & A['b' oW (A['c' oW AG ?] | 'd')])", "AF AX A['b' oW (A['c' oW AG ?] | 'd')]", "AF AX (('a' | A[AG ? U 'b']) & 'c')", "AF ('a' & (A['b' oW (A['c' oW AG ?] | 'd')] | 'e'))", "A['a' U A['b' dW A['c' oU A[AG (AG ? | 'd') U 'e']]]]", "A['a' U A['b' oU A['c' oU A[AG (AG ? | 'd') U 'e']]]]", "A['a' U A[A['b' oU A[AG (AG ? | 'c') U 'd']] oU 'e']]", "A['a' U A['b' dU A['c' oU A[AG (AG ? | 'd') U 'e']]]]", "A['a' U A[A['b' oU A[AG (AG ? | 'c') U 'd']] oW 'e']]", "A['a' U A['b' oW A['c' oU A[AG (AG ? | 'd') U 'e']]]]", "AF A['a' oU A['b' oW A[AG A[AG ? U 'c'] U 'd']]]", "A['a' U AX A['b' U A[AG ? U 'c']]]", "A['a' U AX A['b' W A[AG ? U 'c']]]", "A['a' U AX A['b' dU A[AG ? U 'c']]]", "A['a' U AX A['b' dW A[AG ? U 'c']]]", "A['a' U AX A[A[AG ? U 'b'] U 'c']]", "A['a' U AX A[A[AG ? U 'b'] W 'c']]", "A['a' U AX A[A[AG ? U 'b'] oU 'c']]", "A['a' U AX A[A[AG ? U 'b'] oW 'c']]"] for ko in kos: self.assertFalse(check_ctlqx(negation_normal_form(parse_ctlq(ko))))
def test_ok(self): oks = [ "?", "~?", "? & 'a'", "'a' & ?", "? | 'a'", "'a' | ?", "? -> 'a'", "'a' -> ?", "AX ?", "AG ?", "~EX ?", "~EF ?", "A[? U 'a']", "A[? W 'a']", "A[? oU 'a']", "A[? oW 'a']", "A['a' dW ?]", "A['a' dU ?]", "AX ((AG A['b' dU ?]) | EX 'a')", "~(? -> AF 'a')", "True & A[? U 'a']", "True | A[? U 'a']", "True & A['a' oU A[? U 'b']]", "True | A['a' oU A[? U 'b']]", "AX A[? U 'a']", "AX A['a' oU A[? U 'b']]", "AF A[? U 'a']", "AG A[? U 'a']", "AG A['a' oU A[? U 'b']]", "A[A[? U 'a'] U 'b']", "A[A['a' oU A[? U 'b']] U 'c']", "A['a' U A[? U 'b']]", "A[A[? U 'a'] W 'b']", "A[A['a' oU A[? U 'b']] W 'c']", "A['a' W A[? U 'b']]", "A[A[? U 'a'] oU 'b']", "A[A['a' oU A[? U 'b']] oU 'c']", "A['a' dU A[? U 'b']]", "A['a' dU A['b' oU A[? U 'c']]]", "A[A[? oW 'a'] U 'b']", "A[A[? U 'a'] oW 'b']", "A[A['a' oU A[? U 'b']] oW 'c']", "A['a' oW A[? U 'b']]", "A['a' dW A[? U 'b']]", "A['a' dW A['b' oU A[? U 'c']]]", "A['a' W A['b' W A[? U 'c']]]", "A[A[A[? U 'a'] W 'b'] W 'c']", "A['a' U A['b' W A[? U 'c']]]", "A[A[A[? U 'a'] W 'b'] U 'c']", "AG A['b' W A[? U 'c']]", "AF A['b' W A[? U 'c']]", "A['a' dW A['b' W A['c' U AG AG ?]]]", "AF A['a' oW AG ?]", "A['a' oU A[AG ? oU 'b']]", "A['a' oW A[AG ? oW 'b']]", "A['a' dU A['b' dU A['c' oW AG ?]]]", "AX A['a' oW AG ?]", "AF A['a' oW ('b' | A['c' oW AG ?])]", "AF A[AG ? U False]", "A['a' dW A['b' oW A[A[A['c' oW AG ?] oU 'd'] oW 'e']]]", "A['a' U A['b' oW AG ?]]", "A['a' W A['b' oW AG ?]]", "A['a' oU A['b' oW AG ?]]", "AG A['a' oU A[AG ? U 'b']]", "AG AX AF ('a' | ('b' & AG A['c' oW AG ?]))", "A['a' W A[A['b' U A[AG A['c' oW AG ?] U 'd']] W 'e']]", "A['a' oW A[A['b' oU A[AG A['c' oW AG ?] oU 'd']] oW 'e']]", "A['a' dU A['b' dW AG A['c' oW AG ?]]]", "A['a' dU (AG A['b' dW ('c' | AG ?)] | 'd')]", "A[('a' | AG A['b' oU (AG ? | 'c')]) oU 'd']", "A[('a' | AG A['b' U (AG ? | 'c')]) U 'd']", "A[('a' | AG A['b' W (AG ? | 'c')]) W 'd']", "A['a' W A['b' oU A[A['c' oW AG ?] U 'd']]]", "A[A['a' oW A[A['b' oW AG ?] W 'c']] U 'd']", "A[A['a' oU A[AG ? U 'b']] W 'c']", "A['a' U A['b' oU A[AG ? U 'c']]]" ] for ok in oks: self.assertTrue(check_ctlqx(negation_normal_form(parse_ctlq(ok))))
def test_ok(self): oks = ["?", "~?", "? & 'a'", "'a' & ?", "? | 'a'", "'a' | ?", "? -> 'a'", "'a' -> ?", "AX ?", "AG ?", "~EX ?", "~EF ?", "A[? U 'a']", "A[? W 'a']", "A[? oU 'a']", "A[? oW 'a']", "A['a' dW ?]", "A['a' dU ?]", "AX ((AG A['b' dU ?]) | EX 'a')", "~(? -> AF 'a')", "True & A[? U 'a']", "True | A[? U 'a']", "True & A['a' oU A[? U 'b']]", "True | A['a' oU A[? U 'b']]", "AX A[? U 'a']", "AX A['a' oU A[? U 'b']]", "AF A[? U 'a']", "AG A[? U 'a']", "AG A['a' oU A[? U 'b']]", "A[A[? U 'a'] U 'b']", "A[A['a' oU A[? U 'b']] U 'c']", "A['a' U A[? U 'b']]", "A[A[? U 'a'] W 'b']", "A[A['a' oU A[? U 'b']] W 'c']", "A['a' W A[? U 'b']]", "A[A[? U 'a'] oU 'b']", "A[A['a' oU A[? U 'b']] oU 'c']", "A['a' dU A[? U 'b']]", "A['a' dU A['b' oU A[? U 'c']]]", "A[A[? oW 'a'] U 'b']", "A[A[? U 'a'] oW 'b']", "A[A['a' oU A[? U 'b']] oW 'c']", "A['a' oW A[? U 'b']]", "A['a' dW A[? U 'b']]", "A['a' dW A['b' oU A[? U 'c']]]", "A['a' W A['b' W A[? U 'c']]]", "A[A[A[? U 'a'] W 'b'] W 'c']", "A['a' U A['b' W A[? U 'c']]]", "A[A[A[? U 'a'] W 'b'] U 'c']", "AG A['b' W A[? U 'c']]", "AF A['b' W A[? U 'c']]", "A['a' dW A['b' W A['c' U AG AG ?]]]", "AF A['a' oW AG ?]", "A['a' oU A[AG ? oU 'b']]", "A['a' oW A[AG ? oW 'b']]", "A['a' dU A['b' dU A['c' oW AG ?]]]", "AX A['a' oW AG ?]", "AF A['a' oW ('b' | A['c' oW AG ?])]", "AF A[AG ? U False]", "A['a' dW A['b' oW A[A[A['c' oW AG ?] oU 'd'] oW 'e']]]", "A['a' U A['b' oW AG ?]]", "A['a' W A['b' oW AG ?]]", "A['a' oU A['b' oW AG ?]]", "AG A['a' oU A[AG ? U 'b']]", "AG AX AF ('a' | ('b' & AG A['c' oW AG ?]))", "A['a' W A[A['b' U A[AG A['c' oW AG ?] U 'd']] W 'e']]", "A['a' oW A[A['b' oU A[AG A['c' oW AG ?] oU 'd']] oW 'e']]", "A['a' dU A['b' dW AG A['c' oW AG ?]]]", "A['a' dU (AG A['b' dW ('c' | AG ?)] | 'd')]", "A[('a' | AG A['b' oU (AG ? | 'c')]) oU 'd']", "A[('a' | AG A['b' U (AG ? | 'c')]) U 'd']", "A[('a' | AG A['b' W (AG ? | 'c')]) W 'd']", "A['a' W A['b' oU A[A['c' oW AG ?] U 'd']]]", "A[A['a' oW A[A['b' oW AG ?] W 'c']] U 'd']", "A[A['a' oU A[AG ? U 'b']] W 'c']", "A['a' U A['b' oU A[AG ? U 'c']]]"] for ok in oks: self.assertTrue(check_ctlqx(negation_normal_form(parse_ctlq(ok))))
def test_au(self): ast = negation_normal_form(parse_ctlq("A[? U 'state = processing']")) self.assertTrue(check_ctlqx(ast)) fsm = self.init_model() solution = { HashableDict({ 'admin': 'none', 'state': 'starting' }), HashableDict({ 'admin': 'none', 'state': 'choosing' }), HashableDict({ 'admin': 'alice', 'state': 'waiting' }), HashableDict({ 'admin': 'bob', 'state': 'waiting' }) } self.assertCountEqual(bdd_to_set(fsm, solve_ctlqx(fsm, ast)), solution)
def test_and(self): ast = parse_ctlq("? & True") self.assertEqual(type(ast), And) self.assertEqual(type(ast.left), Placeholder) self.assertEqual(type(ast.right), TrueExp)
def test_ax(self): ast = parse_ctlq("AX ?") self.assertEqual(type(ast), AX) self.assertEqual(type(ast.child), Placeholder)
def test_or(self): ast = parse_ctlq("False | ?") self.assertEqual(type(ast), Or) self.assertEqual(type(ast.left), FalseExp) self.assertEqual(type(ast.right), Placeholder)