diff --git a/.gitignore b/.gitignore index 9654eeb..7dd0ffb 100644 --- a/.gitignore +++ b/.gitignore @@ -3,10 +3,7 @@ dist/ automathon.egg-info/ workspace.code* .eggs/ -automathon/__pycache__/ -automathon/finiteAutomata/__pycache__/ -tests/__pycache__/ -automathon/errors/__pycache__/ +__pycache__/ build/ .idea/ bazel-* diff --git a/automathon/finite_automata/nfa.py b/automathon/finite_automata/nfa.py index 5b284eb..74f0e02 100644 --- a/automathon/finite_automata/nfa.py +++ b/automathon/finite_automata/nfa.py @@ -377,13 +377,11 @@ def __get_e_closure( for st in self.delta[q][""]: if st not in visited: visited.append(st) - ans.extend( - [ - k - for k in self.__get_e_closure(st, visited) - if k not in ans - ] - ) + ans.extend([ + k + for k in self.__get_e_closure(st, visited) + if k not in ans + ]) return ans def __ret_get_new_transitions( @@ -493,9 +491,9 @@ def __extend_local_transitions( ) -> None: if tmp and s in local_transitions: # avoid add repeated values - local_transitions[s].extend( - [k for k in tmp if k not in local_transitions[s]] - ) + local_transitions[s].extend([ + k for k in tmp if k not in local_transitions[s] + ]) elif tmp: local_transitions[s] = list(tmp) @@ -522,39 +520,33 @@ def minimize(self) -> "NFA": local_nfa.renumber() return local_nfa - def renumber(self) -> None: - """Change the name of the states, renumbering each of the labels""" - idx = 0 - new_tags = dict() + def renumber(self, prefix="q") -> None: + """ + Change the name of the states, renumbering each of the labels - # New values - q = set() - delta = dict() - f = set() + Parameters + ---------- + prefix : str + Prefix for the renumbered state names. + """ - # Setting the new label for each state - tmp_q = list(self.q) - tmp_q.sort() + delta = dict() - for _q in tmp_q: - new_tags[_q] = str(idx) - q.add(str(idx)) - idx += 1 + # Create new mappings for states + new_tags = {state: f"{prefix}{idx}" for idx, state in enumerate(self.q)} + # Update states + q = {new_tags[state] for state in self.q} + f = {new_tags[state] for state in self.f} initial_state = new_tags[self.initial_state] - # Changing the labels for the final states - for _f in self.f: - f.add(new_tags[_f]) - + # Update transitions for _q in self.delta: delta[new_tags[_q]] = dict() for s in self.delta[_q]: - nxt_states = list() - for nxt_state in self.delta[_q][s]: - nxt_states.append(new_tags[nxt_state]) - - delta[new_tags[_q]][s] = set(nxt_states) + delta[new_tags[_q]][s] = { + new_tags[nxt_state] for nxt_state in self.delta[_q][s] + } self.q, self.f, self.delta, self.initial_state = ( q, diff --git a/tests/test_nfa.py b/tests/test_nfa.py index e638363..f1e590e 100644 --- a/tests/test_nfa.py +++ b/tests/test_nfa.py @@ -178,27 +178,30 @@ def test_intersection(self): self.assertFalse(intersection_result.accept("abbbbbb")) def test_renumber(self): - from automathon import DFA - - automata_1 = NFA( - q={"3", "1", "2", "0"}, + q = {"alpha", "beta", "gamma", "sigma"} + delta = { + "sigma": {"A": {"beta"}}, + "beta": {"B": {"gamma"}, "": {"gamma"}}, + "gamma": {"C": {"alpha"}}, + } + initial_state = "sigma" + f = {"alpha"} + + automaton = NFA( + q=q, sigma={"", "A", "B", "C"}, - delta={ - "0": {"A": {"1"}}, - "1": {"B": {"2"}, "": {"2"}}, - "2": {"C": {"3"}}, - }, - initial_state="0", - f={"3"}, + delta=delta, + initial_state=initial_state, + f=f, ) - automata_2: NFA = automata_1.remove_epsilon_transitions() - automata_3: DFA = automata_2.get_dfa() - automata_4: NFA = automata_3.get_nfa() - - automata_4.renumber() + automaton.renumber(prefix="q") - self.assertTrue(automata_4.is_valid()) + self.assertTrue(automaton.is_valid()) + self.assertSetEqual(automaton.q, {"q0", "q1", "q2", "q3"}) + self.assertNotEqual(automaton.f, f) + self.assertNotEqual(automaton.initial_state, initial_state) + self.assertNotEqual(automaton.delta, delta) if __name__ == "__main__":