/// <summary> /// Converts NFA to DFA using "Subset Construction" /// </summary> /// <param name="stateStartNfa">Starting state of NFA</param> /// <param name="setMasterDfa">Contains set of all DFA states when this function returns</param> /// <returns>Starting state of DFA</returns> public static State ConvertToDfa(State stateStartNfa) { if (stateStartNfa == null) { throw new ArgumentNullException(nameof(stateStartNfa)); } HashSet <string> setAllInput = new HashSet <string>(); HashSet <State> setAllState = new HashSet <State>(); GetAllStateAndInput(stateStartNfa, setAllState, setAllInput); setAllInput.Remove(MetaSymbol.EPSILON); NfaToDfaHelper helper = new NfaToDfaHelper(); HashSet <State> setMove = null; HashSet <State> setE_closure = null; // first, we get E_Closure of the start state of NFA ( just following the algorithm) setE_closure = E_Closure(stateStartNfa); State stateStartDfa = new State(); // create a new DFA state to represent the above E_Closure // NOTE: // we keep track of the NFA E_Closure and the DFA state that represent the E_Closure. // we maintain a relationship between the NFA E_Closure and DFA state that represents the NFA E_Closure. // all these are done in the NfaToDfaHelper class. if (IsAcceptingGroup(setE_closure)) { stateStartDfa.AcceptingState = true; } helper.AddDfaState(stateStartDfa, setE_closure); // please see "subset construction" algorithm // for clear understanding State stateT = null; HashSet <State> setT = null; State stateU = null; while ((stateT = helper.GetNextUnmarkedDfaState()) != null) { helper.Mark(stateT); // flag it to indicate that we have processed this state. // the DFA state stateT represents a set of NFA E_Closure. // so, we retrieve the E_Closure. setT = helper.GetE_ClosureByDfaState(stateT); foreach (string str in setAllInput) { setMove = Move(setT, str); if (setMove.Count > 0) { setE_closure = E_Closure(setMove); stateU = helper.FindDfaStateByE_Closure(setE_closure); if (stateU == null) // so set setEnclosure must be a new one and we should crate a new DFA state { stateU = new State(); if (IsAcceptingGroup(setE_closure)) { stateU.AcceptingState = true; } helper.AddDfaState(stateU, setE_closure); // add new state (as unmarked by default) } stateT.AddTransition(str, stateU); } } // end of foreach..loop } // end of while..loop return(stateStartDfa); } // end of ConvertToDfa method
} // end of CreateNfa method /// <summary> /// Converts NFA to DFA using "Subset Construction" /// </summary> /// <param name="stateStartNfa">Starting state of NFA</param> /// <param name="setMasterDfa">Contains set of all DFA states when this function returns</param> /// <returns>Starting state of DFA</returns> private State ConvertToDfa(State stateStartNfa) { //Subset Construction算法 Set setAllInput = new Set(); Set setAllState = new Set(); GetAllStateAndInput(stateStartNfa, setAllState, setAllInput); setAllInput.RemoveElement(MetaSymbol.EPSILON); NfaToDfaHelper helper = new NfaToDfaHelper(); Set setMove = null; Set setEclosure = null; // first, we get Eclosure of the start state of NFA ( just following the algoritham) setEclosure = Eclosure(stateStartNfa); State stateStartDfa = new State(); // create a new DFA state to represent the above Eclosure // NOTE: // we keep track of the NFA Eclosure and the DFA state that represent the Eclosure. // we maintain a relationship between the NFA Eclosure and DFA state that represents the NFA Eclosure. // all these are done in the NfaToDfaHelper class. if (IsAcceptingGroup(setEclosure) == true) { stateStartDfa.AcceptingState = true; } helper.AddDfaState(stateStartDfa, setEclosure); string sInputSymbol = String.Empty; // dummy // please see "subset construction" algoritham // for clear understanding State stateT = null; Set setT = null; State stateU = null; while ((stateT = helper.GetNextUnmarkedDfaState()) != null) { helper.Mark(stateT); // flag it to indicate that we have processed this state. // the DFA state stateT represents a set of NFA Eclosure. // so, we retrieve the Eclosure. setT = helper.GetEclosureByDfaState(stateT); foreach (object obj in setAllInput) { sInputSymbol = obj.ToString(); setMove = Move(setT, sInputSymbol); if (setMove.IsEmpty() == false) { setEclosure = Eclosure(setMove); stateU = helper.FindDfaStateByEclosure(setEclosure); if (stateU == null) // so set setEclosure must be a new one and we should crate a new DFA state { stateU = new State(); if (IsAcceptingGroup(setEclosure) == true) { stateU.AcceptingState = true; } helper.AddDfaState(stateU, setEclosure); // add new state (as unmarked by default) } stateT.AddTransition(sInputSymbol, stateU); } } // end of foreach..loop } // end of while..loop return(stateStartDfa); } // end of ConverToDfa method