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