diff --git a/src/Generator/Utils/FSM/ConsoleWriter.cs b/src/Generator/Utils/FSM/ConsoleWriter.cs new file mode 100644 index 00000000..4c05ae95 --- /dev/null +++ b/src/Generator/Utils/FSM/ConsoleWriter.cs @@ -0,0 +1,20 @@ +using System; + +namespace CppSharp.Utils.FSM{ + public class ConsoleWriter{ + public static void Failure(string message){ + Console.ForegroundColor = ConsoleColor.DarkRed; + Write(message); + } + + public static void Success(string message){ + Console.ForegroundColor = ConsoleColor.DarkGreen; + Write(message); + } + + private static void Write(string message){ + Console.WriteLine(message); + Console.ResetColor(); + } + } +} diff --git a/src/Generator/Utils/FSM/DFSM.cs b/src/Generator/Utils/FSM/DFSM.cs new file mode 100644 index 00000000..125ccef2 --- /dev/null +++ b/src/Generator/Utils/FSM/DFSM.cs @@ -0,0 +1,139 @@ +using System.Collections.Generic; +using System.Linq; +using System.Text; + +namespace CppSharp.Utils.FSM +{ + public class DFSM{ + public readonly List Q = new List(); + public readonly List Sigma = new List(); + public readonly List Delta = new List(); + public List Q0 = new List(); + public readonly List F = new List(); + + public DFSM(IEnumerable q, IEnumerable sigma, IEnumerable delta, + IEnumerable q0, IEnumerable f){ + Q = q.ToList(); + Sigma = sigma.ToList(); + AddTransitions(delta); + AddInitialStates(q0); + AddFinalStates(f); + } + + private void AddTransitions(IEnumerable transitions){ + foreach (var transition in transitions.Where(ValidTransition)){ + Delta.Add(transition); + } + } + + private bool ValidTransition(Transition transition){ + return Q.Contains(transition.StartState) && + Q.Contains(transition.EndState) && + Sigma.Contains(transition.Symbol) && + !TransitionAlreadyDefined(transition); + } + + private bool TransitionAlreadyDefined(Transition transition){ + return Delta.Any(t => t.StartState == transition.StartState && + t.Symbol == transition.Symbol); + } + + private void AddInitialStates(IEnumerable q0){ + foreach (var startingState in q0.Where(q => q != null && Q.Contains(q))){ + Q0.Add(startingState); + } + } + + private void AddFinalStates(IEnumerable finalStates){ + foreach (var finalState in finalStates.Where(finalState => Q.Contains(finalState))){ + F.Add(finalState); + } + } + + public void Accepts(string input){ + ConsoleWriter.Success("Trying to parse: " + input); + if (InvalidInputOrFSM(input)){ + return; + } + foreach (var q0 in Q0){ + var currentState = q0; + var steps = new StringBuilder(); + foreach (var symbol in input.ToCharArray()){ + var transition = Delta.Find(t => t.StartState == currentState && + t.Symbol == symbol); + if (transition == null){ + ConsoleWriter.Failure("No transitions for current state and symbol"); + ConsoleWriter.Failure(steps.ToString()); + continue; + } + currentState = transition.EndState; + steps.Append(transition + "\n"); + } + if (F.Contains(currentState)){ + ConsoleWriter.Success("Accepted the input with steps:\n" + steps); + return; + } + ConsoleWriter.Failure("Stopped in state " + currentState + + " which is not a final state."); + ConsoleWriter.Failure(steps.ToString()); + } + } + + private bool InvalidInputOrFSM(string input){ + if (InputContainsNotDefinedSymbols(input)){ + return true; + } + if (InitialStateNotSet()){ + ConsoleWriter.Failure("No initial state has been set"); + return true; + } + if (NoFinalStates()){ + ConsoleWriter.Failure("No final states have been set"); + return true; + } + return false; + } + + private bool InputContainsNotDefinedSymbols(string input){ + foreach (var symbol in input.ToCharArray().Where(symbol => !Sigma.Contains(symbol))){ + ConsoleWriter.Failure("Could not accept the input since the symbol " + symbol + " is not part of the alphabet"); + return true; + } + return false; + } + + private bool InitialStateNotSet(){ + return Q0.Count == 0; + } + + private bool NoFinalStates(){ + return F.Count == 0; + } + + public void RemoveUnreachableStates(){ + var reachableStates = new HashSet(Q0); + var newStates = new HashSet(Q0); + do{ + var temp = new HashSet(); + foreach (var q in newStates){ + var reachableFromQ = Delta.FindAll(t => t.StartState == q).Select(t => t.EndState); + temp.UnionWith(reachableFromQ); + } + temp.ExceptWith(reachableStates); + newStates = temp; + reachableStates.UnionWith(newStates); + } while (newStates.Count > 0); + var unreachableStates = Q.Where(q => !reachableStates.Contains(q)); + for (int i = Delta.Count - 1; i > 0; i--){ + var transition = Delta[i]; + if (unreachableStates.Contains(transition.EndState) || + unreachableStates.Contains(transition.StartState)){ + Delta.Remove(transition); + } + } + foreach (var unrechableState in unreachableStates){ + Q.Remove(unrechableState); + } + } + } +} \ No newline at end of file diff --git a/src/Generator/Utils/FSM/Minimize.cs b/src/Generator/Utils/FSM/Minimize.cs new file mode 100644 index 00000000..71cb06ae --- /dev/null +++ b/src/Generator/Utils/FSM/Minimize.cs @@ -0,0 +1,71 @@ +using System.Collections.Generic; +using System.Linq; + +namespace CppSharp.Utils.FSM{ + internal class Minimize{ + public static DFSM MinimizeDFSM(DFSM fsm){ + var reversedNDFSM = Reverse(fsm); + var reversedDFSM = PowersetConstruction(reversedNDFSM); + var NDFSM = Reverse(reversedDFSM); + return PowersetConstruction(NDFSM); + } + + private static NDFSM Reverse(DFSM d){ + var delta = new List(); + foreach (var transition in d.Delta){ + delta.Add(new Transition(transition.EndState, transition.Symbol, transition.StartState)); + } + return new NDFSM(d.Q, d.Sigma, delta, d.F, d.Q0); + } + + public static DFSM PowersetConstruction(NDFSM ndfsm){ + var Q = new List(); + var Sigma = ndfsm.Sigma.ToList(); + var Delta = new List(); + var Q0 = new List { string.Join(" ", ndfsm.Q0) }; + var F = new List(); + + var processed = new List(); + var queue = new Queue(); + queue.Enqueue(string.Join(",", ndfsm.Q0)); + + while (queue.Count > 0){ + var setState = queue.Dequeue(); + processed.Add(setState); + Q.Add(CleanupState(setState)); + + var statesInCurrentSetState = setState.Split(',').ToList(); + foreach (var state in statesInCurrentSetState){ + if (ndfsm.F.Contains(state)){ + F.Add(CleanupState(setState)); + break; + } + } + var symbols = ndfsm.Delta + .Where(t => statesInCurrentSetState.Contains(t.StartState)) + .Select(t => t.Symbol) + .Distinct(); + foreach (var symbol in symbols){ + var reachableStates = + ndfsm.Delta + .Where(t => t.Symbol == symbol && + statesInCurrentSetState.Contains(t.StartState)) + .OrderBy(t => t.EndState). + Select(t => t.EndState); + var reachableSetState = string.Join(",", reachableStates); + + Delta.Add(new Transition(CleanupState(setState), symbol, CleanupState(reachableSetState))); + + if (!processed.Contains(reachableSetState)){ + queue.Enqueue(reachableSetState); + } + } + } + return new DFSM(Q, Sigma, Delta, Q0, F); + } + + private static string CleanupState(string state){ + return state.Replace(",", " "); + } + } +} \ No newline at end of file diff --git a/src/Generator/Utils/FSM/NDFSM.cs b/src/Generator/Utils/FSM/NDFSM.cs new file mode 100644 index 00000000..9defe173 --- /dev/null +++ b/src/Generator/Utils/FSM/NDFSM.cs @@ -0,0 +1,79 @@ +using System.Collections.Generic; +using System.Linq; +using System.Text; + +namespace CppSharp.Utils.FSM{ + public class NDFSM{ + private readonly List Q = new List(); + public readonly List Sigma = new List(); + public readonly List Delta = new List(); + public List Q0 = new List(); + public readonly List F = new List(); + + public NDFSM(IEnumerable q, IEnumerable sigma, + IEnumerable delta, IEnumerable q0, IEnumerable f){ + Q = q.ToList(); + Sigma = sigma.ToList(); + AddTransitions(delta); + AddInitialStates(q0); + AddFinalStates(f); + } + + private void AddTransitions(IEnumerable transitions){ + foreach (var transition in transitions.Where(ValidTransition)){ + Delta.Add(transition); + } + } + + private bool ValidTransition(Transition transition){ + return Q.Contains(transition.StartState) && + Q.Contains(transition.EndState) && + Sigma.Contains(transition.Symbol); + } + + private void AddInitialStates(IEnumerable q0){ + foreach (var startingState in q0.Where(q => q != null && Q.Contains(q))){ + Q0.Add(startingState); + } + } + + private void AddFinalStates(IEnumerable finalStates){ + foreach (var finalState in finalStates.Where(finalState => Q.Contains(finalState))){ + F.Add(finalState); + } + } + + public void Accepts(string input){ + ConsoleWriter.Success("Trying to accept: " + input); + if (Q0.Any(q0 => Accepts(q0, input, new StringBuilder()))){ + return; + } + ConsoleWriter.Failure("Could not accept the input: " + input); + } + + private bool Accepts(string currentState, string input, StringBuilder steps){ + if (input.Length > 0){ + var transitions = GetAllTransitions(currentState, input[0]); + foreach (var transition in transitions){ + var currentSteps = new StringBuilder(steps.ToString() + transition); + if (Accepts(transition.EndState, input.Substring(1), currentSteps)){ + return true; + } + } + return false; + } + if (F.Contains(currentState)){ + ConsoleWriter.Success("Successfully accepted the input " + input + " " + + "in the final state " + currentState + + " with steps:\n" + steps); + return true; + } + return false; + } + + private IEnumerable GetAllTransitions(string currentState, char symbol){ + return Delta.FindAll(t => t.StartState == currentState && + t.Symbol == symbol); + } + } +} \ No newline at end of file diff --git a/src/Generator/Utils/FSM/Program.cs b/src/Generator/Utils/FSM/Program.cs new file mode 100644 index 00000000..6b0cf528 --- /dev/null +++ b/src/Generator/Utils/FSM/Program.cs @@ -0,0 +1,21 @@ +using System.Collections.Generic; + +namespace CppSharp.Utils.FSM{ + internal class Program{ + private static void Main(string[] args){ + var Q = new List{"q0", "q1"}; + var Sigma = new List{'0', '1'}; + var Delta = new List{ + new Transition("q0", '0', "q0"), + new Transition("q0", '1', "q1"), + new Transition("q1", '1', "q1"), + new Transition("q1", '0', "q0") + }; + var Q0 = new List{"q0"}; + var F = new List{"q0", "q1"}; + var DFSM = new DFSM(Q, Sigma, Delta, Q0, F); + + var minimizedDFSM = Minimize.MinimizeDFSM(DFSM); + } + } +} \ No newline at end of file diff --git a/src/Generator/Utils/FSM/Transition.cs b/src/Generator/Utils/FSM/Transition.cs new file mode 100644 index 00000000..2c0f3b9b --- /dev/null +++ b/src/Generator/Utils/FSM/Transition.cs @@ -0,0 +1,18 @@ +namespace CppSharp.Utils.FSM{ + public class Transition{ + public string StartState { get; private set; } + public char Symbol { get; private set; } + public string EndState { get; private set; } + + public Transition(string startState, char symbol, string endState){ + StartState = startState; + Symbol = symbol; + EndState = endState; + } + + public override string ToString(){ + return string.Format("({0}, {1}) -> {2}\n", StartState, Symbol, EndState); + } + } +} +