public static DeterminedFiniteAutomaton ConvertNFAToDFA(NondeterminedFiniteAutomaton nfa) { //DeterminedFiniteAutomaton dfa nfa = nfa.GetEquivalentDeletedEpsilons(); HashSet <string> currentStates, accessibleStates; List <HashSet <string> > allSetsOfStates = new List <HashSet <string> >(); allSetsOfStates.Add(new HashSet <string>(nfa.GetStartStates())); DeterminedFiniteAutomaton dfa = new DeterminedFiniteAutomaton("q0"); List <string> names = new List <string>(); dfa.AddSymbols(nfa.GetAlphabet()); var finalStates = nfa.GetFinalStates(); string from, to; bool f = true; for (int allSetsCounter = 0, currentSetNumber = 0, pos; currentSetNumber <= allSetsCounter; currentSetNumber++) { currentStates = allSetsOfStates[currentSetNumber]; if (currentStates.Any(state => nfa.GetFinalStates().Contains(state))) { dfa.AddToFinalStates(string.Format("q{0}", currentSetNumber)); } foreach (var symbol in nfa.GetAlphabet()) { accessibleStates = GetAccessibleStates(nfa, currentStates, symbol); if (accessibleStates.Count != 0) { pos = CheckIsListContains(allSetsOfStates, accessibleStates); from = string.Format("q{0}", currentSetNumber); to = string.Format("q{0}", pos); if (pos == -1) { allSetsCounter++; to = string.Format("q{0}", allSetsCounter); dfa.AddState(to); allSetsOfStates.Add(new HashSet <string>(accessibleStates)); } dfa.AddTransition(from, to, symbol); } } } return(dfa); }
public static NondeterminedFiniteAutomaton GetEquivalentDeletedEpsilons(this NondeterminedFiniteAutomaton epsilonNfa) { NondeterminedFiniteAutomaton noEpsilonsNfa = new NondeterminedFiniteAutomaton(); // копируем состояния и алфавит var alphabet = epsilonNfa.GetAlphabet(); var states = epsilonNfa.GetStates(); var finalStates = new HashSet <string>(epsilonNfa.GetFinalStates()); var startStates = new HashSet <string>(epsilonNfa.GetStartStates()); noEpsilonsNfa.AddSymbols(alphabet); noEpsilonsNfa.AddStates(states); noEpsilonsNfa.SetFinalStates(finalStates); noEpsilonsNfa.SetStartStates(startStates); // добавляем необходимые переходы foreach (var state in states) { // состояния в которые мы можем перейти из состояния state, используя эпсилон переходы. var statesReachByEpsilons = GetAllDestinationsByEpsilons(epsilonNfa, state); foreach (var symbol in alphabet) { // состояния в которые мы можем попасть используя сперва эпсилон переходы, // а затем символ symbol единажды var statesReachByEpsilonsAndSymbol = statesReachByEpsilons.SelectMany((reachedByEps) => (epsilonNfa.GetTransitionDestinations(reachedByEps, symbol))).Distinct(); // состояния в которые мы можем перейти из состояния state, используя символ symbol единажды // и эпсилон переходы в любом порядке var statesOneSymbolAndEpsilons = statesReachByEpsilonsAndSymbol.SelectMany((stateFrom => GetAllDestinationsByEpsilons(epsilonNfa, stateFrom))).Distinct(); foreach (var reachedState in statesOneSymbolAndEpsilons) { noEpsilonsNfa.AddTransition(state, reachedState, symbol); } } if (startStates.Contains(state)) { foreach (var s in statesReachByEpsilons) { startStates.Add(s); noEpsilonsNfa.AddToStartStates(s); } } // Если это начальное состояние и из него достижимо заключительное по эпсилон // то сделаем его заключительным if (startStates.Contains(state) && statesReachByEpsilons.Any(finalStates.Contains)) { noEpsilonsNfa.AddToFinalStates(state); } } foreach (var state in finalStates) { noEpsilonsNfa.AddToFinalStates(state); } return(noEpsilonsNfa); }