//O(log|V|) - O(1) ops except for siftdown function. //Siftdown has same complexity as bubbleUp - O(log|V|) - for same reasons public SearchSpace Deletemin() { SearchSpace v = q[1]; //remember, q is 1-indexed //******** siftdown function **********// SearchSpace lastV = q.Last(); q.Remove(lastV); //trim last leaf if (NotEmpty()) { q[1] = lastV; //put last at root int currQi = 1; //sift the root down: int childQi = HighestPriorityChildQi(currQi); bool swap = (childQi == 0) ? false : (q[childQi].DepthRemaining == lastV.DepthRemaining) ? q[childQi].Bound < lastV.Bound : q[childQi].DepthRemaining < lastV.DepthRemaining; while (swap) //while current has children and //the distance of the smallest child < the distance of the previously last node { q[currQi] = q[childQi]; //put smallest child at current position currQi = childQi; //set current = smallest child childQi = HighestPriorityChildQi(currQi); //get new smallest child swap = (childQi == 0) ? false : (q[childQi].DepthRemaining == lastV.DepthRemaining) ? q[childQi].Bound < lastV.Bound : q[childQi].DepthRemaining < lastV.DepthRemaining; } q[currQi] = lastV; //put lastV in it's appropriate position } //********** end siftdown ************// return(v); }
//returns number of updates to BSSF made during the exploration private void explore(SearchSpace current, PriorityQ q) { List <int> citiesRemaining = current.CitiesRemaining; bool leaf = true; //O() foreach (int city in citiesRemaining) { leaf = false; SearchSpace child = new SearchSpace(current, city);//O(n^2) statesCreated++; if (child.Bound < costOfBssf()) { q.Insert(child); } else { statesPruned++; } } if (leaf) { TSPSolution possibleSoln = new TSPSolution(current.Route, Cities); if (possibleSoln.costOfRoute() < costOfBssf()) { bssf = possibleSoln; solutionsFound++; } } }
//O(log|V|) from BubbleUp. Other ops are O(1) public void Insert(SearchSpace v) { q.Add(v); BubbleUp(v); if (Count > maxCount) { maxCount = Count; } }
/// <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]; Stopwatch timer = new Stopwatch(); timer.Start(); double[,] graphMatrix = buildGraphMatrix(); defaultGetBSSF(); //replace with greedy or however you want to initialize BSSF //build cityIndices list. Stupid but need it List <int> cityIndices = initCityIndices(); //O(n) //Build the q with the initial searchSpace having {0} as it's current route PriorityQ q = new PriorityQ(); q.Makequeue(); //O(1) q.Insert(new SearchSpace(new List <int>(), cityIndices, 0, graphMatrix, 0, _size)); //O(log|V|) statesCreated++; //Branch and bound. //O(n^2n!) while (q.NotEmpty() && timer.ElapsedMilliseconds < 60 * 1000) //could run O(n!) times { SearchSpace curr = q.Deletemin(); //O(log|V|) if (curr.Bound < costOfBssf()) { explore(curr, q); } else { statesPruned++; } } timer.Stop(); results[COST] = costOfBssf().ToString(); // load results array results[TIME] = timer.Elapsed.ToString(); results[COUNT] = solutionsFound.ToString(); statesStoredMax = q.MaxCount; statesPruned += q.Count; return(results); }
//O(log|V|) - I use a look up array for the Q-index, so that's O(1). //There can be at most log|V| swaps (height of tree), and each swap does only O(1) ops. private void BubbleUp(SearchSpace v) { int Qi = q.IndexOf(v); int parentQi = Qi / 2; //swap represents if the child has higher priority than the parent //This is based on depth remaining unless equal. If equal, it's based on the bounds bool swap = (Qi == 1) ? false : (q[parentQi].DepthRemaining == v.DepthRemaining) ? q[parentQi].Bound > v.Bound : q[parentQi].DepthRemaining > v.DepthRemaining; while (swap) //while not at root and while parent's key is lower priority than inserted node's key { q[Qi] = q[parentQi]; //put parent in child's place Qi = parentQi; //increment current to parent's position parentQi = Qi / 2; //find parent of current's new position swap = (Qi == 1) ? false : (q[parentQi].DepthRemaining == v.DepthRemaining) ? q[parentQi].Bound > v.Bound : q[parentQi].DepthRemaining > v.DepthRemaining; } q[Qi] = v; //put v in it's appropriate position }
public SearchSpace(SearchSpace prevSS, int cityVisiting) : this(prevSS.Route, prevSS.citiesRemaining, prevSS.Bound, prevSS.Matrix, cityVisiting, prevSS.size) { }
//O(log|V|) - just calls BubbleUp public void OnKeyDecreased(SearchSpace v) { BubbleUp(v); }