コード例 #1
0
        /*  METHOD TO EXECUTE ARBITRARY SET OPERATIONS ON THE LANGUAGES OF AUTOMATA
         *
         *   Input:  automataList:   The list of deterministic automata on which the set operation is executed
         *           boolOp:         The boolean operation describing the set operation, that is to be executed
         *
         *   Output: Deterministic automaton, that encodes the language obtained from applying the specified set operation on the languages of the input automata
         */
        public static DFA <C, NTuple <State <S> > > ExecuteSetOperation <C, S>(List <DFA <C, S> > automataList, BooleanOperation boolOp)
        {
            int noAutomata = automataList.Count;

            //Initialize all five components (Q, Sigma, delta, q_0, F) of the resulting automaton:
            var Q     = new HashSet <State <NTuple <State <S> > > >();
            var Sigma = automataList[0].Sigma;
            var delta = new Dictionary <TwoTuple <State <NTuple <State <S> > >, C>, State <NTuple <State <S> > > >();
            var F     = new HashSet <State <NTuple <State <S> > > >();

            var TupleStateDict = new Dictionary <NTuple <State <S> >, State <NTuple <State <S> > > >();

            var q_0_as_array = new State <S> [noAutomata];

            for (int i = 0; i < noAutomata; i++)
            {
                q_0_as_array[i] = automataList[i].q_0;
            }
            var q_0_as_ntuple = new NTuple <State <S> >(q_0_as_array);

            //Initialize workset with q_0. The workset contains all state (in NTuple-form) that still need to be processed
            var W = new HashSet <NTuple <State <S> > >();

            W.Add(q_0_as_ntuple);

            int id  = 0;
            var q_0 = new State <NTuple <State <S> > >(id, q_0_as_ntuple); id++;

            Q.Add(q_0);
            TupleStateDict.Add(q_0_as_ntuple, q_0);

            //Main loop:
            while (W.Count > 0)
            {
                var q_tuple = W.ElementAt(0);
                W.Remove(q_tuple);

                State <NTuple <State <S> > > q;
                if (!TupleStateDict.TryGetValue(q_tuple, out q))
                {
                    //TODO: Exception ??
                }

                //If 'q_tuple' is final, add it to 'F_Tuples'
                bool[] q_acceptance_array = new bool[noAutomata];
                for (int i = 0; i < noAutomata; i++)
                {
                    q_acceptance_array[i] = automataList[i].F.Contains(q_tuple.content[i]);
                }
                if (boolOp.IsTrueForInterpretation(q_acceptance_array))
                {
                    F.Add(q);
                }

                //Determine where transitions out of 'q_tuple' need to go
                foreach (C a in Sigma)
                {
                    var q_dash_array = new State <S> [noAutomata];
                    for (int i = 0; i < noAutomata; i++)
                    {
                        State <S> q_i_dash;
                        var       q_i_a_tuple = new TwoTuple <State <S>, C>(q_tuple.content[i], a);
                        if (!automataList[i].delta.TryGetValue(q_i_a_tuple, out q_i_dash))
                        {
                            //TODO: Throw exception. Non-total transition function!
                        }
                        q_dash_array[i] = q_i_dash;
                    }
                    var q_dash_tuple = new NTuple <State <S> >(q_dash_array);
                    State <NTuple <State <S> > > q_dash;
                    if (!TupleStateDict.ContainsKey(q_dash_tuple))
                    {
                        W.Add(q_dash_tuple);
                        q_dash = new State <NTuple <State <S> > >(id, q_dash_tuple); id++;
                        Q.Add(q_dash);
                        TupleStateDict.Add(q_dash_tuple, q_dash);
                    }
                    else if (!TupleStateDict.TryGetValue(q_dash_tuple, out q_dash))
                    {
                        //TODO: Exception. That'd be weird.
                    }
                    delta.Add(new TwoTuple <State <NTuple <State <S> > >, C>(q, a), q_dash);
                }
            }

            return(new DFA <C, NTuple <State <S> > >(Q, Sigma, delta, q_0, F));
        }
コード例 #2
0
        //Old version of method 'ExecuteSetOperation':
        public static DFA <C, List <State <S> > > ExecuteSetOperationOld <C, S>(List <DFA <C, S> > automataList, BooleanOperation boolOp)
        {
            int noAutomata = automataList.Count;

            //Give every state in each automaton 'Q' in 'automataList' a unique id between '0' and 'Q.Count' (included and excluded):
            foreach (DFA <C, S> D in automataList)
            {
                D.Enumerate();
            }

            //Array, thats i-th component contains the number of states of 'automataList[i]':
            int[] automataSizes = new int[noAutomata];
            for (int i = 0; i < noAutomata; i++)
            {
                automataSizes[i] = automataList[i].Q.Count;
            }

            //Stores references to all states of product-automaton, that have already been created:
            Array Q_reference_array = Array.CreateInstance(typeof(State <List <State <S> > >), automataSizes);

            //Initialize all five components (Q,Sigma,delta,q_0,F) of the resulting automaton:
            HashSet <State <List <State <S> > > > Q = new HashSet <State <List <State <S> > > >();
            HashSet <C> Sigma = automataList[0].Sigma;
            Dictionary <TwoTuple <State <List <State <S> > >, C>, State <List <State <S> > > > delta = new Dictionary <TwoTuple <State <List <State <S> > >, C>, State <List <State <S> > > >();
            HashSet <State <List <State <S> > > > F = new HashSet <State <List <State <S> > > >();

            List <State <S> > q_0_as_list = new List <State <S> >();

            foreach (DFA <C, S> D in automataList)
            {
                q_0_as_list.Add(D.q_0);
            }

            //Initialize workset with the initial state [q_0_1, q_0_2, ...]:
            HashSet <List <State <S> > > W = new HashSet <List <State <S> > >();

            W.Add(q_0_as_list);

            while (W.Count > 0)
            {
                //Pick 'q = [q_1,q_2,...]' from 'W' and add it to 'Q'.
                //Mark in 'Q_reference_array', that 'q' has been added, by referencing it at the position determined by the id's of the states 'q_1', 'q_2', ... respectively:
                List <State <S> > q_list = W.ElementAt(0);
                W.Remove(q_list);

                int[] indices_q = new int[noAutomata];
                for (int i = 0; i < noAutomata; i++)
                {
                    indices_q[i] = q_list[i].id;
                }

                State <List <State <S> > > q;
                if (Q_reference_array.GetValue(indices_q) == null)
                {
                    q = new State <List <State <S> > >(q_list);
                    Q_reference_array.SetValue(q, indices_q);
                }
                else
                {
                    q = (State <List <State <S> > >)Q_reference_array.GetValue(indices_q);
                }
                Q.Add(q);

                //Add q to F if it is accepting
                bool[] q_acceptance_array = new bool[noAutomata];
                for (int i = 0; i < noAutomata; i++)
                {
                    q_acceptance_array[i] = automataList[i].F.Contains(q_list[i]);
                }
                if (boolOp.IsTrueForInterpretation(q_acceptance_array))
                {
                    F.Add(q);
                }

                //Determine, where transitions out of 'q' need to go:
                foreach (C c in Sigma)
                {
                    //Determine 'q_new = delta(q, c)' and its id-array ('indices'):
                    List <State <S> > q_new_list = new List <State <S> >();
                    int[]             indices    = new int[noAutomata];
                    for (int i = 0; i < noAutomata; i++)
                    {
                        State <S> q_temp;
                        TwoTuple <State <S>, C> tuple = new TwoTuple <State <S>, C>(q_list[i], c);
                        if (!automataList[i].delta.TryGetValue(tuple, out q_temp))
                        {
                            return(null); //TODO: throw proper exception rather than returning null
                        }
                        q_new_list.Add(q_temp);
                        indices[i] = q_temp.id;
                    }

                    //If not yet in there, add 'q_new' to 'Q':
                    State <List <State <S> > > q_new;
                    if (Q_reference_array.GetValue(indices) == null)
                    {
                        q_new = new State <List <State <S> > >(q_new_list);
                        Q_reference_array.SetValue(q_new, indices);
                        W.Add(q_new_list);
                    }
                    else
                    {
                        q_new = (State <List <State <S> > >)Q_reference_array.GetValue(indices);
                    }

                    //Add new transition to 'delta':
                    TwoTuple <State <List <State <S> > >, C> key = new TwoTuple <State <List <State <S> > >, C>(q, c);
                    delta.Add(key, q_new);
                }
            }

            //Determine id-array of initial state:
            int[] indices_q_0 = new int[noAutomata];
            for (int i = 0; i < noAutomata; i++)
            {
                indices_q_0[i] = automataList[i].q_0.id;
            }

            State <List <State <S> > > q_0 = (State <List <State <S> > >)Q_reference_array.GetValue(indices_q_0);

            //Return new DFA composed of calculated sets:
            return(new DFA <C, List <State <S> > >(Q, Sigma, delta, q_0, F));
        }