public void Should_ReturnFalse_When_IsValid_AutomataIsInvalidDFA() { List <char> alphabet = new List <char> { 'a', 'b', 'c' }; FiniteAutomata dfaTest = new FiniteAutomata(FiniteAutomataType.DFA, alphabet); _ = dfaTest.AddState(true); // q0 _ = dfaTest.AddState(); // q1 _ = dfaTest.AddState(isFinalState: true); // q2 _ = dfaTest.AddTransition('b', "q0", "q2"); // TR: q0 'b' geçiþi ile q2'ye gider. _ = dfaTest.AddTransition('c', "q0", "q0"); // TR: q0 'c' geçiþi ile q0'a gider. _ = dfaTest.AddTransition('c', "q0", "q1"); // TR: q0 'c' geçiþi ile q1'e gider. _ = dfaTest.AddTransition('a', "q1", "q0"); // TR: q1 'a' geçiþi ile q0'a gider. _ = dfaTest.AddTransition('b', "q1", "q1"); // TR: q1 'b' geçiþi ile q1'e gider. _ = dfaTest.AddTransition('c', "q1", "q2"); // TR: q1 'c' geçiþi ile q2'ye gider. _ = dfaTest.AddTransition('a', "q2", "q0"); // TR: q2 'a' geçiþi ile q0'a gider. _ = dfaTest.AddTransition('b', "q2", "q2"); // TR: q2 'b' geçiþi ile q2'ye gider. _ = dfaTest.AddTransition('c', "q2", "q2"); // TR: q2 'c' geçiþi ile q2'ye gider. Assert.IsFalse(dfaTest.IsValid); }
/// <summary> /// Converts 2DFA to DFA /// </summary> /// <param name="input">2DFA object</param> /// <returns>DFA object</returns> public FiniteAutomata Convert2DFAToDFA(FiniteAutomata input) { if (input is null) { throw new FAConverterException("Input automata cannot be NULL"); } if (input.AutomataType != FiniteAutomataType.TwoWayDFA) { throw new FAConverterException($"Unexpected Automata Type {input.AutomataType}"); } FiniteAutomata DFA = new FiniteAutomata(FiniteAutomataType.DFA, input.Alphabet.ToList()); DFA = InsertRightDirectionStates(input, DFA); DFA = InsertLeftDirectionStates(input, DFA); List <FATransition> transitions = DFA.Transitions.Where(x => x.Direction == false).ToList(); for (int i = 0; i < transitions.Count; i++) { transitions[i].Direction = true; } return(DFA); }
public void Should_ReturnsDFAAutomata_When_Convert2DFAToDFA_WithValid2DFA() { List <char> alphabet = new List <char> { '0', '1' }; FiniteAutomata twdfaTest = new FiniteAutomata(FiniteAutomataType.TwoWayDFA, alphabet); _ = twdfaTest.AddState("q0", isInitialState: true); _ = twdfaTest.AddState("q1"); _ = twdfaTest.AddState("q2"); _ = twdfaTest.AddState("q3", isFinalState: true); _ = twdfaTest.AddTransition('0', "q0", "q1", 1); _ = twdfaTest.AddTransition('1', "q0", "q2", 1); _ = twdfaTest.AddTransition('0', "q1", "q3", 0); _ = twdfaTest.AddTransition('1', "q1", "q2", 0); _ = twdfaTest.AddTransition('0', "q2", "q2", 1); _ = twdfaTest.AddTransition('1', "q2", "q3", 1); _ = twdfaTest.AddTransition('0', "q3", "q1", 1); _ = twdfaTest.AddTransition('1', "q3", "q2", 0); FiniteAutomataConverter automataConverter = new FiniteAutomataConverter(); FiniteAutomata converterDFA = automataConverter.Convert2DFAToDFA(twdfaTest); if (converterDFA.InitialState.StateName == twdfaTest.InitialState.StateName && converterDFA.FinalState.Count() == twdfaTest.FinalState.Count()) { Assert.Pass(); } Assert.Fail(); }
public void Should_ThrowsException_When_FiniteAutomata_AlphabetIsNull() { Assert.Throws <FAAlphabetException>(delegate { FiniteAutomata automata = new FiniteAutomata(FiniteAutomataType.DFA, null); }); }
private static void TWDFAFunction(string inputString) { Timer.Start(); FiniteAutomata automata1 = TWDFABuilder3(); ConsoleOperations.WriteBMarkReset("2DFA Creation"); ConsoleOperations.WriteTitle("2DFA Info"); ConsoleOperations.WriteAutomataInfo(automata1); Timer.Restart(); FiniteAutomataConverter dfaConverter1 = new FiniteAutomataConverter(); FiniteAutomata resultX = dfaConverter1.Convert2DFAToDFA(automata1); ConsoleOperations.WriteBMarkReset("Automata Conversion"); Console.WriteLine("\n>>>2DFA is converted to DFA<<<\n"); ConsoleOperations.WriteTitle("DFA Info"); ConsoleOperations.WriteAutomataInfo(resultX); ConsoleOperations.WriteTitle("DFA Trace"); Timer.Restart(); bool result = resultX.Run(inputString); ConsoleOperations.WriteBMarkReset("DFA Run"); Timer.Stop(); ConsoleOperations.WriteTitle("Automata Results"); Console.WriteLine("DFA Response: Input is " + (result ? "Accepted" : "Rejected")); ConsoleOperations.WriteTitle("Benchmark Results"); BenchmarkResults.ForEach(x => Console.WriteLine(x)); }
private State AddTrapState(FiniteAutomata dfa) { var trapState = new State("trap") {Id = int.MaxValue}; for (int i = 0; i <= Byte.MaxValue; i++) { trapState.AddTransitionTo(trapState, InputChar.For((byte) i)); } var states = dfa.GetStates(); foreach (var state in states) { bool[] usedTransitions = new bool[Byte.MaxValue + 1]; // All nulls foreach (var transition in state.Transitions) { usedTransitions[transition.Key.Value] = true; // mark used symbol } for (int i = 0; i <= Byte.MaxValue; i++) { if (!usedTransitions[i]) { state.AddTransitionTo(trapState, InputChar.For((byte)i)); } } } return trapState; }
public void Should_ReturnTrue_When_IsValid_AutomataIsValid2DFA() { List <char> alphabet = new List <char> { '0', '1' }; FiniteAutomata twdfaTest = new FiniteAutomata(FiniteAutomataType.TwoWayDFA, alphabet); _ = twdfaTest.AddState("q0", isInitialState: true); _ = twdfaTest.AddState("q1"); _ = twdfaTest.AddState("q2"); _ = twdfaTest.AddState("q3", isFinalState: true); _ = twdfaTest.AddTransition('0', "q0", "q1", 1); _ = twdfaTest.AddTransition('1', "q0", "q2", 1); _ = twdfaTest.AddTransition('0', "q1", "q3", 0); _ = twdfaTest.AddTransition('1', "q1", "q2", 0); _ = twdfaTest.AddTransition('0', "q2", "q2", 1); _ = twdfaTest.AddTransition('1', "q2", "q3", 1); _ = twdfaTest.AddTransition('0', "q3", "q1", 1); _ = twdfaTest.AddTransition('1', "q3", "q2", 0); Assert.True(twdfaTest.IsValid); }
private void runDFAButton_Click(object sender, EventArgs e) { if (DFA is null) { Convertor automataConverter = new Convertor(); FiniteAutomata dfa = automataConverter.NFAToDFA(NFA); var(result, text) = dfa.Run(inputString); dfaResult = result; if (result == false) { Console.WriteLine("Not Valid"); } automataOutputRichTextBox.Text = text; } else { var(result, text) = DFA.Run(inputString); dfaResult = result; if (result == false) { Console.WriteLine("Not Valid"); } automataOutputRichTextBox.Text = text; } }
internal override FiniteAutomata AsNFA() { var nfa = new FiniteAutomata("range"); for (int c = mLeft; c <= mRight; c++) { var literal = (char) c; var bytes = Encoding.GetBytes(new[] { literal }); State state = nfa.StartState; InputChar inputChar; for (int i = 0; i < bytes.Length - 1; i++) { List<State> transitions; inputChar = InputChar.For(bytes[i]); if (state.Transitions.TryGetValue(inputChar, out transitions) && transitions.Count > 0) { state = transitions[0]; } else { var newState = new State("range:" + bytes[i]); state.Transitions.Add(inputChar, new List<State> { newState }); state = newState; } } // Assign last transition to Terminator for everyone inputChar = InputChar.For(bytes[bytes.Length - 1]); state.AddTransitionTo(nfa.Terminator, inputChar); } return nfa; }
public void Should_ReturnFalse_When_Run_DFAWithABCABCABC() { List <char> alphabet = new List <char>() { 'a', 'b', 'c' }; FiniteAutomata automata = new FiniteAutomata(FiniteAutomataType.DFA, alphabet); _ = automata.AddState("q0", isInitialState: true, isFinalState: true); _ = automata.AddState("q1"); _ = automata.AddState("q2"); _ = automata.AddState("q3"); _ = automata.AddTransition('a', "q0", "q1"); _ = automata.AddTransition('b', "q0", "q1"); _ = automata.AddTransition('c', "q0", "q1"); _ = automata.AddTransition('a', "q1", "q2"); _ = automata.AddTransition('b', "q1", "q2"); _ = automata.AddTransition('c', "q1", "q2"); _ = automata.AddTransition('a', "q2", "q3"); _ = automata.AddTransition('b', "q2", "q3"); _ = automata.AddTransition('c', "q2", "q3"); _ = automata.AddTransition('a', "q3", "q0"); _ = automata.AddTransition('b', "q3", "q0"); _ = automata.AddTransition('c', "q3", "q0"); Assert.False(automata.Run("abcabcabc")); }
private void convertButton_Click(object sender, EventArgs e) { Convertor automataConverter = new Convertor(); FiniteAutomata converterDFA = automataConverter.NFAToDFA(NFA); DFA = converterDFA; }
public void Test_NFA_RUN_Should_Return_False_Invalid_Input() { var inputString = "10001"; List <char> alphabet = new List <char> { '0', '1' }; FiniteAutomata nfaTest = new FiniteAutomata(AutomataType.NFA, alphabet); _ = nfaTest.AddState("A", isInitialState: true, false); //A _ = nfaTest.AddState("B", false, false); //B _ = nfaTest.AddState("C", false, isFinalState: true); //C _ = nfaTest.AddTransition('0', "A", "A"); // TR: A '0' _ = nfaTest.AddTransition('1', "A", "B,C"); // TR: A '1' _ = nfaTest.AddTransition('0', "B", "A"); // TR: B '0' _ = nfaTest.AddTransition('1', "B", "A,C"); // TR: B '1' _ = nfaTest.AddTransition('0', "C", "A,B"); // TR: C '0' _ = nfaTest.AddTransition('1', "C", "C"); // TR: C '1' var result = nfaTest.Run(inputString); Assert.AreEqual(false, result); }
private static FiniteAutomata TWDFABuilder3() { List <char> alphabet = new List <char> { '0', '1' }; FiniteAutomata twdfaTest = new FiniteAutomata(FiniteAutomataType.TwoWayDFA, alphabet); _ = twdfaTest.AddState("q0", isInitialState: true); _ = twdfaTest.AddState("q1"); _ = twdfaTest.AddState("q2"); _ = twdfaTest.AddState("q3"); _ = twdfaTest.AddState("q4", isFinalState: true); _ = twdfaTest.AddTransition('0', "q0", "q1", 1); _ = twdfaTest.AddTransition('1', "q0", "q2", 1); _ = twdfaTest.AddTransition('0', "q1", "q4", 1); _ = twdfaTest.AddTransition('1', "q1", "q2", 0); _ = twdfaTest.AddTransition('0', "q2", "q3", 1); _ = twdfaTest.AddTransition('1', "q2", "q2", 1); _ = twdfaTest.AddTransition('0', "q3", "q1", 0); _ = twdfaTest.AddTransition('1', "q3", "q2", 0); _ = twdfaTest.AddTransition('0', "q4", "q4", 0); _ = twdfaTest.AddTransition('1', "q4", "q4", 1); return(twdfaTest); }
public void Should_ReturnsDFAAutomata_When_ConvertNFAToDFA_WithValidNFA() { List <char> alphabet = new List <char> { '0', '1' }; FiniteAutomata nfaTest = new FiniteAutomata(FiniteAutomataType.NFA, alphabet); _ = nfaTest.AddState("A", isInitialState: true); //A _ = nfaTest.AddState("B"); //B _ = nfaTest.AddState("C", isFinalState: true); //C _ = nfaTest.AddTransition('0', "A", "A"); // TR: A '0' geçişiyle A'ya gider. _ = nfaTest.AddTransition('1', "A", "B,C"); // TR: A '1' geçişiyle B ya da C'ye gider. _ = nfaTest.AddTransition('0', "B", "A"); // TR: B '0' geçişiyle B'ye gider. _ = nfaTest.AddTransition('1', "B", "A,C"); // TR: B '1' geçişiyle A ya da C'ye gider. _ = nfaTest.AddTransition('0', "C", "A,B"); // TR: C '0' geçişiyle A ya da B'ye gider. _ = nfaTest.AddTransition('1', "C", "C"); // TR: C '1' geçişiyle C'ye gider. FiniteAutomata dfaTest = new FiniteAutomata(FiniteAutomataType.DFA, alphabet); _ = dfaTest.AddState("A", isInitialState: true); _ = dfaTest.AddState("B&C", isFinalState: true); _ = dfaTest.AddState("A&B"); _ = dfaTest.AddState("A&C", isFinalState: true); _ = dfaTest.AddState("A&B&C", isFinalState: true); _ = dfaTest.AddTransition('0', "A", "A"); _ = dfaTest.AddTransition('1', "A", "B&C"); _ = dfaTest.AddTransition('0', "B&C", "A&B"); _ = dfaTest.AddTransition('1', "B&C", "A&C"); _ = dfaTest.AddTransition('0', "A&B", "A"); _ = dfaTest.AddTransition('1', "A&B", "A&B&C"); _ = dfaTest.AddTransition('0', "A&C", "A&B"); _ = dfaTest.AddTransition('1', "A&C", "B&C"); _ = dfaTest.AddTransition('0', "A&B&C", "A&B"); _ = dfaTest.AddTransition('1', "A&B&C", "A&B&C"); FiniteAutomataConverter automataConverter = new FiniteAutomataConverter(); FiniteAutomata converterDFA = automataConverter.ConvertNFAToDFA(nfaTest); if (converterDFA.InitialState.StateName == dfaTest.InitialState.StateName && converterDFA.FinalState.Count() == dfaTest.FinalState.Count() && converterDFA.States.Count() == dfaTest.States.Count() && converterDFA.Transitions.Count() == dfaTest.Transitions.Count() && converterDFA.States.Count() == dfaTest.States.Count() && converterDFA.Transitions.Last().TransitionSymbol == dfaTest.Transitions.Last().TransitionSymbol) { Assert.Pass(); } Assert.Fail(); }
public void Should_ThrowsException_When_FiniteAutomata_AlphabetIsEmpty() { Assert.Throws <FAAlphabetException>(delegate { List <char> alphabet = new List <char>(); FiniteAutomata automata = new FiniteAutomata(FiniteAutomataType.DFA, alphabet); }); }
public void Test_Should_ReturnsDFAAutomata_When_ConvertNFAToDFA_WithValidNFA() { List <char> alphabet = new List <char> { '0', '1' }; FiniteAutomata nfaTest = new FiniteAutomata(AutomataType.NFA, alphabet); _ = nfaTest.AddState("A", isInitialState: true, false); //A _ = nfaTest.AddState("B", false, false); //B _ = nfaTest.AddState("C", false, isFinalState: true); //C _ = nfaTest.AddTransition('0', "A", "A"); // TR: A '0' _ = nfaTest.AddTransition('1', "A", "B,C"); // TR: A '1' _ = nfaTest.AddTransition('0', "B", "A"); // TR: B '0' _ = nfaTest.AddTransition('1', "B", "A,C"); // TR: B '1' _ = nfaTest.AddTransition('0', "C", "A,B"); // TR: C '0' _ = nfaTest.AddTransition('1', "C", "C"); // TR: C '1' FiniteAutomata dfaTest = new FiniteAutomata(AutomataType.DFA, alphabet); _ = dfaTest.AddState("A", isInitialState: true); _ = dfaTest.AddState("B&C", isFinalState: true); _ = dfaTest.AddState("A&B", false, false); _ = dfaTest.AddState("A&C", isFinalState: true); _ = dfaTest.AddState("A&B&C", isFinalState: true); _ = dfaTest.AddTransition('0', "A", "A"); _ = dfaTest.AddTransition('1', "A", "B&C"); _ = dfaTest.AddTransition('0', "B&C", "A&B"); _ = dfaTest.AddTransition('1', "B&C", "A&C"); _ = dfaTest.AddTransition('0', "A&B", "A"); _ = dfaTest.AddTransition('1', "A&B", "A&B&C"); _ = dfaTest.AddTransition('0', "A&C", "A&B"); _ = dfaTest.AddTransition('1', "A&C", "B&C"); _ = dfaTest.AddTransition('0', "A&B&C", "A&B"); _ = dfaTest.AddTransition('1', "A&B&C", "A&B&C"); Convertor automataConverter = new Convertor(); FiniteAutomata converterDFA = automataConverter.NFAToDFA(nfaTest); if (converterDFA.InitialState().StateName == dfaTest.InitialState().StateName && converterDFA.FinalState().Count() == dfaTest.FinalState().Count() && converterDFA.states.Count() == dfaTest.states.Count() && converterDFA.transitions.Count() == dfaTest.transitions.Count() && converterDFA.transitions.Last().transitionSymbol == dfaTest.transitions.Last().transitionSymbol) { Assert.Pass(); } Assert.Fail(); }
/// <summary> /// Print the state machine as DOT notation suitable for drawing graphs. /// This is a useful debug functionality!! /// </summary> /// <param name="automata">Automata to generate graph for</param> /// <param name="input">Input to highlight the current state with</param> /// <param name="graphName">Graph name as specified in notation</param> /// <returns></returns> internal static string AsDotNotation <TState>(this FiniteAutomata <TState> automata, string input, string graphName = "automata") where TState : FiniteAutomata <TState> .BaseState { // Draw the *FA as a directed graph with the state numbers in circles // Use a double circle for accepting states // // digraph graphname { // digraph G { // [node shape="circle"] // 1 [shape="doublecircle"] // 1 -> 2 [label=a] //} StringBuilder sb = new StringBuilder(); sb.Append("digraph " + graphName + " {\n"); sb.Append("\t[node shape=\"circle\"]\n"); sb.Append("\tgraph [rankdir=\"LR\"]\n"); IEnumerable <TState> currentStates = Enumerable.Empty <TState>(); bool matchSuccessful = false; if (!string.IsNullOrEmpty(input)) { StimulateResult <TState> stimulateResult = automata.Stimulate(input); matchSuccessful = (input == stimulateResult.Matched); sb.AppendFormat("\tlabel=\"Matched: {0}\"\n", stimulateResult.Matched.Replace("\"", "\\\"")); sb.Append("\tlabelloc=top;\n"); sb.Append("\tlabeljust=center;\n"); currentStates = stimulateResult.ActiveStates; } foreach (Transition <TState> transition in automata.Transitions) { sb.Append(string.Format("\t{0} -> {1} [label=\"{2}\"]\n", transition.From.StateNumber, transition.To.StateNumber, transition.TransitionLabel().Replace("\\", "\\\\").Replace("\"", "\\\""))); } foreach (TState state in automata.States.Where(f => f.AcceptState || currentStates.Contains(f))) { sb.AppendFormat("\t{0} [{1}{2}]\n", state.StateNumber, state.AcceptState ? "shape=\"doublecircle\"" : "", currentStates.Contains(state) ? string.Format(" fillcolor=\"{0}\" style=\"filled\"", matchSuccessful ? "green" : "red") : ""); } sb.Append("}"); return(sb.ToString()); }
private void runButton_Click(object sender, EventArgs e) { inputString = inputStringTextBox.Text; string[] tokens = automataConfig.Split("\n"); var splitter = ";"; List <char> alphabet = new List <char>(); List <State> states = new List <State>(); List <Transition> transitions = new List <Transition>(); string[] transitionData = new string[] { }; FiniteAutomata automata = null; for (int i = 0; i < tokens.Length - 1; i++) { if (i == 0) { alphabet = tokens[i].Split(splitter).SelectMany(s => s.ToCharArray()).Distinct().ToList(); automata = new FiniteAutomata(AutomataType.NFA, alphabet); } else if (i == 1) { var statesNames = tokens[i].Split(splitter); for (int j = 0; j < statesNames.Length; j++) { if (j == 0) { var state = new State(statesNames[j], true, false); automata.AddState(state); } else if (j == statesNames.Length - 1) { var state = new State(statesNames[j], false, true); automata.AddState(state); } else { var state = new State(statesNames[j], false, false); automata.AddState(state); } } } else { transitionData = tokens[i].Split(splitter); automata.AddTransition(transitionData[0].ToCharArray()[0], transitionData[1], transitionData[2]); } } var(result, text) = automata.Run(inputString); nfaResult = result; if (result == false) { Console.WriteLine("Not Valid"); } automataOutputRichTextBox.Text = text; NFA = automata; }
private void button3_Click(object sender, EventArgs e) { this.PerformAction(() => { this.automata = this.automata.ToDfa(); this.DrawAutomata(); AutomataFileWriter.WriteToFile(this.automata, "DFAConverted"); }); }
public void Should_Pass_When_FiniteAutomata_AlphabetIsNotNull() { List <char> alphabet = new List <char>() { 'a' }; FiniteAutomata automata = new FiniteAutomata(FiniteAutomataType.DFA, alphabet); Assert.Pass(); }
public void Should_ReturnTrue_When_AddState_PassStateNameAndInitialStateAndFinalState() { List <char> alphabet = new List <char>() { 'a' }; FiniteAutomata automata = new FiniteAutomata(FiniteAutomataType.DFA, alphabet); Assert.True(automata.AddState("State Name", isInitialState: true, isFinalState: true)); }
internal override FiniteAutomata AsNFA() { var nfa = new FiniteAutomata("OptionalRegExpNFA"); FiniteAutomata optionalExpNFA = OptionalExpression.AsNFA(); nfa.StartState.AddTransitionTo(optionalExpNFA.StartState, InputChar.Epsilon()); nfa.StartState.AddTransitionTo(nfa.Terminator, InputChar.Epsilon()); optionalExpNFA.Terminator.AddTransitionTo(nfa.Terminator, InputChar.Epsilon()); return nfa; }
private static void AssignIdsToStates(FiniteAutomata automata) { var idProvider = new IDProvider(); var states = automata.GetStates(); foreach (var state in states) { state.Id = idProvider.GetNext(); } }
public void EmptyGraphTest() { var FA = FiniteAutomata.ConvertGraphToAutomata(graph.Edges.ToList(), graph.Vertices.ToList()); Assert.False(FA.DoAllTransitions("12345")); FA.SetString("12345"); FA.SingleStep(); //Assert.False(FA.CanDoStep()); //TODO: Debug CanDoStep on an empty FA Assert.AreEqual(ResultEnum.NotRunned, FA.StepResult); }
public void Should_ReturnTrue_When_AddState_WithOnlyPassIsFinalStateParameter() { List <char> alphabet = new List <char>() { 'a' }; FiniteAutomata automata = new FiniteAutomata(FiniteAutomataType.DFA, alphabet); Assert.IsTrue(automata.AddState(isFinalState: true)); }
public void Should_ReturnTrue_When_AddState_WithoutParamter() { List <char> alphabet = new List <char>() { 'a' }; FiniteAutomata automata = new FiniteAutomata(FiniteAutomataType.DFA, alphabet); Assert.IsTrue(automata.AddState()); }
public void Should_ReturnTrue_When_AddState_WithFAState() { List <char> alphabet = new List <char>() { 'a' }; FiniteAutomata automata = new FiniteAutomata(FiniteAutomataType.DFA, alphabet); FAState state = new FAState("State"); Assert.True(automata.AddState(state)); }
public void Should_ReturnTrue_When_AddState_MultipleAddFinalState() { List <char> alphabet = new List <char>() { 'a' }; FiniteAutomata automata = new FiniteAutomata(FiniteAutomataType.DFA, alphabet); _ = automata.AddState(isFinalState: true); Assert.True(automata.AddState(isFinalState: true)); }
public void Should_ReturnFalse_When_AddState_WithNullFaState() { List <char> alphabet = new List <char>() { 'a' }; FiniteAutomata automata = new FiniteAutomata(FiniteAutomataType.DFA, alphabet); FAState state = null; Assert.False(automata.AddState(state)); }
private void button1_Click(object sender, EventArgs e) { this.PerformAction(() => { if (openFileDialog1.ShowDialog() == DialogResult.OK) { var lines = File.ReadLines(openFileDialog1.FileName); this.automata = Parser.FiniteAutomataParser.CreateAutomata(lines.ToList()); this.DrawAutomata(); } }); }
internal override FiniteAutomata AsNFA() { var nfa = new FiniteAutomata("RepetitionRegExpNFA"); FiniteAutomata innerExpNFA = ExpressionToRepeat.AsNFA(); nfa.StartState.AddTransitionTo(innerExpNFA.StartState, InputChar.Epsilon()); nfa.StartState.AddTransitionTo(nfa.Terminator, InputChar.Epsilon()); innerExpNFA.Terminator.AddTransitionTo(nfa.Terminator, InputChar.Epsilon()); innerExpNFA.Terminator.AddTransitionTo(innerExpNFA.StartState, InputChar.Epsilon()); return nfa; }
public void Should_ReturnFalse_When_AddTransition_WithNullFATransition() { List <char> alphabet = new List <char>() { 'a' }; FiniteAutomata automata = new FiniteAutomata(FiniteAutomataType.DFA, alphabet); FATransition transition = null; Assert.False(automata.AddTransition(transition)); }
public void Should_ThrowException_When_Convert2DFAToDFA_InputAutomataTypeIsNot2DFA() { _ = Assert.Throws <FAConverterException>(delegate { List <char> alphabet = new List <char> { 'a', 'b' }; FiniteAutomata automata = new FiniteAutomata(FiniteAutomataType.NFA, alphabet); FiniteAutomataConverter converter = new FiniteAutomataConverter(); _ = converter.Convert2DFAToDFA(automata); }); }
public void Should_ReturnTrue_When_AddTransition_WithFATranstion() { List <char> alphabet = new List <char>() { 'a' }; FiniteAutomata automata = new FiniteAutomata(FiniteAutomataType.DFA, alphabet); FAState state1 = new FAState("q1", isInitialState: true, isFinalState: true); FATransition transition = new FATransition('a', state1, state1); Assert.True(automata.AddTransition(transition)); }
public void Should_Equal_When_InitalState_ComparedByInitialState() { List <char> alphabet = new List <char> { '0', '1' }; FiniteAutomata automata = new FiniteAutomata(FiniteAutomataType.NFA, alphabet); FAState state = new FAState("A", isInitialState: true); automata.AddState(state); Assert.AreEqual(state, automata.InitialState); }
// TODO: Think about: // - Whether it's needed or not to remove all transitions from dfa2 accepting state (i.e. mCrossState[dfa1State][dfa2State.IsAccepting].RemoveAllransitions // - What to do with trap states internal void Construct(FiniteAutomata dfa1, FiniteAutomata dfa2) { var dfa1TrapState = AddTrapState(dfa1); var dfa2TrapState = AddTrapState(dfa2); var dfa1States = dfa1.GetStates(); var dfa2States = dfa2.GetStates(); BuildCrossStates(dfa1States, dfa2States); StartState = mCrossStates[dfa1.StartState][dfa2.StartState]; //Terminator = new State("cross-terminator"); foreach (var dfa1SourceState in dfa1States) { foreach (var dfa2SourceState in dfa2States) { for (int i = 0; i <= Byte.MaxValue; i++) { var inputChar = InputChar.For((byte)i); var dfa1DestinationState = dfa1SourceState.Transitions[inputChar][0]; var dfa2DestinationState = dfa2SourceState.Transitions[inputChar][0]; // Source state in cross-automata var sourceState = mCrossStates[dfa1SourceState][dfa2SourceState]; sourceState.IsAccepting = dfa2SourceState.IsAccepting; // This checks if we need to add this transition at all if ((dfa2DestinationState == dfa2TrapState && dfa1DestinationState == dfa1TrapState) || dfa2SourceState.IsAccepting) continue; if (dfa1DestinationState.IsAccepting) { // In case we reach accepting state of the repeated automata, go to start dfa1DestinationState = dfa1.StartState; } if (dfa2DestinationState == dfa2TrapState && dfa1DestinationState != dfa1TrapState) { // In case there is no transition in suffix automata, but there is one in repeated // automata, go to start in suffix automata dfa2DestinationState = dfa2.StartState; } var destinationState = mCrossStates[dfa1DestinationState][dfa2DestinationState]; sourceState.AddTransitionTo(destinationState, inputChar); } } } }
/// <summary> /// Converts NFA to DFA. The result DFA is not minimalized, hence it /// probably will contain redundant states. /// </summary> /// <param name="nfa">Finite automata representing NFA</param> /// <returns>Target DFA</returns> internal static FiniteAutomata Convert(FiniteAutomata nfa) { var marked = new Dictionary<State, bool>(); var dStates = new Dictionary<State, HashSet<State>>(); var startState = new State("DFA start"); dStates[startState] = EpsilonClosure(nfa.StartState); State tState; while (TryGetUnmarkedDState(dStates, marked, out tState)) { marked[tState] = true; for (int i = byte.MinValue; i <= byte.MaxValue; i++) { byte a = (byte) i; HashSet<State> u = EpsilonClosure(Move(dStates[tState], InputChar.For(a))); if (u.Count <= 0) continue; State uState; KeyValuePair<State, HashSet<State>>? stateKvp = GetStatesSet(dStates, u); if (stateKvp == null) { uState = new State("DFA state"); dStates[uState] = u; marked[uState] = false; } else { uState = ((KeyValuePair<State, HashSet<State>>) stateKvp).Key; } tState.AddTransitionTo(uState, InputChar.For(a)); } } DefineAcceptingStates(dStates); var dfa = new FiniteAutomata("DFA") {StartState = startState}; AssignIdsToStates(dfa); return dfa; }
internal override FiniteAutomata AsNFA() { var nfa = new FiniteAutomata("SequenceRegExpNFA", false); var startNFA = ChildExpressions[0].AsNFA(); // First RegExp Nfa var endNFA = ChildExpressions[ChildExpressions.Length - 1].AsNFA(); // Last RegExp Nfa nfa.StartState = startNFA.StartState; nfa.Terminator = endNFA.Terminator; State lastAddedTerminator = startNFA.Terminator; for (int i = 1; i < ChildExpressions.Length - 1; i++) { var newNfa = ChildExpressions[i].AsNFA(); lastAddedTerminator.AddTransitionTo(newNfa.StartState, InputChar.Epsilon()); lastAddedTerminator = newNfa.Terminator; } lastAddedTerminator.AddTransitionTo(endNFA.StartState, InputChar.Epsilon()); return nfa; }
internal override FiniteAutomata AsNFA() { var nfa = new FiniteAutomata("LiteralRegExpNFA"); State state = nfa.StartState; int i; for (i = 0; i < Literals.Length - 1; i++) { var newState = new State(Literals[i].ToString()); state.AddTransitionTo(newState, InputChar.For(Literals[i])); state = newState; } state.AddTransitionTo(nfa.Terminator, InputChar.For(Literals[i])); // the last transition return nfa; }
// internal RegExp Alternative1 { get; set; } // internal RegExp Alternative2 { get; set; } internal override FiniteAutomata AsNFA() { var nfa = new FiniteAutomata("AlternationRegExpNFA"); foreach (var regExp in ChildExpressions) { var newNfa = regExp.AsNFA(); nfa.StartState.AddTransitionTo(newNfa.StartState, InputChar.Epsilon()); newNfa.Terminator.AddTransitionTo(nfa.Terminator, InputChar.Epsilon()); } // FiniteAutomata alternative1NFA = Alternative1.AsNFA(); // FiniteAutomata alternative2NFA = Alternative2.AsNFA(); // nfa.StartState.AddTransitionTo(alternative1NFA.StartState, InputChar.Epsilon()); // nfa.StartState.AddTransitionTo(alternative2NFA.StartState, InputChar.Epsilon()); // alternative1NFA.Terminator.AddTransitionTo(nfa.Terminator, InputChar.Epsilon()); // alternative2NFA.Terminator.AddTransitionTo(nfa.Terminator, InputChar.Epsilon()); return nfa; }
// Thread unsafe static FiniteAutomata ConstructEncodingDfa(Encoding encoding) { FiniteAutomata encodingDfa; if (!sEncodingDfas.TryGetValue(encoding, out encodingDfa)) { int bytesNum = encoding.GetMaxByteCount(1); encodingDfa = new FiniteAutomata("encoding-dfa", true); // Construct matrix with states for building trunk DFA var statesMatrix = new State[bytesNum,bytesNum]; for (int i = 0; i < bytesNum; i++) { statesMatrix[i, i] = encodingDfa.Terminator; for (int j = 0; j < i; j++) { // i - path length, j - state number statesMatrix[i, j] = new State(String.Format("state-for-byte-[{0},{1}]", i, j)); } } // Set transitions between states of trunk DFA for (int c = 0; c <= char.MaxValue; c++) { var bytes = encoding.GetBytes(new[] {(char) c}); State state = statesMatrix[bytes.Length - 1, 0]; var inputChar = InputChar.For(bytes[0]); List<State> transitions; if (!encodingDfa.StartState.Transitions.TryGetValue(inputChar, out transitions) || !transitions.Contains(state)) { encodingDfa.StartState.AddTransitionTo(state, inputChar); } for (int j = 1; j < bytes.Length; j++) { var nextState = statesMatrix[bytes.Length - 1, j]; state.AddTransitionTo(nextState, InputChar.For(bytes[j])); state = nextState; } } sEncodingDfas[encoding] = encodingDfa; } return encodingDfa; }
public CrossAutomata(FiniteAutomata dfaRepeated, FiniteAutomata dfaSuffix) { Construct(dfaRepeated, dfaSuffix); }
private State[,] GenerateStatesMatrix(FiniteAutomata trunkNFA) { var byteCount = Encoding.GetMaxByteCount(1); var statesMatrix = new State[byteCount, byteCount]; var visitedStates = new HashSet<State>(); foreach (var transition in trunkNFA.StartState.Transitions) { foreach (var state in transition.Value) { if (visitedStates.Contains(state)) break; visitedStates.Add(state); // Calculate length of path var pathLength = 0; for (var nextState = state; nextState != trunkNFA.Terminator; nextState = CommonRoutines.GetKVP(nextState.Transitions, 0).Value[0]) { pathLength++; } // Fill matrix var i = 0; for (var nextState = state; nextState != trunkNFA.Terminator; nextState = CommonRoutines.GetKVP(nextState.Transitions, 0).Value[0]) { statesMatrix[pathLength, i++] = nextState; } statesMatrix[pathLength, i] = trunkNFA.Terminator; } } return statesMatrix; }
// Merges ignorees tree with trunk DFA utilizing BFS-like algorithm // Example: // Ignorees Trunk // (S) -------a----(S) // a| /a | // (a)--- (1) // b| \ | // (b) ---∑\b-->(2) // | | // [T] (T) private void EstablishTransitionsToTrunk(FiniteAutomata ignoreesTreeNFA, FiniteAutomata trunkNFA) { var queue = new Queue<State>(); var ignoreesTreeStartState = ignoreesTreeNFA.StartState; foreach (var transition in ignoreesTreeStartState.Transitions) { if (transition.Value.Count > 0) queue.Enqueue(transition.Value[0]); } // Get next state while (queue.Count > 0) { var ignoreeState = queue.Dequeue(); if (ignoreeState.IsAccepting) continue; var layer = mLayers[ignoreeState]; var bytesCount = mLiteralBytesCount[ignoreeState]; var trunkState = mStatesMatrix[bytesCount-1, layer+1]; foreach (var transition in ignoreeState.Transitions) { queue.Enqueue(transition.Value[0]); } ComplementTransitions(ignoreeState, trunkState); } }
// Builds only tree of ignored characters // Example. Literals: aaa, abc, bac: // (S) // / \ // (a) (b) // / \ \ // (a) (b) (a) // | | | // (a) (c) (c) <-- These are terminators // \ | / <-- These transitions do not exist // \ | / I placed them here only for better understanding // [T] // Terminator is marked as accepting state private FiniteAutomata BuildIgnoreesTree() { var nfa = new FiniteAutomata(); foreach (var literal in mLiterals) { var bytes = Encoding.GetBytes(new[] { literal }); State state = nfa.StartState; InputChar inputChar; for (int i = 0; i < bytes.Length - 1; i++) { List<State> transitions; inputChar = InputChar.For(bytes[i]); if (state.Transitions.TryGetValue(inputChar, out transitions) && transitions.Count > 0) { state = transitions[0]; } else { var newState = new State("ignorees-tree:" + bytes[i]); mLayers[newState] = i; mLiteralBytesCount[newState] = bytes.Length; state.Transitions.Add(inputChar, new List<State> {newState}); state = newState; } } // Assign last transition to Terminator for everyone inputChar = InputChar.For(bytes[bytes.Length - 1]); state.Transitions.Add(inputChar, new List<State> { nfa.Terminator }); mLayers[nfa.Terminator] = int.MaxValue; } nfa.Terminator.IsAccepting = true; return nfa; }