/// <summary>
        ///  solve the problem.  This is the entry point for the solver when the run button is clicked
        /// right now it just picks a simple solution.
        /// </summary>
        public void solveProblem()
        {
            //start the time
            Stopwatch timer = new Stopwatch();

            timer.Start();

            //Farthest Insertion Algorithm
            ArrayList bssfRoute = new ArrayList();
            int       m         = 0;
            int       r         = 0;
            double    maxCost   = 0;

            //Find initial vertices to add to subgraph
            for (int k = 0; k < Cities.Length; ++k)
            {
                for (int j = k + 1; j < Cities.Length; ++j)
                {
                    double cost = Cities[k].costToGetTo(Cities[j]);
                    if (maxCost < cost)
                    {
                        m       = k;
                        r       = j;
                        maxCost = cost;
                    }
                }
            }

            bssfRoute.Add(m);
            bssfRoute.Add(r);
            int    first = 0;
            int    last  = 0;
            double minCost;

            //Run until all cities are accounted for
            while (bssfRoute.Count < Cities.Length)
            {
                maxCost = 0;
                m       = 0;
                //Find the vertex that is farthest away from any vertex in the sub-graph
                foreach (int inBssf in bssfRoute)
                {
                    for (int k = 0; k < Cities.Length; ++k)
                    {
                        //Only add if we haven't visited and the cost is larger
                        if (!bssfRoute.Contains(k) && maxCost <
                            Cities[k].costToGetTo(Cities[inBssf]))
                        {
                            m       = k;
                            maxCost = Cities[k].costToGetTo(Cities[inBssf]);
                        }
                    }
                }
                //Find the arc(i,j) that has the cheapest cost to insert the newest vertex
                minCost = double.PositiveInfinity;
                for (int k = 0; k < bssfRoute.Count; ++k)
                {
                    int kIndex = (int)bssfRoute[k];
                    int j      = k + 1;
                    if (j == bssfRoute.Count)
                    {
                        j = 0;
                    }
                    int    jIndex = (int)bssfRoute[j];
                    double cost   = findMinCost(kIndex, jIndex, m);
                    if (cost < minCost)
                    {
                        first   = kIndex;
                        last    = j;
                        minCost = cost;
                    }
                }
                bssfRoute.Insert(last, m);
            }

            //Convert indexes to Route of cities
            int bssfchangecounter = 0;

            Route = new ArrayList();
            foreach (int k in bssfRoute)
            {
                Route.Add(Cities[k]);
            }

            bssf = new TSPSolution(Route);

            double  bssfCost   = bssf.costOfRoute();
            Boolean hasChanged = true;
            Boolean didChange  = false;

            //Check to see if swapping any two vertices produces a better route
            while (hasChanged)
            {
                hasChanged = false;
                didChange  = false;
                ArrayList holder = (ArrayList)Route.Clone();
                for (int i = 0; i < holder.Count; ++i)
                {
                    for (int j = i + 1; j < holder.Count; ++j)
                    {
                        ArrayList temporary = (ArrayList)holder.Clone();
                        City      c         = (City)temporary[i];
                        temporary[i] = temporary[j];
                        temporary[j] = c;
                        TSPSolution newBssf = new TSPSolution(temporary);
                        if (bssfCost > newBssf.costOfRoute())
                        {
                            hasChanged = true;
                            didChange  = true;
                            holder     = (ArrayList)temporary.Clone();
                            bssfCost   = newBssf.costOfRoute();
                        }
                    }
                }
                if (didChange)
                {
                    Route = (ArrayList)holder.Clone();
                    bssf  = new TSPSolution(Route);
                    bssfchangecounter++;
                }
            }
            Console.WriteLine("bssf changed " + bssfchangecounter + " number of times");
            //update the BSSF
            bssf     = new TSPSolution(Route);
            bssfCost = bssf.costOfRoute();

            //Prepare to start Branch and Bound
            //create matrix of distances
            double totalCosts = 0;

            double[,] matrix = new double[Cities.Length, Cities.Length];
            for (int i = 0; i < Cities.Length; i++)
            {
                matrix[i, i] = double.PositiveInfinity;
                for (int j = i + 1; j < Cities.Length; j++)
                {
                    double cost = Cities[i].costToGetTo(Cities[j]);
                    matrix[i, j] = cost;
                    matrix[j, i] = cost;
                    totalCosts  += cost;
                }
            }

            //get children of initial state
            ArrayList childrenIndexes = new ArrayList();

            for (int i = 1; i < Cities.Length; i++)
            {
                childrenIndexes.Add(i);
            }

            //generate initial state
            State s = new State(0, childrenIndexes, (double[, ])matrix.Clone(),
                                new ArrayList(), 0, 0, Cities, 0);

            //bound on initial state
            double bound = s.lowerBound;

            //initial state onto queue
            TSP.PriorityQueue <double, State> q =
                new TSP.PriorityQueue <double, State>();
            q.Enqueue(bound - DEFAULT_SIZE * s.depthIntoSolution, s);

            int maxSize = 0;

            int numberofstatescreated = 1;

            //Branch and Bound: 30 second time limit
            while (!q.IsEmpty && timer.Elapsed.Seconds < 30)
            {
                if (q.Count > maxSize)
                {
                    maxSize = q.Count;
                }

                State u = q.Dequeue().Value;

                //lazy pruning
                if (u.lowerBound < bssfCost)
                {
                    ArrayList childStates = u.generateChildrenStates();
                    numberofstatescreated += childStates.Count;
                    foreach (State w in childStates)
                    {
                        if (timer.Elapsed.Seconds > 30)
                        {
                            break;
                        }
                        //only deal with child state if bound is lower than bssf
                        if (w.lowerBound < bssfCost)
                        {
                            if (w.solutionFound && w.currentCost < bssfCost)
                            {
                                bssfCost  = w.currentCost;
                                bssfRoute = w.pathSoFar;
                            }
                            else
                            {
                                double cBound = w.lowerBound;
                                q.Enqueue(w.lowerBound - DEFAULT_SIZE *
                                          w.depthIntoSolution, w);
                            }
                        }
                    }
                }
            }
            Console.WriteLine("States created " + numberofstatescreated);
            Console.WriteLine("Max number of states stored = " + maxSize);
            Console.WriteLine("Numnber of states pruned = " + (numberofstatescreated - maxSize));

            timer.Stop();

            bssf = new TSPSolution(Route);

            //write out solution
            Program.MainForm.tbCostOfTour.Text = " "
                                                 + bssf.costOfRoute();
            TimeSpan ts          = timer.Elapsed;
            string   elapsedTime = String.Format("{0:00}:{1:00}",
                                                 ts.Minutes, ts.Seconds);

            Program.MainForm.tbElapsedTime.Text = elapsedTime;
            Program.MainForm.Invalidate();

            Console.WriteLine(ToStringSolution());
        }