//public AutomatonModel ConvertNdfaToDfa(AutomatonModel ndfa) //{ // var dfa = new AutomatonModel(); // //Find epsilon transitions for each state // var stateToEpsilonN = new Dictionary<StateModel, List<StateModel>>(); // foreach (var state in ndfa.States) // { // FindEpsilonN(ndfa, stateToEpsilonN, state); // } // //FindEpsilonN only adds the E* which have an actual E transitions // //but does not consider the state itself then, hence the loop below // foreach (var state in ndfa.States) // { // if (!stateToEpsilonN.ContainsKey(state)) // { // stateToEpsilonN.Add(state, new List<StateModel> { state }); // } // } // dfa = BuildDfa(ndfa, stateToEpsilonN); // return dfa; //} private AutomatonModel BuildDfa(AutomatonModel ndfa, Dictionary <StateModel, List <StateModel> > stateToEpsilonN) { var initialState = ndfa.States.FirstOrDefault(x => x.IsInitial); if (initialState == null) { throw new Exception("No initial state found."); } var initList = new List <StateModel> { initialState }; var stack = new Stack <List <StateModel> >(); stack.Push(initList); var dfa = new AutomatonModel(); var stackHistory = new List <IntermediateDfaStateModel>(); FindNewStates(stack, stackHistory, stateToEpsilonN, ndfa, dfa); stackHistory = stackHistory.DistinctBy(s => s.Name).ToList(); FindNewTransitions(stackHistory, ndfa, dfa, stateToEpsilonN); dfa.Alphabet = ndfa.Alphabet; return(dfa); }
/// <summary> /// Reworked assignment five /// </summary> /// <param name="ndfa"></param> /// <returns></returns> public AutomatonModel ConvertNdfaToDfa(AutomatonModel ndfa) { var dfa = new AutomatonModel(); var newStates = new Dictionary <StateModel, List <StateModel> >(); List <StateModel> stateHistory = new List <StateModel>(); Queue <IntermediateDfaStateModel> stack = new Queue <IntermediateDfaStateModel>(); StateModel currentState = new StateModel(); var initialState = ndfa.States.FirstOrDefault(x => x.IsInitial); if (initialState == null) { throw new Exception("No initial state found."); } stateHistory.Add(initialState); stack.Enqueue(new IntermediateDfaStateModel { Name = initialState.Name, States = new List <StateModel> { initialState } }); dfa.States.Add(initialState); dfa.Alphabet = ndfa.Alphabet; TraverseNfa(stack, stateHistory, ndfa, dfa); return(dfa); }
public List <string> GetAllWords(AutomatonModel automaton) { _words = new List <string>(); var initialState = automaton.States.FirstOrDefault(x => x.IsInitial); _words = FindWords(automaton, new List <StateModel>(), initialState, ""); return(_words); }
private bool HasOneFinalState(AutomatonModel automaton) { var finalStatesCount = automaton.States.Count(i => i.IsFinal); if (finalStatesCount > 1) { return(false); } return(true); }
public GraphVizFileModel ConvertAutomatonToGenericFile(AutomatonModel automaton) { var graphVizFile = new GraphVizFileModel(); //ALPHABET string alphabetLine = ""; foreach (var letter in automaton.Alphabet) { alphabetLine += letter; } graphVizFile.Lines.Add(alphabet + " " + alphabetLine); //STATES string statesLine = ""; for (int index = 0; index < automaton.States.Count; index++) { var automatonState = automaton.States[index]; if (index == automaton.States.Count - 1) { statesLine += automatonState.Name; } else { statesLine += automatonState.Name + ","; } } graphVizFile.Lines.Add(states + " " + statesLine); //FINAL var finalStates = automaton.States.Where(x => x.IsFinal); var finalLine = ""; foreach (var finalState in finalStates) { finalLine += finalState.Name; } graphVizFile.Lines.Add(final + " " + finalLine); //TRANSITIONS graphVizFile.Lines.Add("transitions:"); foreach (var automatonTransition in automaton.Transitions) { var transitionLine = $"{automatonTransition.BeginState.Name},{automatonTransition.Value} --> {automatonTransition.EndState.Name}"; graphVizFile.Lines.Add(transitionLine); } //END. graphVizFile.Lines.Add("end."); return(graphVizFile); }
public AutomatonModel GetAutomaton(string input) { _automaton = new AutomatonModel(); var nodes = ParseRegularExpression(input); _automaton = NodesToAutomaton(nodes); _stateCount = 0; return(_automaton); }
private void TryAddTransitionOnItself(AutomatonModel automaton, TransitionModel transition, string newWord) { var moreTransitions = automaton.Transitions.Where( x => x.BeginState == x.EndState && x.BeginState == transition.EndState); if (moreTransitions.Count() > 0) { foreach (var moreTransition in moreTransitions) { _words.Add(GetNewWord(newWord, moreTransition)); } } }
public string IsStringAcceptedInFile(string input, AutomatonModel automaton) { var inFile = automaton.Words.FirstOrDefault(t => t.Key == input); if (inFile.Key == null) { return("NaN"); } if (inFile.Value) { return("True"); } else if (!inFile.Value) { return("False"); } return("NaN"); }
private bool HasOutputsEqualAlphabetCount(AutomatonModel automaton) { foreach (var automatonState in automaton.States) { int outputCount = 0; foreach (var automatonTransition in automaton.Transitions) { if (automatonTransition.BeginState == automatonState) { outputCount++; } } if (outputCount != automaton.Alphabet.Count) { return(false); } } return(true); }
private bool StatesHaveOutputsWithAllLetters(AutomatonModel automaton) { foreach (var automatonState in automaton.States) { List <char> letters = new List <char>(); foreach (var automatonTransition in automaton.Transitions) { if (automatonTransition.BeginState == automatonState) { letters.Add(Convert.ToChar(automatonTransition.Value)); } } var sequenceEqual = letters.OrderBy(t => t).SequenceEqual(automaton.Alphabet.OrderBy(t => t)); if (!sequenceEqual) { return(false); } } return(true); }
public GraphVizFileModel ConvertToGraphVizFile(AutomatonModel automaton) { var file = new GraphVizFileModel(); file.Lines.Add("digraph myAutomaton {"); file.Lines.Add("rankdir=LR;"); file.Lines.Add("\"\"[shape = none]"); //Add initials foreach (var automatonState in automaton.States) { if (automatonState.IsFinal && automatonState.IsInitial) { file.Lines.Add($"\"{automatonState.Name}\" [shape=doublecircle]"); file.Lines.Add($"\"\" -> \"{automatonState.Name}\""); } else if (automatonState.IsFinal) { file.Lines.Add($"\"{automatonState.Name}\" [shape=doublecircle]"); } else if (automatonState.IsInitial) { file.Lines.Add($"\"{automatonState.Name}\" [shape=circle]"); file.Lines.Add($"\"\" -> \"{automatonState.Name}\""); } else { file.Lines.Add($"\"{automatonState.Name}\" [shape=circle]"); } } //add transitions foreach (var transition in automaton.Transitions) { file.Lines.Add($"\"{transition.BeginState.Name}\" -> \"{transition.EndState.Name}\" [label=\"{transition.Value}\"]"); } file.Lines.Add("}"); return(file); }
public bool IsAutomatonDfa(AutomatonModel automaton) { //conditions: //outputs of all states are equal to alphabet count //outputs of all states have all alphabet values //only one final state if (!HasOneFinalState(automaton)) { return(false); } if (!HasOutputsEqualAlphabetCount(automaton)) { return(false); } if (!StatesHaveOutputsWithAllLetters(automaton)) { return(false); } return(true); }
private void FindEpsilonN(AutomatonModel ndfa, Dictionary <StateModel, List <StateModel> > stateToEpsilonN, StateModel state) { foreach (var transition in ndfa.Transitions) { if (transition.BeginState == state && transition.Value == "ε") { if (stateToEpsilonN.ContainsKey(state)) { stateToEpsilonN[state].Add(transition.EndState); } else { stateToEpsilonN.Add(state, new List <StateModel> { state, transition.EndState }); } FindEpsilonN(ndfa, stateToEpsilonN, transition.EndState); } } }
private List <string> FindWords(AutomatonModel automaton, List <StateModel> passedStates, StateModel state, string word) { foreach (var transition in automaton.Transitions) { if (transition.BeginState == state) { var newWord = GetNewWord(word, transition); var newPassedStates = new List <StateModel>(passedStates) { state }; if (!IsLoop(passedStates, state)) { if (transition.EndState.IsFinal) { _words.Add(newWord); TryAddTransitionOnItself(automaton, transition, newWord); } else { FindWords(automaton, newPassedStates, transition.EndState, newWord); } } else { if (transition.EndState.IsFinal) { _words.Add(newWord); TryAddTransitionOnItself(automaton, transition, newWord); } } } } return(_words); }
private StateModel AddHistoryToDfa(AutomatonModel dfa, IntermediateDfaStateModel newHistoryItem) { var newState = new StateModel() { Name = newHistoryItem.Name, }; if (dfa.States.All(s => s.Name != newState.Name)) { dfa.States.Add(newState); } else { newState = dfa.States.Find(s => s.Name == newState.Name); } dfa.Transitions.Add(new TransitionModel { BeginState = newHistoryItem.OriginatingState, EndState = newState, Value = newHistoryItem.Value }); return(newState); }
public bool IsAcceptedStringByPda(string input, AutomatonModel automaton) { Stack <string> stack = new Stack <string>(); List <char> values = new List <char>(); List <TransitionModel> possibleTransitions = new List <TransitionModel>(); StateModel currentState = new StateModel(); _isAcceptedStringFound = false; currentState = automaton.States.FirstOrDefault(s => s.IsInitial); if (string.IsNullOrEmpty(input) || string.IsNullOrWhiteSpace(input)) { return(IsEmptyWordAccepted(automaton, currentState, stack, false)); } foreach (var c in input) { values.Add(c); } return(TraversePda(automaton, values, currentState, stack, false)); }
public void IsAutomatonDfaWithNonDfa_Test() { // arrange DfaService dfaService = new DfaService(); AutomatonModel automaton = new AutomatonModel() { IsDfaInFile = true }; var stateZ = new StateModel() { IsFinal = false, IsInitial = true, Name = "z" }; var stateA = new StateModel() { IsFinal = false, IsInitial = false, Name = "a" }; var stateB = new StateModel() { IsFinal = true, IsInitial = false, Name = "b" }; List <StateModel> states = new List <StateModel> { stateB, stateA, stateZ }; List <TransitionModel> transitions = new List <TransitionModel>() { new TransitionModel() { BeginState = stateZ, EndState = stateA, Value = "a" }, new TransitionModel() { BeginState = stateZ, EndState = stateZ, Value = "b" }, new TransitionModel() { BeginState = stateZ, EndState = stateB, Value = "b" }, new TransitionModel() { BeginState = stateA, EndState = stateZ, Value = "b" }, new TransitionModel() { BeginState = stateA, EndState = stateB, Value = "a" }, new TransitionModel() { BeginState = stateB, EndState = stateB, Value = "b" }, new TransitionModel() { BeginState = stateB, EndState = stateZ, Value = "a" }, }; var alphabet = new List <char>() { 'a', 'b' }; automaton.States = states; automaton.Transitions = transitions; automaton.Alphabet = alphabet; var expected = false; // act var actual = dfaService.IsAutomatonDfa(automaton); // assert Assert.AreEqual(expected, actual); }
private void TraverseNfa(Queue <IntermediateDfaStateModel> queue, List <StateModel> stateHistory, AutomatonModel ndfa, AutomatonModel dfa) { IntermediateDfaStateModel currentStates = new IntermediateDfaStateModel(); if (queue.Any()) { currentStates = queue.Dequeue(); } else { return; } var originatingState = dfa.States.Find(s => s.Name == currentStates.Name); foreach (var letter in ndfa.Alphabet) { IntermediateDfaStateModel newHistoryItem = new IntermediateDfaStateModel(); foreach (var currentState in currentStates.States) { foreach (var state in ndfa.States) { foreach (var transition in ndfa.Transitions) { if (currentState == state && transition.Value == letter.ToString() && transition.BeginState == currentState) { //create history item //add each state to states list and add statename like += to history name newHistoryItem.States.Add(transition.EndState); newHistoryItem.Name += transition.EndState.Name; newHistoryItem.Value = transition.Value; newHistoryItem.OriginatingState = originatingState; } else if (currentState == state && transition.Value == _empty && transition.BeginState == currentState) { IntermediateDfaStateModel epsilonHistoryItem = FindEpsilonTransitions(originatingState, currentState, transition.EndState, letter, ndfa, dfa); if (epsilonHistoryItem.Name == null) { continue; } newHistoryItem.States.AddRange(epsilonHistoryItem.States); newHistoryItem.Name += epsilonHistoryItem.Name; newHistoryItem.Value = epsilonHistoryItem.Value; newHistoryItem.OriginatingState = originatingState; } } } //build new state and transition of the dfa //also add the new state to the stack } if (newHistoryItem.Name == null) { continue; } var newState = AddHistoryToDfa(dfa, newHistoryItem); if (stateHistory.All(s => s.Name != newState.Name)) { queue.Enqueue(newHistoryItem); stateHistory.Add(newState); } } //from the history add to stack //and also create new state with transition if (queue.Any()) { TraverseNfa(queue, stateHistory, ndfa, dfa); } else { //check also if a final state exists //Im not entirely sure about the theory for dfa's //but i made only one final state possible. //either the last processed one or //if the first processed state was initial already if (dfa.States.Any(s => s.IsFinal)) { return; } var lastState = dfa.States.LastOrDefault(); if (lastState != null) { lastState.IsFinal = true; } } }
private List <TransitionModel> ReadPdaTransitions(GraphVizFileModel graphVizFileModel, int lower, int upper, AutomatonModel automaton) { var transitions = new List <TransitionModel>(); for (int i = lower; i < upper; i++) { var transition = new TransitionModel(); var transitionString = graphVizFileModel.Lines[i]; var beginStateString = transitionString.Substring(0, transitionString.IndexOf(',')).Trim(); string valueString = "", leftStackString = "", rightStackString = ""; if (transitionString.Contains("[")) { valueString = transitionString.Substring(transitionString.IndexOf(',') + 1, transitionString.IndexOf('[') - 2) .Trim(); leftStackString = transitionString.Substring(transitionString.IndexOf('[') + 1, transitionString.IndexOf(',')).ToLower(); rightStackString = transitionString.Substring(transitionString.IndexOf(',', transitionString.IndexOf(',') + 1) + 1, 1).ToLower(); } else { valueString = transitionString.Substring(transitionString.IndexOf(',') + 1, transitionString.IndexOf(',') + 3) .Trim(); leftStackString = "_"; rightStackString = "_"; } var endStateString = transitionString.Substring(transitionString.IndexOf('>') + 1).Trim(); foreach (var state in automaton.States) { if (state.Name.Equals(beginStateString) && i == lower) { transition.BeginState = state; state.IsInitial = true; } else if (state.Name.Equals(beginStateString)) { transition.BeginState = state; } if (state.Name.Equals(endStateString)) { transition.EndState = state; } if (transition.BeginState != null && transition.EndState != null) { break; } } valueString = valueString.ToLower(); if (valueString.Equals("_")) { valueString = "ε"; } if (leftStackString.Equals("_")) { leftStackString = "ε"; } if (rightStackString.Equals("_")) { rightStackString = "ε"; } transition.PushStack = rightStackString; transition.PopStack = leftStackString; transition.Value = valueString; transitions.Add(transition); } return(transitions); }
public AutomatonModel ParseGraphVizFile(GraphVizFileModel graphVizFileModel) { string states = "states:"; string final = "final:"; string alphabet = "alphabet:"; string stack = "stack:"; var automaton = new AutomatonModel(); foreach (var line in graphVizFileModel.Lines) { if (line.Contains(alphabet)) { var chars = GetSubstring(line, alphabet); foreach (var c in chars) { automaton.Alphabet.Add(char.ToLower(c)); } } else if (line.Contains(stack)) { var chars = GetSubstring(line, stack); foreach (var c in chars) { automaton.AccecptedStack.Add(char.ToLower(c).ToString()); } automaton.IsPda = true; } else if (line.Contains(states)) { var sub = GetSubstring(line, states); var chars = SplitOnComma(sub); foreach (var c in chars) { var state = new StateModel() { Name = c.ToUpper() }; automaton.States.Add(state); } } else if (line.Contains(final)) { var sub = GetSubstring(line, final); var chars = SplitOnComma(sub); foreach (var c in chars) { foreach (var state in automaton.States) { if (c.Equals(state.Name)) { state.IsFinal = true; } } } } else if (line.Contains("transitions")) { var lower = graphVizFileModel.Lines.IndexOf(line) + 1; //todo: change upper to next "end." var upper = FindUpperLimit(graphVizFileModel.Lines.IndexOf(line), graphVizFileModel.Lines); var transitions = new List <TransitionModel>(); transitions = !automaton.IsPda ? ReadRegularAutomatonTransitions(graphVizFileModel, lower, upper, automaton) : ReadPdaTransitions(graphVizFileModel, lower, upper, automaton); automaton.Transitions = transitions; //break; } else if (line.Contains("words")) { var lower = graphVizFileModel.Lines.IndexOf(line) + 1; var upper = FindUpperLimit(graphVizFileModel.Lines.IndexOf(line), graphVizFileModel.Lines); automaton.Words = ReadWords(graphVizFileModel, lower, upper); } else if (line.Contains("dfa")) { var last = line[line.Length - 1]; automaton.IsDfaInFile = last == 'y'; } else if (line.Contains("finite")) { var last = line[line.Length - 1]; automaton.IsFiniteInFile = last == 'y'; } } return(automaton); }
public void IsAcceptedString_Test() { //arrange LanguageCheckService languageCheckService = new LanguageCheckService(); AutomatonModel automaton = new AutomatonModel() { IsDfaInFile = false }; var stateZ = new StateModel() { IsFinal = false, IsInitial = true, Name = "z" }; var stateA = new StateModel() { IsFinal = false, IsInitial = false, Name = "a" }; var stateB = new StateModel() { IsFinal = true, IsInitial = false, Name = "b" }; List <StateModel> states = new List <StateModel> { stateB, stateA, stateZ }; List <TransitionModel> transitions = new List <TransitionModel>() { new TransitionModel() { BeginState = stateZ, EndState = stateA, Value = "a" }, new TransitionModel() { BeginState = stateZ, EndState = stateZ, Value = "b" }, new TransitionModel() { BeginState = stateA, EndState = stateZ, Value = "b" }, new TransitionModel() { BeginState = stateA, EndState = stateB, Value = "a" }, new TransitionModel() { BeginState = stateB, EndState = stateB, Value = "b" }, new TransitionModel() { BeginState = stateB, EndState = stateZ, Value = "a" }, }; var alphabet = new List <char>() { 'a', 'b' }; automaton.States = states; automaton.Transitions = transitions; automaton.Alphabet = alphabet; //accepted var word1 = "aab"; var word2 = "baab"; var word3 = "abaa"; var word4 = "abaab"; //not accepted var word5 = "abb"; var word6 = "ba"; var word7 = "aaa"; var expected_word1 = true; var expected_word2 = true; var expected_word3 = true; var expected_word4 = true; var expected_word5 = false; var expected_word6 = false; var expected_word7 = false; //act //accepted var actual_word1 = languageCheckService.IsAcceptedString(word1, automaton); var actual_word2 = languageCheckService.IsAcceptedString(word2, automaton); var actual_word3 = languageCheckService.IsAcceptedString(word3, automaton); var actual_word4 = languageCheckService.IsAcceptedString(word4, automaton); //not accepted var actual_word5 = languageCheckService.IsAcceptedString(word5, automaton); var actual_word6 = languageCheckService.IsAcceptedString(word6, automaton); var actual_word7 = languageCheckService.IsAcceptedString(word7, automaton); //assert Assert.AreEqual(expected_word1, actual_word1); Assert.AreEqual(expected_word2, actual_word2); Assert.AreEqual(expected_word3, actual_word3); Assert.AreEqual(expected_word4, actual_word4); Assert.AreEqual(expected_word5, actual_word5); Assert.AreEqual(expected_word6, actual_word6); Assert.AreEqual(expected_word7, actual_word7); }
private bool TraversePda(AutomatonModel automaton, List <char> values, StateModel currentState, Stack <string> stack, bool localIsAcceptedStringFound) { string empty = "ε"; List <TransitionModel> possibleTransitions; //if there is stack but empty transition can remove stack we still have //to check the top of stack and see if transition can remove it //then another recursion, there are possibly more stack items if (stack.Any() && !values.Any()) { possibleTransitions = automaton.Transitions.Where(s => s.BeginState == currentState && s.Value == empty).ToList(); if (!possibleTransitions.Any()) { return(false); } foreach (var possibleTransition in possibleTransitions) { if (possibleTransition.PopStack != empty && possibleTransition.PushStack == empty) { if (stack.Any() && stack.Peek() == possibleTransition.PopStack) { stack.Pop(); } else { //if multiple stack letters are possible its not automatically false. if (stack.Any() && automaton.AccecptedStack.Contains(stack.Peek())) { continue; } return(false); } if (!stack.Any() && possibleTransition.EndState.IsFinal) { _isAcceptedStringFound = true; } TraversePda(automaton, values, possibleTransition.EndState, stack, false); } } } //check if values empty = processed all inputs //+ if the currentstate is an endstate //+ stack is empty if (!values.Any() && currentState.IsFinal && !stack.Any()) { _isAcceptedStringFound = true; return(_isAcceptedStringFound); } foreach (var value in values) { possibleTransitions = automaton.Transitions.Where(s => s.BeginState == currentState).ToList(); foreach (var possibleTransition in possibleTransitions) { //must conisder also emtpyt //must check if final state when word complete //accepted string: final state & stack empty if (possibleTransition.Value == value.ToString()) { //pop/push = empty and stack empty if (possibleTransition.PopStack == empty && possibleTransition.PushStack == empty && !stack.Any()) { return(_isAcceptedStringFound); } //[_, x] case 1 else if (possibleTransition.PopStack == empty && possibleTransition.PushStack != empty) { if (_isAcceptedStringFound) { return(true); } stack.Push(possibleTransition.PushStack); //var newStack = GetNewPushedStack(stack, possibleTransition.PushStack); var newValues = GetNewValues(values); TraversePda(automaton, newValues, possibleTransition.EndState, stack, false); } //[x,_] case 1 else if (possibleTransition.PopStack != empty && possibleTransition.PushStack == empty) { if (_isAcceptedStringFound) { return(true); } if (stack.Any() && stack.Peek() == possibleTransition.PopStack) { stack.Pop(); } else { return(false); } var newValues = GetNewValues(values); TraversePda(automaton, newValues, possibleTransition.EndState, stack, false); } //[x,x] if (possibleTransition.PopStack == possibleTransition.PushStack && possibleTransition.PopStack != empty && possibleTransition.PushStack != empty && stack.Any()) { if (_isAcceptedStringFound) { return(true); } var newValues = GetNewValues(values); TraversePda(automaton, newValues, possibleTransition.EndState, stack, false); } } else if (possibleTransition.Value == empty) { if (_isAcceptedStringFound) { return(true); } // case 3 if (stack.Any()) { if (stack.Peek() == possibleTransition.PopStack) { stack.Pop(); } else if (possibleTransition.PopStack == empty) // pop stack is empty = traverse w/o removing values { //do nothing } else { return(false); } TraversePda(automaton, values, possibleTransition.EndState, stack, false); } //case 4 else { if (possibleTransition.PopStack == empty && possibleTransition.PushStack == empty) { TraversePda(automaton, values, possibleTransition.EndState, stack, false); } else if (possibleTransition.PopStack == empty && possibleTransition.PushStack != empty) { stack.Push(possibleTransition.PushStack); TraversePda(automaton, values, possibleTransition.EndState, stack, false); } } } } // if (!stack.Any() && value == values[values.Count - 1]) return true; //doesnt consider end state } return(_isAcceptedStringFound); }
private void FindNewStates(Stack <List <StateModel> > stack, List <IntermediateDfaStateModel> stackHistory, Dictionary <StateModel, List <StateModel> > stateToEpsilonN, AutomatonModel ndfa, AutomatonModel dfa) { List <StateModel> currentStates; if (stack.Any()) { currentStates = stack.Pop(); } else { return; } foreach (var currentState in currentStates) { foreach (var state in ndfa.States) { foreach (var letter in ndfa.Alphabet) { foreach (var transition in ndfa.Transitions) { //check if state is in epsilon transition if (currentState == state && state == transition.BeginState && letter.ToString() == transition.Value) { AddToStackHistory(stackHistory, currentStates); var epsilonStates = stateToEpsilonN[transition.EndState]; var newStatesForRecursion = new List <StateModel>(); var newState = new StateModel(); foreach (var epsilonState in epsilonStates) { newStatesForRecursion.Add(epsilonState); newState.Name += epsilonState.Name + ","; } if (newState.Name.EndsWith(",")) { newState.Name = newState.Name.TrimEnd(','); } //TODO: eventually add something extra for final state if ((state.IsInitial || state.IsFinal) && dfa.States.All(s => s.Name != state.Name)) { dfa.States.Add(state); } else if (transition.EndState.IsFinal && dfa.States.All(s => s.Name != transition.EndState.Name)) { dfa.States.Add(transition.EndState); stackHistory.Add(new IntermediateDfaStateModel() { Name = transition.EndState.Name, States = new List <StateModel> { transition.EndState } }); } if (dfa.States.All(s => s.Name != newState.Name)) { dfa.States.Add(newState); stack.Push(newStatesForRecursion); } FindNewStates(stack, stackHistory, stateToEpsilonN, ndfa, dfa); //dfa.Transitions.Add(new TransitionModel //{ // BeginState = state, // EndState = newState, // Value = letter.ToString() //}); } } } } } }
private void FindNewTransitions(List <IntermediateDfaStateModel> stackHistory, AutomatonModel ndfa, AutomatonModel dfa, Dictionary <StateModel, List <StateModel> > stateToEpsilonN) { //check each transition in original automaton for each letter //beginstate must be in stackhistory and endstate is E* //then the transition is beginstate = stackhistory combined and end state is E* //there must be verified if the transition in the new automaton already exists foreach (var history in stackHistory) { foreach (var historyState in history.States) { foreach (var transition in ndfa.Transitions) { foreach (var letter in ndfa.Alphabet) { if (historyState == transition.BeginState && transition.Value == letter.ToString()) { var epsilonStates = stateToEpsilonN[transition.EndState]; if (history.States.Count == 1) { if (historyState.IsInitial || historyState.IsFinal) { var endStateName = ""; foreach (var epsilonState in epsilonStates) { if (epsilonState == epsilonStates[epsilonStates.Count - 1]) { endStateName += epsilonState.Name; } else { endStateName += epsilonState.Name + ","; } } var endState = new StateModel { Name = endStateName }; var trans = new TransitionModel { BeginState = historyState, EndState = endState, Value = letter.ToString() }; if (dfa.States.All(s => s.Name != historyState.Name)) { dfa.States.Add(historyState); } if (dfa.States.All(s => s.Name != endState.Name)) { dfa.States.Add(endState); } dfa.Transitions.Add(trans); } } else if (history.States.Count > 1) { var beginStateName = ""; foreach (var state in history.States) { if (state == history.States[history.States.Count - 1]) { beginStateName += state.Name; } else { beginStateName += state.Name + ","; } } var beginState = new StateModel { Name = beginStateName }; var endStateName = ""; foreach (var epsilonState in epsilonStates) { if (epsilonState == epsilonStates[epsilonStates.Count - 1]) { endStateName += epsilonState.Name; } else { endStateName += epsilonState.Name + ","; } } var endState = new StateModel { Name = endStateName }; var trans = new TransitionModel { BeginState = beginState, EndState = endState, Value = letter.ToString() }; if (dfa.States.All(s => s.Name != endState.Name)) { dfa.States.Add(endState); } if (dfa.States.All(s => s.Name != beginState.Name)) { dfa.States.Add(beginState); } dfa.Transitions.Add(trans); } } } } } } }
public bool IsAcceptedString(string input, AutomatonModel automaton) { List <StateModel> currentStates = automaton.States.Where(x => x.IsInitial).ToList(); List <StateModel> nextStates = new List <StateModel>(); List <char> values = new List <char>(); List <TransitionModel> possibleTransitions = new List <TransitionModel>(); foreach (var c in input) { values.Add(c); } for (int i = 0; i < values.Count; i++) { var value = values[i]; possibleTransitions = automaton.Transitions.Where(s => currentStates.Contains(s.BeginState)).ToList(); for (int index = 0; index < possibleTransitions.Count; index++) { var possibleTransition = possibleTransitions[index]; //check if transition is possible and if its the last one if (possibleTransition.Value == value.ToString()) { nextStates.Add(possibleTransition.EndState); } else if (possibleTransition.Value == "ε") { //check if epsilon endState has a transition with value[index] //if yes add to nextstates var transitionsAfterEpsilon = automaton.Transitions.Where( transition => transition.BeginState == possibleTransition.EndState && transition.Value == Convert.ToString(values[i])) .ToList(); if (transitionsAfterEpsilon.Any()) { foreach (var transition in transitionsAfterEpsilon) { nextStates.Add(transition.BeginState); } } } if (possibleTransition.EndState.IsFinal && i == values.Count - 1 && nextStates.Any()) { return(true); } } //if yes then check the next state; if (!nextStates.Any()) { return(false); } currentStates.Clear(); currentStates = new List <StateModel>(nextStates); nextStates.Clear(); } return(false); }
private IntermediateDfaStateModel FindEpsilonTransitions(StateModel originatingState, StateModel currentState, StateModel transitionEndState, char letter, AutomatonModel ndfa, AutomatonModel dfa) { IntermediateDfaStateModel historyItem = new IntermediateDfaStateModel(); foreach (var transition in ndfa.Transitions) { if (transition.BeginState == transitionEndState && transition.Value == letter.ToString()) { //create the new history item and return historyItem.States.Add(transition.EndState); historyItem.Name += transition.EndState.Name; historyItem.Value = transition.Value; historyItem.OriginatingState = originatingState; } else if (transition.BeginState == transitionEndState && transition.Value == _empty) { //continue recursion } } return(historyItem); }
public void ConvertNdfaToDfa_Test2() { //arrange DfaService dfaService = new DfaService(); AutomatonModel ndfa = new AutomatonModel(); StateModel state1 = new StateModel() { IsFinal = false, IsInitial = true, Name = "1" }; StateModel state2 = new StateModel() { IsFinal = false, IsInitial = false, Name = "2" }; StateModel state3 = new StateModel() { IsFinal = true, IsInitial = false, Name = "3" }; StateModel state4 = new StateModel() { IsFinal = false, IsInitial = false, Name = "4" }; ndfa.States.Add(state1); ndfa.States.Add(state2); ndfa.States.Add(state3); ndfa.States.Add(state4); TransitionModel trans1 = new TransitionModel() { BeginState = state1, EndState = state2, Value = "a" }; TransitionModel trans2 = new TransitionModel() { BeginState = state1, EndState = state4, Value = "c" }; TransitionModel trans3 = new TransitionModel() { BeginState = state2, EndState = state1, Value = "ε" }; TransitionModel trans4 = new TransitionModel() { BeginState = state2, EndState = state3, Value = "b" }; TransitionModel trans5 = new TransitionModel() { BeginState = state3, EndState = state2, Value = "a" }; TransitionModel trans6 = new TransitionModel() { BeginState = state4, EndState = state3, Value = "ε" }; TransitionModel trans7 = new TransitionModel() { BeginState = state4, EndState = state3, Value = "c" }; ndfa.Transitions.Add(trans1); ndfa.Transitions.Add(trans2); ndfa.Transitions.Add(trans3); ndfa.Transitions.Add(trans4); ndfa.Transitions.Add(trans5); ndfa.Transitions.Add(trans6); ndfa.Transitions.Add(trans7); ndfa.Alphabet.Add('a'); ndfa.Alphabet.Add('b'); ndfa.Alphabet.Add('c'); int expected_nr_transitions = 8; int expected_transitions_with_a = 4; int expected_transitions_with_b = 1; int expected_transitions_with_c = 3; int expected_nr_states = 4; //act var dfa = dfaService.ConvertNdfaToDfa(ndfa); int actual_nr_transitions = dfa.Transitions.Count; int actual_transitions_with_a = dfa.Transitions.Where(t => t.Value == "a").ToList().Count; int actual_transitions_with_b = dfa.Transitions.Where(t => t.Value == "b").ToList().Count; int actual_transitions_with_c = dfa.Transitions.Where(t => t.Value == "c").ToList().Count; int actual_nr_states = dfa.States.Count; //assert Assert.AreEqual(expected_nr_states, actual_nr_states); Assert.AreEqual(expected_nr_transitions, actual_nr_transitions); Assert.AreEqual(expected_transitions_with_a, actual_transitions_with_a); Assert.AreEqual(expected_transitions_with_b, actual_transitions_with_b); Assert.AreEqual(expected_transitions_with_c, actual_transitions_with_c); }
private List <TransitionModel> ReadRegularAutomatonTransitions(GraphVizFileModel graphVizFileModel, int lower, int upper, AutomatonModel automaton) { var transitions = new List <TransitionModel>(); for (int i = lower; i < upper; i++) { var transition = new TransitionModel(); var transitionString = graphVizFileModel.Lines[i]; var beginStateString = transitionString.Substring(0, transitionString.IndexOf(',')).Trim(); var valueString = transitionString.Substring(transitionString.IndexOf(',') + 1, transitionString.IndexOf('-') - 2) .Trim(); var endStateString = transitionString.Substring(transitionString.IndexOf('>') + 1).Trim(); foreach (var state in automaton.States) { if (state.Name.Equals(beginStateString) && i == lower) { transition.BeginState = state; state.IsInitial = true; } else if (state.Name.Equals(beginStateString)) { transition.BeginState = state; } if (state.Name.Equals(endStateString)) { transition.EndState = state; } if (transition.BeginState != null && transition.EndState != null) { break; } } valueString = valueString.ToLower(); if (valueString.Equals("_")) { valueString = "ε"; } transition.Value = valueString; transitions.Add(transition); } return(transitions); }
private AutomatonModel BuildAutomaton(NodeModel currentNode, NodeModel previousNode, StateModel leftState, StateModel rightState) { if (currentNode == null) { return(null); } #region dot if (currentNode.Value == Dot) { if (previousNode == null) //initial aut. { var state1 = new StateModel { IsInitial = true, IsFinal = false, Name = _stateCount++.ToString() }; var state2 = new StateModel { IsInitial = false, IsFinal = false, Name = _stateCount++.ToString() }; var state3 = new StateModel { IsInitial = false, IsFinal = true, Name = _stateCount++.ToString() }; var dotAutomaton = new AutomatonModel() { States = { state1, state2, state3 }, }; _automaton = dotAutomaton; if (IsOperandOrAsterix(currentNode.LeftChild.Value)) { BuildAutomaton(currentNode.LeftChild, currentNode, state1, state2); } else { _automaton.Transitions.Add(new TransitionModel { BeginState = state1, EndState = state2, Value = currentNode.LeftChild.Value }); } if (IsOperandOrAsterix(currentNode.RightChild.Value)) { BuildAutomaton(currentNode.RightChild, currentNode, state2, state3); } else { _automaton.Transitions.Add(new TransitionModel { BeginState = state2, EndState = state3, Value = currentNode.RightChild.Value }); } } else { var middleState = new StateModel { Name = _stateCount++.ToString() }; _automaton.States.Add(middleState); if (IsOperandOrAsterix(currentNode.LeftChild.Value)) { BuildAutomaton(currentNode.LeftChild, currentNode, leftState, middleState); } else { if (currentNode.LeftChild != null) { var trans = new TransitionModel { BeginState = leftState, EndState = middleState, Value = currentNode.LeftChild.Value }; _automaton.Transitions.Add(trans); } } if (IsOperandOrAsterix(currentNode.RightChild.Value)) { BuildAutomaton(currentNode.RightChild, currentNode, middleState, rightState); } else // in the value { if (currentNode.RightChild != null) { var trans = new TransitionModel() { BeginState = middleState, EndState = rightState, Value = currentNode.RightChild.Value }; _automaton.Transitions.Add(trans); } } } } #endregion #region asterix else if (currentNode.Value == Asterix) { if (previousNode == null) //initial aut. { var state1 = new StateModel { IsFinal = false, IsInitial = true, Name = _stateCount++.ToString() }; var state2 = new StateModel { IsFinal = false, IsInitial = false, Name = _stateCount++.ToString() }; var state3 = new StateModel { IsFinal = false, IsInitial = false, Name = _stateCount++.ToString() }; var state4 = new StateModel { IsFinal = true, IsInitial = false, Name = _stateCount++.ToString() }; var trans1 = new TransitionModel { BeginState = state1, EndState = state2, Value = "ε" }; var trans3 = new TransitionModel { BeginState = state3, EndState = state4, Value = "ε" }; var trans4 = new TransitionModel { BeginState = state1, EndState = state4, Value = "ε" }; var trans5 = new TransitionModel { BeginState = state3, EndState = state2, Value = "ε" }; var asterixAutomaton = new AutomatonModel() { States = { state1, state2, state3, state4 }, Transitions = { trans1, trans3, trans4, trans5 } }; _automaton = asterixAutomaton; if (IsOperandOrAsterix(currentNode.RightChild.Value)) { BuildAutomaton(currentNode.RightChild, currentNode, state2, state3); } else { _automaton.Transitions.Add(new TransitionModel() { BeginState = state2, EndState = state3, Value = currentNode.RightChild.Value }); } } else { var state1 = new StateModel { IsFinal = false, IsInitial = false, Name = _stateCount++.ToString() }; var state2 = new StateModel { IsFinal = false, IsInitial = false, Name = _stateCount++.ToString() }; var state3 = new StateModel { IsFinal = false, IsInitial = false, Name = _stateCount++.ToString() }; var state4 = new StateModel { IsFinal = false, IsInitial = false, Name = _stateCount++.ToString() }; var transLeftTo1 = new TransitionModel { BeginState = leftState, EndState = state1, Value = "ε" }; var trans4ToRight = new TransitionModel { BeginState = state4, EndState = rightState, Value = "ε" }; var trans1To2 = new TransitionModel { BeginState = state1, EndState = state2, Value = "ε" }; var trans1To4 = new TransitionModel { BeginState = state1, EndState = state4, Value = "ε" }; var trans3To2 = new TransitionModel { BeginState = state3, EndState = state2, Value = "ε" }; var trans3To4 = new TransitionModel { BeginState = state3, EndState = state4, Value = "ε" }; _automaton.States.Add(state1); _automaton.States.Add(state2); _automaton.States.Add(state3); _automaton.States.Add(state4); _automaton.Transitions.Add(transLeftTo1); _automaton.Transitions.Add(trans4ToRight); _automaton.Transitions.Add(trans1To2); _automaton.Transitions.Add(trans1To4); _automaton.Transitions.Add(trans3To2); _automaton.Transitions.Add(trans3To4); if (IsOperandOrAsterix(currentNode.RightChild.Value)) { BuildAutomaton(currentNode.RightChild, currentNode, state2, state3); } else { if (currentNode.RightChild != null) { _automaton.Transitions.Add(new TransitionModel() { BeginState = state2, EndState = state3, Value = currentNode.RightChild.Value }); } } } } #endregion #region or else if (currentNode.Value == Or) { if (previousNode == null) { var state1 = new StateModel { IsInitial = true, IsFinal = false, Name = _stateCount++.ToString() }; var state2 = new StateModel { IsInitial = false, IsFinal = true, Name = _stateCount++.ToString() }; var orAutomaton = new AutomatonModel { States = { state1, state2 } }; _automaton = orAutomaton; if (IsOperandOrAsterix(currentNode.LeftChild.Value)) { BuildAutomaton(currentNode.LeftChild, currentNode, state1, state2); } else { _automaton.Transitions.Add(new TransitionModel { BeginState = state1, EndState = state2, Value = currentNode.LeftChild.Value }); } if (IsOperandOrAsterix(currentNode.RightChild.Value)) { BuildAutomaton(currentNode.RightChild, currentNode, state1, state2); } else { _automaton.Transitions.Add(new TransitionModel { BeginState = state1, EndState = state2, Value = currentNode.RightChild.Value }); } } else { if (IsOperandOrAsterix(currentNode.LeftChild.Value)) { BuildAutomaton(currentNode.LeftChild, currentNode, leftState, rightState); } else { _automaton.Transitions.Add(new TransitionModel() { BeginState = leftState, EndState = rightState, Value = currentNode.LeftChild.Value }); } if (IsOperandOrAsterix(currentNode.RightChild.Value)) { BuildAutomaton(currentNode.RightChild, currentNode, leftState, rightState); } else { _automaton.Transitions.Add(new TransitionModel() { BeginState = leftState, EndState = rightState, Value = currentNode.RightChild.Value }); } } } #endregion return(_automaton); }
private bool IsEmptyWordAccepted(AutomatonModel automaton, StateModel currentState, Stack <string> stack, bool localIsAcceptedStringFound) { string empty = "ε"; List <TransitionModel> possibleTransitions; if (currentState.IsFinal && !stack.Any()) { //check if final is start and see if transition exists //where push/pop = empty //else false if (currentState.IsFinal && currentState.IsInitial) { possibleTransitions = automaton.Transitions.Where(s => s.BeginState == currentState && s.BeginState == s.EndState && s.PopStack == empty && s.PushStack == empty) .ToList(); if (possibleTransitions.Any()) { _isAcceptedStringFound = true; } else { return(false); } } _isAcceptedStringFound = true; } possibleTransitions = automaton.Transitions.Where(s => s.BeginState == currentState).ToList(); foreach (var possibleTransition in possibleTransitions) { if (possibleTransition.Value == empty) { if (possibleTransition.PopStack == empty && possibleTransition.PushStack == empty && !stack.Any()) { if (possibleTransition.EndState.IsFinal) { _isAcceptedStringFound = true; } else { IsEmptyWordAccepted(automaton, possibleTransition.EndState, stack, false); } } else if (possibleTransition.PopStack == empty && possibleTransition.PushStack != empty) { if (_isAcceptedStringFound) { return(true); } stack.Push(possibleTransition.PushStack); IsEmptyWordAccepted(automaton, possibleTransition.EndState, stack, false); } //[x,_] case 1 else if (possibleTransition.PopStack != empty && possibleTransition.PushStack == empty) { if (_isAcceptedStringFound) { return(true); } if (stack.Any() && stack.Peek() == possibleTransition.PopStack) { stack.Pop(); } else { return(false); } IsEmptyWordAccepted(automaton, possibleTransition.EndState, stack, false); } } } return(_isAcceptedStringFound); }