// swap two nodes
        public void swap(int a, int b)
        {
            ReducedMatrix temp = tree[a];

            tree[a] = tree[b];
            tree[b] = temp;
        }
 public ReducedMatrix(ReducedMatrix parent, City nextCity, int citynum)
 {
     matrix     = DeepCopy <double[, ]>(parent.matrix);
     bound      = parent.bound + parent.matrix[parent.cityNumber, citynum];
     Route      = new ArrayList(parent.Route);
     cityNumber = citynum;
     n          = parent.n;
     Route.Add(nextCity);
 }
        /**
         * add a new node.
         *  Insert the new node as a leaf node (last index)
         *  and start comparing with its root nodes and swap positions if the new node has the small bound.
         **/
        public void add(ReducedMatrix newMatrix)
        {
            tree.Add(newMatrix);
            size++;
            int k = size;

            while (k > 1)
            {
                if (tree[k / 2].bound > tree[k].bound)
                {
                    swap(k, k / 2);
                }
                else
                {
                    break;
                }
                k = k / 2;
            }
        }
Example #4
0
        /// <summary>
        /// performs a Branch and Bound search of the state space of partial tours
        /// stops when time limit expires and uses BSSF as solution
        /// </summary>
        /// <returns>results array for GUI that contains three ints: cost of solution, time spent to find solution, number of solutions found during search (not counting initial BSSF estimate)</returns>
        public string[] bBSolveProblem()
        {
            Stopwatch timer = new Stopwatch();

            timer.Start();
            initialBSSF = true;
            greedySolveProblem();
            string[] results = new string[3];
            int      n       = Cities.Length;

            double[,] baseMatrix = new double[n, n];
            int           count;
            ReducedMatrix currentCity;

            queue = new PriorityQueue();
            ReducedMatrix reduced;

            for (int i = 0; i < n; i++)
            {
                for (int j = 0; j < n; j++)
                {
                    if (i == j)
                    {
                        baseMatrix[i, j] = Double.PositiveInfinity;
                    }
                    else
                    {
                        baseMatrix[i, j] = Cities[i].costToGetTo(Cities[j]);
                    }
                }
            }
            reduced = new ReducedMatrix(baseMatrix, Cities.Length, Cities[0]);
            reduced.reduce();
            queue.add(reduced);
            count       = 0;
            totalStates = 1;
            while (true)
            {
                if (queue.getSize() > maxStroedStates)
                {
                    maxStroedStates = queue.getSize();
                }
                if (timer.ElapsedMilliseconds > time_limit)
                {
                    break;
                }
                currentCity = queue.remove();
                if (currentCity == null)
                {
                    break;
                }
                if (currentBssf < currentCity.bound)
                {
                    break;
                }
                for (int i = 1; i < n; i++)
                {
                    if (currentCity.matrix[currentCity.cityNumber, i] != INFINITY)
                    {
                        ReducedMatrix newMatrix = new ReducedMatrix(currentCity, Cities[i], i);
                        newMatrix.cancel(currentCity.cityNumber, i);
                        newMatrix.reduce();
                        if (newMatrix.Route.Count == Cities.Length)
                        {
                            if (newMatrix.bound < currentBssf)
                            {
                                numBSSFUpdates++;
                                bssf        = new TSPSolution(newMatrix.Route);
                                currentBssf = newMatrix.bound;
                            }
                            count++;
                            break;
                        }
                        if (newMatrix.bound < currentBssf)
                        {
                            queue.add(newMatrix);
                            totalStates++;
                        }
                        else
                        {
                            numStatesPruned++;
                        }
                    }
                }
            }

            timer.Stop();
            numStatesPruned += queue.getSize();

            String track;

            track  = "MAX #of stored states " + maxStroedStates + "\n";
            track += "#of BSSF updates " + numBSSFUpdates + "\n";
            track += "Total states created " + totalStates + "\n";
            track += "Total states pruned " + numStatesPruned + "\n";

            MessageBox.Show(track);


            results[COST]  = bssf.costOfRoute().ToString();   // load results into array here, replacing these dummy values
            results[TIME]  = timer.Elapsed.ToString();
            results[COUNT] = count.ToString();

            return(results);
        }
        /**
         * remove function for priority queue
         *  save the root node(the node with the minimum bound) and put the node with the last index as a root node.
         *  start comparing the bound values with its children and find the right place for this node.
         **/
        public ReducedMatrix remove()
        {
            if (size == 0)
            {
                return(null);
            }
            ReducedMatrix root = tree[1];

            tree[1] = tree[size];
            tree.RemoveAt(size);
            size--;
            int     k    = 1;
            Boolean flag = true;

            if (size == 0)
            {
                return(root);
            }
            while (flag)
            {
                if (k * 2 > size)
                {
                    break;
                }
                flag = false;
                if (k * 2 == size)
                {
                    if (tree[k * 2].bound > tree[k].bound)
                    {
                        swap(k, k * 2);
                        k   *= 2;
                        flag = true;
                    }
                    break;
                }
                if (tree[k * 2].bound < tree[k * 2 + 1].bound)
                {
                    if (tree[k * 2].bound < tree[k].bound)
                    {
                        swap(k, k * 2);
                        k   *= 2;
                        flag = true;
                    }
                    else if (tree[k * 2 + 1].bound < tree[k].bound)
                    {
                        swap(k * 2 + 1, k);
                        k    = k * 2 + 1;
                        flag = true;
                    }
                }
                else
                {
                    if (tree[k * 2 + 1].bound < tree[k].bound)
                    {
                        swap(k, k * 2 + 1);
                        k    = k * 2 + 1;
                        flag = true;
                    }
                    else if (tree[k * 2].bound < tree[k].bound)
                    {
                        swap(k, k * 2);
                        k    = k * 2;
                        flag = true;
                    }
                }
            }
            return(root);
        }