static public Automata <String> getExampleSlide8Lesson2() { char[] alphabet = { 'a', 'b' }; Automata <String> automata = new Automata <string>(alphabet); automata.AddTransition(new Transition <String>("q0", "q1", 'a')); automata.AddTransition(new Transition <String>("q0", "q4", 'b')); automata.AddTransition(new Transition <String>("q1", "q4", 'a')); automata.AddTransition(new Transition <String>("q1", "q2", 'b')); automata.AddTransition(new Transition <String>("q2", "q3", 'a')); automata.AddTransition(new Transition <String>("q2", "q4", 'b')); automata.AddTransition(new Transition <String>("q3", "q1", 'a')); automata.AddTransition(new Transition <String>("q3", "q2", 'b')); // the error state, loops for a and b: automata.AddTransition(new Transition <String>("q4", 'a')); automata.AddTransition(new Transition <String>("q4", 'b')); // only on start state in a dfa: automata.DefineAsStartState("q0"); // two final states: automata.DefineAsFinalState("q2"); automata.DefineAsFinalState("q3"); return(automata); }
/// <summary> /// Turns a <see cref="RegExp"/> into a <see cref="Automata{string}"/>, which is a NDFA. /// </summary> /// <param name="expressionToTranslate">The <see cref="RegExp"/> to translate.</param> /// <returns>A <see cref="Automata{string}"/>, which is a NDFA or null if there was a problem</returns> public Automata <string> GenerateNDFA(RegExp expressionToTranslate) { HashSet <char> alphabet = new HashSet <char>(); String regexAsString = expressionToTranslate.ToString(); foreach (char c in regexAsString) { if (IsUsableCharacter(c)) { alphabet.Add(c); } } ; ThompsonPart completeNdfaAsThompson = GenerateThompsonPart(regexAsString); if (completeNdfaAsThompson.Equals(new ThompsonPart())) { return(null); } Automata <string> NDFA = new Automata <string>(alphabet.ToArray()); foreach (Transition <string> thompsonTransition in completeNdfaAsThompson.transitions) { NDFA.AddTransition(thompsonTransition); } NDFA.DefineAsStartState(completeNdfaAsThompson.startState); NDFA.DefineAsFinalState(completeNdfaAsThompson.finalState); return(NDFA); }
/// <summary> /// Generates the dfa for the given dictionary of states /// </summary> private void GenerateDFA() { dfa = new Automata <T>(ndfa.Symbols); //Start building the DFA as normal, with the state names being the combined states to be reached in one string, with a - as delimiter. //Starting with the start state, foreach symbol create two string builder objects, build up the string in the state + - format //Create a transition with the symbol and the states. //Should we reach an empty collection, create the $ state, and for each symbol in the alphabet make a transition to this state //Begin with the start state and all transitions List <Transition <T> > dfaStart = GenerateDfaStart(); //Keep track of states that we still need to visit HashSet <T> statesToTraverse = new HashSet <T>(); foreach (Transition <T> transition in dfaStart) { dfa.AddTransition(transition); if (!transition.FromState.Equals(transition.ToState)) { statesToTraverse.Add(transition.ToState); } } //Sets all the transitions for the following states GenerateOtherTransitions(statesToTraverse); //After that, for all states check if it's a start state or end state. MarkStatesAsStartOrEnd(); }
/// <summary> /// This makes sure only a single - will end up between states. /// </summary> /// <param name="dfaToRemap">The dfa to remap the states for</param> /// <returns>A re mapped version of the given automata</returns> private Automata <T> RemapStates(Automata <T> dfaToRemap) { Dictionary <T, T> stateMap = new Dictionary <T, T>(); for (int i = 0; i < dfaToRemap.States.Count; i++) { string newState = "q" + i; T newStateT = (T)Convert.ChangeType(newState, typeof(T)); stateMap.Add(dfaToRemap.States.ElementAt(i), newStateT); } Console.WriteLine("Now printing the remap dictionary:"); foreach (KeyValuePair <T, T> map in stateMap) { Console.WriteLine("Mapped {0} as {1}", map.Key, map.Value); } Console.WriteLine("-----------------------------------------"); Automata <T> remappedDfa = new Automata <T>(dfaToRemap.Symbols); foreach (Transition <T> transition in dfaToRemap.Transitions) { remappedDfa.AddTransition(new Transition <T>(stateMap[transition.FromState], stateMap[transition.ToState], transition.Identifier)); } foreach (T startState in dfaToRemap.StartStates) { remappedDfa.DefineAsStartState(stateMap[startState]); } foreach (T finalState in dfaToRemap.FinalStates) { remappedDfa.DefineAsFinalState(stateMap[finalState]); } return(remappedDfa); }
/// <summary> /// Turns a dfa into a form in which the original is not accepted. /// </summary> /// <param name="originalDfa">The dfa to make a reverse of</param> /// <returns>A dfa that is a reverse of the original dfa</returns> public Automata <T> ReverseDfa(Automata <T> originalDfa) { if (!originalDfa.IsDfa()) { throw new ArgumentException("Given automata is not a DFA."); } Automata <T> reversedDfa = new Automata <T>(originalDfa.Symbols); //Every transition is swapped as follows: new transition(original end state, symbol, original start state) foreach (Transition <T> transition in originalDfa.Transitions) { reversedDfa.AddTransition(new Transition <T>(transition.ToState, transition.FromState, transition.Identifier)); } //All start states become end states foreach (T startState in originalDfa.StartStates) { reversedDfa.DefineAsFinalState(startState); } //All end states become start states foreach (T endState in originalDfa.FinalStates) { reversedDfa.DefineAsStartState(endState); } return(reversedDfa); }
/// <summary> /// Turns a dfa into a form in which the original is not accepted. /// </summary> /// <param name="originalDfa">The dfa to "invert"</param> /// <returns>A dfa that is !the original dfa</returns> public Automata <T> NotDfa(Automata <T> originalDfa) { if (!originalDfa.IsDfa()) { throw new ArgumentException("Given automata is not a DFA."); } Automata <T> notDfa = new Automata <T>(originalDfa.Symbols); //Alles wat geen end state is word een end, en omgekeerd. //Filter all end states from all the states IEnumerable <T> newEndStates = originalDfa.States.Except(originalDfa.FinalStates); //Set everthing in the new dfa foreach (Transition <T> transition in originalDfa.Transitions) { notDfa.AddTransition(transition); } foreach (T startState in originalDfa.StartStates) { notDfa.DefineAsStartState(startState); } foreach (T finalState in newEndStates) { notDfa.DefineAsFinalState(finalState); } return(notDfa); }
/// <summary> /// Traverses the <see cref="Dictionary{TKey, TValue}"/> to generate a dfa. This recursively happen untill there are no more states to traverse. /// </summary> /// <param name="combinedDfa">The combined dfa, modified and passed every loop.</param> /// <param name="statesToTraverse">The next states to traverse.</param> private void GenerateCombinedDfa(Automata <T> combinedDfa, List <T> statesToTraverse) { List <T> statesToTraverseNext = new List <T>(); //Add all the new transitions to the combined dfa. foreach (T state in statesToTraverse) { List <KeyValuePair <char, T> > transitionsFromThisState = combinedTransitionsMap[state]; foreach (KeyValuePair <char, T> symbolAndToState in transitionsFromThisState) { if (DfaContainsStateCombinedDfa(combinedDfa, symbolAndToState.Value)) { combinedDfa.AddTransition(new Transition <T>(state, symbolAndToState.Value, symbolAndToState.Key)); continue; } //Skip this state if it is already in the dfa. But do add a transition if (state.Equals(symbolAndToState.Value)) { combinedDfa.AddTransition(new Transition <T>(state, symbolAndToState.Key)); } else { combinedDfa.AddTransition(new Transition <T>(state, symbolAndToState.Value, symbolAndToState.Key)); statesToTraverseNext.Add(symbolAndToState.Value); } } } //And a zero means that we have reached the end. if (statesToTraverseNext.Count <= 0) { return; } else { GenerateCombinedDfa(combinedDfa, statesToTraverseNext); } }
static public Automata <String> ndfaToDfaTest() { char[] alphabet = { 'a', 'b' }; Automata <String> automata = new Automata <String>(alphabet); automata.AddTransition(new Transition <string>("A", "B", 'a')); automata.AddTransition(new Transition <string>("A", "C", 'b')); automata.AddTransition(new Transition <string>("B", "D", 'a')); automata.AddTransition(new Transition <string>("C", "B", 'b')); automata.AddTransition(new Transition <string>("C", "D")); automata.AddTransition(new Transition <string>("D", "A", 'b')); automata.AddTransition(new Transition <string>("D", "E", 'a')); automata.AddTransition(new Transition <string>("E", "C")); automata.AddTransition(new Transition <string>("E", "F", 'a')); automata.DefineAsStartState("A"); automata.DefineAsFinalState("F"); return(automata); }
/// <summary> /// Uses the given dictionary and the given list of states to get more transitions /// </summary> /// <param name="statesToLoopThrough">The states to loop through</param> /// <returns></returns> private void GenerateOtherTransitions(HashSet <T> statesToLoopThrough) { List <Transition <T> > transitions = new List <Transition <T> >(); HashSet <T> statesToTraverseNext = new HashSet <T>(); foreach (T currentStateLoopingThrough in statesToLoopThrough) { if (currentStateLoopingThrough.Equals(emptyStateT)) { foreach (char symbol in ndfa.Symbols) { transitions.Add(new Transition <T>(emptyStateT, symbol)); } continue; } //For the state (which may be a composite) get all single states string[] splitStates = currentStateLoopingThrough.ToString().Split('-'); List <T> splitStatesT = new List <T>(); //List of all states contained in this state foreach (string stateAsString in splitStates) { T stateT = (T)Convert.ChangeType(stateAsString, typeof(T)); splitStatesT.Add(stateT); } foreach (char symbol in ndfa.Symbols) { HashSet <T> reachableStatesWithThisSymbol = new HashSet <T>(); foreach (T stateToLookFor in splitStatesT) { //Then gather all states this can go to HashSet <T> statesReachedByGivenState = reachableStates[stateToLookFor].Find(x => x.Key == symbol).Value; //Find the states reached with this state-symbol combination foreach (T foundState in statesReachedByGivenState) { reachableStatesWithThisSymbol.Add(foundState); } } //For which the collection forms a single to state StringBuilder toState = new StringBuilder(); if (reachableStatesWithThisSymbol.Count == 0) { toState.Append("$"); } //Create the empty to state else { foreach (T reachableState in reachableStatesWithThisSymbol) { //Append to the string toState.Append(reachableState.ToString() + '-'); } //And remove last toState.Remove(toState.Length - 1, 1); } T toStateT = (T)Convert.ChangeType(toState.ToString(), typeof(T)); if (StatesAreEqual(currentStateLoopingThrough, toStateT)) { //Should the toState and the current state be equal, we can point to ourself transitions.Add(new Transition <T>(currentStateLoopingThrough, symbol)); } else { //Which then gives us the transition of: //state as the from state, //The collection as the to state //And the symbol as the identifier statesToTraverseNext.Add(toStateT); transitions.Add(new Transition <T>(currentStateLoopingThrough, toStateT, symbol)); } } } foreach (Transition <T> transition in transitions) { dfa.AddTransition(transition); } //Check if there still are states left to traverse, which we haven't traversed yet HashSet <T> statesAlreadyTraversed = new HashSet <T>(); foreach (Transition <T> transition in dfa.Transitions) { statesAlreadyTraversed.Add(transition.FromState); } //Quick filter all states that happen to be the exact same (for example, C-D-E might be in the to traverse and the already traversed as the same string) statesToTraverseNext = new HashSet <T>(statesToTraverseNext.Except(statesAlreadyTraversed)); //Since this method adds states anyway, only continue if we still need to traverse states. if (statesToTraverseNext.Count > 0) { GenerateOtherTransitions(statesToTraverseNext); } }
static public Automata <String> dfaMutationTestL1() { char[] alphabet = { 'a', 'b' }; Automata <String> automata = new Automata <String>(alphabet); automata.AddTransition(new Transition <string>("A", "B", 'b')); automata.AddTransition(new Transition <string>("B", "C", 'a')); automata.AddTransition(new Transition <string>("C", "D", 'b')); automata.AddTransition(new Transition <string>("D", "E", 'a')); automata.AddTransition(new Transition <string>("E", "F", 'a')); automata.AddTransition(new Transition <string>("A", "G", 'a')); automata.AddTransition(new Transition <string>("B", "G", 'b')); automata.AddTransition(new Transition <string>("C", "G", 'a')); automata.AddTransition(new Transition <string>("D", "G", 'b')); automata.AddTransition(new Transition <string>("E", "G", 'b')); //End point shenenigans so testing goes a bit smoother automata.AddTransition(new Transition <string>("F", 'a')); automata.AddTransition(new Transition <string>("F", 'b')); automata.AddTransition(new Transition <string>("G", 'a')); automata.AddTransition(new Transition <string>("G", 'b')); automata.DefineAsStartState("A"); automata.DefineAsFinalState("F"); return(automata); }
static public Automata <String> getExampleSlide14Lesson2() { char[] alphabet = { 'a', 'b' }; Automata <String> automata = new Automata <String>(alphabet); automata.AddTransition(new Transition <String>("A", "C", 'a')); automata.AddTransition(new Transition <String>("A", "B", 'b')); automata.AddTransition(new Transition <String>("A", "C", 'b')); automata.AddTransition(new Transition <String>("B", "C", 'b')); automata.AddTransition(new Transition <String>("B", "C")); automata.AddTransition(new Transition <String>("C", "D", 'a')); automata.AddTransition(new Transition <String>("C", "E", 'a')); automata.AddTransition(new Transition <String>("C", "D", 'b')); automata.AddTransition(new Transition <String>("D", "B", 'a')); automata.AddTransition(new Transition <String>("D", "C", 'a')); automata.AddTransition(new Transition <String>("E", 'a')); automata.AddTransition(new Transition <String>("E", "D")); // only on start state in a dfa: automata.DefineAsStartState("A"); // two final states: automata.DefineAsFinalState("C"); automata.DefineAsFinalState("E"); return(automata); }