Ejemplo n.º 1
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()
        {
            string[] results = new string[3];

            results[COST]  = "not implemented";   // load results into array here, replacing these dummy values
            results[TIME]  = "-1";
            results[COUNT] = "-1";

            int count = 0;

            Console.Out.WriteLine("City costs: ");
            for (int j = 0; j < Cities.Length; j++)
            {
                for (int h = 0; h < Cities.Length; h++)
                {
                    Console.Write(Cities[j].costToGetTo(Cities[h]) + ",");
                }
                Console.WriteLine();
            }

            Stopwatch timer = new Stopwatch();

            timer.Start();

            PriorityQueue queue = new PriorityQueue();

            queue.make_queue(Cities.Length * Cities.Length * Cities.Length * Cities.Length);

            //Here I run the greedy algorithm and use that BSSF result as my starting BSSF
            greedySolveProblem();
            Console.Out.WriteLine("Greedy BSSF: " + costOfBssf());

            matrix_and_bound initial_matrix = construct_initial_matrix();


            for (int j = 0; j < Cities.Length; j++)
            {
                for (int h = 0; h < Cities.Length; h++)
                {
                    Console.Write(initial_matrix.Matrix[j, h] + ",");
                }
                Console.WriteLine();
            }
            Console.WriteLine(initial_matrix.Lower_bound);
            //Console.WriteLine();


            //This loop will do my initial population of the queue by looping through each city and getting the lower bound
            for (int i = 0; i < Cities.Length; i++)
            {
                for (int k = 0; k < Cities.Length; k++)
                {
                    if (i != k)
                    {
                        //I need to get the lower bound of each reduced matrix and the bound
                        matrix_and_bound current = matrix_reduction(initial_matrix, i, k);


                        //Console.WriteLine();

                        //If the lower bound is less than current bssf add to queue for later checking, otherwise ignore
                        if (current.Lower_bound < costOfBssf())
                        {
                            //need to create new state_data object with state data set
                            state_data data = new state_data();
                            //I guess depth doesn't matter to be exact so long as it's relative, so I'll keep this first one as 0
                            data.Depth = 0;
                            data.Mb    = current;

                            data.add_city(Cities[i]);
                            data.add_city(Cities[k]);

                            data.add_city_index(i);
                            data.add_city_index(k);

                            data.set_priority();
                            Console.Out.WriteLine("bound " + data.Mb.Lower_bound);
                            //I'm not sure this id is necessary but I'll have to see
                            data.Id = id;

                            queue.insert(data, id);
                            id++;
                        }
                    }
                }
            }

            Console.Out.WriteLine("Queue length Initial " + queue.Length);
            //now run while queue is not empty and timer is less than 60
            while (timer.Elapsed.TotalSeconds < 60 && queue.Length > 0)
            {
                //pop off of queue and repeat above matrix reduction process
                state_data current = queue.delete_min();
                //if it's greater or equal to the current bssf I can just ignore it, this is the culling
                if (current.Mb.Lower_bound < costOfBssf())
                {
                    //Priority queue looks like it's working
                    //Console.Out.WriteLine(current.Mb.Lower_bound);

                    /*
                     * Now I need to matrix reduce each child of the current node,
                     * see if it's still smaller than the current bssf if it's a leaf node
                     * I put it as the current bssf, otherwise I push it on the queue
                     */

                    for (int k = 0; k < Cities.Length; k++)
                    {
                        if (!current.City_list.Contains(k))
                        {
                            matrix_and_bound child = matrix_reduction(current.Mb, (int)current.City_list[current.City_list.Count - 1], k);

                            //Console.Out.WriteLine("here");

                            //Console.Out.WriteLine("Current depth: " + );
                            for (int j = 0; j < Cities.Length; j++)
                            {
                                for (int h = 0; h < Cities.Length; h++)
                                {
                                    Console.Write(child.Matrix[j, h] + ",");
                                }
                                Console.WriteLine();
                            }
                            Console.WriteLine(child.Lower_bound);

                            if (child.Lower_bound < costOfBssf())
                            {
                                //need to create new state_data object with state data set
                                state_data data = new state_data();
                                //I guess depth doesn't matter to be exact so long as it's relative, so I'll keep this first one as 0
                                data.Depth = current.Depth + 1;
                                data.Mb    = child;

                                //The last value in the path is the current city
                                data.Path      = current.Path;
                                data.City_list = current.City_list;
                                data.add_city(Cities[k]);

                                /* Console.Out.WriteLine("The Current Path and length " + data.City_list.Count);
                                 * for (int j = 0; j < data.City_list.Count; j++)
                                 * {
                                 *   Console.Out.Write(data.City_list[j] + "->");
                                 * }
                                 * Console.Out.WriteLine();*/


                                data.City_list = current.City_list;
                                data.add_city_index(k);

                                data.set_priority();
                                //Console.Out.WriteLine("Set Priority " + data.Priority);
                                //I'm not sure this id is necessary but I'll have to see
                                data.Id = id;
                                id++;

                                // Console.Out.WriteLine("Intermediate Lower Bound " + data.Mb.Lower_bound);

                                if (data.City_list.Count < Cities.Length)
                                {
                                    queue.insert(data, id);
                                }
                                else if (data.Mb.Lower_bound < costOfBssf())//it's a leaf node and it's less than the current BSSF
                                {
                                    Console.Out.WriteLine("Current Lower Bound " + costOfBssf());
                                    Console.Out.WriteLine("Final Lower Bound " + data.Mb.Lower_bound);
                                    for (int j = 0; j < data.City_list.Count; j++)
                                    {
                                        Console.Out.Write(data.City_list[j] + "->");
                                    }


                                    bssf = new TSPSolution(data.Path);
                                    count++;
                                }
                            }
                        }
                    }
                }
            }

            results[COST]  = costOfBssf().ToString();
            results[TIME]  = timer.Elapsed.ToString();
            results[COUNT] = count.ToString();

            return(results);
        }