public State makeExclude(int x, int y, State state) //O(n^2) { State excludeState = new State(copyMatrix(state.getMap()), state.getLB(), state.getEdges()); //O(n^2) excludeState.setPoint(x, y, double.PositiveInfinity); //make chosen point infinity reduceMatrix(excludeState); //O(n^2) excludeState.setEdges(state.getEdges()); //initialize excludeStates edges return(excludeState); }
public bool isDictionaryFilled(State state) //O(n) { //returns whether or not the all of the edges have been added for (int i = 0; i < state.getEdges().Count; i++) { if (state.getEdge(i) == -1) { return(false); //if one hasn't been added, then it isn't full } } return(true); }
public void checkCycles(State state, int i, int j) //O(n) { Dictionary <int, int> edges = new Dictionary <int, int>(state.getEdges()); if (getDictionarySize(edges) == edges.Count) //if the dictionary is full, stop { return; } int[] entered = new int[edges.Count]; int[] exited = new int[edges.Count]; for (int x = 0; x < entered.Length; x++) //O(n) { entered[x] = -1; } for (int x = 0; x < edges.Count; x++) //O(n) { exited[x] = edges[x]; if (exited[x] != -1) { entered[exited[x]] = x; } } //the two loops above "flip" the arrays with value and index, e.g. if //entered contained [0]=2, [1]=0, [2]=1 //exited will now contain [0]=1, [1]=2, [2]=0 entered[j] = i; exited[i] = j; int start = i; int end = j; while (exited[end] != -1) //O(n) { end = exited[end]; } while (entered[start] != -1)//O(n) { start = entered[start]; } if (getDictionarySize(edges) != edges.Count - 1) //if there is only one point left to fill, { //this will think there is a cycle, so make while (start != j) //O(n) make sure there isn't one element left { state.setPoint(end, start, double.PositiveInfinity); state.setPoint(j, start, double.PositiveInfinity); start = exited[start]; } } }
public State makeInclude(int x, int y, State state) //O(n^2) { State includeState = new State(copyMatrix(state.getMap()), state.getLB(), state.getEdges()); //O(n^2) includeState.setPoint(y, x, double.PositiveInfinity); //set the "opposite point to infinity" for (int j = 0; j < includeState.getMap().GetLength(1); j++) //set the row to infinity, O(n) { includeState.setPoint(x, j, double.PositiveInfinity); } for (int i = 0; i < includeState.getMap().GetLength(0); i++) //set the column to infinity, O(n) { includeState.setPoint(i, y, double.PositiveInfinity); } reduceMatrix(includeState); //O(n^2) includeState.setEdges(state.getEdges()); //initialize includeState's dictionary of edges return(includeState); }
//O(n^2) public State makeInclude(int x, int y, State state) { State includeState = new State(copyMatrix(state.getMap()), state.getLB(), state.getEdges()); //O(n^2) includeState.setPoint(y, x, double.PositiveInfinity); //set the "opposite point to infinity" for (int j = 0; j < includeState.getMap().GetLength(1); j++) //set the row to infinity, O(n) { includeState.setPoint(x, j, double.PositiveInfinity); } for (int i = 0; i < includeState.getMap().GetLength(0); i++) //set the column to infinity, O(n) { includeState.setPoint(i, y, double.PositiveInfinity); } reduceMatrix(includeState); //O(n^2) includeState.setEdges(state.getEdges()); //initialize includeState's dictionary of edges return includeState; }
//O(n^2) public State makeExclude(int x, int y, State state) { State excludeState = new State(copyMatrix(state.getMap()), state.getLB(), state.getEdges()); //O(n^2) excludeState.setPoint(x, y, double.PositiveInfinity); //make chosen point infinity reduceMatrix(excludeState); //O(n^2) excludeState.setEdges(state.getEdges()); //initialize excludeStates edges return excludeState; }
//O(n) public bool isDictionaryFilled(State state) { //returns whether or not the all of the edges have been added for (int i = 0; i < state.getEdges().Count; i++) { if (state.getEdge(i) == -1) return false; //if one hasn't been added, then it isn't full } return true; }
//O(n) public void checkCycles(State state, int i, int j) { Dictionary<int, int> edges = new Dictionary<int, int>(state.getEdges()); if (getDictionarySize(edges) == edges.Count) //if the dictionary is full, stop return; int[] entered = new int[edges.Count]; int[] exited = new int[edges.Count]; for (int x = 0; x < entered.Length; x++) //O(n) entered[x] = -1; for (int x = 0; x < edges.Count; x++) //O(n) { exited[x] = edges[x]; if (exited[x] != -1) entered[exited[x]] = x; } //the two loops above "flip" the arrays with value and index, e.g. if //entered contained [0]=2, [1]=0, [2]=1 //exited will now contain [0]=1, [1]=2, [2]=0 entered[j] = i; exited[i] = j; int start = i; int end = j; while (exited[end] != -1) //O(n) end = exited[end]; while (entered[start] != -1)//O(n) start = entered[start]; if (getDictionarySize(edges) != edges.Count - 1) //if there is only one point left to fill, { //this will think there is a cycle, so make while (start != j) //O(n) make sure there isn't one element left { state.setPoint(end, start, double.PositiveInfinity); state.setPoint(j, start, double.PositiveInfinity); start = exited[start]; } } }
Stopwatch timer; //global timer public void branchAndBoundSolve() { initialState = new State(new Double[Cities.Length, Cities.Length]); timer = new Stopwatch(); timer.Start(); for (int i = 0; i < Cities.Length; i++) //O(n^2), initialize initialStates map { for (int x = 0; x < Cities.Length; x++) { initialState.setPoint(i, x, Cities[i].costToGetTo(Cities[x])); if (initialState.getPoint(i, x) == 0) { initialState.setPoint(i, x, double.PositiveInfinity); } } } initialState.initializeEdges(); //initializeEdges initializes the state's dictionary //with key 0 to n (# of cities), value -> -1 reduceMatrix(initialState); //reduce the matrix to find lower bound queue = new IntervalHeap <State>(); //this is a global queue BSSF = greedy(); //find initial best solution so far, O(n^4) Console.WriteLine("BSSF: " + BSSF); findGreatestDiff(initialState); //exclude minus include, O(n^3) TimeSpan ts = timer.Elapsed; bool terminatedEarly = false; //boolean to keep track if we stopped after 30 seconds int maxStates = 0; //keeps track of the maximum amount of states in the queue at one point int totalSeconds = 0; while (queue.Count != 0) //O(2^n * n^3), because each time you expand a node, it expands it 2 times, exponentially { //where n is the number of cities if (queue.Count > maxStates) //if maxStates needs to be updated, update it { maxStates = queue.Count; } ts = timer.Elapsed; State min = queue.DeleteMin(); if (totalSeconds < ts.Seconds) { totalSeconds = ts.Seconds; Console.WriteLine("seconds: " + totalSeconds); } if (min.getLB() < BSSF) //if the min popped off the queue has a lowerbound less than { findGreatestDiff(min); //the BSSF, expand it, otherwise, prune it. -> O(n^3) } else {//all of the lowerbounds are worse than the BSSF, break! break; } } if (!terminatedEarly)//if it solved the problem in less than 30 seconds { int city = 0; for (int i = 0; i < bestState.getEdges().Count; i++) //O(n) { if (i == 0) //outputting a map into the Route list { Route.Add(Cities[i]); city = bestState.getEdge(i); } else { Route.Add(Cities[city]); city = bestState.getEdge(city); } } bssf = new TSPSolution(Route); // update the cost of the tour. Program.MainForm.tbCostOfTour.Text = " " + bssf.costOfRoute(); Program.MainForm.tbElapsedTime.Text = ts.TotalSeconds.ToString(); // do a refresh. Program.MainForm.Invalidate(); } }