public bool extend() { if (citiesLeft.Count() != 0) { foreach (int i in citiesLeft) { double initialCost = matrix[path.Last()][i] + cost; double[][] newMatrix = this.matrix.Select(a => a.ToArray()).ToArray(); for (int j = 0; j < matrix.Count(); j++) { newMatrix[path.Last()][j] = Double.PositiveInfinity; newMatrix[j][i] = Double.PositiveInfinity; } List <int> newPath = path.Select(a => a).ToList(); newPath.Add(i); List <int> newCitiesLeft = citiesLeft.Select(a => a).ToList(); newCitiesLeft.Remove(i); BBState state = new BBState(newMatrix, newPath, newCitiesLeft, initialCost); PriorityQueue.getInstance().insert(state); } return(false); } else { cost = matrix[path.Last()][0] + cost; path.Add(0); return(true); } }
//initializes the distances with the given list and sets the lastIndex which //is used to track which elements have been checked //public PriorityQueue(List<double> costs) //{ // foreach (double distance in costs) // { // insert(distance); // } // lastIndex = costs.Count - 1; //} //adds element to the bottom of the tree and if its not the max value then bubble up //Insert is O(log(|v|)) because Heapify is O(log(|v|)) and add is O(1) public void insert(BBState state) { states.Add(state); double cost = state.getCost(); this.cost.Insert(++lastIndex,cost); pointers.Add(pointers.Count); if (cost != Int32.MaxValue) { HeapifyUp(lastIndex); } }
//initializes the distances with the given list and sets the lastIndex which //is used to track which elements have been checked //public PriorityQueue(List<double> costs) //{ // foreach (double distance in costs) // { // insert(distance); // } // lastIndex = costs.Count - 1; //} //adds element to the bottom of the tree and if its not the max value then bubble up //Insert is O(log(|v|)) because Heapify is O(log(|v|)) and add is O(1) public void insert(BBState state) { states.Add(state); double cost = state.getCost(); this.cost.Insert(++lastIndex, cost); pointers.Add(pointers.Count); if (cost != Int32.MaxValue) { HeapifyUp(lastIndex); } }
//swaps the minimum with the lastIndexed item and bubbles down //DeleteMin is O(log(|v|)), because of the reorder public BBState deletemin() { int node = pointers[0]; pointers[0] = pointers[lastIndex]; pointers[lastIndex] = node; cost[0] = cost[lastIndex]; cost[lastIndex] = -1; //this make it O(log(|v|)) HeapifyDown(0); lastIndex--; BBState state = states.ElementAt(node); return(state); //return node; }
/// <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]; double bssf = Double.PositiveInfinity; // TODO: Add your implementation for a branch and bound solver here. //List<int> citiesLeft = new List<int>(); //double[][] matrix = new double[Cities.Length][]; //for (int i = 0; i < Cities.Length; i++) //{ // citiesLeft.Add(i); // matrix[i] = new double[Cities.Length]; // for (int j = 0; j < Cities.Length; j++) // { // if (i != j) // matrix[i][j] = Cities[i].costToGetTo(Cities[j]); // else // matrix[i][j] = Double.PositiveInfinity; // } //} //citiesLeft.RemoveAt(0); double[][] matrix = new double[4][]; matrix[0] = new double[4] { Double.PositiveInfinity, 7, 3, 12 }; matrix[1] = new double[4] { 3, Double.PositiveInfinity, 6, 14 }; matrix[2] = new double[4] { 5, 8, Double.PositiveInfinity, 6 }; matrix[3] = new double[4] { 9, 3, 5, Double.PositiveInfinity }; BBState state = new BBState(matrix, new List<int>() { 0 }, new List<int>() { 1,2,3 },0); //BBState state = new BBState(matrix, new List<int>() { 0 }, citiesLeft,0); PriorityQueue.getInstance().insert(state); BBState current; while (!PriorityQueue.getInstance().isEmpty()) { current = PriorityQueue.getInstance().deletemin(); if(state.extend()) { if(current.getCost() < bssf) { bssf = current.getCost(); PriorityQueue.getInstance().trim(bssf); } } } results[COST] = "not implemented"; // load results into array here, replacing these dummy values results[TIME] = "-1"; results[COUNT] = "-1"; return results; }
/// <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]; double bssf = Double.PositiveInfinity; // TODO: Add your implementation for a branch and bound solver here. //List<int> citiesLeft = new List<int>(); //double[][] matrix = new double[Cities.Length][]; //for (int i = 0; i < Cities.Length; i++) //{ // citiesLeft.Add(i); // matrix[i] = new double[Cities.Length]; // for (int j = 0; j < Cities.Length; j++) // { // if (i != j) // matrix[i][j] = Cities[i].costToGetTo(Cities[j]); // else // matrix[i][j] = Double.PositiveInfinity; // } //} //citiesLeft.RemoveAt(0); double[][] matrix = new double[4][]; matrix[0] = new double[4] { Double.PositiveInfinity, 7, 3, 12 }; matrix[1] = new double[4] { 3, Double.PositiveInfinity, 6, 14 }; matrix[2] = new double[4] { 5, 8, Double.PositiveInfinity, 6 }; matrix[3] = new double[4] { 9, 3, 5, Double.PositiveInfinity }; BBState state = new BBState(matrix, new List <int>() { 0 }, new List <int>() { 1, 2, 3 }, 0); //BBState state = new BBState(matrix, new List<int>() { 0 }, citiesLeft,0); PriorityQueue.getInstance().insert(state); BBState current; while (!PriorityQueue.getInstance().isEmpty()) { current = PriorityQueue.getInstance().deletemin(); if (state.extend()) { if (current.getCost() < bssf) { bssf = current.getCost(); PriorityQueue.getInstance().trim(bssf); } } } results[COST] = "not implemented"; // load results into array here, replacing these dummy values results[TIME] = "-1"; results[COUNT] = "-1"; return(results); }
/** * Solve the TSP using an include/exclude B&B strategy * * First, get an upper bound, bssf. * * Generate the initial Reduced Cost Matrix, (RCM) which * will give us the initial lower bound. * * */ public void solveBranchAndBound() { // Stats int totalStatesGenerated = 0, statesPruned = 0, maxStatesStored = 0; bool initialBssfIsFinal = true; // Get an upper bound getGreedyRoute(); bssf = new TSPSolution(Route); // Generate the RCM, and get it's lower bound from the reduction double[,] rcm = generateRCM(); double lowerBound = reduceCM(ref rcm); // Now we need to start throwing states on the queue and processing them.. PriorityQueue<BBState> stateQueue = new PriorityQueue<BBState>(); // Create initial state BBState initialState = new BBState(rcm, lowerBound); stateQueue.Enqueue(initialState, initialState.bound); totalStatesGenerated = maxStatesStored = 1; // Ok, now we kick off the process! // Start the timer.. Stopwatch timer = new Stopwatch(); timer.Start(); BBState curState = null; while (stateQueue.Count > 0) { /*if (timer.ElapsedMilliseconds > 30000) // 30 seconds break; */ curState = stateQueue.Dequeue(); // If this state's lower bound is greater than BSSF, then we // prune it out if (curState.bound > costOfBssf()) { statesPruned++; continue; } // If it's not, then see if it's a complete solution. If it is, // then update BSSF. if (curState.isCompleteSolution(ref Cities)) { bssf = new TSPSolution(curState.getRoute(ref Cities)); initialBssfIsFinal = false; continue; } // If it's not a complete solution, but it's within range, then // expand it into two child states, one with an included edge, one // with the same edge excluded. Tuple<int, int> edge = curState.getNextEdge(); if (edge == null) continue; // Ok, now we have the next edge to include and exclude in different states to maximize // the difference in bounds. So we need to create states corresponding to each and put // them in the queue. BBState incState = new BBState(curState.cm, curState.bound, curState.includedEdges); incState.includedEdges.Add(edge); incState.cm[edge.Item1, edge.Item2] = double.PositiveInfinity; incState.cm[edge.Item2, edge.Item1] = double.PositiveInfinity; for (int t = 0; t < incState.cm.GetLength(0); t++) incState.cm[t, edge.Item2] = double.PositiveInfinity; for (int t = 0; t < incState.cm.GetLength(1); t++) incState.cm[edge.Item1, t] = double.PositiveInfinity; // Need to take out edges in incState that could be used to complete a premature cycle if (incState.includedEdges.Count < incState.cm.GetLength(0) - 1) { int start = edge.Item1, end = edge.Item2, city; city = getCityExited(start, incState.includedEdges); while (city != -1) { start = city; city = getCityExited(start, incState.includedEdges); } city = getCityEntered(end, incState.includedEdges); while (city != -1) { end = city; city = getCityEntered(end, incState.includedEdges); } while (start != edge.Item2) { incState.cm[end, start] = double.PositiveInfinity; incState.cm[edge.Item2, start] = double.PositiveInfinity; start = getCityEntered(start, incState.includedEdges); } } // finish setting up the state and put it in the queue incState.bound = curState.bound + reduceCM(ref incState.cm); totalStatesGenerated++; if (incState.bound > costOfBssf()) { statesPruned++; } else { stateQueue.Enqueue(incState, incState.bound); if (stateQueue.Count > maxStatesStored) maxStatesStored = stateQueue.Count; } BBState exState = new BBState(curState.cm, curState.bound, curState.includedEdges); exState.cm[edge.Item1, edge.Item2] = double.PositiveInfinity; exState.bound = curState.bound + reduceCM(ref exState.cm); totalStatesGenerated++; if (exState.bound > costOfBssf()) { statesPruned++; } else { stateQueue.Enqueue(exState, exState.bound); if (stateQueue.Count > maxStatesStored) maxStatesStored = stateQueue.Count; } } timer.Stop(); Program.MainForm.tbElapsedTime.Text = " " + timer.Elapsed; // update the cost of the tour. Program.MainForm.tbCostOfTour.Text = " " + bssf.costOfRoute(); // do a refresh. Program.MainForm.Invalidate(); String msg = "\tB&B RESULTS\n"; if (timer.ElapsedMilliseconds > 30000) msg += "\nSearch timed out, 30 seconds expired."; if (initialBssfIsFinal) msg += "\nInitial BSSF (Greedy) is final solution."; else msg += "\nA better BSSF than the initial was found."; msg += "\n\n\tSTATS:"; msg += "\nTotal States Created:\t" + totalStatesGenerated; msg += "\nTotal States Pruned:\t" + statesPruned; msg += "\nMax States Stored: \t" + maxStatesStored; MessageBox.Show(msg); return; }
public bool extend() { if (citiesLeft.Count() != 0) { foreach (int i in citiesLeft) { double initialCost = matrix[path.Last()][i] + cost; double[][] newMatrix = this.matrix.Select(a => a.ToArray()).ToArray(); for(int j = 0; j < matrix.Count(); j++) { newMatrix[path.Last()][j] = Double.PositiveInfinity; newMatrix[j][i] = Double.PositiveInfinity; } List<int> newPath = path.Select(a => a).ToList(); newPath.Add(i); List<int> newCitiesLeft = citiesLeft.Select(a => a).ToList(); newCitiesLeft.Remove(i); BBState state = new BBState(newMatrix, newPath, newCitiesLeft, initialCost); PriorityQueue.getInstance().insert(state); } return false; } else { cost = matrix[path.Last()][0] + cost; path.Add(0); return true; } }