Пример #1
0
        static void TestCase4()
        {
            var random = new Random();
            var myHeap = new FibonacciHeap<double>(int.MinValue, Comparer<double>.Default);
            var thirdPartyHeap = new FastPriorityQueue<FastPriorityQueueNode>(1000);

            for (var i = 0; i < 1000; i++)
            {
                if (random.Next(3) == 0 && thirdPartyHeap.Any())
                {
                    var myResult = myHeap.ExtractMin();
                    var otherResult = thirdPartyHeap.Dequeue();
                    Assert(myResult.Item1);
                    Assert(Math.Abs(myResult.Item2 - otherResult.Priority) < double.Epsilon);
                }
                else
                {
                    var value = random.NextDouble()*10;
                    myHeap.Insert(value);
                    thirdPartyHeap.Enqueue(new FastPriorityQueueNode(), value);
                }
            }

            while (thirdPartyHeap.Any())
            {
                var myResult = myHeap.ExtractMin();
                var otherResult = thirdPartyHeap.Dequeue();
                Assert(myResult.Item1);
                Assert(Math.Abs(myResult.Item2 - otherResult.Priority) < double.Epsilon);
            }
        }
Пример #2
0
        public static int Dijkstra(Vertex from, Vertex to, Graph graph)
        {
            HashSet<Vertex> visited = new HashSet<Vertex>();
            Dictionary<Vertex, FibonacciHeap<int, Vertex>.Node> nodes = new Dictionary<Vertex, FibonacciHeap<int, Vertex>.Node>();
            FibonacciHeap<int, Vertex> labels = new FibonacciHeap<int, Vertex>();
            // Initialize labels.
            foreach (var vertex in graph.Vertices)
            {
                var n = labels.Add(vertex == from ? 0 : int.MaxValue, vertex);
                nodes.Add(vertex, n);
            }

            int currentLabel = int.MaxValue;
            while (!visited.Contains(to))
            {
                var currentNode = labels.ExtractMin();
                var current = currentNode.Value;
                currentLabel = currentNode.Key;

                // Consider all edges ending in unvisited neighbours
                var edges =
                    graph.GetEdgesForVertex(current).Where(x => !visited.Contains(x.Other(current)));
                // Update labels on the other end.
                foreach (var edge in edges)
                {
                    if (currentNode.Key + edge.Cost < nodes[edge.Other(current)].Key)
                        labels.DecreaseKey(nodes[edge.Other(current)], currentNode.Key + edge.Cost);
                }

                visited.Add(current);
            }

            return currentLabel;
        }
Пример #3
0
    public IList <ILevelTile> CalculatePath(ILevelTile from, ILevelTile to)
    {
        target       = to;
        openNodes    = new FibonacciHeap <float>();
        closedNodes  = new HashSet <AStarNode>();
        tilesToNodes = new Dictionary <ILevelTile, AStarNode>();

        AStarNode startNode = new AStarNode(from, heuristic.GetDistance(from.CenterPos, to.CenterPos));

        startNode.cost = 0;
        tilesToNodes.Add(from, startNode);
        openNodes.Insert(startNode);

        do
        {
            AStarNode currNode = (AStarNode)openNodes.ExtractMin();
            if (currNode.tile.Equals(to))
            {
                return(GetPathToNode(currNode));
            }

            closedNodes.Add(currNode);

            ExpandNode(currNode);
        } while (openNodes.IsEmpty() == false);

        // No path found
        return(null);
    }
    public void ConsolidatedHeapExtractMin_CorrectConsolidation()
    {
        // Create consolidated heap
        FibonacciHeap <int> heap  = new FibonacciHeap <int>();
        IList <int>         input = new List <int>()
        {
            0,
            28,
            -13,
            80,
            3,
            7,
            -7,
            42,
            -11,
            12
        };

        IList <int> expectedElementOrder = new List <int>()
        {
            7,
            42,
            12,
            28,
            80,
            3,
            0,
            -7
        };

        foreach (int value in input)
        {
            heap.Insert(value);
        }
        heap.ExtractMin();

        // Trigger second consolidation
        heap.ExtractMin();

        IList <int> result = heap.GetAllValues();

        for (int i = 0; i < expectedElementOrder.Count; ++i)
        {
            NUnit.Framework.Assert.IsTrue(expectedElementOrder[i] == result[i]);
        }
        NUnit.Framework.Assert.IsTrue(heap.GetMin() == -7);
    }
    public void ConsolidatedHeapDecreaseKey_CorrectCuts()
    {
        FibonacciHeap <int>          heap  = new FibonacciHeap <int>();
        IList <FibonacciNode <int> > input = new List <FibonacciNode <int> >()
        {
            new FibonacciNode <int>(0),
            new FibonacciNode <int>(28),
            new FibonacciNode <int>(-13),
            new FibonacciNode <int>(80),
            new FibonacciNode <int>(3),
            new FibonacciNode <int>(7),
            new FibonacciNode <int>(-7),
            new FibonacciNode <int>(42),
            new FibonacciNode <int>(-11),
            new FibonacciNode <int>(12)
        };

        IList <int> expectedElementOrder = new List <int>()
        {
            7,
            -8,
            -11,
            12,
            -42,
            80,
            -1,
            -3,
            0
        };

        foreach (FibonacciNode <int> value in input)
        {
            heap.Insert(value);
        }
        heap.ExtractMin();

        // A decrease key with no structural changes
        heap.DecreaseKey(input[6], -8);

        // Normal cuts with parent marked
        heap.DecreaseKey(input[7], -42);
        heap.DecreaseKey(input[4], -1);

        // Double cascading cut
        heap.DecreaseKey(input[1], -3);

        IList <int> result = heap.GetAllValues();

        for (int i = 0; i < expectedElementOrder.Count; ++i)
        {
            NUnit.Framework.Assert.IsTrue(expectedElementOrder[i] == result[i]);
        }
        NUnit.Framework.Assert.IsTrue(heap.GetMin() == -42);
    }
Пример #6
0
        public static Path DijkstraPath(Vertex from, Vertex to, Graph graph)
        {
            HashSet<Vertex> visited = new HashSet<Vertex>();
            Dictionary<Vertex, FibonacciHeap<int, Vertex>.Node> nodes =
                new Dictionary<Vertex, FibonacciHeap<int, Vertex>.Node>();
            Dictionary<Vertex, Edge> comingFrom = new Dictionary<Vertex, Edge>();
            FibonacciHeap<int, Vertex> labels = new FibonacciHeap<int, Vertex>();
            // Initialize labels.
            foreach (var vertex in graph.Vertices)
            {
                var n = labels.Add(vertex == from ? 0 : int.MaxValue, vertex);
                nodes.Add(vertex, n);
                comingFrom.Add(vertex, null);
            }

            while (!visited.Contains(to))
            {
                var currentNode = labels.ExtractMin();
                var current = currentNode.Value;

                // Consider all edges ending in unvisited neighbours
                var edges =
                    graph.GetEdgesForVertex(current).Where(x => !visited.Contains(x.Other(current)));
                // Update labels on the other end.
                foreach (var edge in edges)
                {
                    if (currentNode.Key + edge.Cost < nodes[edge.Other(current)].Key)
                    {
                        labels.DecreaseKey(nodes[edge.Other(current)], currentNode.Key + edge.Cost);
                        comingFrom[edge.Other(current)] = edge;
                    }
                }

                visited.Add(current);
            }

            // Now travel back, to find the actual path
            List<Edge> pathEdges = new List<Edge>();
            Vertex pathVertex = to;
            while (pathVertex != from)
            {
                pathEdges.Add(comingFrom[pathVertex]);
                pathVertex = comingFrom[pathVertex].Other(pathVertex);
            }

            pathEdges.Reverse();
            Path path = new Path(from);
            path.Edges.AddRange(pathEdges);
            return path;
        }
    public void UnconsolidatedHeapExtractMin_CorrectValue()
    {
        FibonacciNode <int> node  = new FibonacciNode <int>(-20);
        FibonacciHeap <int> heap  = new FibonacciHeap <int>();
        IList <int>         input = new List <int>()
        {
            0,
            28,
            -13,
            80
        };

        heap.Insert(node);
        foreach (int value in input)
        {
            heap.Insert(value);
        }

        NUnit.Framework.Assert.IsTrue(heap.ExtractMin() == node);
        NUnit.Framework.Assert.IsTrue(heap.GetMin() == -13);
        NUnit.Framework.Assert.IsTrue(heap.GetAllValues().Count == input.Count);
    }
    public void EmptyHeapExtractMin_ReturnsNull()
    {
        FibonacciHeap <int> heap = new FibonacciHeap <int>();

        NUnit.Framework.Assert.Null(heap.ExtractMin());
    }
Пример #9
0
        public static Dictionary<Vertex, Path> DijkstraPathToAll(Vertex from, Graph graph, bool onlyTerminals)
        {
            Dictionary<Vertex, Edge> comingFrom = new Dictionary<Vertex, Edge>();
            HashSet<Vertex> visited = new HashSet<Vertex>();
            Dictionary<Vertex, FibonacciHeap<int, Vertex>.Node> nodes =
                new Dictionary<Vertex, FibonacciHeap<int, Vertex>.Node>();
            Dictionary<Vertex, Path> paths = new Dictionary<Vertex, Path>();
            FibonacciHeap<int, Vertex> labels = new FibonacciHeap<int, Vertex>();
            // Initialize labels.
            foreach (var vertex in graph.Vertices)
            {
                var n = labels.Add(vertex == from ? 0 : int.MaxValue, vertex);
                nodes.Add(vertex, n);
            }

            while (paths.Count < (onlyTerminals ? graph.Terminals.Count - 1 : graph.NumberOfVertices - 1))
            {
                var currentNode = labels.ExtractMin();
                var current = currentNode.Value;

                // Consider all edges ending in unvisited neighbours
                var edges =
                    graph.GetEdgesForVertex(current).Where(x => !visited.Contains(x.Other(current)));
                // Update labels on the other end.
                foreach (var edge in edges)
                {
                    if (currentNode.Key + edge.Cost < nodes[edge.Other(current)].Key)
                    {
                        labels.DecreaseKey(nodes[edge.Other(current)], currentNode.Key + edge.Cost);
                        comingFrom[edge.Other(current)] = edge;
                    }
                }

                visited.Add(current);
                if (current != from && (!onlyTerminals || graph.Terminals.Contains(current)))
                {
                    // Travel back the path
                    List<Edge> pathEdges = new List<Edge>();
                    Vertex pathVertex = current;
                    while (pathVertex != from)
                    {
                        pathEdges.Add(comingFrom[pathVertex]);
                        pathVertex = comingFrom[pathVertex].Other(pathVertex);
                    }

                    pathEdges.Reverse();
                    Path path = new Path(from);
                    path.Edges.AddRange(pathEdges);
                    paths[current] = path;
                }
            }

            return paths;
        }
Пример #10
0
        public static List<Path> NearestTerminals(Vertex from, Graph graph, int n)
        {
            List<Path> foundPaths = new List<Path>();
            HashSet<Vertex> visited = new HashSet<Vertex>();
            Dictionary<Vertex, FibonacciHeap<int, Vertex>.Node> nodes = new Dictionary<Vertex, FibonacciHeap<int, Vertex>.Node>();
            FibonacciHeap<int, Vertex> labels = new FibonacciHeap<int, Vertex>();
            Dictionary<Vertex, Edge> comingFrom = new Dictionary<Vertex, Edge>();

            if (graph.Terminals.Contains(from))
                foundPaths.Add(new Path(from));

            // Initialize labels.
            foreach (var vertex in graph.Vertices)
            {
                var node = labels.Add(vertex == from ? 0 : int.MaxValue, vertex);
                nodes.Add(vertex, node);
                comingFrom.Add(vertex, null);
            }

            while (!labels.IsEmpty() && foundPaths.Count < n)
            {
                var currentNode = labels.ExtractMin();
                var current = currentNode.Value;

                // Consider all edges ending in unvisited neighbours
                var edges =
                    graph.GetEdgesForVertex(current).Where(x => !visited.Contains(x.Other(current)));
                // Update labels on the other end.
                foreach (var edge in edges)
                {
                    if (currentNode.Key + edge.Cost < nodes[edge.Other(current)].Key)
                    {
                        labels.DecreaseKey(nodes[edge.Other(current)], currentNode.Key + edge.Cost);
                        comingFrom[edge.Other(current)] = edge;
                    }
                }

                visited.Add(current);

                if (graph.Terminals.Contains(current) && current != from)
                {
                    // Now travel back, to find the actual path
                    List<Edge> pathEdges = new List<Edge>();
                    Vertex pathVertex = current;
                    while (pathVertex != from)
                    {
                        pathEdges.Add(comingFrom[pathVertex]);
                        pathVertex = comingFrom[pathVertex].Other(pathVertex);
                    }

                    pathEdges.Reverse();
                    Path path = new Path(from);
                    path.Edges.AddRange(pathEdges);
                    foundPaths.Add(path);
                }
            }

            return foundPaths;
        }