Beispiel #1
0
        /// <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);
        }
Beispiel #2
0
        /// <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));
        }
Beispiel #3
0
 /// <summary>
 /// Determines whether two states should be in the same group
 /// </summary>
 /// <param name="s1">A state</param>
 /// <param name="s2">Another state</param>
 /// <param name="old">The old partition</param>
 /// <returns></returns>
 private static bool AddState_SameGroup(DFAState s1, DFAState s2, DFAPartition old)
 {
     if (s1.Transitions.Count != s2.Transitions.Count)
     {
         return(false);
     }
     // For each transition from state 1
     foreach (CharSpan key in s1.Transitions)
     {
         // If state 2 does not have a transition with the same value : not same group
         if (!s2.HasTransition(key))
         {
             return(false);
         }
         // Here State1 and State2 have both a transition of the same value
         // If the target of these transitions are in the same group in the old partition : same transition
         if (old.AddState_GetGroupOf(s1.GetChildBy(key)) != old.AddState_GetGroupOf(s2.GetChildBy(key)))
         {
             return(false);
         }
     }
     return(true);
 }