public void Count_2Node_2Count()
        {
            var fh = new FibonacciHeap <int>();

            fh.Push(7);
            fh.Push(8);

            Assert.AreEqual(2, fh.Count);
        }
Example #2
0
        public void Peek_2NodesSmallerLast_CorrectValue()
        {
            var fh = new FibonacciHeap <int>();

            fh.Push(3);
            fh.Push(2);

            Assert.AreEqual(2, fh.Peek());
        }
        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_TryIncreaseKey_ThrowsCorrectException()
        {
            var heap = new FibonacciHeap <int>();
            var item = heap.Push(1);

            Assert.Throws <InvalidOperationException>(() => heap.DecreaseKey(item, 2));
        }
Example #5
0
        public void Peek_1Node_CorrectValue()
        {
            var fh = new FibonacciHeap <int>();

            fh.Push(3);

            Assert.AreEqual(3, fh.Peek());
        }
        public void Count_1Node_1Count()
        {
            var fh = new FibonacciHeap <int>();

            fh.Push(7);

            Assert.AreEqual(1, fh.Count);
        }
        public void PopMin_2Nodes_CorrectNode()
        {
            var fh = new FibonacciHeap <int>();

            fh.Push(7);
            fh.Push(6);

            var first  = fh.PopMin();
            var second = fh.PopMin();

            Assert.Multiple(() =>
            {
                Assert.AreEqual(6, first);
                Assert.AreEqual(7, second);

                Assert.Throws <HeapEmptyException>(() => fh.PopMin());
            });
        }
Example #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 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;
            }
        }
        private static FibonacciHeap <int> BuildTestHeap()
        {
            var heap  = new FibonacciHeap <int>();
            var elems = new[] { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };

            foreach (var i in elems)
            {
                heap.Push(i);
            }

            return(heap);
        }
        public void PopMin_1Node_CorrectNode()
        {
            var fh = new FibonacciHeap <int>();

            fh.Push(7);
            var actual = fh.PopMin();

            Assert.Multiple(() =>
            {
                Assert.AreEqual(7, actual);

                Assert.Throws <HeapEmptyException>(() => fh.PopMin());
            });
        }
Example #12
0
        public void Peek_MultipleValues_CorrectValue(int[] sequence)
        {
            var fh = new FibonacciHeap <int>();

            foreach (var value in sequence)
            {
                if (value < 0)
                {
                    var val = fh.Peek();
                    Assert.AreEqual(System.Math.Abs(value), val);
                }
                else
                {
                    fh.Push(value);
                }
            }
        }
        public static FibonacciHeap <int> ProcessIntArray(int[] sequence)
        {
            var fh = new FibonacciHeap <int>();

            foreach (var s in sequence)
            {
                if (s < 0)
                {
                    var val = fh.PopMin();
                    Assert.AreEqual(System.Math.Abs(s), val);
                }
                else
                {
                    fh.Push(s);
                }
            }

            return(fh);
        }
        public void Count_MultipleValuesPushedAndPopped_CorrectCount(int[] sequence)
        {
            var fh    = new FibonacciHeap <int>();
            var count = 0;

            foreach (var value in sequence)
            {
                if (value < 0)
                {
                    var val = fh.PopMin();
                    Assert.AreEqual(--count, fh.Count);
                }
                else
                {
                    fh.Push(value);
                    count++;
                }
            }
        }
        public void ProcessIntArray(int[] sequence)
        {
            var fh = new FibonacciHeap <int>();

            foreach (var s in sequence)
            {
                if (s < 0)
                {
                    var val = fh.PopMin();
                    Assert.AreEqual(System.Math.Abs(s), val);
                }
                else
                {
                    fh.Push(s);
                }
            }

            Assert.Throws <HeapEmptyException>(() => fh.PopMin());
        }
Example #16
0
        public void FibonacciHeap_ShouldOrderLargeDataset()
        {
            var random = new Random(123);

            var numbers = Enumerable
                          .Range(0, 8)
                          .Select(_ => random.Next(1, 1000000))
                          .Distinct()
                          .ToList();

            var heap = new FibonacciHeap <int>();

            foreach (var i in numbers)
            {
                heap.Push(i);
            }

            foreach (var i in numbers.OrderBy(n => n))
            {
                Assert.AreEqual(i, heap.PopMin());
            }
        }
Example #17
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 void PopMin_5Nodes_CorrectNode()
        {
            var fh = new FibonacciHeap <int>();

            fh.Push(7);
            fh.Push(6);
            fh.Push(5);
            fh.Push(8);
            fh.Push(4);
            fh.Push(2);
            fh.Push(1);
            fh.Push(3);

            var first  = fh.PopMin();
            var second = fh.PopMin();
            var third  = fh.PopMin();
            var fourth = fh.PopMin();
            var fifth  = fh.PopMin();
            var sixth  = fh.PopMin();
            var seven  = fh.PopMin();
            var eigth  = fh.PopMin();

            Assert.Multiple(() =>
            {
                Assert.AreEqual(1, first);
                Assert.AreEqual(2, second);
                Assert.AreEqual(3, third);
                Assert.AreEqual(4, fourth);
                Assert.AreEqual(5, fifth);
                Assert.AreEqual(6, sixth);
                Assert.AreEqual(7, seven);
                Assert.AreEqual(8, eigth);

                Assert.Throws <HeapEmptyException>(() => fh.PopMin());
            });
        }
        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);
        }
Example #20
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);
        }
Example #21
0
        public void FibonacciHeap_ShouldPerform()
        {
            var stringBuilder = new System.Text.StringBuilder();

            stringBuilder.AppendLine();
            var mod    = 4;
            var random = new Random(123);

            var numbers = Enumerable
                          .Range(0, 200000)
                          .Select(_ => random.Next(1, 1000000))
                          .Distinct()
                          .ToList();


            var baselineTimer = Stopwatch.StartNew();
            var queueB        = new BaselinePriorityQueue <int>();

            for (var i = 0; i < numbers.Count; i++)
            {
                queueB.Push(numbers[i]);
                if (i % mod == 0)
                {
                    queueB.PopMin();
                }
            }
            baselineTimer.Stop();
            var queueElapsed = baselineTimer.ElapsedMilliseconds;

            var heapTimer = Stopwatch.StartNew();
            var heap      = new FibonacciHeap <int>();

            for (var i = 0; i < numbers.Count; i++)
            {
                heap.Push(numbers[i]);
                if (i % mod == 0)
                {
                    heap.PopMin();
                }
            }
            heapTimer.Stop();
            var heapElapsed = heapTimer.ElapsedMilliseconds;

            stringBuilder.AppendLine($"Heap: {numbers.Count} processed in {heapElapsed}ms");

            // timer = Stopwatch.StartNew();
            // var list = new List<int>();
            // for (var i = 0; i < numbers.Count; i++)
            // {
            //     list.Add(numbers[i]);
            //     if (i % mod == 0) {
            //         list.Remove(list.Min());
            //     }
            // }
            // timer.Stop();
            // stringBuilder.AppendLine($"List: {numbers.Count} processed in {timer.ElapsedMilliseconds}ms");


            var variance = ((double)heapElapsed / (double)queueElapsed) * (double)100;

            stringBuilder.AppendLine($"Queue: {numbers.Count} processed in {queueElapsed}ms");

            stringBuilder.AppendLine();
            stringBuilder.AppendLine($"variance {heapElapsed - queueElapsed}ms ({Math.Round(variance, 2)}%)");
            stringBuilder.AppendLine();

            Console.WriteLine(stringBuilder.ToString());

            // Assert.Less(heapElapsed, queueElapsed);
        }
Example #22
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);
    }
Example #23
0
        public void HeapTest2()
        {
            const int Count     = 100000;
            const int Size      = 100;
            Random    random    = new Random(0);
            Stopwatch stopwatch = new Stopwatch();

            int[] values = Enumerable.Range(0, Size).Select(x => random.Next(0, 1000000)).ToArray();

            BinaryHeap <int, int> binaryHeap = new BinaryHeap <int, int>(Size);

            stopwatch.Restart();

            for (int i = 0; i < Count; i++)
            {
                for (int j = 0, jj = random.Next(10, 100); j < jj; j++)
                {
                    binaryHeap.Push(random.Next(0, 100), 1000);
                }

                Pop(binaryHeap, random.Next(binaryHeap.Count / 2, 3 * binaryHeap.Count / 4));
            }

            Pop(binaryHeap, binaryHeap.Count);

            stopwatch.Stop();

            Console.WriteLine("{0:F4} ms", stopwatch.ElapsedMilliseconds /* / Count*/);

            FibonacciHeap <int, int> fibonacciHeap = new FibonacciHeap <int, int>(Size);

            stopwatch.Restart();

            for (int i = 0; i < Count; i++)
            {
                for (int j = 0, jj = random.Next(10, 100); j < jj; j++)
                {
                    fibonacciHeap.Push(random.Next(0, 100), 1000);
                }

                Pop(fibonacciHeap, random.Next(fibonacciHeap.Count / 2, 3 * fibonacciHeap.Count / 4));
            }

            Pop(fibonacciHeap, binaryHeap.Count);

            stopwatch.Stop();

            Console.WriteLine("{0:F4} ms", stopwatch.ElapsedMilliseconds /* / Count*/);

            SortedList <int, int> list = new SortedList <int, int>(Size, Comparer <int> .Default);

            stopwatch.Restart();

            for (int i = 0; i < Count; i++)
            {
                for (int j = 0, jj = values.Length; j < jj; j++)
                {
                    list.Add(values[j], values[j]);
                }

                while (list.Count > 0)
                {
                    list.RemoveAt(0);
                }
            }

            stopwatch.Stop();

            Console.WriteLine("{0:F4} ms", stopwatch.ElapsedMilliseconds /* / Count*/);

            void Pop(IHeap <int, int> heap, 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;
                    }
                }
            }
        }