void addsubproblems(double [,] oldgraph, int row, int col, ref HashSet <Subproblem> priorityqueue, Subproblem currentnodetoadd, int location, double addcosttogethere, double bestscore, ref int numberofstatescreated, ref int numberofstatespruned) //adds thing to the queue { if (currentnodetoadd.score > bestscore) //pruning measure { numberofstatespruned++; return; } if (currentnodetoadd.mylist.Contains(location))//don't go inloops forever { return; } if (addcosttogethere == Double.PositiveInfinity)//another pruning measure { numberofstatespruned++; return; } double[,] newgraph = updatethegraph(oldgraph, row, col);//create new seprate graph an n^2 +n operation for time and n for space List <int> mylist = new List <int>(); mylist.AddRange(currentnodetoadd.mylist); Subproblem temp = new Subproblem(currentnodetoadd.score, newgraph, mylist, location); double lowerbound = normalizearray(ref temp.mygraph);//update graph an n^2+n operation and get lowerbound temp.score += lowerbound; temp.score += addcosttogethere; temp.mylist.Add(location); numberofstatescreated++; priorityqueue.Add(temp); }
/// <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() { int numberofupdates = 0; Stopwatch timer = new Stopwatch(); timer.Start(); HashSet <Subproblem> priorityqueue = new HashSet <Subproblem>(); //my pq is a simple list string[] results = new string[3]; double[,] mygraph = new double[Cities.Length, Cities.Length]; //graph is a simple 2d array for (int x = 0; x < Cities.Length; x++) //this sets up the intial matrix which is insignificant in the grad scheme of things. it would be n^2 for the number of cities but this is only done once so its constant { for (int y = 0; y < Cities.Length; y++) { if (x == y) { mygraph[x, y] = Double.PositiveInfinity; } else { mygraph[x, y] = Cities[x].costToGetTo(Cities[y]); } } } double lowerbound = normalizearray(ref mygraph); //call my normalize function which is big o(n^2) List <int> path = new List <int>(); path.Add(0); Subproblem currentsubproblem = new Subproblem(lowerbound, mygraph, path, 0); priorityqueue.Add(currentsubproblem); double bestscore = Convert.ToDouble(greedySolveProblem()[COST]); //call the greedy function which is n^2 to get a nice lower cost hopefully. int numberofstatescreated = 0; int numberofstatespruned = 0; int maxiumumpqsize = 0; while (priorityqueue.Count > 0) //While we can keep checking things { if (timer.Elapsed.TotalSeconds > TIME_LIMIT) { break; } for (int i = 1; i < Cities.Length; i++) //n for the number of cities for time and also n subproblems each with n^2 matrices for space { addsubproblems(currentsubproblem.mygraph, currentsubproblem.location, i, ref priorityqueue, currentsubproblem, i, currentsubproblem.mygraph[currentsubproblem.location, i], bestscore, ref numberofstatescreated, ref numberofstatespruned); //adds problems to explore see the function for description and analysis } if (priorityqueue.Count > maxiumumpqsize) { maxiumumpqsize = priorityqueue.Count; } priorityqueue.Remove(currentsubproblem);//get rid of element we don't need if (priorityqueue.Count == 0) { break;//escape if we get to 0 stuff } Subproblem bestone = new Subproblem(Double.MaxValue, null, path, -1); foreach (Subproblem s in priorityqueue) //n operation to get best element off of prioirty queue NOT the most efficient but still works. { if (s.score / (s.mylist.Count * 2) < bestone.score / (bestone.mylist.Count * 2)) { bestone = s; } } currentsubproblem = bestone; if (currentsubproblem.mylist.Count == Cities.Length)//if we have a potential solution { Console.WriteLine("a solution approaches"); for (int i = 0; i < currentsubproblem.mylist.Count; i++) { Console.WriteLine(currentsubproblem.mylist[i]); } if (currentsubproblem.score < bestscore && Cities[currentsubproblem.mylist[currentsubproblem.mylist.Count - 1]].costToGetTo(Cities[currentsubproblem.mylist[0]]) != Double.PositiveInfinity) //a check to see if we have a better score { numberofupdates++; bestscore = currentsubproblem.score; path = currentsubproblem.mylist; } if (Cities[currentsubproblem.mylist[currentsubproblem.mylist.Count - 1]].costToGetTo(Cities[currentsubproblem.mylist[0]]) == Double.PositiveInfinity)//bad if an infinity sneaks through { numberofstatespruned++; } } } Route.Clear(); if (path.Count != Cities.Length) { Console.WriteLine("failure"); //aka I wasn't able to get anything better then the GREEDY APROACH. } else { //converts my path route into its equivalent City Route. Just a constant time based on the number of Cities n SO pretty insigninficant. for (int i = 0; i < path.Count; i++) { Console.WriteLine(path[i]); Route.Add(Cities[path[i]]); } bssf = new TSPSolution(Route); } timer.Stop(); //print out my results for the table in the write up Console.WriteLine("My maximum queue size is " + maxiumumpqsize); Console.WriteLine("My maximum number of states created " + numberofstatescreated); Console.WriteLine("My maximum number of prunings I do is " + numberofstatespruned); results[COST] = Convert.ToString(bestscore); results[TIME] = timer.Elapsed.ToString(); results[COUNT] = Convert.ToString(numberofupdates); return(results); }