public DfaTransitionDiagram minimizeStates()
        {
            List <List <State> > pi = new List <List <State> >();

            //initialize pi
            pi.Add(this.finalStates);

            List <State> temp = new List <State>();

            //find non final states
            foreach (State s in this.states)
            {
                if (s.type == stateType.intermediate || s.type == stateType.initial)
                {
                    temp.Add(s);
                }
            }

            if (temp.Count != 0)
            {
                pi.Add(temp);
            }

            //now pi has two sets: finals and non-finals

            if (pi.Count == 1) // i.e. pi has only one set because all the states are either final or both (initial & final)
            {
                MessageBox.Show("The diagram is already minimized");
                return(this);
            }

            DfaTransitionDiagram newDiagram = new DfaTransitionDiagram();

            newDiagram.inputs     = this.inputs;
            newDiagram.noOfInputs = this.noOfInputs;
            newDiagram.setCanvas(canvasMain);


            List <List <State> > newPi = pi; // for the initial condition
            List <List <State> > set;

            while (true)
            {
                pi  = newPi;
                set = pi;
                List <List <State> > piTemp = null;
                foreach (String input in inputs)
                {
                    piTemp = new List <List <State> >();

                    foreach (List <State> ls in set)
                    {
                        if (ls.Count == 1)
                        {
                            //beacuse if a set contains only a single item then it will remain single
                            piTemp.Add(new List <State>());
                            piTemp.Last().Add(ls[0]);
                            continue;
                        }

                        List <int> abc = new List <int>();

                        foreach (State s in ls)
                        {
                            State stt = table[s.index, getIndexOfInput(input)];
                            if (stt == null)
                            {
                                MessageBox.Show("To minimize a DFA, For each State you must define transitions for all input symbols");
                                return(null);
                            }
                            else
                            {
                                abc.Add(piTemp.Count + getSetIndex(pi, stt));
                            }
                        }

                        //pitemp.count is added because before that it was problematic for the iteration
                        //with the next set on same input symbol due to same 0 1 etc in abc

                        for (int i = 0; i < abc.Count; i++)
                        {
                            piTemp.Add(new List <State>());
                        }

                        while (piTemp.Count <= abc.Max())
                        {
                            piTemp.Add(new List <State>());
                        }

                        int j = 0;
                        foreach (int i in abc)
                        {
                            piTemp[i].Add(ls[j]);
                            j++;
                        }


                        // remove empty lists
                        List <List <State> > t = new List <List <State> >(); // to bypass the collection modified error
                        foreach (List <State> ls2 in piTemp)
                        {
                            if (ls2.Count == 0)
                            {
                                t.Add(ls2);
                            }
                        }

                        foreach (List <State> ls2 in t)
                        {
                            piTemp.Remove(ls2);
                        }
                    }

                    set = piTemp;
                }

                newPi = piTemp;

                if (isPiEqualsNewPi(pi, newPi))
                {
                    break;
                }
            }

            canvasMain.Children.Clear();

            // now create a new diagram by taking states from pi

            foreach (List <State> ls in pi)
            {
                State s = newDiagram.addState(State.getNewStatePosition());
                s.figure.ToolTip = getToolTip(ls);
                if (containsInitialState(ls))
                {
                    s.addStartingArrow(canvasMain);
                    newDiagram.initialStates.Add(s);
                    s.type = stateType.initial;

                    if (containsFinalState(ls))
                    {
                        s.type = stateType.both;
                        newDiagram.finalStates.Add(s);
                        s.figure.Stroke          = Brushes.Black;
                        s.figure.StrokeThickness = 2;
                    }
                }
                else if (containsFinalState(ls))
                {
                    s.type = stateType.final;
                    newDiagram.finalStates.Add(s);
                    s.figure.Stroke          = Brushes.Black;
                    s.figure.StrokeThickness = 2;
                }
            }

            foreach (List <State> ls in pi)
            {
                State source = ls[0];
                foreach (string input in newDiagram.inputs)
                {
                    State dest = table[ls[0].index, getIndexOfInput(input)];
                    if (dest != null)
                    {
                        source = getStateByToolTip(newDiagram, getToolTip(ls));

                        foreach (List <State> ls2 in pi)
                        {
                            if (ls2.Contains(dest))
                            {
                                dest = getStateByToolTip(newDiagram, getToolTip(ls2));
                                break;
                            }
                        }

                        if (source != null && dest != null)
                        {
                            Transition tr = newDiagram.addTransition(source, dest);
                            if (tr != null)
                            {
                                ((ComboBox)((StackPanel)tr.figure.Tag).Children[0]).SelectedItem = input;
                            }
                        }
                    }
                }
            }

            //code inserted later to patch the flaws in algorithm

            bool isDeletedSomeState = true;

            while (isDeletedSomeState)
            {
                isDeletedSomeState = false;

                bool isOrphanState;

                List <State> tmp = new List <State>(newDiagram.states);

                foreach (State s in tmp)
                {
                    isOrphanState = true;

                    bool hasSource = false, hasDest = false;

                    foreach (Transition t in s.transitions)
                    {
                        if (s.type == stateType.initial || s.type == stateType.final || s.type == stateType.both)
                        {
                            isOrphanState = false;
                            break;
                        }

                        if (t.destState.index == s.index)
                        {
                            hasDest = true;
                        }

                        if (t.sourceState.index == s.index)
                        {
                            hasSource = true;
                        }

                        if (hasSource && hasDest)
                        {
                            isOrphanState = false;
                            break;
                        }
                    }

                    if (isOrphanState)
                    {
                        newDiagram.selectedState = s;
                        newDiagram.deleteState();
                        isDeletedSomeState = true;
                    }
                }
            }

            return(newDiagram);
        }
        public DfaTransitionDiagram convertToDfa()
        {
            NfaTransitionDiagram diagram = this.removeNullMoves();

            DfaTransitionDiagram newDiagram = new DfaTransitionDiagram();

            newDiagram.setCanvas(canvasMain);
            canvasMain.Children.Clear();

            newDiagram.inputs     = diagram.inputs;
            newDiagram.noOfInputs = diagram.noOfInputs;

            State.resetPoints(); // because the some state positions have been consumed by removeNullMoves(), so reset them

            //add the initial state
            State iState = newDiagram.addState(State.getNewStatePosition());

            iState.addStartingArrow(canvasMain);
            iState.type = diagram.initialStates[0].type;
            newDiagram.initialStates.Add(iState);

            if (iState.type == stateType.both)
            {
                newDiagram.finalStates.Add(iState);
                iState.figure.Stroke          = Brushes.Black;
                iState.figure.StrokeThickness = 2;
            }

            iState.figure.ToolTip    = diagram.initialStates[0].figure.ToolTip;
            newDiagram.selectedState = iState;

            List <List <State> > newStates = new List <List <State> >();

            List <State> temp = new List <State>();

            temp.Add(iState);
            newStates.Add(temp);


            string tooltip;

            int i = -1;

            while (i < newStates.Count - 1)
            {
                List <State> currentState = newStates[++i];

                newDiagram.selectedState = getStateByToolTip(newDiagram, getToolTip(currentState));

                foreach (string input in newDiagram.inputs)
                {
                    List <State> nextState = new List <State>();

                    foreach (State s in currentState)
                    {
                        if (diagram.table[s.index, diagram.getIndexOfInput(input)] != null)
                        {
                            foreach (State t in diagram.table[s.index, diagram.getIndexOfInput(input)])
                            {
                                if (!nextState.Contains(t))
                                {
                                    nextState.Add(t);
                                }
                            }
                        }
                    }

                    tooltip = getToolTip(nextState);

                    if (tooltip != "")
                    {
                        State x = getStateByToolTip(newDiagram, tooltip);

                        if (x == null) //nextState do not exists in the newStates or newDiagram.States
                        {
                            // a new state is found
                            State s = newDiagram.addState(State.getNewStatePosition());
                            s.figure.ToolTip = tooltip;

                            if (containsFinalState(nextState))
                            {
                                s.type = stateType.final;
                                newDiagram.finalStates.Add(s);
                                s.figure.Stroke          = Brushes.Black;
                                s.figure.StrokeThickness = 2;
                            }

                            Point pt1 = new Point();

                            Random rnd = new Random();
                            pt1.X = (double)rnd.Next((int)canvasMain.ActualWidth);
                            pt1.X = (double)rnd.Next((int)canvasMain.ActualHeight);

                            Transition tr = newDiagram.addTransition(newDiagram.selectedState, s, pt1.ToString());
                            ((ComboBox)((StackPanel)tr.figure.Tag).Children[0]).SelectedItem = input;

                            newStates.Add(nextState);
                        }
                        else
                        {
                            Transition tr = newDiagram.addTransition(newDiagram.selectedState, x);
                            if (tr != null)
                            {
                                ((ComboBox)((StackPanel)tr.figure.Tag).Children[0]).SelectedItem = input;
                            }
                        }
                    }
                }
            }

            return(newDiagram);
        }