/// <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()); }