private static void WriteInMissingTransitions(StateGraph.Node node, StateGraph graph, List <int> sequenceReversed) { // the sequence is in reversed order which is kinda unnatural, but the Stack<> container does not have index-based // access, thus I'm using List<> adding to and removing from its back var t = node.Transitions; for (int i = 0; i < t.Length; ++i) { sequenceReversed.Add(i); StateGraph.Node transitionNode = t[i]; if (transitionNode != null) { WriteInMissingTransitions(transitionNode, graph, sequenceReversed); } else { t[i] = graph.FindNode(sequenceReversed); } sequenceReversed.RemoveLast(); } }
private static void WriteInMissingSequenceIndices(StateGraph.Node node, StateGraph graph, List <int> sequenceReversed) { if (node.SequenceIndex < 0) { node.SequenceIndex = graph.FindNode(sequenceReversed).SequenceIndex; } var t = node.Transitions; var tLenght = t.Length; if (tLenght != graph.AlphabetSize) { throw new ArgumentException("Node transition count is not consistent with the alphabet size"); } for (int i = 0; i < tLenght; ++i) { sequenceReversed.Add(i); var transitionNode = t[i]; if (transitionNode != null) { WriteInMissingSequenceIndices(transitionNode, graph, sequenceReversed); } sequenceReversed.RemoveLast(); } }
public void AcceptSymbol(int symbol) { try { _currentNode = _currentNode.Transitions[symbol]; } catch (IndexOutOfRangeException e) { throw new ArgumentException("symbol is out of state range", e); } Symbol = symbol; }
private static void PrintGraphExpressionRecursive(StateGraph.Node root, StringBuilder sb, HashSet <StateGraph.Node> visitedNodes) { if (visitedNodes.Contains(root)) { sb.Append($"(~{root.PrintCore()}"); } else { sb.Append($"({root.PrintCore()}"); visitedNodes.Add(root); if (root.Transitions.Any(n => n != null)) { sb.Append(">"); } var t = root.Transitions; for (int i = 0; i < t.Length; ++i) { var transitionNode = t[i]; if (transitionNode == null) { continue; } sb.Append($"{i}'"); PrintGraphExpressionRecursive(transitionNode, sb, visitedNodes); } } sb.Append(")"); }
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; }
public void Reset() { _currentNode = Graph.Root; Symbol = StateGraph.DefaultSymbol; }