private int Get_Destination_From_State(StateNode state, string read) { foreach (Transition transition in state.transitions) { if (transition.read == read) { return(transition.to); //Return the state's id that this state is pointing to, hence, its destination } } return(-1); }
/// <summary> /// Function that will find in the 2D array, any state that can be merge into a single one /// And then converts the stair 2D array into a list of StateNode objects /// </summary> /// <returns></returns> private List <StateNode> Convert_To_List(StateNode[] vArray, StateNode[] hArray, sbyte[][] stair_array) { List <StateNode> new_state_nodes = new List <StateNode>(); List <int> ids_used = new List <int>(); int id_counter = 0, y_counts = 0; double x = 70, y = 50; /* Find in the stair array an empty spot and merged the two states */ for (int i = 0; i < state_nodes.Count - 1; i++) { for (int j = 0; j < stair_array[i].Length; j++) { //If this position in the array is empty, it means it can be merged if (stair_array[i][j] == -1) { StateNode nodeA = vArray[i]; StateNode nodeB = hArray[j]; //Update both statenode's merge info int indexOFNodeA = state_nodes.IndexOf(nodeA); int indexOFNodeB = state_nodes.IndexOf(nodeB); state_nodes[indexOFNodeA].mergeInfo = new MergeInfo(nodeB.name, nodeA.name, true); state_nodes[indexOFNodeB].mergeInfo = new MergeInfo(nodeA.name, nodeB.name, true); //Add both state's id soo that they are no longer used ids_used.Add(nodeA.id); ids_used.Add(nodeB.id); StateNode new_state_node = new StateNode(); new_state_node.name = nodeB.name + ", " + nodeA.name; new_state_node.id = id_counter++; new_state_node.isInitial = nodeA.isInitial || nodeB.isInitial; new_state_node.isFinal = nodeA.isFinal || nodeB.isFinal; new_state_node.coordinate = new Coordinate(x, y); //The new state node should remember its transitions new_state_node.transitions = new List <Transition>(nodeA.transitions); new_state_node.transitions.AddRange(nodeB.transitions); new_state_nodes.Add(new_state_node); x += 100; y_counts++; if (y_counts == 2) { y_counts = 0; y += 100; } } } } /* Add all the old unrepeated states that in the new state nodes list */ foreach (StateNode oldStateNode in state_nodes) { bool isThisNodeNew = true; foreach (int id_used in ids_used) { if (oldStateNode.id == id_used) { isThisNodeNew = false; break; } } if (isThisNodeNew) { oldStateNode.id = id_counter++; new_state_nodes.Add(oldStateNode); } } /* Update transition in every state */ for (int i = 0; i < new_state_nodes.Count; i++) { for (int j = 0; j < new_state_nodes[i].transitions.Count; j++) { Transition t; foreach (StateNode lookingForDestinationState in new_state_nodes) { if (lookingForDestinationState.name == new_state_nodes[i].transitions[j].destination_name || lookingForDestinationState.name.Contains(new_state_nodes[i].transitions[j].destination_name)) { t = new Transition(lookingForDestinationState.id, new_state_nodes[i].transitions[j].read, lookingForDestinationState.name); new_state_nodes[i].transitions[j] = t; } } } } /* Eliminate Duplicates */ //List<T> withDupes = LoadSomeData(); //List<T> noDupes = withDupes.Distinct().ToList(); for (int i = 0; i < new_state_nodes.Count; i++) { for (int j = 0; j < new_state_nodes[i].transitions.Count; j++) { new_state_nodes[i].transitions = new_state_nodes[i].transitions.Distinct().ToList(); } } //foreach(StateNode newState in new_state_nodes) //{ // foreach(Transition transition in newState.transitions) // { // Transition t; // foreach(StateNode lookingForDestinationState in new_state_nodes) // { // if(lookingForDestinationState.name == transition.destination_name || lookingForDestinationState.name.Contains(transition.destination_name)) // { // t = new Transition(lookingForDestinationState.id, transition.read, lookingForDestinationState.name); // transition.Value = t; // } // } // } //} //foreach(StateNode stateNode in state_nodes) //{ // if (stateNode.mergeInfo.isMerge) // { // //Find the new state with the info of the old state to add the transitions // string merge_name = stateNode.mergeInfo.name_before_merge + ", " + stateNode.mergeInfo.merge_with; // foreach(StateNode newStateNode in new_state_nodes) // { // if(newStateNode.name == merge_name) // { // newStateNode.transitions = stateNode.transitions; // //check first if the old statenode transition is also merge, if it is, we have to point to the merged state // foreach(Transition transition in stateNode.transitions) // { // string destination_name = transition.destination_name; // foreach(StateNode findNewStateName in new_state_nodes) // { // if (findNewStateName.name.Contains(destination_name)) // { // //This means that the original state transition destination is merged, so we need to point to it // } // } // } // } // } // } //} return(new_state_nodes); }
private bool RelationShip_Exist_Between_State(StateNode vState, StateNode hState, sbyte[][] stair_array, sbyte counter, StateNode[] vArray, StateNode[] hArray) { /* * (1,a) = 2 (1,b) = 6 * (2,a) = 7 (2,b) = 3 * --------------------------- * (2,7) = no (6,3) = ? * (7,2) = ? (3,6) = si */ sbyte nextCount = Convert.ToSByte(counter + 1); //For every letter of the alphabet, check the states relationships for (int k = 0; k < this.alphabet.Count; k++) { #region Primera Tupla Con Letra //Get both state's destination with the first letter of the alphabet int firstPairID_1 = Get_Destination_From_State(vState, this.alphabet[k]); //(first_state, a) = 2, returns -1 if this state didnt have a destination int firstPairID_2 = Get_Destination_From_State(hState, this.alphabet[k]); //(second_state, a) = 7 //Find this ID its real index from the vertical and horizontal position for (int i = 0; i < state_nodes.Count - 1; i++) { if (vArray[i].id == firstPairID_1) { firstPairID_1 = i; break; } } //X2 for (int i = 0; i < state_nodes.Count - 1; i++) { //Missing by one index! Estoy buscando por id y por nombre y por eso tira indeces diferentes if (hArray[i].id == firstPairID_2) { firstPairID_2 = i; break; } } // (7,2) Check the stair array if this tuple has a mark available with the current counter in that position if (firstPairID_1 != -1 && firstPairID_2 != -1) { // (7,2) if (firstPairID_2 < stair_array[firstPairID_1].Length) { if (stair_array[firstPairID_1][firstPairID_2] == counter) { return(true); } } } #endregion #region Primera Tupla Reverse Con Letra //Get both state's destination with the first letter of the alphabet int reversePairID_1 = Get_Destination_From_State(vState, this.alphabet[k]); //(first_state, a) = 2, returns -1 if this state didnt have a destination int reversePairID_2 = Get_Destination_From_State(hState, this.alphabet[k]); //(second_state, a) = 7 //Find this ID its real index from the vertical and horizontal position for (int i = 0; i < state_nodes.Count - 1; i++) { if (hArray[i].id == reversePairID_1) { reversePairID_1 = i; break; } } //X2 for (int i = 0; i < state_nodes.Count - 1; i++) { //Missing by one index! Estoy buscando por id y por nombre y por eso tira indeces diferentes if (vArray[i].id == reversePairID_2) { reversePairID_2 = i; break; } } // (2, 7) Check the stair array if this tuple has a mark available with the current counter in that position if (reversePairID_1 != -1 && reversePairID_2 != -1) { // (2, 7) if (reversePairID_1 < stair_array[reversePairID_2].Length) { if (stair_array[reversePairID_2][reversePairID_1] == counter) { return(true); } } } #endregion } return(false); }
public string Minimize_Automaton() { /* * Vertical States | stair array * 2 -> [] * 3 -> [] [] * 4 -> [] [] [] * 5 -> [] [] [] [] * Horizontal States ---> 1 2 3 4 */ StateNode[] vertical_states, horizontal_states; sbyte[][] stair_array; /* Check if its DFA */ if (!Check_IF_DFA()) { return("The loaded automaton isnt a DFA"); } /* First, find unreacheable states and delete them */ Delete_Unreacheable_States(); /*Initialize*/ vertical_states = new StateNode[state_nodes.Count - 1]; horizontal_states = new StateNode[state_nodes.Count - 1]; stair_array = new sbyte[state_nodes.Count - 1][]; /* Then, build every array */ Build_2D_Stair_Array(ref stair_array); Build_Vertical_State_Array(ref vertical_states); Build_Horizontal_State_Array(ref horizontal_states); /* Then, mark with 0 those states that are distintive from one another */ bool is_any_state_distinct = Find_Distinct_State(vertical_states, horizontal_states, ref stair_array); /* If no state was distinct from one or another, then just stop the algorithm */ if (!is_any_state_distinct) { return("The automaton cant be minimized! All states are the same (final or not final)"); } /* Keep doing a while loop till no new distinct states appear */ bool did_new_state_appear = false; sbyte counter = 1; do { did_new_state_appear = Mark_Distinct_State(vertical_states, horizontal_states, ref stair_array, counter); counter++; } while (did_new_state_appear); /* Check if the automaton was minimized already to send a message that says that the automaton is already minimized */ if (Automaton_Is_Already_Minimized(stair_array)) { return("The loaded Automaton is minimized already!"); } /* Now, create merge new states into a single one and also convert the 2D array to list array */ state_nodes = Convert_To_List(vertical_states, horizontal_states, stair_array); //TODO: This, convert all the empty spaces from the stair array into a single statenode, merging all of its transitions return("Success! The loaded automaton is minimized! Try saving it now"); }