/// <summary> /// Prunes all the unreachable states from this automaton /// </summary> public void Prune() { DFAInverse inverse = new DFAInverse(this); List <DFAState> finals = inverse.CloseByAntecedents(inverse.Finals); // no changes if (finals.Count == states.Count) { return; } // Prune the transitions for (int i = 0; i != finals.Count; i++) { DFAState state = finals[i]; List <CharSpan> transitions = new List <CharSpan>(state.Transitions); foreach (CharSpan key in transitions) { DFAState child = state.GetChildBy(key); if (!finals.Contains(child)) { // the child should be dropped state.RemoveTransition(key); } } } // prune DFAState first = states[0]; finals.Remove(states[0]); states.Clear(); states.Add(first); states.AddRange(finals); }
/// <summary> /// Extracts the sub-DFA that leads to any of the specified states /// </summary> /// <param name="targets">States in this DFA</param> /// <returns>The sub-DFA for the specified states</returns> public DFA ExtractSubTo(IEnumerable <DFAState> targets) { if (targets == null) { throw new System.ArgumentException("The specified collection must not be null"); } // build a list of all the required states DFAInverse inverse = new DFAInverse(this); List <DFAState> originals = inverse.CloseByAntecedents(targets); // setup the list int index = originals.IndexOf(states[0]); if (index == -1) { throw new System.ArgumentException("The specified states are not reachable from the starting state"); } originals[index] = originals[0]; originals[0] = states[0]; // copies the states List <DFAState> copy = new List <DFAState>(); for (int i = 0; i != originals.Count; i++) { copy.Add(new DFAState(i)); } for (int i = 0; i != originals.Count; i++) { DFAState original = originals[i]; DFAState clone = copy[i]; clone.AddItems(original.Items); foreach (CharSpan key in original.Transitions) { index = originals.IndexOf(original.GetChildBy(key)); if (index != -1) { clone.AddTransition(key, copy[index]); } } } return(new DFA(copy)); }