public StateMachine(StateGraph stateGraph) { Graph = stateGraph ?? throw new ArgumentNullException(nameof(stateGraph)); _currentNode = stateGraph.Root; Symbol = StateGraph.DefaultSymbol; }
public static string PrintGraphExpression(this StateGraph graph) { var sb = new StringBuilder(1000); var visitedNodes = new HashSet <StateGraph.Node>(); PrintGraphExpressionRecursive(graph.Root, sb, visitedNodes); return(sb.ToString()); }
public static string PrintTrivialGraphFormat(this StateGraph graph, string separator = null) { separator = separator ?? Environment.NewLine; var traversalNodes = new LinkedList <StateGraph.Node>(); var visitedNodes = new HashSet <StateGraph.Node>(); var root = graph.Root; traversalNodes.AddLast(root); var nodesPrint = new LinkedList <string>(); var transitionsPrint = new LinkedList <string>(); while (traversalNodes.NotEmpty()) { var currentNode = traversalNodes.GetRemoveFirst(); if (visitedNodes.Contains(currentNode)) { continue; } var t = currentNode.Transitions; nodesPrint.AddLast($"{currentNode.NodeIndex} {currentNode.PrintCore()}"); for (int i = 0; i < t.Length; ++i) { var transitionNode = t[i]; if (transitionNode == null) { continue; } transitionsPrint.AddLast($"{currentNode.NodeIndex} {transitionNode.NodeIndex} {i}"); if (visitedNodes.Contains(transitionNode)) { continue; } traversalNodes.AddLast(transitionNode); } visitedNodes.Add(currentNode); } return(string.Join(separator, nodesPrint.Concat(Enumerable.Repeat("#", 1)).Concat(transitionsPrint))); }
public static int[] ToTransitionMatrix(this StateGraph graph) { var alphabetSize = graph.AlphabetSize; var nodeCount = graph.StateCount; if (nodeCount < alphabetSize + 1) { throw new InvalidOperationException("The graph is underpopulated with nodes"); } var result = new int[alphabetSize * nodeCount]; var traversalNodes = new LinkedList <StateGraph.Node>(); var visitedNodes = new HashSet <StateGraph.Node>(); var root = graph.Root; traversalNodes.AddLast(root); while (traversalNodes.NotEmpty()) { var currentNode = traversalNodes.GetRemoveFirst(); if (visitedNodes.Contains(currentNode)) { continue; } var t = currentNode.Transitions; var currentNodeIndex = currentNode.NodeIndex; var rowFirstIndex = currentNode.NodeIndex * alphabetSize; for (int i = 0; i < t.Length; ++i) { var transitionNode = t[i]; if (transitionNode == null) { throw new InvalidOperationException($"Transition {i} is absent in node {currentNodeIndex}"); } result[rowFirstIndex + i] = transitionNode.NodeIndex; if (visitedNodes.Contains(transitionNode)) { continue; } traversalNodes.AddLast(transitionNode); } visitedNodes.Add(currentNode); if (visitedNodes.Count == nodeCount) { return(result); } } return(result); }
public static void WriteInMissingTransitions(this StateGraph graph) => WriteInMissingTransitions(graph.Root, graph, new List <int>());
public static void WriteInMissingSequenceIndices(this StateGraph graph) => WriteInMissingSequenceIndices(graph.Root, graph, new List <int>());
public static void BuildTrie(this StateGraph graph, int[][] sequences) { if (sequences == null) { throw new ArgumentNullException(nameof(sequences)); } var root = graph.Root; var nodeIndex = 1; var sequenceIndex = 1; var alphabetSize = graph.AlphabetSize; for (int i = 0; i < alphabetSize; ++i) { root.Transitions[i] = new StateGraph.Node(alphabetSize, nodeIndex++) { SequenceIndex = sequenceIndex++ } } ; for (int k = 0; k < sequences.Length; ++k) { var sequence = sequences[k] ?? throw new ArgumentNullException($"sequence {sequenceIndex}"); var lastSymbolIndex = sequence.Length - 1; if (lastSymbolIndex < 0) { throw new ArgumentException($"sequence {sequenceIndex} is empty"); } var currentNode = root; for (int j = 0; j <= lastSymbolIndex; ++j) { var symbol = sequence[j]; if (symbol >= alphabetSize || symbol < 0) { throw new ArgumentException($"symbol {symbol} at index {j} of sequence {sequenceIndex} is out of the boundaries of the alphabet"); } var t = currentNode.Transitions; StateGraph.Node childNode = t[symbol]; if (childNode == null) { childNode = new StateGraph.Node(alphabetSize, nodeIndex++); t[symbol] = childNode; } if (j == lastSymbolIndex) { if (childNode.SequenceIndex == -1) { childNode.SequenceIndex = sequenceIndex++; } else { throw new ArgumentException($"sequence {sequenceIndex} is equal to sequence {childNode.SequenceIndex}"); } } currentNode = childNode; } } graph.StateCount = nodeIndex; }