Пример #1
0
        public void PopTest()
        {
            // Heap
            FibonacciHeap <float, char> heap = new FibonacciHeap <float, char>();
            HashSet <float>             equalPriorirtyMinimums = new HashSet <float>()
            {
                'b', 'e', 'f', 'g'
            };

            // Check heap starts with no nodes
            Assert.AreEqual(heap.Count, 0);

            // Add collection of nodes
            HeapNode <float, char> node2 = heap.Insert(7, 'b');
            HeapNode <float, char> node1 = heap.Insert(3, 'a');
            HeapNode <float, char> node3 = heap.Insert(14, 'c');
            HeapNode <float, char> node4 = heap.Insert(35, 'd');
            HeapNode <float, char> node5 = heap.Insert(7, 'e');
            HeapNode <float, char> node6 = heap.Insert(7, 'f');
            HeapNode <float, char> node7 = heap.Insert(7, 'g');

            // Check heap has correct number of nodes
            Assert.AreEqual(heap.Count, 7);

            char minimum = heap.Pop();

            // Check returned item is the correct value, and is not still in heap
            Assert.AreEqual(minimum, 'a');
            Assert.AreNotEqual(heap.Minimum.Value, minimum);
            Assert.AreEqual(heap.Count, 6);

            // Pop a set of equal priority values, check heap outputs them all (order is undefined)
            for (int i = 0; i < equalPriorirtyMinimums.Count; i++)
            {
                minimum = heap.Pop();

                // Check returned item is the correct value, and is not still in heap
                Assert.IsTrue(equalPriorirtyMinimums.Contains(minimum));
                Assert.AreNotEqual(heap.Minimum.Value, minimum);
                Assert.AreEqual(heap.Count, 5 - i);
            }

            minimum = heap.Pop();

            // Check returned item is the correct value, and is not still in heap
            Assert.AreEqual(minimum, 'c');
            Assert.AreNotEqual(heap.Minimum.Value, minimum);
            Assert.AreEqual(heap.Count, 1);

            minimum = heap.Pop();

            // Check returned item is the correct value
            Assert.AreEqual(minimum, 'd');
            Assert.AreEqual(heap.Count, 0);
        }
        public static void Union_NonEmptyHeap_ReturnsSortedOrder()
        {
            var oddHeap = new FibonacciHeap <int>();

            for (var i = 1; i < 10; i += 2)
            {
                oddHeap.Push(i);
            }

            var evenHeap = new FibonacciHeap <int>();

            for (var i = 0; i < 10; i += 2)
            {
                evenHeap.Push(i);
            }

            oddHeap.Union(evenHeap);

            for (var i = 0; i < 10; i++)
            {
                Assert.AreEqual(i, oddHeap.Pop());
            }

            Assert.Zero(oddHeap.Count);
            Assert.Zero(evenHeap.Count);
        }
        public static void DecreaseKey_NonEmptyHeap_PreservesHeapStructure()
        {
            var heap = new FibonacciHeap <int>();

            for (var i = 11; i < 20; i++)
            {
                heap.Push(i);
            }

            var item = heap.Push(10);

            for (var i = 0; i < 10; i++)
            {
                heap.Push(i);
            }

            var bigItem = heap.Push(20);

            heap.DecreaseKey(item, -1);
            Assert.AreEqual(heap.Pop(), -1);

            var currentVal = -1;

            for (var i = 0; i < 10; i++)
            {
                var newVal = heap.Pop();
                Assert.True(currentVal < newVal);

                currentVal = newVal;
            }

            heap.DecreaseKey(bigItem, -1);
            Assert.AreEqual(heap.Pop(), -1);

            currentVal = -1;
            for (var i = 0; i < 9; i++)
            {
                var newVal = heap.Pop();
                Assert.True(currentVal < newVal);

                currentVal = newVal;
            }
        }
Пример #4
0
        public void TestBasicFunctionality()
        {
            var heap = new FibonacciHeap <int>();

            heap.Insert(4, 4);
            heap.Insert(1, 1);
            heap.Insert(5, 5);
            heap.Insert(2, 2);
            heap.Insert(3, 3);
            int a = heap.Pop();
            int b = heap.Pop();
            int c = heap.Pop();
            int d = heap.Pop();
            int e = heap.Pop();

            Assert.AreEqual(1, a);
            Assert.AreEqual(2, b);
            Assert.AreEqual(3, c);
            Assert.AreEqual(4, d);
            Assert.AreEqual(5, e);
        }
Пример #5
0
        /// <summary>
        /// Uses A*-algorithm to find the best route between two tiles.
        /// </summary>
        /// <param name="start">First tile to search from.</param>
        /// <param name="goal">Goal to find.</param>
        /// <param name="previous">Tile just before the first tile.</param>
        /// <param name="forbidden">List of tiles that should be never used on route.</param>
        /// <param name="sign">Optional function for building signs.</param>
        /// <returns></returns>
        internal static List <PathInfo> FindPath(TileIndex start, TileIndex goal, TileIndex previous, HashSet <TileIndex> forbidden = null, Action <TileIndex, string> sign = null)
        {
            // Nodes to evaluate
            var tilesToProcess = new FibonacciHeap <TileIndex>();

            tilesToProcess.Insert(start, 0);

            // Nodes evaluated
            var cameFrom = new Dictionary <TileIndex, PathInfo>();

            cameFrom[start] = new PathInfo(start, 1, 0, BuildType.Basic, previous != null ? new PathInfo(previous, 1, 0, BuildType.Basic, null) : null);

            while (tilesToProcess.Count() > 0)
            {
                var current = tilesToProcess.Pop();
                //AILog.Info($"Processing: {Helper.FormatTile(current)}");
                if (current == goal)
                {
                    // We found the target.
                    return(RoadBuilder.BuildFinalPath(cameFrom[current]));
                }

                var neighbors = RoadBuilder.GetNeighbors(current, cameFrom[current]);
                foreach (var neighborItem in neighbors)
                {
                    var neighbor = neighborItem.Tile;
                    if ((neighbor == previous) || ((forbidden != null) && forbidden.Contains(neighbor)))
                    {
                        // We can't go here.
                        continue;
                    }

                    var neighborDist = neighborItem.Length;
                    if (!cameFrom.ContainsKey(neighbor))
                    {
                        tilesToProcess.Insert(neighbor, neighborItem.Cost);
                    }
                    else
                    {
                        if (neighborItem.Cost >= cameFrom[neighbor].Cost)
                        {
                            continue;
                        }
                    }

                    sign?.Invoke(neighbor, neighborItem.Cost.ToString());
                    cameFrom[neighbor] = neighborItem;
                }
            }

            return(null);
        }
Пример #6
0
        public void FibonacciHeapTest1()
        {
            const int Count  = 1000000;
            Random    random = new Random(0);

            FibonacciHeap <int, int> heap = new FibonacciHeap <int, int>(100);

            int count = 0;

            while (count < Count)
            {
                // add more elements to the heap
                for (int i = 0, ii = random.Next(10, 100); i < ii; i++, count++)
                {
                    heap.Push(random.Next(0, 100), 1000);
                }

                // pop some elements
                Pop(random.Next(heap.Count / 2, 3 * heap.Count / 4));
            }

            // pop remaining element
            Pop(heap.Count);

            void Pop(int popcount)
            {
                if (popcount > 0)
                {
                    int previous = heap.Pop().key;

                    for (int i = 0, ii = Math.Max(0, popcount - 1); i < ii; i++)
                    {
                        int value = heap.Pop().key;
                        Assert.IsTrue(previous <= value);
                        previous = value;
                    }
                }
            }
        }
        public static void Pop_NonEmptyHeap_ReturnsInSortedOrder()
        {
            var heap = new FibonacciHeap <int>();

            var rand     = new Random();
            var heapSize = 100;

            for (var i = 0; i < heapSize; i++)
            {
                heap.Push(rand.Next(1000));
            }

            var element = heap.Pop();

            for (var i = 0; i < heapSize - 1; i++)
            {
                var newElement = heap.Pop();
                Assert.LessOrEqual(element, newElement);
                element = newElement;
            }

            Assert.Zero(heap.Count);
        }
Пример #8
0
    public List <Tile> FindReachableTiles(Unit unit, Tile center, int ap)
    {
        List <Tile> tiles = new List <Tile>();

        Dictionary <Tile, FibonacciHeapNode <TileMeta> > tileMap = new Dictionary <Tile, FibonacciHeapNode <TileMeta> >();
        FibonacciHeap <TileMeta> heap = new FibonacciHeap <TileMeta>();

        tileMap.Add(center, heap.Push(new TileMeta(center, 0)));

        while (!heap.IsEmpty())
        {
            TileMeta tileMeta = heap.Pop().Value;
            Tile     tile     = tileMeta.tile;

            tiles.Add(tile);

            int previousCost = tileMeta.value;

            foreach (Vector2Int gridPosition in GetAdjacentGridPositions(tile.x, tile.y))
            {
                tile = GetTile(gridPosition);

                if (IsAccessible(unit, tile))
                {
                    int cost = previousCost + unit.Statistics.CalculateEffectiveFatigue(tile.Cost, FatigueType.Movement);

                    if (tileMap.ContainsKey(tile))
                    {
                        FibonacciHeapNode <TileMeta> node = tileMap[tile];
                        if (cost < node.Value.value)
                        {
                            heap.Decrement(node, new TileMeta(tile, cost));
                        }
                    }
                    else if (cost <= ap)
                    {
                        tileMap.Add(tile, heap.Push(new TileMeta(tile, cost)));
                    }
                }
            }
        }

        return(tiles);
    }
        public static void Pop_EmptyHeap_ThrowsCorrectException()
        {
            var heap = new FibonacciHeap <int>();

            Assert.Throws <InvalidOperationException>(() => heap.Pop());
        }
Пример #10
0
    public static Path <T> FindPath <T>(INavGrid <T> navGrid, T start, T destination, AccessibilityPredicate IsAccessible) where T : IEquatable <T>
    {
        Vector2Int startIndices       = navGrid.GetGridPosition(start);
        Vector2Int destinationIndices = navGrid.GetGridPosition(destination);

        if (!IsAccessible(startIndices.x, startIndices.y) || !IsAccessible(destinationIndices.x, destinationIndices.y))
        {
            return(null);
        }

        if (start.Equals(destination))
        {
            return(new Path <T>(start));
        }

        int length = navGrid.Length;
        int width  = navGrid.Width;

        bool[,] closedList = new bool[length, width];

        AStarTile <T>[,] tiles = new AStarTile <T> [length, width];

        for (int x = 0; x < length; x++)
        {
            for (int y = 0; y < width; y++)
            {
                tiles[x, y].indices  = new Vector2Int(x, y);
                tiles[x, y].previous = new Vector2Int(-1, -1);
                tiles[x, y].f        = float.MaxValue;
                tiles[x, y].g        = float.MaxValue;
                tiles[x, y].h        = float.MaxValue;
            }
        }

        FibonacciHeap <AStarTile <T> > openList = new FibonacciHeap <AStarTile <T> >();
        Dictionary <Vector2Int, FibonacciHeapNode <AStarTile <T> > > openListMap = new Dictionary <Vector2Int, FibonacciHeapNode <AStarTile <T> > >();

        tiles[startIndices.x, startIndices.y].indices  = startIndices;
        tiles[startIndices.x, startIndices.y].previous = startIndices;
        tiles[startIndices.x, startIndices.y].f        = 0;
        tiles[startIndices.x, startIndices.y].g        = 0;
        tiles[startIndices.x, startIndices.y].h        = 0;

        openListMap.Add(startIndices, openList.Push(tiles[startIndices.x, startIndices.y]));

        while (!openList.IsEmpty())
        {
            AStarTile <T> current = openList.Pop().Value;

            Vector2Int currentIndices = current.indices;
            int        x = currentIndices.x;
            int        y = currentIndices.y;

            closedList[x, y] = true;

            List <Vector2Int> adjacentGridPositions = navGrid.GetAdjacentGridPositions(x, y);
            for (int i = 0; i < adjacentGridPositions.Count; i++)
            {
                Vector2Int neighborIndices = adjacentGridPositions[i];

                int xi = neighborIndices.x;
                int yi = neighborIndices.y;

                if (neighborIndices == destinationIndices)
                {
                    tiles[xi, yi].previous = currentIndices;

                    LinkedList <T> wayPoints = new LinkedList <T>();

                    while (neighborIndices != startIndices)
                    {
                        wayPoints.AddFirst(navGrid.GetTile(neighborIndices));
                        neighborIndices = tiles[neighborIndices.x, neighborIndices.y].previous;
                    }

                    return(new Path <T>(start, wayPoints));
                }

                if (closedList[xi, yi] || !IsAccessible(xi, yi))
                {
                    continue;
                }

                float gNew = current.g + MathUtility.ManhattanDistance(xi, yi, x, y);
                float hNew = MathUtility.ManhattanDistance(xi, yi, destinationIndices.x, destinationIndices.y);
                float fNew = gNew + hNew;

                if (tiles[xi, yi].f < fNew)
                {
                    continue;
                }

                tiles[xi, yi].previous = currentIndices;
                tiles[xi, yi].g        = gNew;
                tiles[xi, yi].h        = hNew;
                tiles[xi, yi].f        = fNew;

                if (!openListMap.ContainsKey(neighborIndices))
                {
                    openListMap.Add(neighborIndices, openList.Push(tiles[xi, yi]));
                }
                else
                {
                    openList.Decrement(openListMap[neighborIndices], tiles[xi, yi]);
                }
            }
        }

        return(null);
    }
Пример #11
0
        private List <TraceEvent> Sort1007(IDictionary <int, List <TraceEvent> > rawBatches)
        {
            var pending = 0;
            Span <EventBatch> batches = new EventBatch[rawBatches.Count];
            var result = new List <TraceEvent>();

            foreach (var(i, eventList) in rawBatches.Values.Select((val, i) => (i, val)))
            {
                pending   += eventList.Count;
                batches[i] = new EventBatch(eventList, false);
            }

            using var totalProgress = _registry?.Start("Sort Events", "Sort events based on states transition");
            var gs         = new Dictionary <ulong, GState>();
            var frontier   = new FibonacciHeap <OrderEvent>();
            var totalCount = pending;

            using (var progress =
                       _registry?.Start("Reorganize events", "Reorganize events based on relationship", totalProgress))
            {
                for (; pending != 0; pending--)
                {
                    if (!(progress is null))
                    {
                        progress.PercentComplete = (totalCount - pending) / (float)totalCount;
                    }

                    for (var i = 0; i < rawBatches.Count; i++)
                    {
                        ref var b = ref batches[i];
                        if (b.Selected || !b.HasMore())
                        {
                            continue;
                        }
                        var ev = b.Head;
                        var(g, init, next) = StateTransition(ev);
                        if (!TransitionReady(g, gs.GetValueOrDefault(g), init))
                        {
                            continue;
                        }
                        frontier.Add(new OrderEvent(ev, i, g, init, next));
                        b.MoveNext();
                        b.Selected = true;
                        switch (ev.Type)
                        {
                        case EventType.GoStartLocal:
                            ev.Type = EventType.GoStart;
                            break;

                        case EventType.GoUnblockLocal:
                            ev.Type = EventType.GoUnblock;
                            break;

                        case EventType.GoSysExitLocal:
                            ev.Type = EventType.GoSysExit;
                            break;
                        }
                    }

                    if (frontier.Count == 0)
                    {
                        throw new InvalidTraceException("no consistent ordering of events possible");
                    }
                    var f = frontier.Pop();
                    Transition(gs, f.G, f.Init, f.Next);
                    result.Add(f.Event);
                    if (!batches[f.Batch].Selected)
                    {
                        throw new Exception("frontier batch is not selected");
                    }
                    batches[f.Batch].Selected = false;
                }
            }
Пример #12
0
        public override IPath FindPath(Grid grid, Location start, Location goal)
        {
            OnStarted();

            Statistics.Reset();
            Statistics.TotalGridNodes = grid.Width * grid.Height;
            Statistics.StartTimer();

            if (!ValidateGoal(grid, goal))
            {
                var p = new Path(start, start);
                p.PushBack(start);
                OnPathNotFound();

                return(p);
            }

            var openList  = new FibonacciHeap <uint, Location>(0);
            var isClosed  = new bool[grid.Width, grid.Height];
            var soFarCost = new uint[grid.Width, grid.Height];
            var parents   = new Location?[grid.Width, grid.Height];
            var queueNode = new IPair <uint, Location> [grid.Width, grid.Height];
            var hotspot   = start;

            queueNode[start.X, start.Y] = openList.Push(0, hotspot);

            var adjacents = new Location[8];

            while (hotspot != goal)
            {
                Statistics.UpdateMaximumOpenNodes((uint)openList.Count);

                if (openList.Count <= 0)
                {
                    OnPathNotFound();
                    return(null);
                }

                hotspot = openList.Pop().Value;
                isClosed[hotspot.X, hotspot.Y] = true;
                Statistics.AddClosedNode();

                SetAdjacentArray(adjacents, hotspot);

                for (var i = 0; i < adjacents.Length; i++)
                {
                    var pos = adjacents[i];

                    if (ProbeMode == EProbeMode.FourDirections &&
                        pos.X != hotspot.X &&
                        pos.Y != hotspot.Y)
                    {
                        continue;
                    }

                    if (grid.InBounds(pos) &&
                        hotspot != pos &&
                        grid[pos] &&
                        !isClosed[pos.X, pos.Y])
                    {
                        if (!HasCornerBetween(grid, hotspot, pos) &&
                            !HasDiagonalWall(grid, hotspot, pos))
                        {
                            if (queueNode[pos.X, pos.Y] == null)
                            {
                                parents[pos.X, pos.Y] = hotspot;

                                var scoreH = CalculateHeuristicCost(pos, goal);
                                var scoreG = soFarCost[hotspot.X, hotspot.Y] + CalculateDistance(pos, hotspot);
                                var score  = scoreH + scoreG;

                                queueNode[pos.X, pos.Y] = openList.Push(score, pos);
                                soFarCost[pos.X, pos.Y] = scoreG;

                                Statistics.AddOpenedNode();
                            }
                            else
                            {
                                if (!parents[pos.X, pos.Y].HasValue)
                                {
                                    continue;
                                }

                                var currentParent = parents[pos.X, pos.Y].Value;
                                var currentScoreG = soFarCost[currentParent.X, currentParent.Y]
                                                    + CalculateDistance(pos, currentParent);

                                var newScoreG = soFarCost[hotspot.X, hotspot.Y]
                                                + CalculateDistance(pos, hotspot);

                                if (newScoreG < currentScoreG)
                                {
                                    parents[pos.X, pos.Y]   = hotspot;
                                    soFarCost[pos.X, pos.Y] = newScoreG;

                                    var score = newScoreG + CalculateHeuristicCost(pos, goal);

                                    openList.DecreaseKey(queueNode[pos.X, pos.Y], score);
                                }
                            }
                        }
                    }

                    OnIteration();
                    Statistics.AddIteration();
                }
            }

            Statistics.PathCost = soFarCost[hotspot.X, hotspot.Y];

            var      inverter = new Stack <Location>();
            Location?aux      = hotspot;

            while (aux.HasValue)
            {
                inverter.Push(aux.Value);
                aux = parents[aux.Value.X, aux.Value.Y];
            }

            var path = new Path(start, goal);

            while (inverter.Count > 0)
            {
                path.PushBack(inverter.Pop());
            }

            OnPathFound();
            Statistics.StopTimer();
            Statistics.PathLength = path.Size;

            return(path);
        }