예제 #1
0
        // Kruskal's algorithm is (get the min weight edge from PQ and keep adding to tree if it does not cause a cycle
        // repeat until v-1 edges are added to the tree or until all edges are exhausted.
        private void Kruskal(EdgeWeightedGraph <V> graph)
        {
            PriorityQueueHeap <Edge <V> > _pq = new PriorityQueueHeap <Edge <V> >();

            foreach (Edge <V> edge in graph.Edges())
            {
                _pq.Insert(edge);
            }
            DisjointSets_UnionFind uf = new DisjointSets_UnionFind();

            // This should be extractMin (but we can subtract the weight from 100 or something
            // such that the min weight becomes the max item
            while (!_pq.IsEmpty && _queue.Count < graph.TotalVertices() - 1)
            {
                var item      = _pq.Extract();
                V   start     = item.Either;
                V   end       = item.Other;
                var startHash = ModedHash(start.GetHashCode());
                var endHash   = ModedHash(end.GetHashCode());

                // Union find works in iterated logarithm since path compression helps move the children
                // near the root or parent of the tree.
                if (!uf.Connected(startHash, endHash))
                {
                    uf.MakeSet(startHash);
                    uf.MakeSet(endHash);
                    uf.Union(startHash, endHash);
                    _queue.Enqueue(item);
                }
            }
        }
예제 #2
0
        // Eager prim needs indexed priority queue

        // start at first vertex, find the min weight edge and add it to the tree.
        // Now find a min weight edge that goes out from the tree to non-tree vertex and add it and so on.
        private void LazyPrim(EdgeWeightedGraph <V> graph)
        {
            var marked = new Boolean[graph.TotalVertices()];
            var _pq    = new PriorityQueueHeap <Edge <V> >();

            LazyPrimVisit(graph, graph.Edges().First().Either, marked, _pq);

            while (!_pq.IsEmpty)
            {
                // This should be extractMin (but we can subtract the weight from 100 or something
                // such that the min weight becomes the max item
                var item      = _pq.Extract();
                V   start     = item.Either;
                V   end       = item.Other;
                var startHash = ModedHash(start.GetHashCode());
                var endHash   = ModedHash(end.GetHashCode());

                if (marked[startHash] && marked[endHash])
                {
                    continue;
                }

                _queue.Enqueue(item);
                if (!marked[startHash])
                {
                    LazyPrimVisit(graph, start, marked, _pq);
                }

                if (!marked[endHash])
                {
                    LazyPrimVisit(graph, end, marked, _pq);
                }
            }
        }
예제 #3
0
        private static void customHeapSort(int[] arr, int size)             // O(n*log(n))
        {
            PriorityQueueHeap priorityQueue = new PriorityQueueHeap(size);

            for (int i = 0; i < size; i++)
            {
                priorityQueue.Push(arr[i]);
            }

            for (int i = 0; i < size; i++)
            {
                arr[i] = priorityQueue.Top();
                priorityQueue.Pop();
            }
        }
예제 #4
0
 private void LazyPrimVisit(EdgeWeightedGraph <V> graph, V either, Boolean[] marked, PriorityQueueHeap <Edge <V> > pq)
 {
     marked[ModedHash(either.GetHashCode())] = true;
     foreach (var edge in graph.Adjacency(either))
     {
         if (!marked[ModedHash(edge.GetHashCode())])
         {
             pq.Insert(edge);
         }
     }
 }
예제 #5
0
        public List <SearchNode> Search(TData root, float costLimit = float.MaxValue)
        {
            NextCostLimitThreshhold = float.MaxValue;

            var priorityQueue = new PriorityQueueHeap <SearchNode>();

            // Start at root
            var rootNode = new SearchNode
            {
                Data   = root,
                Action = default(TAction),
                Parent = null,
                Cost   = 0,
                EstimatedRemainingCost = Config.HeuristicFunc(root),
            };

            priorityQueue.Insert(rootNode.EstimatedTotalCost, rootNode);

            while (!priorityQueue.IsEmpty)
            {
                CurrentNode = priorityQueue.ExtractTop();
                if (Config.IsGoalFunc(CurrentNode))
                {
                    return(ReconstructPath(CurrentNode));
                }



                var actions = Config.ActionsListFunc(CurrentNode);
                foreach (var action in actions)
                {
                    var newNode = new SearchNode
                    {
                        Parent = CurrentNode,
                        Data   = Config.ActionApplierFunc(CurrentNode, action),
                        Action = action,
                        Cost   = CurrentNode.Cost + Config.ActionCostFunc(CurrentNode, action),
                    };
                    newNode.EstimatedRemainingCost = Config.HeuristicFunc(newNode.Data);

                    if (newNode.Cost <= costLimit)
                    {
                        priorityQueue.Insert(newNode.EstimatedTotalCost, newNode);

                        OnNodeGenerated();
                    }
                    else
                    {
                        if (newNode.Cost < NextCostLimitThreshhold)
                        {
                            NextCostLimitThreshhold = newNode.Cost;
                        }
                    }
                }

                OnNodeExpanded();
                NodesRetainedCount = priorityQueue.Count;
            }

            return(null);
        }
예제 #6
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;
        }