예제 #1
0
        public static IAutomaton Minimize(this IAutomaton @this)
        {
            //prepare NFA automaton to a DFA automaton
            var automaton = @this.Determinize();
            //mark all distinguishable pairs (unacceptable <-> acceptable)
            var stateCount           = automaton.StateCount;
            var distinguishablePairs = new bool?[stateCount, stateCount];

            foreach (var acceptable in automaton.AcceptingStates)
            {
                foreach (var unacceptable in Enumerable.Range(0, stateCount)
                         .Except(automaton.AcceptingStates))
                {
                    distinguishablePairs[acceptable, unacceptable] = true;
                    distinguishablePairs[unacceptable, acceptable] = true;
                }
            }
            //try to mark all others
            // Example (#=4)
            // 1 X
            // 2 X X
            // 3 X X X
            //   0 1 2
            var mergedByState = new Dictionary <int, HashSet <int> >();
            var merged        = new HashSet <HashSet <int> >();

            for (var aIndex = 1; aIndex < stateCount; aIndex++)
            {
                for (var bIndex = 0; bIndex < aIndex; bIndex++)
                {
                    if (!MarkDistinguishables(distinguishablePairs, automaton, aIndex, bIndex))
                    {
                        var list = mergedByState.GetValueOrInsertedDefault(aIndex, mergedByState.GetValueOrInsertedLazyDefault(bIndex, () => new HashSet <int>()));
                        list.Add(aIndex);
                        list.Add(bIndex);
                        merged.Add(list);
                    }
                }
            }
            var mappings        = new Dictionary <int, int>(); //old automaton to new automaton states
            var inverseMappings = new Dictionary <int, int>();
            //NOW BUILD THE F*****G AUTOMATON!!!
            var builder = new AutomatonBuilder();

            foreach (var mergedStates in merged)
            {
                var newState = builder.AddState();
                inverseMappings[newState] = mergedStates.First();
                foreach (var oldState in mergedStates)
                {
                    mappings[oldState] = newState;
                }
            }
            for (var state = 0; state < automaton.StateCount; state++)
            {
                if (!mappings.ContainsKey(state))
                {
                    var newState = builder.AddState();
                    mappings[state]           = newState;
                    inverseMappings[newState] = state;
                }
            }
            //mark starts and ends
            builder.SetStartState(mappings[automaton.StartState]);
            foreach (var accept in automaton.AcceptingStates)
            {
                builder.AcceptState(mappings[accept]);
            }
            //add transitions
            foreach (var kv in inverseMappings)
            {
                var oldState = kv.Value;
                var newState = kv.Key;
                foreach (var transition in automaton.TransitionsBySource.GetOrDefault(oldState, AutomatonExtensions.EmptyTargets))
                {
                    builder.AddTransition(newState, transition.Key, mappings[transition.First()]);
                }
            }
            //build
            return(builder.Build());
        }