mirror of https://github.com/mono/CppSharp.git
6 changed files with 348 additions and 0 deletions
@ -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 @@ |
|||||||
|
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 @@ |
|||||||
|
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 @@ |
|||||||
|
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 @@ |
|||||||
|
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 @@ |
|||||||
|
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