Example #1
0
        // Initial state, reduces matrix
        public State(City[] cities)
        {
            queue = new HeapPriorityQueue<State>(10000);
            root = this;
            Watch = new Stopwatch();

            Watch.Start();
            State.cities = cities;
            cityCount = cities.Length;
            matrix = new double[cities.Length, cities.Length];
            for (int i = 0; i < cities.Length; i++)
            {
                for (int j = 0; j < cities.Length; j++)
                {
                    matrix[i, j] = cities[i].costToGetTo(cities[j]);

                    // Set diagonals to infinity (negative)
                    if (i == j)
                    {
                        matrix[i, j] = double.PositiveInfinity;
                    }
                }
            }
            bound = 0;
            route = new ArrayList();
            visited = new ArrayList();

            pathsLeft = cityCount;
            setInitialBSSF();

            reduceMatrix();

            // Start expanding until agenda is empty, time is up, or BSSF cost is equal to original LB.
            Expand();
        }
Example #2
0
 public State(State state)
 {
     Matrix = new Matrix(state.Matrix);
     LowerBound = state.LowerBound;
     _cityFrom = (int[])state._cityFrom.Clone();
     _cityTo = (int[])state._cityTo.Clone();
     _citiesInSolution = state._citiesInSolution;
 }
 public LbDifferenceResult(State includeState, State excludeState, double lowerBoundDifference, int fromCity, int toCity)
 {
     IncludeState = includeState;
     ExcludeState = excludeState;
     LowerBoundDifference = lowerBoundDifference;
     FromCity = fromCity;
     ToCity = toCity;
 }
Example #4
0
        public void Add(State newState)
        {
            int position = newState.routeSF.Count;
            System.Console.WriteLine(position);

            if (_states[position] == null)
                _states[position] = new ArrayList();

            _states[position].Add(newState);

            count++;
            if (count > _maxCount)
                _maxCount = count;
        }
 //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^3)
        public void findGreatestDiff(State state)
        {
            int chosenX = 0; //city x to city y
            int chosenY = 0;
            double greatestDiff = double.NegativeInfinity; //initialize to -oo to find what the greatest
                                                           //difference is
            List<PointF> points = new List<PointF>();
            for (int i = 0; i < state.getMap().GetLength(0); i++) //rows, O(n)
            {
                for (int j = 0; j < state.getMap().GetLength(1); j++) //columns
                {
                    if (state.getPoint(i, j) == 0) //if point is 0
                    {
                        points.Add(new PointF(i, j)); //store all 0's in a point array

                    }
                }
            }
            for (int i = 0; i < points.Count; i++) //loop through 0's to find the greatest difference
            {//O(n^3)                               there will be atmost n points, because the entire
             //matrix will be 0
                int possibleMax = findExcludeMinusInclude(Convert.ToInt32(points[i].X), Convert.ToInt32(points[i].Y), state); //O(n^2)
                if (possibleMax >= greatestDiff) //set the point to point values, if it is 0 is covered by =
                {
                    chosenX = Convert.ToInt32(points[i].X);
                    chosenY = Convert.ToInt32(points[i].Y);
                    greatestDiff = possibleMax;
                }
            }
            State include = makeInclude(chosenX, chosenY, state); //O(n^2)
            if (BSSF > include.getLB()) //if include's lowerbound is better than the BSSF
            {
                include.setEdge(chosenX, chosenY); //set the edge in the dictionary
                checkCycles(include, chosenX, chosenY); //O(n), make sure there are no potential cycles
                queue.Add(include); //add to the queue to be popped off later
            }

            if (isDictionaryFilled(include))//O(n), have all of the edges been filled? then the include.LB is better
            {                               //than the current BSSF, set the BSSF
                BSSF = include.getLB();
                bestState = include; //save the "bestState"
            }

            State exclude = makeExclude(chosenX, chosenY, state);//O(n^2)
            if (BSSF > exclude.getLB()) //if exclude's lowerbound is than the BSSF, add it to the queue
                queue.Add(exclude);
            if (isDictionaryFilled(exclude))//O(n), have all of the edges been filled?
            {                               // then exclude's lowerbound is better, set the BSSF to exclude.LB
                BSSF = exclude.getLB();
                bestState = exclude;
            }
        }
        //O(n^2)
        public int findExcludeMinusInclude(int x, int y, State state)
        {
            //finds the exlude minus the include of a point in a matrix
            State excludeState = makeExclude(x, y, state); //O(n^2)
            reduceMatrix(excludeState);//O(n^2)

            State includeState = makeInclude(x, y, state); //O(n^2)
            reduceMatrix(includeState); //O(n^2)

            int cost = Convert.ToInt32(excludeState.getLB() - includeState.getLB());
            return cost;
        }
        //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];
                }
            }
        }
        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();
            }
        }
 public IncludeExcludeStates(State includeState, State excludeState)
 {
     this.includeState = includeState;
     this.excludeState = excludeState;
 }
Example #12
0
            /**
            * This method updates the nodes in the queue after inserting a new node
            * Time Complexity: O(log(|V|)) as reording the heap works by bubbling up the min value to the top
            * which takes as long as the depth of the tree which is log|V|.
            * Space Complexity: O(1) as it does not create any extra variables that vary with the size of the input.
            */
            public void insert(State newState)
            {
                // update the count
                count++;
                states[count] = newState;
                if (count > maxNum)
                    maxNum = count;

                // as long as its parent has a larger value and have not hit the root
                int indexIterator = count;
                while (indexIterator > 1 && states[indexIterator / 2].getPriority() > states[indexIterator].getPriority())
                {
                    // swap the two nodes
                    State temp = states[indexIterator / 2];
                    states[indexIterator / 2] = states[indexIterator];
                    states[indexIterator] = temp;

                    indexIterator /= 2;
                }
            }
Example #13
0
        /// <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();
            ArrayList CitiesLeft = new ArrayList();

            for (x = 0; x < Cities.Length; x++)
            {
                CitiesLeft.Add( Cities[Cities.Length - x - 1]);
            }

            City curCity = (City)CitiesLeft[0];
            Route.Add(curCity);
            CitiesLeft.RemoveAt(0);

            while (CitiesLeft.Count > 0)
            {
                double minDist = 999999;
                int minInd = 0;

                for (int i = 0; i < CitiesLeft.Count; i++)
                {
                    City temp = (City)CitiesLeft[i];
                    if (curCity.costToGetTo(temp) < minDist)
                    {
                        minDist = curCity.costToGetTo(temp);
                        minInd = i;
                    }
                }
                Program.MainForm.tbCostOfTour.Text += "Ind " + minInd;
                curCity = (City)CitiesLeft[minInd];
                Route.Add(curCity);
                CitiesLeft.RemoveAt(minInd);
            }

            // 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();
            Program.MainForm.tbElapsedTime.Text = "initial bssf";
            // do a refresh.
            Program.MainForm.Invalidate();

            //My solving begins here
            //generate first adjacency matrix
            double[,] firstAdj = new double[Cities.Length,Cities.Length];
            for (int i = 0; i < Cities.Length; i++)
            {
                for (int j = 0; j < Cities.Length; j++)
                {
                    if (i == j)
                        firstAdj[i, j] = 999999;
                    else
                        firstAdj[i, j] = Cities[i].costToGetTo(Cities[j]);
                }
            }
            State firstState = new State(firstAdj);
            Agenda myAgenda = new Agenda(Cities.Length);
            myAgenda.Add(firstState);
            //Start timer and go
            DateTime start = DateTime.Now;
            DateTime timeUp = DateTime.Now.AddSeconds(60);

            while ((myAgenda.hasNextState()) && (DateTime.Now <= timeUp))
            {
                State s = myAgenda.nextState;
                if ((s.routeSF.Count == Cities.Length) && s.costSF < bssf.costOfRoute())
                {
                    TSPSolution posS = new TSPSolution(s.routeSF);
                    if (posS.costOfRoute() < bssf.costOfRoute())
                    {
                        bssf = posS;
                        //Prune the agenda
                        myAgenda.Prune(bssf.costOfRoute());
                        // update the cost of the tour.
                        Program.MainForm.tbCostOfTour.Text = " " + bssf.costOfRoute();
                        Program.MainForm.tbElapsedTime.Text = " " + (DateTime.Now - start);
                        // do a refresh.
                        Program.MainForm.Invalidate();
                    }
                }
                else
                {
                        ArrayList newStates = s.Expand(Cities);
                        foreach (State state in newStates)
                        {
                            if (state.lowerBound < bssf.costOfRoute())
                                myAgenda.Add(state);
                        }
                }
            }
            if (DateTime.Now < timeUp)
                Program.MainForm.tbElapsedTime.Text += " true";

            Program.MainForm.tbCostOfTour.Text += " MC " + myAgenda.MaxCount + " NP " + myAgenda.NumPruned;
        }
 //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;
 }
Example #15
0
        // Copy constructor for making children (Josh)
        // Reduces matrix based on whether edge is included
        // Adds state to queue
        public State(State parent, Boolean include, int from, int to)
        {
            matrix = (double[,])parent.matrix.Clone();
            route = new ArrayList(parent.route);
            visited = new ArrayList(parent.visited);
            bound = parent.bound;
            this.parent = parent;
            depth = parent.depth + 1;

            if (include)
            {
                bound += matrix[from, to];
                pathsLeft = parent.pathsLeft - 1;

                visited.Add(from);
                visited.Add(to);

                for (int i = 0; i < cityCount; i++)
                {
                    matrix[from, i] = double.PositiveInfinity;
                    matrix[i, to] = double.PositiveInfinity;
                }

                // If there's more than one path left, delete paths to used vertices (Josh)
                if (pathsLeft > 2)
                {
                    for (int i = 0; i < visited.Count; i++)
                    {
                        matrix[to, (int)visited[i]] = double.PositiveInfinity;
                        // Shouldn't be necessary, but who knows?
                        matrix[(int)visited[i], from] = double.PositiveInfinity;
                    }
                }
                else if (pathsLeft == 2)
                {
                    //this should keep the path from the final city back to the first one
                    for (int i = 1; i < visited.Count; i++)
                    {
                        matrix[to, (int)visited[i]] = double.PositiveInfinity;
                        // Shouldn't be necessary, but who knows?
                        matrix[(int)visited[i], from] = double.PositiveInfinity;
                    }
                }
                matrix[to, from] = double.PositiveInfinity;
            }
            else
            {
                matrix[from, to] = double.PositiveInfinity;
                pathsLeft = parent.pathsLeft;
            }

            reduceMatrix();

            // set BSSF if necessary (Josh)

            // If not, set BSSF if necessary (Josh)
            if (pathsLeft == 1)
            {
                for (int i = 0; i < cityCount; i++)
                {
                    for (int j = 0; j < cityCount; j++)
                    {
                        if (matrix[i, j] != double.PositiveInfinity)
                        {
                            includeChild = new State(this, true, i, j);
                            Console.WriteLine("Found solution");
                            for (int k = 0; k < includeChild.visited.Count; k++)
                            {
                                Console.WriteLine(includeChild.visited[k]);
                            }
                            if (includeChild.bound < BSSF.bound)
                            {
                                // Calculate route from visited nodes
                                includeChild.calculateRoute();
                                BSSF = includeChild;
                                // Prune states starting with root
                                root.prune();
                            }
                            else
                            {
                                return;
                            }
                        }
                    }
                }
            }

            // Add to queue
            if (pathsLeft > 0 && bound < BSSF.bound)
            {
                queue.Enqueue(this, Priority);
            }
        }
Example #16
0
 private ArrayList generateChildren(State u)
 {
     ArrayList children = new ArrayList();
     int row = (int)u.path[(u.path.Count-1)];
     for (int i = 0; i < Cities.Length; i++)
     {
         if (u.matrix[row, i] != double.MaxValue && !u.path.Contains(i))
         {
             State child = new State(u);
             child.path.Add(i);
             child.boundValue += child.matrix[row, i];
             for (int j = 0; j < Cities.Length; j++)
             {
                 child.matrix[row, j] = double.MaxValue;
                 child.matrix[j, i] = double.MaxValue;
             }
             child.calculateBound();
             children.Add(child);
         }
     }
     return children;
 }
Example #17
0
 // Finds initial BSSF (Brian)
 // Call after setting cost matrix
 // Use vertices to the right (or left) of the diagonal
 // Cost matrix of initial BSSF, doesn't matter
 // Only the route and bound matter
 // So don't worry about the rest of the fields
 public void setInitialBSSF()
 {
     ArrayList bssfCities = new ArrayList();
     double cost = 0;
     // TODO: fill this in
     for (int i = 0; i < cityCount; i++)
     {
         bssfCities.Add(cities[(i + 1) % cityCount]);
         cost += matrix[(i + 1) % cityCount, i];
     }
     BSSF = new State(bssfCities, cost);
 }
Example #18
0
 public State(State m)
 {
     this.path = (ArrayList) m.path.Clone();
     this.matrix = (double[,]) m.matrix.Clone();
     this.boundValue = m.boundValue;
 }
Example #19
0
 private State initState()
 {
     State s = new State();
     s.matrix = new double[Cities.Length, Cities.Length];
     for (int i = 0; i < Cities.Length; i++)
     {
         for (int j = 0; j < Cities.Length; j++)
         {
             double entry = Cities[i].costToGetTo(Cities[j]);
             if (entry == 0)
                 entry = double.MaxValue;
             s.matrix[i, j] = entry;
         }
     }
     s.calculateBound();
     return s;
 }
 //O(n^2)
 public void reduceMatrix(State currentState)
 {
     double lowerBound = currentState.getLB();
     for (int i = 0; i < currentState.getMap().GetLength(0); i++) // reduce rows
     {//O(n^2)
         double minimum = double.PositiveInfinity; //find the lowest value in that row to reduce
         for (int j = 0; j < currentState.getMap().GetLength(1); j++)
         {
             if (currentState.getPoint(i, j) < minimum)
                 minimum = currentState.getPoint(i, j);
         }
         if (minimum == 0) //if there is already a 0 in that row, don't waste time looping through it
             continue;
         if (minimum != double.PositiveInfinity)
         {
             for (int j = 0; j < currentState.getMap().GetLength(1); j++)
             { //reduce the other entire row by that value
                 double reducedPoint = currentState.getPoint(i, j) - minimum;
                 currentState.setPoint(i, j, reducedPoint);
             }
             lowerBound += minimum; //add that lowest value to the lowerBound
         }
     }
     for (int j = 0; j < currentState.getMap().GetLength(1); j++) //reduce columns
     {//O(n^2)
         double minimum = double.PositiveInfinity;
         for (int i = 0; i < currentState.getMap().GetLength(0); i++)
         {
             if (currentState.getPoint(i, j) < minimum)
                 minimum = currentState.getPoint(i, j); //find the lowest value in the column
         }
         if (minimum == 0) //if there is already a 0 in that column, don't waste time looping through it
             continue;
         if (minimum != double.PositiveInfinity)
         {
             for (int i = 0; i < currentState.getMap().GetLength(0); i++)
             {//reduce the entire column by that value
                 double lowerPoint = currentState.getPoint(i, j) - minimum;
                 currentState.setPoint(i, j, lowerPoint);
             }
             lowerBound += minimum; //add that minimum value to the lowerBound
         }
     }
     currentState.setLB(lowerBound); //set the lowerbound
 }
Example #21
0
        /// <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()
        {
            State state = new State(Cities);
            bssf = new TSPSolution(State.BSSF.Route);
            Console.WriteLine(bssf.costOfRoute());
            Console.WriteLine(State.BSSF.Bound);
            Debug.Assert(bssf.costOfRoute() == State.BSSF.Bound);
            Program.MainForm.tbCostOfTour.Text = " " + bssf.costOfRoute();
            Program.MainForm.tbElapsedTime.Text = State.Watch.Elapsed.ToString();
            Program.MainForm.Invalidate();

            // Trivial solution, what appeared here originally
            // Uncomment to see how it works

            /*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 ArrayList RunTSP(City[] Cities)
        {
            Route = new ArrayList();

            Stopwatch timer = new Stopwatch();
            bAndBTime = new TimeSpan();
            timer.Start();

            Greedy greedyAlgorithm = new Greedy(Cities);
            ArrayList greedyRoute = greedyAlgorithm.RunGreedyTSP();

            double[,] matrix = new double[Cities.Length, Cities.Length];
            //Populate each array item with each respective edge cost
            for (int i = 0; i < Cities.Length; i++)
            {//O(n^2)
                for (int j = 0; j < Cities.Length; j++)
                {
                    if (i == j)
                    {
                        matrix[i, j] = double.PositiveInfinity;
                    }
                    else
                    {
                        matrix[i, j] = Cities[i].costToGetTo(Cities[j]);
                    }
                }
            }
            IntervalHeap<State> queue = new IntervalHeap<State>();

            double bestSolutionSoFar = greedyAlgorithm.BestSolutionSoFar();
            bssfUpdatesAmt = 0;
            prunedAmt = 0;
            State bssfState = null;
            totalStatesCreated = 0;
            //Start with some problem
            State curState = new State(matrix, 0, new Edge(-1, -1));
            totalStatesCreated++;
            //Reduce Matrix
            //O(4n^2)
            curState.Reduce();
            //Let the queue be the set of active subproblems
            //O(log(n))
            queue.Add(curState);
            maxQueueCount = 0;

            bool timesUp = false;
            while (queue.Count > 0)
            {//O(2^n) or O(2^(8n^2 + 9n + 2log(n)))
                if (timer.Elapsed.Seconds >= 30)
                {
                    timesUp = true;
                    break;
                }
                //Choose a subproblem and remove it from the queue
                if (queue.Count > maxQueueCount)
                {
                    maxQueueCount = queue.Count;
                }
                //O(log(n))
                curState = queue.DeleteMin();
                if (curState.Cost() < bestSolutionSoFar)
                {//O(8n^2 + 9n + 2log(n))
                    //For each lowest cost (each 0)
                    double highestScore = double.NegativeInfinity;
                    State[] includeExcludeStates = new State[2];
                    foreach (Edge edge in curState.LowestNums())
                    {//O(8n^2 + 9n)
                        //Include Matrix
                        State includeState = new State(curState, edge); //O(n)
                        totalStatesCreated++;
                        includeState.IncludeMatrix(edge.Row(), edge.Col()); //O(4n^2 + 7n)
                        //Exclude Matrix
                        State excludeState = new State(curState, edge); //O(n)
                        totalStatesCreated++;
                        excludeState.ExcludeMatrix(edge.Row(), edge.Col());//O(4n^2)
                        //Find the score for that edge (Exclude cost - Include cost)
                        double score = excludeState.Cost() - includeState.Cost();
                        if (score > highestScore)
                        {
                            includeExcludeStates[0] = includeState;
                            includeExcludeStates[1] = excludeState;
                            highestScore = score;
                        }
                    }

                    foreach (State subproblemState in includeExcludeStates)
                    {//O(2log(n))
                        //if each P (subproblem) chosen is a complete solution, update the bssf
                        if (subproblemState.CompleteSolution() && subproblemState.Cost() < bestSolutionSoFar)
                        {
                            bestSolutionSoFar = subproblemState.Cost();
                            bssfState = subproblemState;
                            bssfUpdatesAmt++;
                        }
                        //else if lowerBound < bestSolutionSoFar
                        else if (!subproblemState.CompleteSolution() && subproblemState.Cost() < bestSolutionSoFar)
                        {
                            //O(log(n))
                            queue.Add(subproblemState);
                        }
                        else
                        {
                            prunedAmt++;
                        }
                    }
                }
            }

            if (!timesUp) prunedAmt += queue.Count;
            //Call this the best solution so far.  bssf is the route that will be drawn by the Draw method.
            if (bssfState != null)
            {
                int index = bssfState.Exited(0);
                Route.Add(Cities[index]);
                index = bssfState.Exited(bssfState.Exited(0));
                while (index != bssfState.Exited(0))
                {//O(n)
                    Route.Add(Cities[index]);
                    index = bssfState.Exited(index);
                }
            }
            else
            {
                Route = greedyRoute;
            }

            timer.Stop();
            bAndBTime = timer.Elapsed;
            this.count = bssfState.Cost();

            // update the cost of the tour.
            timer.Reset();
            return Route;
        }
Example #23
0
        /////////////////////////////////////////////////////////////////////////////////////////////////
        /////////////////////////////////////// BB Algorithm ////////////////////////////////////////////
        /////////////////////////////////////////////////////////////////////////////////////////////////
        #region MainBBAlgorithm
        /// <summary>
        /// performs a Branch and Bound search of the state space of partial tours
        /// stops when time limit expires and uses BSSF as solution
        /// Time Complexity: O((n^2)*(2^n) as that is the most dominant factor in the code, and it is a result
        /// of the loop, for more details scroll to the comment above the loop in the function.
        /// Space Complexity: O((n^2)*(2^n) as that is the most dominant factor in the code, and it is a result
        /// of the loop, for more details scroll to the comment above the loop in the function.
        /// </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];
            
            // Helper variables
            /* This part of the code takes O(1) space and time as we are just initializing some data */
            int numOfCitiesLeft = Cities.Length;
            int numOfSolutions = 0;
            int numOfStatesCreated = 0;
            int numOfStatesNotExpanded = 0;

            // Initialize the time variable to stop after the time limit, which is defaulted to 60 seconds
            /* This part of the code takes O(1) space and time as we are just initializing some data */
            DateTime start = DateTime.Now;
            DateTime end = start.AddSeconds(time_limit/1000);

            // Create the initial root State and set its priority to its lower bound as we don't have any extra info at this point
            /* This part of the code takes O(n^2) space and time as explained above */
            State initialState = createInitialState();
            numOfStatesCreated++;
            initialState.setPriority(calculateKey(numOfCitiesLeft - 1, initialState.getLowerBound()));

            // Create the initial BSSF Greedily
            /* This part of the code takes O(n^2) time and O(n) space as explained above */
            double BSSFBOUND = createGreedyInitialBSSF();

            // Create the queue and add the initial state to it, then subtract the number of cities left
            /* This part of the code takes O(1) time since we are just creating a data structure and 
            O(1,000,000) space which is just a constant so O(1) space as well*/
            PriorityQueueHeap queue = new PriorityQueueHeap();
            queue.makeQueue(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
                State 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]);
                        State childState = new State(ref newPath, ref newLB, ref newCostMatrix, Cities.Length);
                        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;
        }