mirror of https://github.com/mono/CppSharp.git
6 changed files with 348 additions and 0 deletions
@ -0,0 +1,20 @@
@@ -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(); |
||||
} |
||||
} |
||||
} |
@ -0,0 +1,139 @@
@@ -0,0 +1,139 @@
|
||||
using System.Collections.Generic; |
||||
using System.Linq; |
||||
using System.Text; |
||||
|
||||
namespace CppSharp.Utils.FSM |
||||
{ |
||||
public class DFSM{ |
||||
public readonly List<string> Q = new List<string>(); |
||||
public readonly List<char> Sigma = new List<char>(); |
||||
public readonly List<Transition> Delta = new List<Transition>(); |
||||
public List<string> Q0 = new List<string>(); |
||||
public readonly List<string> F = new List<string>(); |
||||
|
||||
public DFSM(IEnumerable<string> q, IEnumerable<char> sigma, IEnumerable<Transition> delta, |
||||
IEnumerable<string> q0, IEnumerable<string> f){ |
||||
Q = q.ToList(); |
||||
Sigma = sigma.ToList(); |
||||
AddTransitions(delta); |
||||
AddInitialStates(q0); |
||||
AddFinalStates(f); |
||||
} |
||||
|
||||
private void AddTransitions(IEnumerable<Transition> 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<string> q0){ |
||||
foreach (var startingState in q0.Where(q => q != null && Q.Contains(q))){ |
||||
Q0.Add(startingState); |
||||
} |
||||
} |
||||
|
||||
private void AddFinalStates(IEnumerable<string> 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<string>(Q0); |
||||
var newStates = new HashSet<string>(Q0); |
||||
do{ |
||||
var temp = new HashSet<string>(); |
||||
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); |
||||
} |
||||
} |
||||
} |
||||
} |
@ -0,0 +1,71 @@
@@ -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<Transition>(); |
||||
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<string>(); |
||||
var Sigma = ndfsm.Sigma.ToList(); |
||||
var Delta = new List<Transition>(); |
||||
var Q0 = new List<string> { string.Join(" ", ndfsm.Q0) }; |
||||
var F = new List<string>(); |
||||
|
||||
var processed = new List<string>(); |
||||
var queue = new Queue<string>(); |
||||
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(",", " "); |
||||
} |
||||
} |
||||
} |
@ -0,0 +1,79 @@
@@ -0,0 +1,79 @@
|
||||
using System.Collections.Generic; |
||||
using System.Linq; |
||||
using System.Text; |
||||
|
||||
namespace CppSharp.Utils.FSM{ |
||||
public class NDFSM{ |
||||
private readonly List<string> Q = new List<string>(); |
||||
public readonly List<char> Sigma = new List<char>(); |
||||
public readonly List<Transition> Delta = new List<Transition>(); |
||||
public List<string> Q0 = new List<string>(); |
||||
public readonly List<string> F = new List<string>(); |
||||
|
||||
public NDFSM(IEnumerable<string> q, IEnumerable<char> sigma, |
||||
IEnumerable<Transition> delta, IEnumerable<string> q0, IEnumerable<string> f){ |
||||
Q = q.ToList(); |
||||
Sigma = sigma.ToList(); |
||||
AddTransitions(delta); |
||||
AddInitialStates(q0); |
||||
AddFinalStates(f); |
||||
} |
||||
|
||||
private void AddTransitions(IEnumerable<Transition> 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<string> q0){ |
||||
foreach (var startingState in q0.Where(q => q != null && Q.Contains(q))){ |
||||
Q0.Add(startingState); |
||||
} |
||||
} |
||||
|
||||
private void AddFinalStates(IEnumerable<string> 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<Transition> GetAllTransitions(string currentState, char symbol){ |
||||
return Delta.FindAll(t => t.StartState == currentState && |
||||
t.Symbol == symbol); |
||||
} |
||||
} |
||||
} |
@ -0,0 +1,21 @@
@@ -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<string>{"q0", "q1"}; |
||||
var Sigma = new List<char>{'0', '1'}; |
||||
var Delta = new List<Transition>{ |
||||
new Transition("q0", '0', "q0"), |
||||
new Transition("q0", '1', "q1"), |
||||
new Transition("q1", '1', "q1"), |
||||
new Transition("q1", '0', "q0") |
||||
}; |
||||
var Q0 = new List<string>{"q0"}; |
||||
var F = new List<string>{"q0", "q1"}; |
||||
var DFSM = new DFSM(Q, Sigma, Delta, Q0, F); |
||||
|
||||
var minimizedDFSM = Minimize.MinimizeDFSM(DFSM); |
||||
} |
||||
} |
||||
} |
@ -0,0 +1,18 @@
@@ -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); |
||||
} |
||||
} |
||||
} |
||||
|
Loading…
Reference in new issue