Shields.Graphs/Graph.cs
/// <summary>
/// Gets the minimum-weight path to a goal using the A* algorithm.
/// </summary>
/// <remarks>Because the heuristic is known to be consistent, we can use the closed set optimization.</remarks>
/// <typeparam name="TNode">The type of a node.</typeparam>
/// <typeparam name="TKey">The type of a node key.</typeparam>
/// <param name="sources">The set of nodes from which to start the search, weighted by their initial cost.</param>
/// <param name="key">The function which maps a node to its key.</param>
/// <param name="next">The function which maps a node to its adjacent nodes.</param>
/// <param name="goal">The goal predicate.</param>
/// <param name="heuristic">The consistent heuristic function.</param>
/// <returns>The minimum-weight path, or null if none exists.</returns>
Gets the minimum-weight path to a goal using the A* algorithm.
Gets the minimum - weight path to a goal using the A * algorithm .
private static Weighted<IEnumerable<TNode>> AStarConsistent<TNode, TKey>(
            IEnumerable<IWeighted<TNode>> sources,
            Func<TNode, TKey> key,
            Func<TNode, IEnumerable<IWeighted<TNode>>> next,
            Func<TNode, bool> goal,
            Func<TNode, double> heuristic)
        {
            var came_from = new Dictionary<TKey, TNode>();
            IPriorityQueue<double, AStarOpen<TNode>> open_queue = new PairingHeap<double, AStarOpen<TNode>>();
            var open_lookup = new Dictionary<TKey, IPriorityQueueHandle<double, AStarOpen<TNode>>>();
            var closed = new HashSet<TKey>();
            foreach (var source in sources)
            {
                var u = source.Value;
                var key_u = key(u);
                var g_u = source.Weight;
                var f_u = g_u + heuristic(u);
                var open_u = new AStarOpen<TNode>(u, g_u);
                open_u.Handle = open_queue.Add(f_u, open_u);
                open_lookup.Add(key_u, open_u.Handle);
            }
            while (open_queue.Count > 0)
            {
                var handle_u = open_queue.Min;
                var u = handle_u.Value.Node;
                var key_u = key(u);
                if (goal(u))
                {
                    var path = ReconstructPath(key, came_from, u);
                    return new Weighted<IEnumerable<TNode>>(path, handle_u.Value.G);
                }
                open_queue.Remove(handle_u);
                open_lookup.Remove(key_u);
                closed.Add(key_u);
                foreach (var uv in next(u))
                {
                    var v = uv.Value;
                    var key_v = key(v);
                    if (closed.Contains(key_v))
                    {
                        continue;
                    }
                    var g_v = handle_u.Value.G + uv.Weight;
                    var f_v = g_v + heuristic(v);
                    IPriorityQueueHandle<double, AStarOpen<TNode>> handle_v;
                    if (open_lookup.TryGetValue(key_v, out handle_v))
                    {
                        if (f_v < handle_v.Key)
                        {
                            open_queue.UpdateKey(handle_v, f_v);
                            handle_v.Value.G = g_v;
                            came_from[key_v] = u;
                        }
                    }
                    else
                    {
                        var open_v = new AStarOpen<TNode>(v, g_v);
                        open_v.Handle = open_queue.Add(f_v, open_v);
                        open_lookup.Add(key_v, open_v.Handle);
                        came_from[key_v] = u;
                    }
                }
            }
            return null;
        }
private static Weighted < IEnumerable < TNode > > AStarConsistent < TNode , TKey > ( IEnumerable < IWeighted < TNode > > sources , Func < TNode , TKey > key , Func < TNode , IEnumerable < IWeighted < TNode > > > next , Func < TNode , bool > goal , Func < TNode , double > heuristic ) { var came_from = new Dictionary < TKey , TNode > ( ) ; IPriorityQueue < double , AStarOpen < TNode > > open_queue = new PairingHeap < double , AStarOpen < TNode > > ( ) ; var open_lookup = new Dictionary < TKey , IPriorityQueueHandle < double , AStarOpen < TNode > > > ( ) ; var closed = new HashSet < TKey > ( ) ; foreach ( var source in sources ) { var u = source . Value ; var key_u = key ( u ) ; var g_u = source . Weight ; var f_u = g_u + heuristic ( u ) ; var open_u = new AStarOpen < TNode > ( u , g_u ) ; open_u . Handle = open_queue . Add ( f_u , open_u ) ; open_lookup . Add ( key_u , open_u . Handle ) ; } while ( open_queue . Count > 0 ) { var handle_u = open_queue . Min ; var u = handle_u . Value . Node ; var key_u = key ( u ) ; if ( goal ( u ) ) { var path = ReconstructPath ( key , came_from , u ) ; return new Weighted < IEnumerable < TNode > > ( path , handle_u . Value . G ) ; } open_queue . Remove ( handle_u ) ; open_lookup . Remove ( key_u ) ; closed . Add ( key_u ) ; foreach ( var uv in next ( u ) ) { var v = uv . Value ; var key_v = key ( v ) ; if ( closed . Contains ( key_v ) ) { continue ; } var g_v = handle_u . Value . G + uv . Weight ; var f_v = g_v + heuristic ( v ) ; IPriorityQueueHandle < double , AStarOpen < TNode > > handle_v ; if ( open_lookup . TryGetValue ( key_v , out handle_v ) ) { if ( f_v < handle_v . Key ) { open_queue . UpdateKey ( handle_v , f_v ) ; handle_v . Value . G = g_v ; came_from [ key_v ] = u ; } } else { var open_v = new AStarOpen < TNode > ( v , g_v ) ; open_v . Handle = open_queue . Add ( f_v , open_v ) ; open_lookup . Add ( key_v , open_v . Handle ) ; came_from [ key_v ] = u ; } } } return null ; }
Gets the minimum-weight path to a goal using the A* algorithm.
Gets the minimum - weight path to a goal using the A * algorithm .
The minimum-weight path, or null if none exists.
The minimum - weight path or null if none exists .
sources
IEnumerable<IWeighted<TNode>>
The set of nodes from which to start the search, weighted by their initial cost.
The set of nodes from which to start the search weighted by their initial cost .
key
Func<TNode, TKey>
The function which maps a node to its key.
The function which maps a node to its key .
next
Func<TNode, IEnumerable<IWeighted<TNode>>>
The function which maps a node to its adjacent nodes.
The function which maps a node to its adjacent nodes .
goal
Func<TNode, bool>
The goal predicate.
The goal predicate .
heuristic
Func<TNode, double>
The consistent heuristic function.
The consistent heuristic function .
remarks
Because the heuristic is known to be consistent, we can use the closed set optimization.
Because the heuristic is known to be consistent we can use the closed set optimization .
typeparam
The type of a node.
The type of a node .
typeparam
The type of a node key.
The type of a node key .