/// <summary>
        /// Creates a new empty beats event queue with the specified way to compute current time.
        /// </summary>
        /// <param name="currentBeatsTimeFunction">The func for computing the current beats time.</param>
        public BeatsBasedEventQueue(Func <double> currentBeatsTimeFunction)
        {
            if (currentBeatsTimeFunction == null)
            {
                throw new ArgumentNullException(nameof(currentBeatsTimeFunction));
            }

            CurrentBeatsTimeFunction = currentBeatsTimeFunction;
            EventQueue = new C5.IntervalHeap <IBeatEvent>(10, new IBeatsEventComparer());
        }
        static State AStar(State initial)

        {
            IComparer <State>      comparer   = new Comparer <State>();
            IPriorityQueue <State> candidates = new C5.IntervalHeap <State>(comparer);

            System.Collections.Generic.HashSet <string> visitedStates = new System.Collections.Generic.HashSet <string>();

            //initialize state
            candidates.Add(initial);
            visitedStates.Add(initial.ToString());

            while (candidates.Count > 0)
            {
                State currentBest = candidates.DeleteMin();

                if (currentBest.GetManhattanDistance() == 0)
                {
                    return(currentBest);
                }

                // move right
                if (currentBest.PositionOf0.Y > 0)
                {
                    var newPositionof0 = new Point(currentBest.PositionOf0.X, currentBest.PositionOf0.Y - 1);
                    AddCandidate(currentBest, newPositionof0, visitedStates, candidates);
                }

                //move left
                if (currentBest.PositionOf0.Y < State.N - 1)
                {
                    var newPositionof0 = new Point(currentBest.PositionOf0.X, currentBest.PositionOf0.Y + 1);
                    AddCandidate(currentBest, newPositionof0, visitedStates, candidates);
                }

                //move down
                if (currentBest.PositionOf0.X > 0)
                {
                    Point newPositionof0 = new Point(currentBest.PositionOf0.X - 1, currentBest.PositionOf0.Y);
                    AddCandidate(currentBest, newPositionof0, visitedStates, candidates);
                }

                // move up
                if (currentBest.PositionOf0.X < State.N - 1)
                {
                    Point newPositionof0 = new Point(currentBest.PositionOf0.X + 1, currentBest.PositionOf0.Y);
                    AddCandidate(currentBest, newPositionof0, visitedStates, candidates);
                }
            }

            return(null);//this should never be reached but the compilator requires it
        }
        public Path GetShortestPath(string from, string to)
        {
            var fromNode = _nodes[from];
            var toNode   = _nodes[to];
            Dictionary <Node, int> distances = new Dictionary <Node, int>();

            foreach (var node in _nodes.Values)
            {
                distances.Add(node, int.MaxValue);
            }

            distances[fromNode] = 0;

            IntervalHeap <NodeEntry> queue = new C5.IntervalHeap <NodeEntry>();

            queue.Add(new NodeEntry(fromNode, 0));

            Dictionary <Node, Node> previousNode = new Dictionary <Node, Node>();

            System.Collections.Generic.HashSet <Node> visited = new System.Collections.Generic.HashSet <Node>();
            while (queue.Count != 0)
            {
                var current = queue.DeleteMin().node;
                visited.Add(current);

                foreach (var edge in current.Edges)
                {
                    if (visited.Contains(edge.to))
                    {
                        continue;
                    }

                    var newDistance = distances[current] + edge.weight;
                    if (newDistance < distances[edge.to])
                    {
                        distances[edge.to] = newDistance;
                        previousNode.Add(edge.to, current);
                        queue.Add(new NodeEntry(edge.to, newDistance));
                    }
                }
            }
            return(BuildPath(previousNode, toNode));
        }