public ProblemAndSolver.TSPSolution Solve() { //Tests show that heap is better for more cities, array is better for less queue = new HeapPriorityQueue(); nodesCreated = 0; prunedNodes = 0; averageDistance = 0; numUpdates = 0; var timer = new Stopwatch(); timer.Start(); //Build the mother node state //Build a starting matrix. time O(n^2) space O(n^2) int count = 0; double[,] motherMatrix = new double[cities.Length, cities.Length]; for (int row = 0; row < cities.Length; row++) { for (int col = 0; col < cities.Length; col++) { double cost = cities[row].costToGetTo(cities[col]); motherMatrix[row, col] = row == col ? double.PositiveInfinity : cost; if (!double.IsPositiveInfinity(cost)) { averageDistance += cost; count++; } } } averageDistance = averageDistance / count; //Reduce the matrix & get the bound. time O(n^2) double bound = ReduceMatrix(motherMatrix); ArrayList route = new ArrayList(); route.Add(cities[0]); //Put them in a new state State motherState = new State(motherMatrix, route, bound, 0); //Expand the mother node state. time O(n^3) space O(n^3) ExpandState(motherState); //While the priority queue is not empty. Worst case Time O(n^3*b^n+log(n!)), with b > 1 while (!queue.IsEmpty() && timer.ElapsedMilliseconds < timeLimit) { //pop off the top state and expand it. time O(n^3) space O(n^3) //DeleteMin could potentially be as bad as time O(logn!) ExpandState(queue.DeleteMin()); } timer.Stop(); //When the timer goes off, update results and return bssf results[ProblemAndSolver.COST] = costOfBssf().ToString(); results[ProblemAndSolver.TIME] = timer.Elapsed.ToString(); results[ProblemAndSolver.COUNT] = numUpdates.ToString(); Console.WriteLine("Max Stored States: " + queue.LargestSize()); Console.WriteLine("States Created: " + nodesCreated); Console.WriteLine("States Pruned: " + prunedNodes); return(bssf); }
/// <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]; int count = 0; Stopwatch timer = new Stopwatch(); PriorityQueue queue = new PriorityQueue(); timer.Start(); greedySolveProblem(); queue.Insert(new PartialPath(CalculateInitialMatrix(), Cities)); /* While there are still partial paths on the queue, * the best one is popped off and its children are generated. * Those that are better than the bssf are added to the queue. */ while (timer.Elapsed.TotalMilliseconds < time_limit && !queue.Empty()) { PartialPath currentNode = queue.DeleteMin(); if (currentNode.FullPath && currentNode.CompletePath) { TSPSolution potentialSolution = new TSPSolution(currentNode.Path); if (potentialSolution.costOfRoute() < costOfBssf()) { bssf = potentialSolution; count++; } } else if (currentNode.LowerBound < costOfBssf()) { GenerateChildren(currentNode, queue); } } timer.Stop(); results[COST] = costOfBssf().ToString(); results[TIME] = timer.Elapsed.ToString(); results[COUNT] = count.ToString(); Console.WriteLine("Branch & Bound Size: " + Cities.Length + " Random: " + Seed + " Path: " + costOfBssf().ToString() + " Time: " + timer.Elapsed.ToString()); return(results); }