Browse Source

Add DFA/NFA state machine utility code.

pull/1546/head
Joao Matos 5 years ago committed by João Matos
parent
commit
4e58e266e6
  1. 20
      src/Generator/Utils/FSM/ConsoleWriter.cs
  2. 139
      src/Generator/Utils/FSM/DFSM.cs
  3. 71
      src/Generator/Utils/FSM/Minimize.cs
  4. 79
      src/Generator/Utils/FSM/NDFSM.cs
  5. 21
      src/Generator/Utils/FSM/Program.cs
  6. 18
      src/Generator/Utils/FSM/Transition.cs

20
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();
}
}
}

139
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<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);
}
}
}
}

71
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<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(",", " ");
}
}
}

79
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<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);
}
}
}

21
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<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);
}
}
}

18
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);
}
}
}
Loading…
Cancel
Save