Beispiel #1
0
        internal FiniteAutomaton(IEnumerable <State> states, char[] alphabet, State initial,
                                 IEnumerable <State> acceptings, TransitionTable table)
        {
            this.states = states.ToArray();

            ValidateAlphabet(alphabet);
            this.alphabet = new Alphabet(alphabet);

            if (!states.Contains(initial))
            {
                throw new ArgumentException("Invalid initial state.");
            }
            this.initial = initial;

            var acceptingList = new List <State>();

            foreach (var state in acceptings)
            {
                if (!states.Contains(state))
                {
                    throw new ArgumentException("Invalid accepting state.");
                }
                acceptingList.Add(state);
            }
            this.acceptings = acceptingList.ToArray();

            var tableStates = table.GetAllStates();

            foreach (var state in tableStates)
            {
                if (!states.Contains(state))
                {
                    throw new ArgumentException("Invalid table.");
                }
            }
            var tableChars = table.GetAllCharactersIncludingEpsilon();

            foreach (var character in tableChars)
            {
                ValidateChar(character);
            }
            this.table = table;
            this.table.WrapUp();
        }
Beispiel #2
0
        public FiniteAutomaton(int statesCount, char[] alphabet, Transition[] transitions,
                               int initialIndex, int[] acceptingIndexes)
        {
            ValidateAlphabet(alphabet);
            this.alphabet = new Alphabet(alphabet);

            this.states = new State[statesCount];
            for (int i = 0; i < statesCount; i++)
            {
                this.states[i] = new State();
            }

            if (ArrayHasDuplicates(acceptingIndexes))
            {
                throw new ArgumentException("Accepting indexes cannot contain duplicates.");
            }
            int acceptingsCount = acceptingIndexes.Length;

            this.acceptings = new State[acceptingsCount];
            for (int i = 0; i < acceptingsCount; i++)
            {
                this.acceptings[i] = StateFromIndex(acceptingIndexes[i]);
            }

            this.initial = StateFromIndex(initialIndex);

            if (ArrayHasDuplicates(transitions))
            {
                throw new ArgumentException("Transitions cannot contain duplicates.");
            }
            this.table = new TransitionTable();

            foreach (var info in transitions)
            {
                AddTransition(info);
            }
            this.table.WrapUp();
        }
Beispiel #3
0
        private FiniteAutomaton Minimize()
        {
            // Algorithm: Table-filling
            // must operate on a DFA, or else


            var considerations = new Queue <StatePair>();
            var allPairs       = new List <StatePair>();

            var reachableStates = GetReachableStates().ToArray();

#if DEBUG
            bool duplicatedStates = reachableStates.Distinct().Count() > reachableStates.Length;
            Debug.Assert(!duplicatedStates);
#endif

            foreach (var pair in GetAllPairs(reachableStates))
            {
                allPairs.Add(pair);
                bool canBeMarked = CanBeConcludedDistinguishable(pair);
                if (canBeMarked)
                {
                    pair.Mark();
                }
                else
                {
                    considerations.Enqueue(pair);
                }
            }

            while (considerations.Count > 0)
            {
                var thisPair = considerations.Dequeue();
                foreach (char character in alphabet)
                {
                    var nextPair = GetNextPair(thisPair, character);
                    if (nextPair.State1 == nextPair.State2)
                    {
                        continue;
                    }

                    var matches = from pair in allPairs
                                  where pair == nextPair
                                  select pair;
                    Debug.Assert(matches.Count() == 1);
                    var match = matches.First();

                    if (match.IsMarked)
                    {
                        thisPair.Mark();
                        break;
                    }
                    else if (considerations.Contains(match))
                    {
                        match.AddEquivalentPair(thisPair);
                    }
                }
            }

            var minimizedToDFA = new Dictionary <State, List <State> >();
            var dfaToMinimized = new Dictionary <State, State>();
            foreach (var dfaState in reachableStates)
            {
                var equivalentClass = new List <State>();
                equivalentClass.Add(dfaState);
                var minimizedState = new State();
                minimizedToDFA.Add(minimizedState, equivalentClass);
                dfaToMinimized.Add(dfaState, minimizedState);
            }
            foreach (var pair in allPairs)
            {
                if (!pair.IsMarked)
                {
                    State minimized1, minimized2;
                    bool  success1 = dfaToMinimized.TryGetValue(pair.State1, out minimized1),
                          success2 = dfaToMinimized.TryGetValue(pair.State2, out minimized2);

                    Debug.Assert(success1);
                    Debug.Assert(success2);

                    List <State> class1, class2;
                    success1 = minimizedToDFA.TryGetValue(minimized1, out class1);
                    success2 = minimizedToDFA.TryGetValue(minimized2, out class2);

                    Debug.Assert(success1);
                    Debug.Assert(success2);

                    class1.AddRange(class2);
                    minimizedToDFA.Remove(minimized2);
                    dfaToMinimized[pair.State2] = minimized1;
                }
            }

            var newTable    = new TransitionTable();
            var transitions = table.GetAllTransitions();
            foreach (var transition in transitions)
            {
                char  character  = transition.Item2;
                State dfaCurrent = transition.Item1,
                      dfaNext    = transition.Item3;

                bool isIsolated = !reachableStates.Contains(dfaCurrent);
                if (isIsolated)
                {
                    continue;
                }

                State minimizedCurrent = dfaToMinimized[dfaCurrent],
                      minimizedNext    = dfaToMinimized[dfaNext];

                bool merged = dfaCurrent != dfaNext && minimizedCurrent == minimizedNext;
                if (merged)
                {
                    continue;
                }

                var  nextStates = newTable.GetNextStates(minimizedCurrent, character);
                bool duplicate  = nextStates.Contains(minimizedNext);
                if (!duplicate)
                {
                    newTable.Add(minimizedCurrent, character, minimizedNext);
                }
            }

            var newStates = from equivalence in minimizedToDFA
                            select equivalence.Key;
            var newInitial   = dfaToMinimized[initial];
            var newAccepting = from equivalence in minimizedToDFA
                               where acceptings.Contains(equivalence.Value.First())
                               select equivalence.Key;

            return(new FiniteAutomaton(newStates.ToArray(), alphabet.ToArray(), newInitial, newAccepting, newTable));
        }
Beispiel #4
0
        public FiniteAutomaton ToDFA()
        {
            // Algorithm: Powerset Construction

            bool isAlreadyDeterministic = IsDeterministic();

            if (isAlreadyDeterministic)
            {
                return(this);
            }


            List <State> dfaStates     = new List <State>(),
                         dfaAcceptings = new List <State>();

            var nfaStatesComparer = new OrderIndependentStatesComparer();
            var nfaToDFA          = new Dictionary <IEnumerable <State>, State>(nfaStatesComparer);
            var dfaToNFA          = new Dictionary <State, IEnumerable <State> >();

            State dfaInitial        = new State();
            var   nfaInitialClosure = table.GetInitialEpsilonClosure(initial);

            if (HasAcceptingState(nfaInitialClosure))
            {
                dfaAcceptings.Add(dfaInitial);
            }
            dfaStates.Add(dfaInitial);
            nfaToDFA.Add(nfaInitialClosure, dfaInitial);
            dfaToNFA.Add(dfaInitial, nfaInitialClosure);

            var dfaTable       = new TransitionTable();
            var considerations = new Queue <State>(dfaStates);

            while (considerations.Count > 0)
            {
                var dfaState = considerations.Dequeue();
                IEnumerable <State> correspondingNFAStates;      // It is OK for this to be empty.
                bool success = dfaToNFA.TryGetValue(dfaState, out correspondingNFAStates);
                Debug.Assert(success);

                foreach (char character in alphabet)
                {
                    var   nextNFAStates = table.GetNextStates(correspondingNFAStates, character);
                    State nextDFAState;
                    success = nfaToDFA.TryGetValue(nextNFAStates, out nextDFAState);
                    if (!success)
                    {
                        nextDFAState = new State();
                        if (HasAcceptingState(nextNFAStates))
                        {
                            dfaAcceptings.Add(nextDFAState);
                        }
                        dfaStates.Add(nextDFAState);
                        nfaToDFA.Add(nextNFAStates, nextDFAState);
                        dfaToNFA.Add(nextDFAState, nextNFAStates);
                        considerations.Enqueue(nextDFAState);
                    }
                    else
                    {
                        Debug.Assert(dfaStates.Contains(nextDFAState));
                    }

                    dfaTable.Add(dfaState, character, nextDFAState);
                }
            }

            return(new FiniteAutomaton(dfaStates, alphabet.ToArray(), dfaInitial, dfaAcceptings, dfaTable));
        }