def get_example_non_minimal(): """ A non minimal example a.a*.b""" enfa0 = EpsilonNFA() state0 = State(0) state3 = State(3) state4 = State(4) state5 = State(5) state6 = State(6) state1 = State(1) state2 = State(2) symb_a = Symbol("a") symb_b = Symbol("b") enfa0.add_start_state(state0) enfa0.add_final_state(state3) enfa0.add_final_state(state4) enfa0.add_transition(state0, symb_a, state1) enfa0.add_transition(state1, symb_a, state2) enfa0.add_transition(state2, symb_a, state5) enfa0.add_transition(state5, symb_a, state6) enfa0.add_transition(state6, symb_a, state1) enfa0.add_transition(state1, symb_b, state3) enfa0.add_transition(state2, symb_b, state4) enfa0.add_transition(state5, symb_b, state3) enfa0.add_transition(state6, symb_b, state4) return enfa0
def test_enfa_intersection(): # Building example automatons enfa0 = EpsilonNFA() state0 = State(0) state1 = State(1) state2 = State(2) symb_a = Symbol("a") symb_b = Symbol("b") symb_c = Symbol("c") enfa0.add_start_state(state0) enfa0.add_final_state(state2) enfa0.add_transition(state0, symb_a, state0) enfa0.add_transition(state0, symb_b, state1) enfa0.add_transition(state1, symb_c, state2) enfa1 = EpsilonNFA() state3 = State(3) state4 = State(4) state5 = State(5) enfa1.add_start_state(state3) enfa1.add_final_state(state5) enfa1.add_transition(state3, symb_a, state4) enfa1.add_transition(state4, symb_b, state5) enfa1.add_transition(state5, symb_c, state5) # getting intersection enfa = enfa0 & enfa1 assert not enfa.accepts([symb_b]) assert not enfa.accepts([symb_a]) assert not enfa.accepts([]) assert not enfa.accepts([symb_a, symb_a, symb_b, symb_c]) assert not enfa.accepts([symb_a, symb_b, symb_c, symb_c]) assert enfa.accepts([symb_a, symb_b, symb_c])
def _test_profiling_intersection(self): size = 50 states = [State(i) for i in range(size * 2 + 1)] symb_a = Symbol("a") symb_b = Symbol("b") dfa = DeterministicFiniteAutomaton(states, {symb_a, symb_b}, start_state=states[0], final_states={states[-1]}) for i in range(size): dfa.add_transition(states[i], symb_a, states[i + 1]) for i in range(size, size * 2): dfa.add_transition(states[i], symb_b, states[i + 1]) ter_a = Terminal("a") ter_b = Terminal("b") var_s = Variable("S") var_s1 = Variable("S1") var_l = Variable("L") productions = [ Production(var_s, [var_l, var_s1]), Production(var_l, [Epsilon()]), Production(var_s1, [ter_a, var_s1, ter_b]), Production(var_s1, [ter_b, var_s1, ter_a]), Production(var_s1, []) ] cfg = CFG(productions=productions, start_symbol=var_s) cfg_i = cfg.intersection(dfa) self.assertFalse(cfg_i.is_empty()) self.assertTrue(cfg_i.contains([ter_a] * size + [ter_b] * size)) self.assertFalse(cfg_i.contains([]))
def test_DFA_intersection(): symb_a = Symbol("a") symb_b = Symbol("b") state0 = State(0) state1 = State(1) dfa1 = DeterministicFiniteAutomaton() dfa2 = DeterministicFiniteAutomaton() dfa1.add_start_state(state0) dfa2.add_start_state(state0) dfa1.add_final_state(state1) dfa2.add_final_state(state1) dfa1.add_transition(state0, symb_a, state1) dfa1.add_transition(state1, symb_b, state0) dfa2.add_transition(state0, symb_a, state1) dfa2.add_transition(state1, symb_b, state1) dfa_intersection = dfa1 & dfa2 assert dfa1.accepts("ababa") assert dfa1.accepts("a") assert not dfa2.accepts("ababa") assert dfa2.accepts("abbbb") assert dfa2.accepts("a") assert not dfa1.accepts("abbbb") assert dfa_intersection.accepts("a") assert not dfa_intersection.accepts("ababa") assert not dfa_intersection.accepts("abbbb")
def _perform_tests_example0(self, dfa): """ Tests for DFA from example 0 """ symb_a = Symbol("a") symb_b = Symbol("b") symb_c = Symbol("c") symb_d = Symbol("d") state0 = State(0) state1 = State(1) self.assertTrue(dfa.accepts([symb_a, symb_b, symb_c])) self.assertTrue(dfa.accepts([symb_a, symb_b, symb_b, symb_b, symb_c])) self.assertTrue(dfa.accepts([symb_a, symb_b, symb_d])) self.assertTrue(dfa.accepts([symb_a, symb_d])) self.assertFalse(dfa.accepts([symb_a, symb_c, symb_d])) self.assertFalse(dfa.accepts([symb_d, symb_c, symb_d])) self.assertFalse(dfa.accepts([])) self.assertEqual(dfa.remove_start_state(state1), 0) self.assertTrue(dfa.accepts([symb_a, symb_b, symb_c])) self.assertEqual(dfa.remove_start_state(state0), 1) self.assertFalse(dfa.accepts([symb_a, symb_b, symb_c])) dfa.add_start_state(0) self.assertTrue(dfa.accepts(["a", "b", "c"])) self.assertTrue(dfa.accepts(["a", "b", "b", "b", "c"])) self.assertTrue(dfa.accepts(["a", "b", "d"])) self.assertTrue(dfa.accepts(["a", "d"])) self.assertFalse(dfa.accepts(["a", "c", "d"])) self.assertFalse(dfa.accepts(["d", "c", "d"])) self.assertFalse(dfa.accepts([])) self.assertEqual(dfa.remove_start_state(1), 0) self.assertTrue(dfa.accepts(["a", "b", "c"])) self.assertEqual(dfa.remove_start_state(0), 1) self.assertFalse(dfa.accepts(["a", "b", "c"]))
def test_intersection_dfa2(self): state0 = State(0) symb_a = Symbol("a") symb_b = Symbol("b") dfa = DeterministicFiniteAutomaton({state0}, {symb_a, symb_b}, start_state=state0, final_states={state0}) dfa.add_transition(state0, symb_a, state0) dfa.add_transition(state0, symb_b, state0) self.assertTrue(dfa.accepts([symb_a, symb_a, symb_b, symb_b])) ter_a = Terminal("a") ter_b = Terminal("b") var_s = Variable("S") var_s1 = Variable("S1") var_l = Variable("L") productions = { Production(var_s, [var_l, var_s1]), Production(var_l, [Epsilon()]), Production(var_s1, [ter_a, var_s1, ter_b]), Production(var_s1, [ter_b, var_s1, ter_a]), Production(var_s1, []) } cfg = CFG(productions=productions, start_symbol=var_s) self.assertTrue(cfg.contains([ter_a, ter_a, ter_b, ter_b])) self.assertFalse(cfg.contains([ter_a, ter_a, ter_b])) cfg_i = cfg.intersection(dfa) self.assertFalse(cfg_i.is_empty()) self.assertTrue(cfg_i.contains([ter_a, ter_a, ter_b, ter_b])) self.assertTrue(cfg_i.contains([]))
def test_minimize_repetition(self): dfa = DeterministicFiniteAutomaton() symb_a = Symbol('a') symb_b = Symbol("b") symb_star = Symbol("star") states = [State(x) for x in range(9)] dfa.add_start_state(states[0]) dfa.add_final_state(states[3]) dfa.add_final_state(states[4]) dfa.add_final_state(states[7]) dfa.add_final_state(states[8]) dfa.add_transition(states[0], symb_a, states[1]) dfa.add_transition(states[1], symb_star, states[2]) dfa.add_transition(states[2], symb_a, states[3]) dfa.add_transition(states[3], symb_star, states[4]) dfa.add_transition(states[3], symb_a, states[1]) dfa.add_transition(states[3], symb_b, states[5]) dfa.add_transition(states[4], symb_a, states[1]) dfa.add_transition(states[4], symb_b, states[5]) dfa.add_transition(states[0], symb_b, states[5]) dfa.add_transition(states[5], symb_star, states[6]) dfa.add_transition(states[6], symb_b, states[7]) dfa.add_transition(states[7], symb_star, states[8]) dfa.add_transition(states[7], symb_a, states[1]) dfa.add_transition(states[7], symb_b, states[5]) dfa.add_transition(states[8], symb_a, states[1]) dfa.add_transition(states[8], symb_b, states[5]) dfa = dfa.minimize() self.assertTrue(dfa.accepts([symb_a, symb_star, symb_a]))
def test_intersection(): state0 = State(0) state1 = State(1) state2 = State(2) symbol_a = Symbol("a") symbol_b = Symbol("b") symbol_c = Symbol("c") dfa0 = EpsilonNFA() dfa0.add_start_state(state0) dfa0.add_final_state(state2) dfa0.add_transition(state0, symbol_a, state1) dfa0.add_transition(state1, symbol_b, state1) dfa0.add_transition(state1, symbol_c, state2) dfa1 = EpsilonNFA() dfa1.add_start_state(state0) dfa1.add_final_state(state2) dfa1.add_transition(state0, symbol_a, state1) dfa1.add_transition(state1, symbol_b, state2) dfa1.add_transition(state1, symbol_c, state2) res = dfa0 & dfa1 check_correctness(res)
def test_intersection(self): """ Tests the intersection with a regex """ regex = Regex("a*b*") dfa = regex.to_epsilon_nfa() symb_a = Symbol("a") symb_b = Symbol("b") self.assertTrue(dfa.accepts([symb_a, symb_a, symb_b, symb_b])) self.assertFalse(dfa.accepts([symb_b, symb_b, symb_a])) ter_a = Terminal("a") ter_b = Terminal("b") var_s = Variable("S") productions = { Production(var_s, [ter_a, var_s, ter_b]), Production(var_s, [ter_b, var_s, ter_a]), Production(var_s, []) } cfg = CFG(productions=productions, start_symbol=var_s) self.assertTrue(cfg.contains([ter_a, ter_a, ter_b, ter_b])) self.assertFalse(cfg.contains([ter_a, ter_a, ter_b])) cfg_i = cfg.intersection(regex) self.assertTrue(cfg_i.contains([ter_a, ter_a, ter_b, ter_b])) self.assertFalse(cfg_i.contains([ter_a, ter_a, ter_b])) self.assertTrue(cfg_i.contains([])) cfg_i = cfg.intersection(dfa) self.assertTrue(cfg_i.contains([ter_a, ter_a, ter_b, ter_b])) self.assertFalse(cfg_i.contains([ter_a, ter_a, ter_b])) self.assertTrue(cfg_i.contains([]))
def test_pda_intersection(): q0 = State("q0") q1 = State("q1") q2 = State("q2") q3 = State("q3") a = Symbol("a") b = Symbol("b") c = Symbol("c") epsilon_nfa_1 = EpsilonNFA(states={q0, q1, q2}, input_symbols={a, b}, start_state={q0}, final_states={q1, q2}) epsilon_nfa_1.add_transition(q0, a, q1) epsilon_nfa_1.add_transition(q1, b, q2) epsilon_nfa_2 = EpsilonNFA(states={q0, q1, q3}, input_symbols={a, c}, start_state={q0}, final_states={q1, q3}) epsilon_nfa_2.add_transition(q0, a, q1) epsilon_nfa_2.add_transition(q1, c, q3) expected_epsilon_nfa = EpsilonNFA(states={q0, q1}, input_symbols={a}, start_state={q0}, final_states={q1}) expected_epsilon_nfa.add_transition(q0, a, q1) actual_intersection = epsilon_nfa_1.get_intersection(epsilon_nfa_2) assert expected_epsilon_nfa.is_equivalent_to(actual_intersection)
def test_intersection(self): """ Tests the intersection of two enfas """ enfa0 = get_enfa_example0() symb_a = Symbol("a") symb_b = Symbol("b") eps = Epsilon() enfa1 = EpsilonNFA() state0 = State(10) state1 = State(11) state2 = State(12) state3 = State(13) state4 = State(14) enfa1.add_start_state(state0) enfa1.add_final_state(state3) enfa1.add_final_state(state4) enfa1.add_transition(state0, eps, state1) enfa1.add_transition(state1, symb_a, state2) enfa1.add_transition(state2, eps, state3) enfa1.add_transition(state3, symb_b, state4) enfa = enfa0 & enfa1 self.assertEqual(len(enfa.start_states), 4) self.assertEqual(len(enfa.final_states), 2) self.assertEqual(len(enfa.symbols), 2) self.assertTrue(enfa.accepts([symb_a, symb_b])) self.assertFalse(enfa.accepts([symb_b])) self.assertFalse(enfa.accepts([symb_a])) self.assertFalse(enfa.accepts([])) self.assertFalse(enfa.accepts([symb_a, symb_a, symb_b]))
def test_minimization(self): """ Tests the minimization algorithm """ enfa = get_enfa_example0_bis() symb_a = Symbol("a") symb_b = Symbol("b") enfa = enfa.minimize() self.assertTrue(enfa.is_deterministic()) self.assertEqual(len(enfa.states), 2) self.assertTrue(enfa.accepts([symb_a, symb_b])) self.assertTrue(enfa.accepts([symb_a, symb_a, symb_b])) self.assertTrue(enfa.accepts([symb_b])) self.assertFalse(enfa.accepts([symb_a])) enfa = get_example_non_minimal() enfa = enfa.minimize() self.assertTrue(enfa.is_deterministic()) self.assertEqual(len(enfa.states), 3) self.assertTrue(enfa.accepts([symb_a, symb_b])) self.assertTrue(enfa.accepts([symb_a, symb_a, symb_b])) self.assertFalse(enfa.accepts([symb_b])) self.assertFalse(enfa.accepts([symb_a])) enfa = EpsilonNFA() enfa = enfa.minimize() self.assertTrue(enfa.is_deterministic()) self.assertEqual(len(enfa.states), 0) self.assertFalse(enfa.accepts([]))
def test_repr(self): """ Tests the representation of symbols """ symbol1 = Symbol("ABC") self.assertEqual(str(symbol1), "ABC") symbol2 = Symbol(1) self.assertEqual(str(symbol2), "1")
def test_intersection_automata(): edges = read_graph(os.path.join(DATA_PATH, 'graph_0.txt')) regex = read_regex(os.path.join(DATA_PATH, 'regex_0.txt')) dfa = regex_to_dfa(regex) query_automaton = Automaton(dfa) graph = Graph(edges) automaton_graph = Automaton.from_graph(graph) res = automaton_graph.get_intersection(query_automaton) res_automaton = res.to_automaton() a = Symbol('a') b = Symbol('b') c = Symbol('c') assert res_automaton.accepts([a, b, c]) assert res_automaton.accepts([a, c]) assert res_automaton.accepts([a, c, c]) assert not res_automaton.accepts([a, b, b, c]) assert not res_automaton.accepts([a]) assert not res_automaton.accepts([b]) assert not res_automaton.accepts([c]) assert not res_automaton.accepts([a, b]) assert not res_automaton.accepts([b, c])
def test_DFA_intersection(): char_a = Symbol("a") char_b = Symbol("b") state_start = State(0) state_final = State(1) dfa_fst = DeterministicFiniteAutomaton() dfa_fst.add_start_state(state_start) dfa_fst.add_final_state(state_final) dfa_snd = DeterministicFiniteAutomaton() dfa_snd.add_start_state(state_start) dfa_snd.add_final_state(state_final) dfa_fst.add_transition(state_start, char_a, state_final) dfa_fst.add_transition(state_final, char_b, state_start) dfa_snd.add_transition(state_start, char_a, state_final) dfa_snd.add_transition(state_final, char_b, state_final) dfa_intersection = dfa_fst & dfa_snd assert not dfa_fst.accepts("abbbb") assert dfa_fst.accepts("ababa") assert dfa_fst.accepts("a") assert not dfa_snd.accepts("ababa") assert dfa_snd.accepts("abbbb") assert dfa_snd.accepts("a") assert not dfa_intersection.accepts("ababa") assert not dfa_intersection.accepts("abbbb") assert dfa_intersection.accepts("a")
def test_check_intersection(): # Declare NFAs enfa0 = EpsilonNFA() enfa1 = EpsilonNFA() # Declare the states states = [State("q" + str(x)) for x in range(7)] # Declare the symbols epsilon = Epsilon() symb_a = Symbol("a") symb_b = Symbol("b") symb_c = Symbol("c") # epsilonNFA 0 # Add a start state enfa0.add_start_state(states[0]) # Add a final state enfa0.add_final_state(states[1]) # Add the transitions enfa0.add_transition(states[0], symb_a, states[1]) enfa0.add_transition(states[1], symb_a, states[1]) # epsilonNFA 1 # Add a start states enfa1.add_start_state(states[0]) enfa1.add_final_state(states[4]) # Add a final states enfa1.add_final_state(states[5]) enfa1.add_final_state(states[6]) # Add the transitions enfa1.add_transition(states[0], symb_a, states[1]) enfa1.add_transition(states[0], symb_b, states[2]) enfa1.add_transition(states[0], symb_c, states[3]) enfa1.add_transition(states[1], symb_a, states[4]) enfa1.add_transition(states[2], symb_b, states[5]) enfa1.add_transition(states[3], symb_c, states[6]) # Now enfa0 accepts a* \ {epsilon} # enfa1 accepts aa, bb, cc # Intersection of enfa0 and enfa1 enfa_res = enfa0.get_intersection(enfa1) # Check if a word is accepted assert enfa_res.accepts([symb_a, symb_a]), "Should accept aa" # Check non-correct words assert not enfa_res.accepts([epsilon]), "Accepts empty word, but it mustn't" assert not enfa_res.accepts([symb_a, symb_a, symb_a]), "Accepts aaa, but it mustn't" assert not enfa_res.accepts([symb_a]), "Accepts a, but it mustn't" assert not enfa_res.accepts([symb_b, symb_b]), "Accepts bb, but it mustn't" assert not enfa_res.accepts([symb_c, symb_c]), "Accepts cc, but it mustn't"
class TestAutomata: symb_a = Symbol("a") symb_b = Symbol("b") symb_c = Symbol("c") symb_d = Symbol("d") def init_dfas(self): # DFA that accepts "ab" and "ac" self.dfa1 = DeterministicFiniteAutomaton() # DFA that accepts "ac" and "ad" self.dfa2 = DeterministicFiniteAutomaton() state0 = State(0) state1 = State(1) state2 = State(2) state3 = State(3) # Add a start state self.dfa1.add_start_state(state0) self.dfa2.add_start_state(state0) # Add two final states self.dfa1.add_final_state(state2) self.dfa1.add_final_state(state3) self.dfa2.add_final_state(state2) self.dfa2.add_final_state(state3) # Create transitions self.dfa1.add_transition(state0, self.symb_a, state1) self.dfa1.add_transition(state1, self.symb_b, state2) self.dfa1.add_transition(state1, self.symb_c, state3) self.dfa2.add_transition(state0, self.symb_a, state1) self.dfa2.add_transition(state1, self.symb_c, state2) self.dfa2.add_transition(state1, self.symb_d, state3) def test_dfa1(self): self.init_dfas() assert (self.dfa1.accepts([self.symb_a, self.symb_b])) assert (self.dfa1.accepts([self.symb_a, self.symb_c])) assert (not self.dfa1.accepts([self.symb_a, self.symb_d])) def test_dfa2(self): self.init_dfas() assert (not self.dfa2.accepts([self.symb_a, self.symb_b])) assert (self.dfa2.accepts([self.symb_a, self.symb_c])) assert (self.dfa2.accepts([self.symb_a, self.symb_d])) def test_dfa_inter(self): self.init_dfas() dfa_inter = self.dfa1 & self.dfa2 # Intersection result should accept only "ac", but not "ab" or "ad" assert (not dfa_inter.accepts([self.symb_a, self.symb_b])) assert (dfa_inter.accepts([self.symb_a, self.symb_c])) assert (not dfa_inter.accepts([self.symb_a, self.symb_d]))
def test_eq(self): """ Tests equality of symbols """ symbol1 = Symbol("ABC") symbol2 = Symbol(1) symbol3 = Symbol("ABC") self.assertEqual(symbol1, symbol3) self.assertEqual(symbol2, 1) self.assertNotEqual(symbol2, symbol3) self.assertNotEqual(symbol1, symbol2)
def test_hash(self): """ Tests the hashing of symbols """ symbol1 = hash(Symbol("ABC")) symbol2 = hash(Symbol(1)) symbol3 = hash(Symbol("ABC")) self.assertIsInstance(symbol1, int) self.assertEqual(symbol1, symbol3) self.assertNotEqual(symbol2, symbol3) self.assertNotEqual(symbol1, symbol2)
def test_not_cyclic2(self): dfa = DeterministicFiniteAutomaton() state0 = State(0) state1 = State(1) symb_a = Symbol('a') symb_b = Symbol('b') dfa.add_start_state(state0) dfa.add_transition(state0, symb_a, state1) dfa.add_transition(state0, symb_b, state1) self.assertTrue(dfa.is_acyclic())
def test_to_regex3(self): """ Tests the transformation to regex """ enfa = EpsilonNFA() state0 = State(0) state1 = State(1) symb_a = Symbol("0") symb_b = Symbol("1") enfa.add_start_state(state0) enfa.add_final_state(state1) enfa.add_transition(state0, symb_a, state0) enfa.add_transition(state1, symb_b, state0) enfa.add_transition(state1, symb_b, state1) regex = enfa.to_regex() enfa2 = regex.to_epsilon_nfa() self.assertFalse(enfa2.accepts([symb_a])) self.assertFalse(enfa2.accepts([symb_a, symb_a])) self.assertFalse(enfa2.accepts([symb_a, symb_a, symb_b])) self.assertFalse( enfa2.accepts([symb_a, symb_a, symb_b, symb_b, symb_a])) self.assertFalse( enfa2.accepts([symb_a, symb_a, symb_b, symb_b, symb_a, symb_b])) self.assertFalse(enfa2.accepts([symb_b])) epsilon = Epsilon() enfa.add_transition(state0, epsilon, state1) regex = enfa.to_regex() enfa2 = regex.to_epsilon_nfa() self.assertTrue(enfa.accepts([])) self.assertTrue(enfa.accepts([symb_a])) self.assertTrue(enfa2.accepts([symb_a])) self.assertTrue(enfa2.accepts([symb_a, symb_a])) self.assertTrue(enfa2.accepts([symb_a, symb_a, symb_b, symb_b])) self.assertTrue( enfa2.accepts([symb_a, symb_a, symb_b, symb_b, symb_a, symb_b])) self.assertTrue(enfa2.accepts([symb_b])) self.assertTrue(enfa2.accepts([])) enfa.remove_transition(state0, symb_a, state0) regex = enfa.to_regex() enfa2 = regex.to_epsilon_nfa() self.assertFalse(enfa2.accepts([symb_a])) self.assertFalse(enfa2.accepts([symb_a, symb_a])) self.assertFalse(enfa2.accepts([symb_a, symb_a, symb_b])) self.assertFalse( enfa2.accepts([symb_a, symb_a, symb_b, symb_b, symb_a])) self.assertFalse( enfa2.accepts([symb_a, symb_a, symb_b, symb_b, symb_a, symb_b])) self.assertTrue(enfa2.accepts([symb_b])) self.assertTrue(enfa2.accepts([])) enfa.remove_transition(state1, symb_b, state1) regex = enfa.to_regex() enfa2 = regex.to_epsilon_nfa() self.assertTrue(enfa2.accepts([symb_b, symb_b])) enfa.add_transition(state0, symb_a, state0) regex = enfa.to_regex() enfa2 = regex.to_epsilon_nfa() self.assertTrue(enfa2.accepts([symb_a, symb_b]))
def add_transitions(self, member, enter_state, exit_state): self.prefix += 1 if member == None: self.add_transition(enter_state, Epsilon(), exit_state) return if member["type"] == "BLANK": self.add_transition(enter_state, Epsilon(), exit_state) if member["type"] == "SYMBOL": if member["name"][0] == "_" and member["name"] not in self.externals: self.add_transitions(self.node_types[member["name"]], enter_state, exit_state) else: symbol = Symbol(member["name"]) self.add_transition(enter_state, symbol, exit_state) if member["type"] == "STRING": symbol = Symbol(member["value"]) self.add_transition(enter_state, symbol, exit_state) # memb = regex_to_member(member["value"]) # self.add_transitions(memb, enter_state, exit_state) if member["type"] == "PATTERN": # symbol = Symbol("regex:"+member["value"]) memb = regex_to_member(member["value"]) self.add_transitions(memb, enter_state, exit_state) # self.add_transition(enter_state, symbol, exit_state) if member["type"] in ["FIELD", "PREC","PREC_LEFT","PREC_RIGHT","ALIAS", "TOKEN"]: self.add_transitions(member["content"], enter_state, exit_state) if member["type"] == "SEQ": prev_state = enter_state for i, SEQ_member in enumerate(member["members"]): next_state = State(f"SEQ{self.prefix}_St_{i}") self.add_transitions(SEQ_member, prev_state, next_state) prev_state = next_state self.add_transition(next_state, Epsilon(), exit_state) if member["type"] == "CHOICE": for i, CHOICE_member in enumerate(member["members"]): choice_state = State(f"CH{self.prefix}_St_{i}") self.add_transitions(CHOICE_member, enter_state, choice_state) self.add_transition(choice_state, Epsilon(), exit_state) if member["type"] == "REPEAT": self.add_transition(enter_state, Epsilon(), exit_state) self.add_transition(exit_state, Epsilon(), enter_state) self.add_transitions(member["content"], enter_state, exit_state) if member["type"] == "REPEAT1": self.add_transition(exit_state, Epsilon(), enter_state) self.add_transitions(member["content"], enter_state, exit_state)
def test_reverse(self): """ Test the reversal of a language """ enfa0 = get_enfa_example0() symb_a = Symbol("a") symb_b = Symbol("b") enfa = ~enfa0 self.assertTrue(enfa.accepts([symb_b])) self.assertTrue(enfa.accepts([symb_b, symb_a])) self.assertTrue(enfa.accepts([symb_b, symb_a, symb_a])) self.assertFalse(enfa.accepts([symb_a, symb_b])) self.assertFalse(enfa.accepts([symb_a])) self.assertFalse(enfa.accepts([]))
def test_kleene(self): """ Tests the kleene star of an epsilon NFA """ enfa0 = get_enfa_example0() symb_a = Symbol("a") symb_b = Symbol("b") enfa = enfa0.kleene_star() self.assertTrue(enfa.accepts([symb_b])) self.assertTrue(enfa.accepts([symb_a, symb_b])) self.assertTrue(enfa.accepts([symb_a, symb_b, symb_a, symb_b])) self.assertTrue(enfa.accepts([])) self.assertTrue(enfa.accepts([symb_b, symb_b])) self.assertFalse(enfa.accepts([symb_a])) self.assertFalse(enfa.accepts([symb_a, symb_b, symb_a]))
def test_concatenate(self): """ Tests the concatenation of two epsilon NFA """ enfa0 = get_enfa_example0() enfa1 = get_enfa_example1() symb_a = Symbol("a") symb_b = Symbol("b") symb_c = Symbol("c") enfa = enfa0.concatenate(enfa1) self.assertTrue(enfa.accepts([symb_b, symb_c])) self.assertTrue(enfa.accepts([symb_a, symb_b, symb_c])) self.assertTrue(enfa.accepts([symb_a, symb_a, symb_b, symb_c])) self.assertFalse(enfa.accepts([symb_c])) self.assertFalse(enfa.accepts([symb_b])) self.assertFalse(enfa.accepts([]))
def test_to_regex(self): """ Tests the transformation to regex """ enfa = EpsilonNFA() state0 = State(0) state1 = State(1) state2 = State(2) symb_e = Symbol("e") symb_f = Symbol("f") symb_g = Symbol("g") enfa.add_start_state(state0) enfa.add_final_state(state2) enfa.add_transition(state0, symb_e, state1) enfa.add_transition(state1, symb_f, state2) enfa.add_transition(state0, symb_g, state2) regex = enfa.to_regex() enfa2 = regex.to_epsilon_nfa() self.assertTrue(enfa2.accepts([symb_e, symb_f])) self.assertTrue(enfa2.accepts([symb_g])) self.assertFalse(enfa2.accepts([])) self.assertFalse(enfa2.accepts([symb_e])) self.assertFalse(enfa2.accepts([symb_f])) enfa.add_final_state(state0) with self.assertRaises(ValueError) as _: enfa.get_regex_simple() regex = enfa.to_regex() enfa3 = regex.to_epsilon_nfa() self.assertTrue(enfa3.accepts([symb_e, symb_f])) self.assertTrue(enfa3.accepts([symb_g])) self.assertTrue(enfa3.accepts([])) self.assertFalse(enfa3.accepts([symb_e])) self.assertFalse(enfa3.accepts([symb_f])) enfa.remove_start_state(state0) regex = enfa.to_regex() enfa3 = regex.to_epsilon_nfa() self.assertFalse(enfa3.accepts([symb_e, symb_f])) self.assertFalse(enfa3.accepts([symb_g])) self.assertFalse(enfa3.accepts([])) self.assertFalse(enfa3.accepts([symb_e])) self.assertFalse(enfa3.accepts([symb_f])) enfa.add_start_state(state0) enfa.add_transition(state0, symb_f, state0) regex = enfa.to_regex() enfa3 = regex.to_epsilon_nfa() self.assertTrue(enfa3.accepts([symb_e, symb_f])) self.assertTrue(enfa3.accepts([symb_f, symb_e, symb_f])) self.assertTrue(enfa3.accepts([symb_g])) self.assertTrue(enfa3.accepts([symb_f, symb_f, symb_g])) self.assertTrue(enfa3.accepts([])) self.assertFalse(enfa3.accepts([symb_e])) self.assertTrue(enfa3.accepts([symb_f]))
def test_union(self): """ Tests the union of two epsilon NFA """ with self.assertRaises(NotImplementedError) as _: Regexable().to_regex() enfa0 = get_enfa_example0() enfa1 = get_enfa_example1() symb_a = Symbol("a") symb_b = Symbol("b") symb_c = Symbol("c") enfa = enfa0.union(enfa1) self.assertTrue(enfa.accepts([symb_b])) self.assertTrue(enfa.accepts([symb_a, symb_b])) self.assertTrue(enfa.accepts([symb_c])) self.assertFalse(enfa.accepts([symb_a])) self.assertFalse(enfa.accepts([]))
def get_transition_function_and_states_and_symbols_non_reduced(functions): states = set() symbols = set() start_state = State("Start") states.add(start_state) final_states = set() counter = 0 transition_function = NondeterministicTransitionFunction() linear_paths = get_all_linear_paths(functions) linear_paths = sorted(linear_paths, key=len) for linear_path in linear_paths: current_state = start_state for i, atom in enumerate(linear_path): symbol = Symbol(atom) symbols.add(symbol) next_state = State(str(counter)) states.add(next_state) counter += 1 transition_function.add_transition(current_state, symbol, next_state) current_state = next_state final_states.add(current_state) for final_state in final_states: transition_function.add_transition(final_state, finite_automaton.Epsilon(), start_state) return transition_function, states, symbols, final_states
def get_enfa_example0(): """ Gives an example ENFA Accepts a*b """ enfa0 = EpsilonNFA() state0 = State(0) state1 = State(1) state2 = State(2) symb_a = Symbol("a") symb_b = Symbol("b") enfa0.add_start_state(state0) enfa0.add_final_state(state2) enfa0.add_transition(state0, symb_a, state0) enfa0.add_transition(state0, Epsilon(), state1) enfa0.add_transition(state1, symb_b, state2) return enfa0
def test_epsilon(self): """ Generic tests for epsilon """ eps0 = Epsilon() eps1 = Epsilon() symb = Symbol(0) self.assertEqual(eps0, eps1) self.assertNotEqual(eps0, symb)