From 46e635bbe14851b5515178eeaaf93e84245405d5 Mon Sep 17 00:00:00 2001 From: "Eliot W. Robson" Date: Sat, 27 Jul 2024 17:39:54 -0400 Subject: [PATCH 1/2] Determinized regex ordering --- automata/fa/gnfa.py | 2 +- tests/test_gnfa.py | 37 +++++++++++++++++++++++++++++++++++++ 2 files changed, 38 insertions(+), 1 deletion(-) diff --git a/automata/fa/gnfa.py b/automata/fa/gnfa.py index 9770c792..10f6ae9a 100644 --- a/automata/fa/gnfa.py +++ b/automata/fa/gnfa.py @@ -340,7 +340,7 @@ def _find_min_connected_node( if to_state != final_state: state_degree[to_state] += 1 - return min(state_degree, key=lambda x: state_degree.get(x, -1)) + return min(state_degree, key=lambda x: (state_degree.get(x, -1), x)) def to_regex(self) -> str: """ diff --git a/tests/test_gnfa.py b/tests/test_gnfa.py index 5b2c8b98..bbacd2e8 100644 --- a/tests/test_gnfa.py +++ b/tests/test_gnfa.py @@ -387,9 +387,46 @@ def test_to_regex(self) -> None: # Test equality through DFA regex conversion self.assertEqual(dfa_1, dfa_2) + def test_gnfa_deterministic(self) -> None: + """ + Check for deterministic conversion to GNFA. + From https://github.com/caleb531/automata/issues/231 + """ + + gt_symbols = {"Connect": "0", "Send_msg": "1", "Ack": "2", "Close": "3"} + gt_dfa = DFA.from_nfa( + NFA( + states={"q0", "q1", "q2"}, + input_symbols={ + gt_symbols["Connect"], + gt_symbols["Send_msg"], + gt_symbols["Close"], + gt_symbols["Ack"], + }, + transitions={ + "q0": {gt_symbols["Connect"]: {"q1"}}, + "q1": {gt_symbols["Close"]: {"q0"}, gt_symbols["Send_msg"]: {"q2"}}, + "q2": {gt_symbols["Ack"]: {"q1", "q0"}}, + }, + initial_state="q0", + final_states={"q0", "q1", "q2"}, + ) + ) + + # Repeat the test multiple times to account for possible non-determinism. + num_reps = 1_000 + starting_gnfa = GNFA.from_dfa(gt_dfa) + + for _ in range(num_reps): + regex = starting_gnfa.to_regex() + self.assertEqual( + "(012(012|12)*(03|3)|03)*(012(012|12)*(01?|1?)|(01?)?)", regex + ) + def test_show_diagram(self) -> None: """ Should construct the diagram for a GNFA. + """ graph = self.gnfa.show_diagram() From f31d84edb15cb405c77fa077342cfa401ac65d94 Mon Sep 17 00:00:00 2001 From: Eliot Robson Date: Sat, 27 Jul 2024 18:00:20 -0400 Subject: [PATCH 2/2] Update tests/test_gnfa.py Co-authored-by: Caleb Evans --- tests/test_gnfa.py | 1 - 1 file changed, 1 deletion(-) diff --git a/tests/test_gnfa.py b/tests/test_gnfa.py index bbacd2e8..8416efab 100644 --- a/tests/test_gnfa.py +++ b/tests/test_gnfa.py @@ -426,7 +426,6 @@ def test_gnfa_deterministic(self) -> None: def test_show_diagram(self) -> None: """ Should construct the diagram for a GNFA. - """ graph = self.gnfa.show_diagram()