Ejemplo n.º 1
0
        /// <summary>
        /// Pops a node from the heap, this node is always the node
        /// with the cheapest expected path cost
        /// </summary>
        public MinHeapNode Pop()
        {
            var top = this.head;

            this.head = this.head.Next;

            return(top);
        }
Ejemplo n.º 2
0
    public List <Vector2Int> FindPath(Vector2Int start, Vector2Int end, int iterationLimit = 200)
    {
        // Convert start and end to working co-ordinates.
        start += new Vector2Int((int)(gridSize.x * 0.5f), (int)(gridSize.y * 0.5f));
        end   += new Vector2Int((int)(gridSize.x * 0.5f), (int)(gridSize.y * 0.5f));

        Debug.Log(start);
        Debug.Log(end);

        // Clear step list.
        StepList.Clear();

        // Check for start/end.
        if (start == end)
        {
            return(new List <Vector2Int> {
                start
            });
        }

        MinHeapNode head = new MinHeapNode(start, ManhattanDistance(start, end));
        MinHeap     open = new MinHeap();

        // Push head node to heap.
        open.Push(head);

        // Define total cost.
        float[]      totalCost = new float[gridSize.x * gridSize.y];
        Vector2Int[] cameFrom  = new Vector2Int[gridSize.x * gridSize.y];

        while (open.HasNext() && iterationLimit > 0)
        {
            // Get current position.
            Vector2Int current = open.Pop().Position;
            MessageCurrent(current, PartiallyReconstructPath(start, end, cameFrom));

            if (current == end)
            {
                List <Vector2Int> path = ReconstructPath(start, end, cameFrom);
                path.Reverse();
                return(path);
            }

            Step(open, cameFrom, totalCost, current, end);

            MessageClose(current);

            --iterationLimit;
        }

        return(null);
    }
    public bool IfContainsRemove(Entity node)
    {
#if ENABLE_UNITY_COLLECTIONS_CHECKS
        AtomicSafetyHandle.CheckReadAndThrow(this.m_Safety);
#endif
        if (head < 0)
        {
            return(false);
        }

        var current = Get(head);

        if (current.NodeEntity == node)
        {
            head = current.Next;
            return(true);
        }

        if (current.Next == -1)
        {
            return(false);
        }

        MinHeapNode prev = current;
        current = Get(current.Next);
        var currentPrev = head;

        while (current.Next > -1)
        {
            if (current.NodeEntity == node)
            {
                prev.Next = current.Next;
                UnsafeUtility.WriteArrayElement(buffer, currentPrev, prev);
                return(true);
            }

            currentPrev = prev.Next;
            prev        = current;
            current     = Get(current.Next);
        }

        if (current.NodeEntity == node)
        {
            prev.Next = -1;
            UnsafeUtility.WriteArrayElement(buffer, currentPrev, prev);
            return(true);
        }
        return(false);
    }
Ejemplo n.º 4
0
            public MinHeapNode ExtractMinKey(MinHeap heap)
            {
                if (IsEmptyMinHeap(heap))
                {
                    return(null);
                }
                MinHeapNode first = heap.array[0];
                MinHeapNode last  = heap.array[heap.size - 1];

                heap.array[0]         = last;
                heap.pos[first.value] = heap.size - 1;
                heap.pos[last.value]  = 0;
                heap.size--;
                MinHeapify(heap, 0);
                return(first);
            }
Ejemplo n.º 5
0
            public static void MergeKSortedArrays(int[,] arr, int k)
            {
                MinHeapNode[] hArr       = new MinHeapNode[k];
                int           resultSize = 0;

                for (int i = 0; i < arr.GetLength(0); i++)
                {
                    MinHeapNode node = new MinHeapNode(arr[i, 0], i, 1);
                    hArr[i]     = node;
                    resultSize += arr.GetLength(1);
                }

                // Create a min heap with k heap nodes.
                // Every heap node has first element of an array
                MinHeap mh = new MinHeap(hArr, k);

                int[] result = new int[resultSize];     // To store output array

                // Now one by one get the minimum element
                // from min heap and replace it with
                // next element of its array
                for (int i = 0; i < resultSize; i++)
                {
                    // Get the minimum element and
                    // store it in result
                    MinHeapNode root = mh.getMin();
                    result[i] = root.element;

                    // Find the next element that will
                    // replace current root of heap.
                    // The next element belongs to same
                    // array as the current root.
                    if (root.j < arr.GetLength(1))
                    {
                        root.element = arr[root.i, root.j++];
                    }

                    // If root was the last element of its array
                    else
                    {
                        root.element = int.MaxValue;
                    }

                    // Replace root with next element of array
                    mh.replaceMin(root);
                }
            }
        public void DijkstraAlgorithm(int sourceVertex)
        {
            MinHeap minHeap = new MinHeap(Vertices);

            int[] distanceTable = new int[Vertices];

            //Set all distances to max value initially
            for (int i = 0; i < distanceTable.Length; i++)
            {
                distanceTable[i] = Int32.MaxValue;
            }

            //Set source vertex's distance as 0;

            minHeap.DecreaseKey(sourceVertex, 0);
            distanceTable[sourceVertex] = 0;

            while (minHeap.HeapSize > 0)
            {
                //Extract min
                MinHeapNode minNode = minHeap.ExtractMin();
                Console.WriteLine("Min value extraxted: " + minNode.Vertex);

                //Look for the node's neighbors in adjacency list
                LinkedListofGraphNodes neighbors = AdjacencyList[minNode.Vertex];
                GraphNode p = neighbors.Head;
                while (p != null)
                {
                    if (minHeap.IsinMinHeap(p.Key) && minNode.Distance != Int32.MaxValue)
                    {
                        int new_distance = minNode.Distance + p.EdgeWeight;

                        if (distanceTable[p.Key] > new_distance)
                        {
                            minHeap.DecreaseKey(p.Key, new_distance);
                            distanceTable[p.Key] = new_distance;
                        }
                    }

                    p = p.Next;
                }
            }

            PrintDistanceTable(distanceTable);
        }
    public void Push(MinHeapNode node)
    {
#if ENABLE_UNITY_COLLECTIONS_CHECKS
        if (length == capacity)
        {
            throw new IndexOutOfRangeException($"Capacity of {capacity} Reached: {length}");
        }

        AtomicSafetyHandle.CheckReadAndThrow(this.m_Safety);
#endif
        if (head < 0)
        {
            head = length;
        }
        else if (node.F_Cost < Get(head).F_Cost ||
                 (node.F_Cost == Get(head).F_Cost&& node.H_Cost < Get(head).H_Cost))
        {
            node.Next = head;
            head      = length;
        }
        else
        {
            var currentPtr = head;
            var current    = Get(head);

            while (current.Next >= 0 && Get(current.Next).F_Cost <= node.F_Cost)
            {
                if (node.F_Cost == Get(current.Next).F_Cost&& node.H_Cost < Get(current.Next).H_Cost)
                {
                    break;
                }

                currentPtr = current.Next;
                current    = Get(current.Next);
            }

            node.Next    = current.Next;
            current.Next = length;

            UnsafeUtility.WriteArrayElement(buffer, currentPtr, current);
        }

        UnsafeUtility.WriteArrayElement(buffer, length, node);
        this.length += 1;
    }
Ejemplo n.º 8
0
    public void Push(MinHeapNode <T> node)
    {
#if ENABLE_UNITY_COLLECTIONS_CHECKS
        if (m_length == m_capacity)
        {
            throw new IndexOutOfRangeException($"Capacity Reached");
        }
        CheckReadAndThrow(m_Safety);
#endif

        if (m_head < 0)
        {
            m_head = m_length;
        }
        else if (node.Cost < this[m_head].Cost)
        {
            node.Next = m_head;
            m_head    = m_length;
        }
        else
        {
            var currentPtr = m_head;
            var current    = this[currentPtr];

            while (current.Next >= 0 && this[current.Next].Cost <= node.Cost)
            {
                currentPtr = current.Next;
                current    = this[current.Next];
            }

            node.Next    = current.Next;
            current.Next = m_length;

            UnsafeUtility.WriteArrayElement(m_Buffer, currentPtr, current);
        }

        UnsafeUtility.WriteArrayElement(m_Buffer, m_length, node);
        m_length += 1;
    }
Ejemplo n.º 9
0
        /// <summary>
        /// Pushes a node onto the heap
        /// </summary>
        public void Push(MinHeapNode node)
        {
            // If the heap is empty, just add the item to the top
            if (this.head == null)
            {
                this.head = node;
            }
            else if (node.ExpectedCost < this.head.ExpectedCost)
            {
                node.Next = this.head;
                this.head = node;
            }
            else
            {
                var current = this.head;
                while (current.Next != null && current.Next.ExpectedCost <= node.ExpectedCost)
                {
                    current = current.Next;
                }

                node.Next    = current.Next;
                current.Next = node;
            }
        }
Ejemplo n.º 10
0
        public void FindPrimsMSTAdjList(int[,] graph)
        {
            int vertext = V;

            int[]   parent  = new int[V];
            int[]   key     = new int[V];
            MinHeap minHeap = new MinHeap(vertext);

            for (int v = 1; v < vertext; v++)
            {
                parent[v]        = -1;
                key[v]           = Int32.MaxValue;
                minHeap.array[v] = new MinHeapNode(v, key[v]);
                minHeap.pos[v]   = v;
            }

            key[0]           = 0;
            minHeap.pos[0]   = 0;
            minHeap.array[0] = new MinHeapNode(0, key[0]);
            minHeap.size     = vertext;
            while (!minHeap.IsEmptyMinHeap(minHeap))
            {
                MinHeapNode node = minHeap.ExtractMinKey(minHeap);
                int         u    = node.value;
                foreach (var item in AdjList[u])
                {
                    int v = item.dest;
                    if (minHeap.IsInMinHeap(minHeap, v) && item.weight < key[v])
                    {
                        key[v]    = item.weight;
                        parent[v] = u;
                        minHeap.DecreaseKey(minHeap, key[v], v);
                    }
                }
            }
        }
Ejemplo n.º 11
0
 public void replaceMin(MinHeapNode root)
 {
     harr[0] = root;
     MinHeapify(0);
 }
Ejemplo n.º 12
0
 public void Clear() => this.head = null;
Ejemplo n.º 13
0
        private unsafe void AStarSolver(int2 start, int2 goal, int index, Entity agent)
        {
            // data containers sliced from shared data structures
            var openSet    = OpenSet.Slice(index * _maxLength, _maxLength);
            var closedSet  = ClosedSet.Slice(index * _maxLength, _maxLength);
            var G_Costs    = Gcosts.Slice(index * _maxLength, _maxLength);
            var neighbours = new NativeList <int2>(8, Allocator.TempJob);

            // reset of data containers
            openSet.Clear();

            void *buffer = closedSet.GetUnsafePtr();

            UnsafeUtility.MemClear(buffer, (long)closedSet.Length * UnsafeUtility.SizeOf <MinHeapNode>());

            buffer = G_Costs.GetUnsafePtr();
            UnsafeUtility.MemClear(buffer, (long)G_Costs.Length * UnsafeUtility.SizeOf <int>());

            var startNode = new MinHeapNode(GridGeneratorSystem.grid[start.x, start.y], start);

            openSet.Push(startNode);

            while (openSet.HasNext())
            {
                var currentNode = openSet.Pop();

                currentNode.IsClosed = 1;
                closedSet[GetIndex(currentNode.Position)] = currentNode;

                // if goal node is reached then the path is created and assigned to the agent entity
                if (currentNode.Position.x == goal.x && currentNode.Position.y == goal.y)
                {
                    var path    = new NativeList <int2>(Allocator.TempJob);
                    var current = currentNode;

                    while (current.ParentPosition.x != -1)
                    {
                        path.Add(current.Position);
                        current = closedSet[GetIndex(current.ParentPosition)];
                    }
                    path.Add(current.Position);

                    CreatePath(agent, ref path);

                    path.Dispose();
                    break;
                }

                GetNeighbours(currentNode.Position, ref neighbours);

                for (int i = 0; i < neighbours.Length; i++)
                {
                    var neighbourEntity = GridGeneratorSystem.grid[neighbours[i].x, neighbours[i].y];

                    // if current neighbour is in closed list or is unwalkable then skip to next
                    if (closedSet[GetIndex(neighbours[i])].IsClosed == 1 || !Walkables[neighbourEntity].Value)
                    {
                        continue;
                    }

                    int costSoFar = G_Costs[GetIndex(currentNode.Position)] + Heuristics.OctileDistance(currentNode.Position, neighbours[i]);

                    if (G_Costs[GetIndex(neighbours[i])] == 0 || costSoFar < G_Costs[GetIndex(neighbours[i])])
                    {
                        // update costs
                        int h = Heuristics.OctileDistance(neighbours[i], goal);
                        int f = costSoFar + h;

                        G_Costs[GetIndex(neighbours[i])] = costSoFar;

                        var node = new MinHeapNode(neighbourEntity, neighbours[i], currentNode.Position, f, h);

                        // if openSet contains node => update node
                        openSet.IfContainsRemove(node.NodeEntity);
                        openSet.Push(node);
                    }
                }
            }
            neighbours.Dispose();
        }