public void CountsOnlyOneFinal() { var m1Start = new GraphState () { IsFinal = true }; var secondFinal = new GraphState () { IsFinal = true }; var thirdFinal = new GraphState () { IsFinal = true }; var m1 = new Graph () { StartState = m1Start }; var epsilonConnection1 = new GraphStateConnection { Start = m1Start, End = secondFinal, ConnectedBy = Word.Epsilon }; var epsilonConnection2 = new GraphStateConnection { Start = secondFinal, End = thirdFinal, ConnectedBy = Word.Epsilon }; m1.StartState.Out.Add (epsilonConnection1); secondFinal.Out.Add (epsilonConnection2); var finals = m1.FindFinalStates (m1.StartState); finals.Count.Should ().Be (3); }
/// <summary> /// Performs the Union on two NDFA's. /// </summary> /// <param name="m2">The NDFA to Union with.</param> /// <returns>>A new NDFA that is the union of the two graphs.</returns> public Graph Union(Graph m2) { var m = new Graph (); var m1 = this; //new start state m.StartState = new GraphState (); //new q0 var newFinalState = new GraphState () { IsFinal = true }; //connection from q0 to q1 over epsilon var q0Toq1 = new GraphStateConnection () { ConnectedBy = Word.Epsilon, Start = m.StartState, End = m1.StartState }; //connection from q0 to q2 var q0Toq2 = new GraphStateConnection () { ConnectedBy = Word.Epsilon, Start = m.StartState, End = m2.StartState }; //attach states. m.StartState.Out.Add (q0Toq1); m.StartState.Out.Add (q0Toq2); var m1Finals = FindFinalStates (m1.StartState); var m2Finals = FindFinalStates (m2.StartState); foreach (var final in m1Finals) { final.IsFinal = false; var finalConnection = new GraphStateConnection () { Start = final, End = newFinalState, ConnectedBy = Word.Epsilon }; final.Out.Add (finalConnection); } foreach (var final in m2Finals) { final.IsFinal = false; var finalConnection = new GraphStateConnection () { Start = final, End = newFinalState, ConnectedBy = Word.Epsilon }; final.Out.Add (finalConnection); } //update the total state count m.StateCount = m1.StateCount + m2.StateCount + 2; if (updateStateNumber) { RenumberStates (m.StartState); } return m; }
/// <summary> /// Concatinates two NDFA's. /// </summary> /// <param name="m1">The second NDFA to concatinate with.</param> /// <returns>The new graph that is this and m1 concatinated.</returns> public Graph Concat(Graph m1) { var m = new Graph (); var m2 = this; var m1FinalStates = m1.FindFinalStates (m1.StartState); foreach (var finalState in m1FinalStates) { //create a new connection to m2 initial state var m1FinalTom2Initial = new GraphStateConnection () { Start = finalState, End = m2.StartState, ConnectedBy = Word.Epsilon }; //make the connection finalState.Out.Add (m1FinalTom2Initial); //kill m1 final states and leave m2 as finals for m finalState.IsFinal = false; } //update state count for new graph m.StartState = m1.StartState; m.StateCount = m1.StateCount + m2.StateCount; if (updateStateNumber) { RenumberStates (m.StartState); } return m; }
/// <summary> /// Perfoms a Kleene operation on the graph. /// </summary> /// <returns>The new graph after the Kleene operation.</returns> public Graph Kleene() { var m = new Graph (); var m1 = this; var finals = FindFinalStates (m1.StartState); var oldInitial = m1.StartState; //create new init and final state. var newInitial = new GraphState (){ IsFinal = true, StateNumber = m1.StateCount + 1 }; //create connection from new initial to the old initial through epsilon var initialEpsilonConnection = new GraphStateConnection { End = oldInitial, Start = newInitial, ConnectedBy = Word.Epsilon }; //add the connection to the states. newInitial.Out.Add (initialEpsilonConnection); foreach (var finalState in finals) { //now create epsilon connections from final to original start state var finalToOldInitialConnection = new GraphStateConnection { End = newInitial, Start = finalState, ConnectedBy = Word.Epsilon }; finalState.IsFinal = false; //now connect them finalState.Out.Add(finalToOldInitialConnection); } //now attach the new init state to the graph m.StartState = newInitial; m.StateCount = m1.StateCount + 1; return m; }