public void Count_2Node_2Count() { var fh = new FibonacciHeap <int>(); fh.Push(7); fh.Push(8); Assert.AreEqual(2, fh.Count); }
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)); }
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()); }); }
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()); }); }
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()); }
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()); } }
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); }
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); }
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); }
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); }
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; } } } }