static void Main() { Console.WriteLine("1. DFSA 'A' Generation."); DFSadj dfsA = new DFSadj(); Console.WriteLine("\n2. Depth of DFSA 'A'."); Console.WriteLine(" - Number of States in 'A': " + dfsA.states.Count); Console.WriteLine(" - Depth of 'A': " + dfsA.GetDepth()); Console.WriteLine("\n3. DFSA 'A' Minimisation."); DFSadj dfsM = dfsA.GetMinimalDFSadj(); Console.WriteLine("\n4. Depth of DFSA 'M'."); Console.WriteLine(" - Number of States in 'M': " + dfsM.states.Count); Console.WriteLine(" - Depth of 'M': " + dfsM.GetDepth()); Console.WriteLine("\n5. Generating 100 random strings [Accept/Reject]"); Console.WriteLine("\n6. Strongly Connected Components in DFSA 'M':"); dfsM.GetSCCs(); Console.WriteLine(" - Number of Strongly Connected Components in 'M': " + dfsM.SCCs.Count); dfsM.MaxminCC(); Console.WriteLine(" - Number of States in the largest SCC: " + dfsM.maxSCC); Console.WriteLine(" - Number of States in the smallest SCC: " + dfsM.minSCC); }
public DFSadj GetMinimalDFSadj() { //States are divided into accepting states and rejecting states HashSet <int> acceptingStates = new HashSet <int>(); HashSet <int> rejectingStates = new HashSet <int>(); foreach (State state in states) { // If the current state could be reached if (adjState[state.stateID]) { // Current state = accepting state if (state.finalState) { // Added int the set of accepting states. acceptingStates.Add(state.stateID); } else { // Else it's added in the set of rejecting states rejectingStates.Add(state.stateID); } } } // The hashsetP := {F, Q \ F} HashSet <HashSet <int> > hashSetP = new HashSet <HashSet <int> >(HashSet <int> .CreateSetComparer()); hashSetP.Add(acceptingStates); hashSetP.Add(rejectingStates); // The hashsetW := {F} HashSet <HashSet <int> > hashSetW = new HashSet <HashSet <int> >(HashSet <int> .CreateSetComparer()); hashSetW.Add(acceptingStates); // whilst hashSetW is not empty while (hashSetW.Count != 0) { // a hashset A is removed from hashset W HashSet <int> hashSetA = hashSetW.ElementAt(0); hashSetW.Remove(hashSetA); // for each c in Σ do for (int ii = 0; ii < adj.GetLength(1); ii++) { // All the transitions c which lead to state a, are stored in hashset X HashSet <int> hashSetX = new HashSet <int>(); foreach (State state in states) { if (adjState[state.stateID]) { if (hashSetA.Contains(adj[state.stateID, ii])) { hashSetX.Add(state.stateID); } } } // When X Intercetion Y and Y set difference X is non empty, in P is hashsetY. HashSet <HashSet <int> > Pcopy = new HashSet <HashSet <int> >(hashSetP, HashSet <int> .CreateSetComparer()); foreach (HashSet <int> setInP in Pcopy) { HashSet <int> hashSetY = new HashSet <int>(setInP); HashSet <int> intersection = new HashSet <int>(hashSetX); intersection.IntersectWith(hashSetY); HashSet <int> difference = new HashSet <int>(hashSetY); difference.ExceptWith(hashSetX); if (intersection.Count > 0 && difference.Count > 0) { // hashsetY is replaced in hashsetp by the 2 sets: X ∩ Y & Y \ X hashSetP.Remove(hashSetY); hashSetP.Add(intersection); hashSetP.Add(difference); // if hashsetY is in hashetW if (hashSetW.Contains(hashSetY)) { // hashsetY is replaced in hashsetW by the 2 sets: X ∩ Y & Y \ X hashSetW.Remove(hashSetY); hashSetW.Add(intersection); hashSetW.Add(difference); } else { // else // if |X ∩ Y| <= |Y \ X| if (intersection.Count <= difference.Count) { // X ∩ Y is added to hashsetW hashSetW.Add(intersection); } else { // else // Y \ X is added to hashsetW hashSetW.Add(difference); } } } } } } // DFSadj M DFSadj dfsaM = new DFSadj(hashSetP.Count); // So that the elements have a fixed order, the hashsetP was changed into a list. List <HashSet <int> > arrayP = new List <HashSet <int> >(hashSetP); // Iterating throughout the list P int i = 0; for (int k = 0; k < arrayP.Count; k++) { HashSet <int> setInP = arrayP[k]; // A new state is cleared for each element State state = new State(); // An id is assigned to the state state.stateID = i; // if the start state of DFSadj A is contained if (setInP.Contains(startStateID)) { // the state is set as start state in DFSadj M dfsaM.startStateID = i; } // if the states are final states, the set represting the partion // is set as an accepting state // Else, the state is set as a rejecting state. if (setInP.Count > 0 && states[0].finalState) { state.finalState = true; } else { state.finalState = false; } // the states in this partition of DFSadj A, are checked were they go to. int oldA = -1, oldB = -1; for (int j = 0; j < states.Count; j++) { // When the state is found, the transitions are stored. if (setInP.Contains(states[j].stateID)) { oldA = adj[j, 0]; oldB = adj[j, 1]; break; } } // when it is known which states a and b lead to in DFSadj A, make these transitions to show where transitions a and be had led to, from the current state. for (int j = 0; j < arrayP.Count; j++) { if (arrayP[j].Contains(oldA)) { dfsaM.adj[i, 0] = j; } if (arrayP[j].Contains(oldB)) { dfsaM.adj[i, 1] = j; } } dfsaM.states.Add(state); i++; } return(dfsaM); }