public string[] fancySolveProblem() { string[] results = new string[3]; // implement simulated annealing string[] origResults = defaultSolveProblem(); double origCost = Convert.ToDouble(origResults[COST]); //City start = (City)Route[0]; double bestCostSoFar = origCost; double tempBestCost = origCost; int temperature = 10000; while (temperature != 0) { Random rand = new Random(); int random = rand.Next(0, Cities.Length); int random2 = rand.Next(0, Cities.Length); City one = (City)Route[random]; City two = (City)Route[random2]; ArrayList copyRoute = new ArrayList(); for (int i = 0; i < Route.Count; i++) { if (i == random) { copyRoute.Add(two); } else if (i == random2) { copyRoute.Add(one); } else { copyRoute.Add(Route[i]); } } TSPSolution temp = new TSPSolution(copyRoute); double var = temp.costOfRoute(); if (temp.costOfRoute() != Double.PositiveInfinity) { if (isAcceptable(tempBestCost, temp.costOfRoute(), temperature)) { Route = copyRoute; tempBestCost = temp.costOfRoute(); if (tempBestCost < bestCostSoFar) { bestCostSoFar = tempBestCost; bssf = temp; } } } temperature -= 5; } results[COST] = bssf.costOfRoute().ToString(); // load results into array here, replacing these dummy values results[TIME] = "-1"; results[Count] = "-1"; return(results); }
public string[] greedySolveProblem() { string[] results = new string[3]; var watch = System.Diagnostics.Stopwatch.StartNew(); for (int i = 0; i < Cities.Length; i++) { TSPSolution temp = greedySolveProblem(i); double tempLength = temp.costOfRoute(); double bssfLength = costOfBssf(); if (bssf == null) { bssf = temp; } else { if (temp.costOfRoute() < costOfBssf()) { bssf = temp; } } } results[COST] = bssf.costOfRoute().ToString(); // load results into array here, replacing these dummy values results[TIME] = watch.Elapsed.ToString(); results[COUNT] = "1"; return(results); }
/// <summary> /// return the cost of the best solution so far. /// </summary> /// <returns></returns> public double costOfBssf() { if (bssf != null) { return(bssf.costOfRoute()); } else { return(-1D); } }
/// <summary> /// return the cost of the best solution so far. /// </summary> /// <returns></returns> public double costOfBssf() { if (bssf != null) { return(bssf.costOfRoute()); } else { return(Double.PositiveInfinity); } }
public void solveProblem() { timer = new Stopwatch(); timer.Start(); counter = 0; max = 0; Console.Out.WriteLine(); initializeSolver(); stack.Push(new TSPSolution(Cities[0])); bool debug = true; while (stack.Count != 0 && (timer.Elapsed.TotalSeconds <= 20 || debug)) { counter++; if (stack.Count > max) { max = stack.Count; } updateUI(); TSPSolution parent = stack.Pop(); if (parent.getBound() >= bssf.costOfRoute()) { continue; } //if (parent.isCrossed()) // continue; List <TSPSolution> children = parent.makeChildren(); foreach (TSPSolution child in children) { if (child.getBound() < bssf.costOfRoute()) { if (child.isSolution()) { Console.Out.WriteLine("Solution: {0}", child.costOfRoute()); bssf = child; } else { stack.Push(child); } } // else discard it (don't explore) } } timer.Stop(); updateUI(); }
/// <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(); //Obtain a BSSF by using a GREEDY approach. int startCity = 0; bssf = new TSPSolution(GenerateInitialBSSF(ref startCity)); //Make an initial Matrix int cityCount = Cities.Length; double[,] initialMatrix = GetInitialMatrix(cityCount); //Put start city in list ArrayList startingRoute = new ArrayList(); startingRoute.Add(Cities[startCity]); //Make Start node int lowerBound = 0; List <bool> citiesVisited = InitializeCitiesVisitedList(startCity, cityCount); NodeState startNode = new NodeState(initialMatrix, lowerBound, startingRoute, startCity, citiesVisited); startNode.ReduceMatrixAndUpdateLowerBound(cityCount); Console.WriteLine("Initial BSSF: " + bssf.costOfRoute().ToString()); List <NodeState> priorityQueue = new List <NodeState>(); priorityQueue.Add(null); priorityQueue.Add(startNode); //Now we are ready to execute the branch and bound algorithm int MaxNodeStateAmount = 1; int BSSFupdates = 0; int TotalNodeStates = 1; int TotalNodeStatesPrunned = 0; BranchAndBound(ref priorityQueue, ref MaxNodeStateAmount, ref BSSFupdates, ref TotalNodeStates, ref TotalNodeStatesPrunned, startCity, ref timer); timer.Stop(); Console.WriteLine("Max NodeState Amount: " + MaxNodeStateAmount.ToString()); Console.WriteLine("Total Node States: " + TotalNodeStates.ToString()); Console.WriteLine("Total Node States Prunned: " + TotalNodeStatesPrunned.ToString() + "\r\n"); results[COST] = bssf.costOfRoute().ToString(); results[TIME] = timer.Elapsed.ToString(); results[COUNT] = BSSFupdates.ToString(); return(results); }
/// <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() { stopwatch = new Stopwatch(); stopwatch.Start(); bssf = generateInitialBSSF(); State s = initState(); agenda = new PriorityQueue <double, State>(); agenda.Add(new KeyValuePair <double, State>(s.boundValue / s.path.Count, s)); maxSize = 0; while (!agenda.IsEmpty && stopwatch.ElapsedMilliseconds < 60000 && bssf.costOfRoute() != s.boundValue) { if (agenda.Count > maxSize) { maxSize = agenda.Count; } State u = agenda.Dequeue().Value; if (u.boundValue < bssf.costOfRoute()) { if (stopwatch.ElapsedMilliseconds % 5000 == 0) { updateUI(); } ArrayList children = generateChildren(u); foreach (State w in children) { if (w.boundValue < bssf.costOfRoute()) { if (w.path.Count == Cities.Length) { bssf = bssfFromIntArray(w.path); myBssf = (int[])w.path.ToArray(System.Type.GetType("System.Int32")); while (updateBssf(myBssf)) { ; } updateUI(); } else { agenda.Add(new KeyValuePair <double, State>(w.boundValue / w.path.Count, w)); } } } } } updateUI(); }
//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++; } } }
public string[] fancySolveProblem() { string[] results = new string[3]; //set initial bssf initialBssf = true; greedySolveProblem(); //defaultSolveProblem(); Console.WriteLine("---------------"); Console.WriteLine("Initial bssf cost: " + bssf.costOfRoute().ToString()); Stopwatch timer = new Stopwatch(); // TODO bssf = output of greedy algorithm int numCities = Cities.Length; int solutions = 0; bool improved = true; timer.Start(); // while(bestChild.route < bssf.route while (improved) { long time = timer.ElapsedMilliseconds; if (time > time_limit) { Console.WriteLine("Fancy timed out"); break; } improved = false; for (int i = 0; i < numCities - 1; i++) { for (int k = 0; k < numCities - 1; k++) { if (i == k) { continue; } // swap i and k TSPSolution checkSolution = swap(i, k); solutions++; double cost = checkSolution.costOfRoute(); // check to see if it's a better solution than best child if (cost < bssf.costOfRoute()) { // if so, set best child be a solutionn bssf = checkSolution; improved = true; } //if didn't improve, found local optimum } } } Console.WriteLine("K-opt cost: " + bssf.costOfRoute().ToString()); Console.WriteLine("Number of solutions: " + solutions); timer.Stop(); results[COST] = bssf.costOfRoute().ToString(); // load results into array here, replacing these dummy values results[TIME] = timer.Elapsed.TotalSeconds.ToString(); results[COUNT] = solutions.ToString(); return(results); }
public string[] fancySolveProblem() { string[] results = new string[3]; Stopwatch timer = new Stopwatch(); int i, swap, temp, count = 0; int[] perm = new int[Cities.Length]; Route = new ArrayList(); Random rnd = new Random(); timer.Start(); const int ITERATIONS = 1000000; for (int iteration = 0; iteration < ITERATIONS; ++iteration) { do { for (i = 0; i < perm.Length; i++) // create a random permutation template { perm[i] = i; } for (i = 0; i < perm.Length; i++) { swap = i; while (swap == i) { swap = rnd.Next(0, Cities.Length); } temp = perm[i]; perm[i] = perm[swap]; perm[swap] = temp; } Route.Clear(); for (i = 0; i < Cities.Length; i++) // Now build the route using the random permutation { Route.Add(Cities[perm[i]]); } TSPSolution solution = new TSPSolution(Route); if (solution.costOfRoute() < costOfBssf() || costOfBssf() == -1) { bssf = solution; } count++; } while (costOfBssf() == double.PositiveInfinity); // until a valid route is found } timer.Stop(); results[COST] = costOfBssf().ToString(); // load results array results[TIME] = timer.Elapsed.ToString(); results[COUNT] = count.ToString(); return(results); }
/// <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() { IDictionary <Tuple <City, City>, double> EdgeRatings = RateEdges(); Route = FindRoute(EdgeRatings); bssf = new TSPSolution(Route); // update the cost of the tour. Program.MainForm.tbCostOfTour.Text = " " + bssf.costOfRoute(); // do a refresh. Program.MainForm.Invalidate(); }
public double getFinalTourLength(City[] cities) { try { TSPSolution solution = new TSPSolution(indexToCities(cities, pathSoFar)); return(solution.costOfRoute()); } catch { return(Double.PositiveInfinity); } }
/// <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 solveProblemBAndB() {//O((2^(8n^2 + 9n + 2log(n)))(2^n)) == O((n^2)(2^n) BranchAndBound branchAndBoundAlgorithm = new BranchAndBound(); Route = branchAndBoundAlgorithm.RunTSP(Cities); bssf = new TSPSolution(Route); Program.MainForm.tbCostOfTour.Text = " " + bssf.costOfRoute(); Program.MainForm.tbElapsedTime.Text = branchAndBoundAlgorithm.bAndBTime.TotalSeconds.ToString(); Program.MainForm.tspOther.Text = "maxQueueCount: " + branchAndBoundAlgorithm.maxQueueCount + ", bssfUpdatesAmt: " + branchAndBoundAlgorithm.bssfUpdatesAmt + ", totalStatesCreated: " + branchAndBoundAlgorithm.totalStatesCreated + ", prunedAmt: " + branchAndBoundAlgorithm.prunedAmt + ", time: " + branchAndBoundAlgorithm.bAndBTime.TotalSeconds.ToString() + ", cost: " + bssf.costOfRoute(); // do a refresh. Program.MainForm.Invalidate(); }
public void solveProblemGreedy() { Greedy greedyAlgorithm = new Greedy(Cities); Route = greedyAlgorithm.RunGreedyTSP(); bssf = new TSPSolution(Route); // update the cost of the tour. Program.MainForm.tbCostOfTour.Text = " " + bssf.costOfRoute(); Program.MainForm.tbElapsedTime.Text = greedyAlgorithm.time.TotalSeconds.ToString(); // do a refresh. Program.MainForm.Invalidate(); }
//TODO - BROKEN/INCORRECT //returns number of solutions considered private int greedyCalcBSSF() { defaultGetBSSF(); //for each starting city: //Route.add(startingCityIndex) //for cities remaining //get the smallest outgoing edge and add that to route //remove it from cities remaining //if this route's cost is < costBSSF //bssf = this route's soln int solutionsConsidered = 0; for (int i = 0; i < _size; i++) { Route.Add(i); List <int> citiesRemaining = initCityIndices(); citiesRemaining.Remove(i); //build greedy route for starting city Cities[i] while (citiesRemaining.Count > 0) { //get closest edge int minCity = citiesRemaining[0]; double minCost = Cities[Route.Last()].costToGetTo(Cities[minCity]); for (int c = 1; c < citiesRemaining.Count; c++) { double costToC = Cities[Route.Last()].costToGetTo(Cities[c]); if (costToC < minCost) { minCity = c; minCost = costToC; } } //add closest edge to route and remove from remaining cities Route.Add(minCity); citiesRemaining.Remove(minCity); } //keep if it's better than BSSF TSPSolution candidate = new TSPSolution(Route, Cities); if (candidate.costOfRoute() < costOfBssf()) { bssf = candidate; solutionsConsidered++; } } return(solutionsConsidered); }
/// <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); }
/// <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() { int x; Route = new ArrayList(); // this is the trivial solution. for (x = 0; x < Cities.Length; x++) { Route.Add(Cities[Cities.Length - x - 1]); } // call this the best solution so far. bssf is the route that will be drawn by the Draw method. bssf = new TSPSolution(Route); // update the cost of the tour. Program.MainForm.tbCostOfTour.Text = " " + bssf.costOfRoute(); // do a refresh. Program.MainForm.Invalidate(); }
public void random() { // start our timer System.Diagnostics.Stopwatch timer = new System.Diagnostics.Stopwatch(); timer.Start(); Route = new ArrayList(); // this is the trivial solution. for (int x = 0; x < Cities.Length; x++) { Route.Add(Cities[x]); } // call this the best solution so far. bssf is the route that will be drawn by the Draw method. bssf = new TSPSolution(Route); Program.MainForm.tbCostOfTour.Text = "" + bssf.costOfRoute(); Program.MainForm.tbElapsedTime.Text = Convert.ToString(timer.Elapsed); }
public string[] fancySolveProblem() { string[] results = new string[3]; var watch = System.Diagnostics.Stopwatch.StartNew(); pher = new double[Cities.Length, Cities.Length]; int iteration = 0; int updates = 0; initializePher(); while (iteration < NUM_ITERATIONS) { initializeAnts(); for (int i = 0; i < numAnts; i++) { doCircut(ants[i]); } PherDecay(); pherUpdate(); TSPSolution tempSolution = getShortestTour(); if (bssf == null) { updates++; bssf = tempSolution; } if (tempSolution.costOfRoute() <= bssf.costOfRoute()) { updates++; bssf = tempSolution; } iteration++; } watch.Stop(); results[COST] = bssf.costOfRoute().ToString(); // load results into array here, replacing these dummy values results[TIME] = watch.Elapsed.ToString(); results[COUNT] = updates.ToString(); return(results); }
// quick_solution, not using initial state cost matrix public void quick_solution() { int x; int currIndex = 0; Route = new ArrayList(); //Get the next neighbor greedily based on lowest cost //While our Route list size is less than the number of cities (meaning we finish once we get to all the cities) while (Route.Count < Cities.Length) { //Get an arbitrarily large minimum cost minCost = double.MaxValue; //Loop through all the cities to find the one with the least cost for (x = 0; x < Cities.Length; x++) { //Make sure we're not trying to check against ourself, because that would definitely be the minimum cost and kind of ruin this whole thing..... if (x != currIndex) { //Make sure the Route list doesn't already contain the city we're trying to add. If it does, it won't be a tour so we don't want to use it again if (!Route.Contains(Cities[x])) { //Get the cost from the current index to the next index. If it's less than what we have, make the 'minCost' equal to our 'currCost' and choose our new minimum index currCost = Cities[currIndex].costToGetTo(Cities[x]); if (currCost < minCost) { minCost = currCost; minIndex = x; } } } } //Once we found the city with the lowest cost that is still not in the tour, we have to add that city to our Route currIndex = minIndex; Route.Add(Cities[currIndex]); } //Once we have a complete tour, we need to calculate the cost of it and make it our initial BSSF bssf = new TSPSolution(Route); BSSF = bssf.costOfRoute(); }
public void randomSolve() { timer = new Stopwatch(); timer.Start(); Random rand = new Random(); double randNum = rand.Next(0, Cities.Length); Route = new ArrayList(Cities.Length); List <double> randNums = new List <double>(); randNums.Add(randNum); Route.Add(Cities[Convert.ToInt32(randNum)]); for (int i = 0; i < Cities.Length - 1; i++) { int startNode = Convert.ToInt32(randNums[randNums.Count - 1]); int size = randNums.Count; while (size == randNums.Count) { randNum = rand.Next(0, Cities.Length); if (randNums.Contains(randNum) || Cities[startNode].costToGetTo(Cities[Convert.ToInt32(randNum)]) == double.PositiveInfinity) { randNum = rand.Next(0, Cities.Length); } else { randNums.Add(randNum); Route.Add(Cities[Convert.ToInt32(randNum)]); } } } bssf = new TSPSolution(Route); // update the cost of the tour. Program.MainForm.tbCostOfTour.Text = " " + bssf.costOfRoute(); TimeSpan ts = timer.Elapsed; Program.MainForm.tbElapsedTime.Text = ts.TotalSeconds.ToString(); // do a refresh. Program.MainForm.Invalidate(); }
///////////////////////////////////////////////////////////////////////////////////////////// // These additional solver methods will be implemented as part of the group project. //////////////////////////////////////////////////////////////////////////////////////////// /// <summary> /// finds the greedy tour starting from each city and keeps the best (valid) one /// </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[] greedySolveProblem() { //this function is pretty simple really just an n^2 complexity due to the two for loops and n for space for the path I need. Stopwatch timer = new Stopwatch(); timer.Start(); HashSet <City> alreadyvisted = new HashSet <City>(); string[] results = new string[3]; City currentcity = Cities[0]; City BestCity = Cities[1]; Route.Clear(); for (int i = 0; i < Cities.Length; i++) { int number = -1; for (int j = 0; j < Cities.Length; j++) { if (!Route.Contains(Cities[j])) { if (currentcity.costToGetTo(Cities[j]) < currentcity.costToGetTo(BestCity)) { BestCity = Cities[j]; number = j; } } } currentcity = BestCity; Route.Add(currentcity); BestCity = new City(100000000, 10000000); } bssf = new TSPSolution(Route); timer.Stop(); results[COST] = Convert.ToString(bssf.costOfRoute()); // load results into array here, replacing these dummy values results[TIME] = Convert.ToString(timer.Elapsed.TotalSeconds); results[COUNT] = "1"; return(results); }
private GSCitizen getRandomSolution() { int i, swap, temp, count = 0; string[] results = new string[3]; int[] perm = new int[Cities.Length]; ArrayList solution = new ArrayList(); TSPSolution tspSolution; List <int> route = new List <int>(); do { for (i = 0; i < perm.Length; i++) // create a random permutation template { perm[i] = i; } for (i = 0; i < perm.Length; i++) { swap = i; while (swap == i) { swap = rnd.Next(0, Cities.Length); } temp = perm[i]; perm[i] = perm[swap]; perm[swap] = temp; } solution.Clear(); for (i = 0; i < Cities.Length; i++) // Now build the route using the random permutation { solution.Add(Cities[perm[i]]); route.Add(perm[i]); } tspSolution = new TSPSolution(solution); count++; } while (tspSolution.costOfRoute() == double.PositiveInfinity); // until a valid route is found return(new GSCitizen(route)); }
//Creates an initial path greedily. Time complexity is O(n^2) because it goes through each city (or edge) in the list to find the smallest edge cost. //Space complexity is O(n) because it creates a list the size of the number of cities. private double createGreedyBssf() { Route = new ArrayList(); Route.Add(Cities[0]); int currCityIndex = 0; while (Route.Count < Cities.Length) { double minVal = double.MaxValue; int minIndex = 0; for (int i = 0; i < Cities.Length; i++) { if (currCityIndex != i) { if (!Route.Contains(Cities[i])) { double currCost = Cities[currCityIndex].costToGetTo(Cities[i]); if (currCost < minVal) { if (Route.Count == Cities.Length - 1 && Cities[i].costToGetTo(Cities[0]) == double.MaxValue) { continue; } minVal = currCost; minIndex = i; } } } } currCityIndex = minIndex; Route.Add(Cities[currCityIndex]); } bssf = new TSPSolution(Route); return(bssf.costOfRoute()); }
/// <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() { int x; Route = new ArrayList(); // this is the trivial solution. for (x = 0; x < Cities.Length; x++) { Route.Add(Cities[Cities.Length - x - 1]); } bssf = new TSPSolution(Route); double bssfCost = bssf.costOfRoute(); BranchAndBound bBound = new BranchAndBound(Cities, bssfCost); PathCalculation result = bBound.CalculatePath(); City[] path = result.Cities; if (path != null) { bssf = new TSPSolution(new ArrayList(path)); bssfCost = bssf.costOfRoute(); } // PLEASE NOTE: If the program times out, then the "TIMED OUT" flag will appear. Program.MainForm.tbElapsedTime.Text = (path == null && result.ElapsedTime > (30 * 1000) ? "TIMED OUT: " : "") + result.ElapsedTime / 1000; Program.MainForm.tbNumberOfSolutions.Text = (path == null ? 0 : result.NumberOfBSSFUpdates).ToString(); // update the cost of the tour. Program.MainForm.tbCostOfTour.Text = " " + bssfCost; // do a refresh. Program.MainForm.Invalidate(); }
/// <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()); }
public string[] fancySolveProblem() { string[] results = new string[3]; Stopwatch timer = new Stopwatch(); timer.Start(); ArrayList[] population = new ArrayList[population_size]; //Get initial population for (int i = 0; i < population_size; i++) { defaultSolveProblem(); population[i] = bestIndexRoute; } Console.WriteLine(population); RouletteWheel wheel = new RouletteWheel(population, Cities); int generations = 0; while (timer.ElapsedMilliseconds <= time_limit) { generations++; ArrayList[] newPopulation = new ArrayList[population_size]; for (int i = 0; i < population_size - 10; i++) { ArrayList parent = wheel.getRandomMember(); int[] childArr = crossingOver(convertToArr(parent)); ArrayList child = new ArrayList(); child.AddRange(childArr); if (isValidRoute(child)) { newPopulation[i] = child; } else { i--; } } // select a few parents to live on for (int i = population_size - 10; i < population_size; i++) { ArrayList parent = wheel.getRandomMember(); newPopulation[i] = parent; } population = newPopulation; } Console.WriteLine("generations: " + generations); timer.Stop(); ArrayList bestSolution = new ArrayList(); foreach (int index in new RouletteWheel(population, Cities).getBestMember()) { bestSolution.Add(Cities[index]); } bssf = new TSPSolution(bestSolution); results[COST] = bssf.costOfRoute().ToString(); // load results into array here, replacing these dummy values results[TIME] = timer.Elapsed.ToString(); 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> // This algorithm implements a greedy approach, 10,000 random attempts, and the branch and bound approach with pruning of leaf // nodes that have values grater than the current BSSF. // O = greedy + 10,000*random + branch and bound // = O(n^3 + 10000*n + (2^n)*(n^2) = O((n^2)*(2^n)) public string[] bBSolveProblem() { // initialize the variables int count = 0; string[] results = new string[3]; int[] perm = new int[Cities.Length]; Route = new ArrayList(); Stopwatch timer = new Stopwatch(); int maxStates = 0; int totalStates = 0; int statesPruned = 0; // start the timer timer.Start(); // start BSSF as positive infinity; double currSol = Double.PositiveInfinity; // see if the BSSF updates with the greedy algorithm // Finding greedy solution = O(n^3) double greedySol = Convert.ToDouble(greedySolveProblem()[0]); if (greedySol < currSol) { currSol = greedySol; count += 1; } // attempt updating the BSSF with 10,000 random solutions // finding random solution = O(n) for (int cycleRand = 0; cycleRand < 10000; cycleRand++) { double tempSol = Convert.ToInt32(defaultSolveProblem()[0]); if (tempSol < currSol) { currSol = tempSol; count += 1; } } // create the List of nodes List <DistMatrix> children = new List <DistMatrix>(); // initialize the first node in the list (root node) children.Add(new DistMatrix(Cities)); // while there are nodes in the node list while (children.Count > 0) { // check if the timer has passed 60 seconds timer.Stop(); long time = timer.ElapsedMilliseconds / 1000; if (time >= 60) { // if it has passed 60 seconds, break out of the while loop break; } timer.Start(); // Find the next node - O(n) if (maxStates < children.Count) { maxStates = children.Count; } // collect the variables to find the best child node DistMatrix currNode = children[0]; double best = children[0].b; int numVisited = children[0].visited.Count; // for each child node, check if it is optimal for (int i = 0; i < children.Count; i++) { double value = children[i].b; int visited = children[i].visited.Count; double diffValue = value - best; int diffVisit = visited - numVisited; // used this little algorithm to try and balance breadth and depth if (value < best * (1 + (diffVisit / .75))) { currNode = children[i]; best = children[i].b; numVisited = children[i].visited.Count; } } // remove that node from the list of possiblities children.RemoveAt(children.IndexOf(currNode)); // if the child node has not reached the end if (!currNode.finished()) { // get the list of nodes that haven't been visited List <int> nextChildren; nextChildren = currNode.returnNodesLeft(); // create a child object for each of those nodes - O(n^2) happening 2^n times // for the worst case scenario where each leaf must be reached in the tree. // This gives a O((n^2)*(2^n)) for (int i = 0; i < nextChildren.Count; i++) { DistMatrix child = new DistMatrix(nextChildren[i], currNode); children.Add(new DistMatrix(nextChildren[i], currNode)); totalStates += 1; } } // if the node is a leaf, check if it's better than the current BSSF //O(n) to check each one, with O(n) to check if any need removing after // an update on the BSSF. else { if (currNode.b < currSol) { // if it is better, replace the current BSSF ArrayList tempRoute = buildRoute(currNode.visited); TSPSolution test = new TSPSolution(tempRoute); if (test.costOfRoute() < currSol) { Route.Clear(); Route = buildRoute(currNode.visited); bssf = null; bssf = new TSPSolution(Route); currSol = costOfBssf(); count += 1; } // filter any children that has a b greater than the current bssf. // remove those children in hopes of speeding up the algorithm } } for (int i = 0; i < children.Count; i++) { if (children[i].b > currSol) { children.RemoveAt(i); statesPruned += 1; i--; } } } // Stop the time and report the results. timer.Stop(); results[COST] = costOfBssf().ToString(); // load results array results[TIME] = timer.Elapsed.ToString(); results[COUNT] = count.ToString(); Console.WriteLine("Max States: {0}, Total States: {1}, Total Pruned: {2}", maxStates, totalStates, statesPruned); return(results); }
///////////////////////////////////////////////////////////////////////////////////////////// // These additional solver methods will be implemented as part of the group project. //////////////////////////////////////////////////////////////////////////////////////////// /// <summary> /// finds the greedy tour starting from each city and keeps the best (valid) one /// </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[] greedySolveProblem() { string[] results = new string[3]; double bestCost = double.MaxValue; this.bssf = null; int count = 0; Stopwatch timer = new Stopwatch(); timer.Start(); for (int i = 0; i < Cities.Length; i++) { if (timer.ElapsedMilliseconds >= time_limit) { break; } ArrayList citiesLeft = new ArrayList(Cities); ArrayList route = new ArrayList(); City currentCity = (City)citiesLeft[i]; citiesLeft.RemoveAt(i); route.Add(currentCity); while (citiesLeft.Count > 0) { double minDistance = Double.PositiveInfinity; City nextCity = null; for (int j = 0; j < citiesLeft.Count; j++) { City city = (City)citiesLeft[j]; double distance = currentCity.costToGetTo(city); if (distance < minDistance) { minDistance = distance; nextCity = city; } } if (nextCity == null) { break; } else { route.Add(nextCity); citiesLeft.Remove(nextCity); currentCity = nextCity; } } if (route.Count == Cities.Length) { TSPSolution tour = new TSPSolution(route); if (tour.costOfRoute() < bestCost) { count++; this.bssf = tour; bestCost = tour.costOfRoute(); } } } timer.Stop(); results[COST] = costOfBssf().ToString(); // load results into array here, results[TIME] = timer.Elapsed.ToString(); results[COUNT] = count.ToString(); return(results); }
//**********************************************BBAlgorithm********************************************************************************* /// <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]; // TODO: Add your implementation for a branch and bound solver here. //Initalize variables. Takes O(1) space and time int numOfCitiesLeft = Cities.Length; int numOfSolutions = 0; int numOfStatesCreated = 0; int numOfStatesNotExpanded = 0; //Initalize time variable for stopping the algorithm after the default of 60 seconds. Takes O(1) space and time DateTime start = DateTime.Now; DateTime end = start.AddSeconds(time_limit / 1000); //Create initial root state and set its priority to its lower bound. Takes O(n^2) space and time as discussed above TSPState initialState = createInitialState(); numOfStatesCreated++; initialState.setPriority(calculateKey(numOfCitiesLeft - 1, initialState.getLowerBound())); //Create initial BSSF greedily double bssfBound = createGreedyBssf(); PriorityQueue queue = new PriorityQueue(Cities.Length); queue.insert(initialState); // Branch and Bound until the queue is empty, we have exceeded the time limit, or we found the optimal solution /* This loop will have a iterate 2^n times approximately with expanding and pruning for each state, then for each state it * does O(n^2) work by reducing the matrix, so over all O((n^2)*(2^n)) time and space as well as it creates a nxn * matrix for each state*/ while (!queue.isEmpty() && DateTime.Now < end && queue.getMinLB() != bssfBound) { // Grab the next state in the queue TSPState currState = queue.deleteMin(); // check if lower bound is less than the BSSF, else prune it if (currState.getLowerBound() < bssfBound) { // Branch and create the child states for (int i = 0; i < Cities.Length; i++) { // First check that we haven't exceeded the time limit if (DateTime.Now >= end) { break; } // Make sure we are only checking cities that we haven't checked already if (currState.getPath().Contains(Cities[i])) { continue; } // Create the State double[,] oldCostMatrix = currState.getCostMatrix(); double[,] newCostMatrix = new double[Cities.Length, Cities.Length]; // Copy the old array in the new one to modify the new without affecting the old for (int k = 0; k < Cities.Length; k++) { for (int l = 0; l < Cities.Length; l++) { newCostMatrix[k, l] = oldCostMatrix[k, l]; } } City lastCityinCurrState = (City)currState.getPath()[currState.getPath().Count - 1]; double oldLB = currState.getLowerBound(); setUpMatrix(ref newCostMatrix, Array.IndexOf(Cities, lastCityinCurrState), i, ref oldLB); double newLB = oldLB + reduceMatrix(ref newCostMatrix); ArrayList oldPath = currState.getPath(); ArrayList newPath = new ArrayList(); foreach (City c in oldPath) { newPath.Add(c); } newPath.Add(Cities[i]); TSPState childState = new TSPState(ref newPath, ref newLB, ref newCostMatrix); numOfStatesCreated++; // Prune States larger than the BSSF if (childState.getLowerBound() < bssfBound) { City firstCity = (City)childState.getPath()[0]; City lastCity = (City)childState.getPath()[childState.getPath().Count - 1]; double costToLoopBack = lastCity.costToGetTo(firstCity); // If we found a solution and it goes back from last city to first city if (childState.getPath().Count == Cities.Length && costToLoopBack != double.MaxValue) { childState.setLowerBound(childState.getLowerBound() + costToLoopBack); bssf = new TSPSolution(childState.getPath()); bssfBound = bssf.costOfRoute(); numOfSolutions++; numOfStatesNotExpanded++; // this state is not expanded because it is not put on the queue } else { // Set the priority for the state and add the new state to the queue numOfCitiesLeft = Cities.Length - childState.getPath().Count; childState.setPriority(calculateKey(numOfCitiesLeft, childState.getLowerBound())); queue.insert(childState); } } else { numOfStatesNotExpanded++; // States that are pruned are not expanded } } } currState = null; } numOfStatesNotExpanded += queue.getSize(); // if the code terminated before queue is empty, then those states never got expanded Console.WriteLine("Number of states generated: " + numOfStatesCreated); Console.WriteLine("Number of states not Expanded: " + numOfStatesNotExpanded); Console.WriteLine("Max Number of states put in queue: " + queue.getMaxNumOfItems()); end = DateTime.Now; TimeSpan diff = end - start; double seconds = diff.TotalSeconds; results[COST] = System.Convert.ToString(bssf.costOfRoute()); // load results into array here, replacing these dummy values results[TIME] = System.Convert.ToString(seconds); results[COUNT] = System.Convert.ToString(numOfSolutions); return(results); }