public override FSM <T> Kleene()
        {
            DFSM <T> result = (DFSM <T>) this.Clone();

            foreach (int i in this._transitions.Keys)
            {
                foreach (T s in this._transitions[i].Keys)
                {
                    foreach (int fs in this._transitions[i][s].Intersect(this.AcceptingStates.Keys))
                    {
                        result._transitions[i][s].Remove(fs);
                        if (!result._transitions[i][s].Contains(0))
                        {
                            result._transitions[i][s].Add(0);
                        }
                    }
                }
            }

            result.AcceptingStates.Clear();
            result.AcceptingStates[0] = new List <string>();

            foreach (int acc in this.AcceptingStates.Keys)
            {
                result.AcceptingStates[0].AddRange(this.AcceptingStates[acc]);
            }

            result.AcceptingStates[0] = result.AcceptingStates[0].Distinct().ToList();

            return(result);
        }
        public override FSM <T> And(FSM <T> fsm)
        {
            DFSM <T> result = (DFSM <T>) this.Clone();

            result.AcceptingStates.Clear();

            if (this._transitions[0].Count == 0)
            {
                return(fsm);
            }

            for (int i = 0; i < this.AcceptingStates.Count; i++)
            {
                int offset = result.States.Last();

                foreach (int state in fsm._transitions.Keys)
                {
                    foreach (T symbol in fsm._transitions[state].Keys)
                    {
                        int startstate = state + offset;
                        if (state == 0)
                        {
                            startstate = this.AcceptingStates.Keys.ToArray()[i];
                        }
                        if (!result._transitions.ContainsKey(startstate))
                        {
                            result._transitions[startstate] = new Dictionary <T, List <int> >();
                        }
                        result._transitions[startstate][symbol] = new List <int>();
                        foreach (int target in fsm._transitions[state][symbol])
                        {
                            int endstate = target + offset;
                            if (target == 0)
                            {
                                endstate = this.AcceptingStates.Keys.ToArray()[i];
                            }
                            result._transitions[startstate][symbol].Add(endstate);
                            if (!result._transitions.ContainsKey(endstate))
                            {
                                result._transitions[endstate] = new Dictionary <T, List <int> >();
                            }

                            if (fsm.AcceptingStates.ContainsKey(target))
                            {
                                result.AcceptingStates[endstate] = new List <string>(fsm.AcceptingStates[target]);
                            }
                        }
                    }
                }
            }

            return(result);
        }
        public object Clone()
        {
            DFSM <T> result = new DFSM <T>();

            foreach (KeyValuePair <int, Dictionary <T, List <int> > > i in this._transitions)
            {
                result._transitions[i.Key] = new Dictionary <T, List <int> >();
                foreach (KeyValuePair <T, List <int> > j in i.Value)
                {
                    result._transitions[i.Key][j.Key] = new List <int>(this._transitions[i.Key][j.Key]);
                }
            }

            foreach (KeyValuePair <int, List <string> > i in this.AcceptingStates)
            {
                result.AcceptingStates[i.Key] = new List <string>(this.AcceptingStates[i.Key]);
            }

            return(result);
        }
        public DFSM <T> Minimize()
        {
            DFSM <T> result = new DFSM <T>();

            //make clone
            result._transitions = new Dictionary <int, Dictionary <T, List <int> > >();
            foreach (int i in this._transitions.Keys)
            {
                result._transitions[i] = new Dictionary <T, List <int> >();
                foreach (T s in this._transitions[i].Keys)
                {
                    result._transitions[i][s] = new List <int>(this._transitions[i][s]);
                }
            }

            foreach (KeyValuePair <int, List <string> > kv in this.AcceptingStates)
            {
                result.AcceptingStates[kv.Key] = new List <string>(kv.Value);
            }

            //remove unreachable and looped states
            result.Trim();

            List <int>      states       = result.States;
            List <int>      acc          = result.AcceptingStates.Keys.ToList();
            List <int>      nonacc       = result.States.Except(acc).ToList();
            List <T>        symbols      = result.Symbols;
            List <BuildSet> distinctsets = new List <BuildSet>();
            List <BuildSet> sets         = new List <BuildSet>();
            Dictionary <BuildSet, List <BuildSet> > deltasets = new Dictionary <BuildSet, List <BuildSet> >();

            //populate all sets
            for (int i = 0; i < states.Count; i++)
            {
                for (int j = i + 1; j < states.Count; j++)
                {
                    BuildSet newset = new BuildSet(new int[] { states[i], states[j] });
                    sets.Add(newset);
                    if ((acc.Contains(states[i]) && nonacc.Contains(states[j])) || (acc.Contains(states[j]) && nonacc.Contains(states[i])))
                    {
                        distinctsets.Add(newset);
                    }
                    else
                    {
                        if (!deltasets.ContainsKey(newset))
                        {
                            deltasets[newset] = new List <BuildSet>();
                        }

                        foreach (T s in symbols)
                        {
                            foreach (int x in result.StatesFrom(states[i], s))
                            {
                                foreach (int y in result.StatesFrom(states[j], s))
                                {
                                    if (x != y)
                                    {
                                        deltasets[newset].Add(new BuildSet(new int[] { x, y }));
                                    }
                                }
                            }
                        }

                        deltasets[newset] = deltasets[newset].Distinct().ToList();
                    }
                }
            }

            //mark all distinct states
            int distcounter = 0;

            while (distinctsets.Count != distcounter)
            {
                distcounter = distinctsets.Count;
                foreach (BuildSet bs in deltasets.Keys)
                {
                    if (deltasets[bs].Intersect(distinctsets).Any())
                    {
                        distinctsets.Add(bs);
                    }

                    if (deltasets[bs].Count == 0)
                    {
                        distinctsets.Add(bs);
                    }
                }

                distinctsets = distinctsets.Distinct().ToList();
                foreach (BuildSet bs in distinctsets)
                {
                    deltasets.Remove(bs);
                }
            }

            //join mergeble sets
            List <BuildSet> identicsets = sets.Except(distinctsets).ToList();

            for (int i = 0; i < identicsets.Count; i++)
            {
                for (int j = i + 1; j < identicsets.Count; j++)
                {
                    if (identicsets[i].Items.Intersect(identicsets[j].Items).Any())
                    {
                        List <int> newset = identicsets[i].Items.Union(identicsets[j].Items).ToList();
                        identicsets.RemoveAt(j);
                        identicsets.RemoveAt(i);
                        identicsets.Insert(i, new BuildSet(newset));
                        j = i;
                    }
                }
            }

            foreach (BuildSet b in identicsets)
            {
                List <int> items = new List <int>(b.Items);
                while (items.Count > 1)
                {
                    result.RenumberState(items[1], items[0]);
                    items.RemoveAt(1);
                }
            }

            return(result);
        }
        public override FSM <T> Or(FSM <T> fsm)
        {
            DFSM <T> result = (DFSM <T>) this.Clone();
            //DFSM<T> result = new DFSM<T>(this);
            Dictionary <int, int> conv = new Dictionary <int, int>();


            if (this._transitions[0].Count == 0)
            {
                return(fsm);
            }

            int        offset = result.States.Last();
            List <int> states = fsm.States;

            conv[0] = 0;

            while (states.Count != 0)
            {
                int start = states[0];
                if (fsm._transitions.ContainsKey(start))
                {
                    foreach (T symbol in fsm._transitions[start].Keys)
                    {
                        foreach (int end in fsm._transitions[start][symbol])
                        {
                            if (!conv.ContainsKey(end))
                            {
                                offset++;
                                conv[end] = offset;
                            }

                            if (!result._transitions.ContainsKey(conv[start]))
                            {
                                result._transitions[conv[start]] = new Dictionary <T, List <int> >();
                            }

                            if (!result._transitions.ContainsKey(conv[end]))
                            {
                                result._transitions[conv[end]] = new Dictionary <T, List <int> >();
                            }

                            if (!result._transitions[conv[start]].ContainsKey(symbol))
                            {
                                result._transitions[conv[start]][symbol] = new List <int>();
                            }

                            result._transitions[conv[start]][symbol].Add(conv[end]);

                            if (fsm.AcceptingStates.ContainsKey(end))
                            {
                                if (!result.AcceptingStates.ContainsKey(conv[end]))
                                {
                                    result.AcceptingStates[conv[end]] = new List <string>(fsm.AcceptingStates[end]);
                                }
                            }
                        }
                    }
                }

                states.RemoveAt(0);
            }

            return(result);
        }