From 960f21385772432006c1588df221115fe14cec4c Mon Sep 17 00:00:00 2001 From: Patrick Totzke Date: Wed, 28 May 2025 15:53:11 +0100 Subject: [PATCH 1/2] test: nfa.is_complete makes sure that multiple transitions with the same label are ok --- src/nfa.rs | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/src/nfa.rs b/src/nfa.rs index b46ecb9..3b7c9bd 100644 --- a/src/nfa.rs +++ b/src/nfa.rs @@ -44,8 +44,6 @@ pub enum StateOrdering { impl Nfa { /// checks if the nfa is complete: /// every state has an outgoing transition for every letter in the alphabet - /// - /// TODO: this uses equality on (sorted) vectors. Are HashSets better? pub fn is_complete(&self) -> bool { // get the alphabet let mut letters = self.get_alphabet(); @@ -563,6 +561,18 @@ mod test { assert!(nfa.is_complete()); } #[test] + fn is_complete3() { + let mut nfa = Nfa::from_size(2); + nfa.add_transition_by_index1(0, 1, 'a'); + nfa.add_transition_by_index1(0, 1, 'b'); + nfa.add_transition_by_index1(1, 0, 'a'); + nfa.add_transition_by_index1(1, 0, 'b'); + + // in addition, we add a second a-edge from state 0. + nfa.add_transition_by_index1(0, 0, 'a'); + assert!(nfa.is_complete()); + } + #[test] fn complete_to_selfloops() { // this NFA is missing a 'b'-strep from state 1. // after completion, there should be a step 1 -b-> 1. From 550ba357d4d19f2f5b66a24f3e6ac7991e553a6d Mon Sep 17 00:00:00 2001 From: Patrick Totzke Date: Wed, 28 May 2025 15:49:51 +0100 Subject: [PATCH 2/2] fix nfa.is_complete for each state, this now collects the *set* of outgoing actions and then checks if every alphabet letter is contained. --- src/nfa.rs | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/src/nfa.rs b/src/nfa.rs index 3b7c9bd..a2ea489 100644 --- a/src/nfa.rs +++ b/src/nfa.rs @@ -50,14 +50,13 @@ impl Nfa { letters.sort(); // for each state, check if it has a transition for each letter in the alphabet for state in 0..self.nb_states() { - let mut state_actions = self + let state_actions = self .transitions .iter() .filter(|t| t.from == state) .map(|t| t.label.clone()) - .collect::>(); - state_actions.sort(); - if state_actions != letters { + .collect::>(); + if !letters.iter().all(|l| state_actions.contains(*l)) { return false; } }