private static Dictionary <Set <State <S> >, TwoTuple <bool, List <Set <State <S> > > > > BuildDependencyGraph <C, S>(DFA <C, S> D)
        {
            //Dependency Graph for automaton D modelled as a Dictionary
            //'Value' is set of all nodes, that 'key' has an edge to
            var G = new Dictionary <Set <State <S> >, TwoTuple <bool, List <Set <State <S> > > > >();

            for (int i = 0; i < D.Q.Count; i++)
            {
                for (int j = i + 1; j < D.Q.Count; j++)
                {
                    var p = D.Q.ElementAt(i);
                    var q = D.Q.ElementAt(j);
                    var v = new Set <State <S> >();
                    v.content.Add(p);
                    v.content.Add(q);
                    var l = new List <Set <State <S> > >();
                    G.Add(v, new TwoTuple <bool, List <Set <State <S> > > >(false, l));
                }
            }

            for (int i = 0; i < D.Q.Count; i++)
            {
                for (int j = i + 1; j < D.Q.Count; j++)
                {
                    var p_dash = D.Q.ElementAt(i);
                    var q_dash = D.Q.ElementAt(j);
                    var v_dash = new Set <State <S> >();
                    v_dash.content.Add(p_dash);
                    v_dash.content.Add(q_dash);

                    foreach (C a in D.Sigma)
                    {
                        var       t1 = new TwoTuple <State <S>, C>(p_dash, a);
                        var       t2 = new TwoTuple <State <S>, C>(q_dash, a);
                        State <S> p, q;
                        if (!D.delta.TryGetValue(t1, out p))
                        {
                        }
                        if (!D.delta.TryGetValue(t2, out q))
                        {
                        }
                        if (!p.Equals(q))
                        {
                            Set <State <S> > v = new Set <State <S> >();
                            v.content.Add(p);
                            v.content.Add(q);
                            TwoTuple <bool, List <Set <State <S> > > > t;
                            if (!G.TryGetValue(v, out t))
                            {
                            }
                            t.second.Add(v_dash);
                        }
                    }
                }
            }

            return(G);
        }
Beispiel #2
0
        public State <S> ReadWordFrom(List <C> sequence, State <S> q)
        {
            State <S> current = q;

            for (int i = 0; i < sequence.Count; i++)
            {
                TwoTuple <State <S>, C> tuple = new TwoTuple <State <S>, C>(current, sequence[i]);
                if (!delta.TryGetValue(tuple, out current))
                {
                    return(null);
                }
            }

            return(current);
        }
Beispiel #3
0
        /*  METHOD THAT RUNS THIS DFA ON A WORD
         *
         *   Input:  sequence:   Word over the alphabet of characters of type C
         *
         *   Output: true, if this DFA accepts the word 'sequence'
         *           false, otherwise
         */
        public bool AcceptsFrom(List <C> sequence, State <S> q)
        {
            State <S> current = q;

            for (int i = 0; i < sequence.Count; i++)
            {
                TwoTuple <State <S>, C> tuple = new TwoTuple <State <S>, C>(current, sequence[i]);
                if (!delta.TryGetValue(tuple, out current))
                {
                    return(false);
                }
            }

            return(F.Contains(current));
        }
        public ThreeTuple <bool, string[], StringBuilder[]> ComputeTapes(string[] tapeList, int maxSteps)
        {
            State <S> current = q_0;
            ThreeTuple <State <S>, string, string> resolutionList = new ThreeTuple <State <S>, string, string>(current, "", "");

            int[]           tapeHeadPosition = new int[tapeList.Length];
            StringBuilder[] strB             = new StringBuilder[tapeList.Length];
            int             i = 0;

            for (i = 0; i < tapeList.Length; i++)
            {
                tapeHeadPosition[i] = 0;
                strB[i]             = new StringBuilder(tapeList[i]);
            }
            bool acceptState;

            i = 0;
            for (i = 0; i < maxSteps; i++)
            {
                string readingSymbols = "";// = ""; //tapeList[tapeHeadPostiotions[]] + tapeList[] + tapeList[]);
                for (int j = 0; j < tapeHeadPosition.Length; j++)
                {
                    //readingSymbols = readingSymbols + tapeList[j][tapeHeadPosition[j]];
                    readingSymbols = readingSymbols + strB[j][tapeHeadPosition[j]];
                }
                TwoTuple <State <S>, string> tuple = new TwoTuple <State <S>, string>(current, readingSymbols);
                if (!delta.TryGetValue(tuple, out resolutionList))
                {
                    break;
                }
                for (int k = 0; k < tapeHeadPosition.Length; k++)
                {
                    //tapeList[k][tapeHeadPosition[k]] = resolutionList.second.ToCharArray()[k];
                    strB[k][tapeHeadPosition[k]] = resolutionList.second.ToCharArray()[k];
                    current = resolutionList.first;
                    switch (resolutionList.third.ToCharArray()[k])
                    {
                    case 'R':
                        tapeHeadPosition[k]++;
                        if (tapeHeadPosition[k] == strB[k].Length)
                        {
                            strB[k].Append("?");
                        }
                        break;

                    case 'L':
                        if (tapeHeadPosition[k] == 0)
                        {
                            strB[k].Insert(0, "?");
                        }
                        else
                        {
                            tapeHeadPosition[k]--;
                        }
                        break;

                    case 'N':
                        break;
                    }
                }
            }

            if (i == maxSteps)
            {
                acceptState = false;
            }
            else
            {
                acceptState = F.Contains(current);
            }

            /*State<S> current = q_0;
             * int[] tapeHeadPosition = new int[tapeList.Length];
             *
             * for (int i = 0; i < maxSteps; i++)
             * {
             *  S[] readingSymbols = new S[tapeList.Length];// = ""; //tapeList[tapeHeadPostiotions[]] + tapeList[] + tapeList[]);
             *  for (int j = 0; j < tapeHeadPosition.Length; j++)
             *  {
             *      readingSymbols[j] = tapeList[tapeHeadPosition[j]];
             *      TwoTuple<State<S>, S> tuple = new TwoTuple<State<S>, S>(current, readingSymbols);
             *      if (!delta.TryGetValue(tuple, out current))
             *          break;// return false;
             *  }
             *
             *  return F.Contains(current);*/

            //TODO List generation from tapeList
            //var resolutionStringList = new List<string>();
            var resolutionStringList = new string[tapeHeadPosition.Length];

            for (int j = 0; j < tapeHeadPosition.Length; j++)
            {
                string currentTapeWord = "";
                while (tapeHeadPosition[j] < strB[j].Length && strB[j][tapeHeadPosition[j]] != '?')
                {
                    currentTapeWord = currentTapeWord + strB[j][tapeHeadPosition[j]];
                    tapeHeadPosition[j]++;
                }
                resolutionStringList[j] = currentTapeWord;
            }
            return(new ThreeTuple <bool, string[], StringBuilder[]>(acceptState, resolutionStringList, strB));
        }
Beispiel #5
0
        /*  METHOD THAT MINIMIZES THIS DFA USING HOPCROFT'S ALGORITHM
         *
         *   Output: Minimal DFA recognizing the same language as this one.
         *           States are labelled as sets of states of this automaton.
         */
        public DFA <C, HashSet <State <S> > > MinimizeHopcroft()
        {
            int no_states = Q.Count;

            //Stores for state q (key) in which set (value) of the state partition it is
            //(the value is the new state made out of this set).
            var state_dict = new Dictionary <State <S>, State <HashSet <State <S> > > >();

            var P         = ComputeLanguagePartition();
            var Q_new     = new HashSet <State <HashSet <State <S> > > >();
            var delta_new = new Dictionary <TwoTuple <State <HashSet <State <S> > >, C>, State <HashSet <State <S> > > >();
            var F_new     = new HashSet <State <HashSet <State <S> > > >();

            State <HashSet <State <S> > > q_0_new = null;

            int i = 0;

            foreach (HashSet <State <S> > B in P)
            {
                var B_as_State = new State <HashSet <State <S> > >(i, B);

                Q_new.Add(B_as_State);
                if (F.Contains(B.ElementAt(0)))
                {
                    F_new.Add(B_as_State);
                }

                foreach (State <S> q in B)
                {
                    state_dict.Add(q, B_as_State);
                    if (q.Equals(q_0))
                    {
                        q_0_new = B_as_State;
                    }
                }
                i++;
            }

            foreach (var c in delta)
            {
                State <HashSet <State <S> > > B1, B2;
                State <S> q1 = c.Key.first, q2 = c.Value;
                C         a = c.Key.second;

                if (!state_dict.TryGetValue(q1, out B1) | !state_dict.TryGetValue(q2, out B2))
                {
                    //TODO: Throw some exception
                }
                var tuple = new TwoTuple <State <HashSet <State <S> > >, C>(B1, a);
                State <HashSet <State <S> > > B_out;
                if (!delta_new.TryGetValue(tuple, out B_out))
                {
                    delta_new.Add(new TwoTuple <State <HashSet <State <S> > >, C>(B1, a), B2);
                }
            }

            if (q_0_new == null)
            {
                //TODO: throw some exception or another
            }

            return(new DFA <C, HashSet <State <S> > >(Q_new, Sigma, delta_new, q_0_new, F_new));
        }
        /*  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));
        }
        //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));
        }