コード例 #1
0
        /// <summary>
        /// Gets the minimum-weight path to a goal using the A* algorithm.
        /// </summary>
        /// <remarks>Because the heuristic is not known to be consistent, we cannot 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 possibly-inconsistent heuristic function.</param>
        /// <returns>The minimum-weight path, or null if none exists.</returns>
        private static IWeighted <IEnumerable <TNode> > AStarInconsistent <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> > >();

            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);
                foreach (var uv in next(u))
                {
                    var v     = uv.Value;
                    var key_v = key(v);
                    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);
        }
コード例 #2
0
        /// <summary>
        /// Gets the minimum-weight path to a goal using uniform cost search.
        /// </summary>
        /// <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>
        /// <returns>The minimum-weight path, or null if none exists.</returns>
        public static IWeighted <IEnumerable <TNode> > UniformCostSearch <TNode, TKey>(
            this IEnumerable <IWeighted <TNode> > sources,
            Func <TNode, TKey> key,
            Func <TNode, IEnumerable <IWeighted <TNode> > > next,
            Func <TNode, bool> goal)
        {
            var came_from   = new Dictionary <TKey, TNode>();
            var open_lookup = new Dictionary <TKey, IPriorityQueueHandle <double, TNode> >();
            IPriorityQueue <double, TNode> open_queue = new PairingHeap <double, TNode>();
            var closed = new HashSet <TKey>();

            foreach (var source in sources)
            {
                var u   = source.Value;
                var g_u = source.Weight;
                open_lookup.Add(key(u), open_queue.Add(g_u, u));
            }
            while (open_queue.Count > 0)
            {
                var handle_u = open_queue.Min;
                var u        = handle_u.Value;
                var key_u    = key(u);
                var g_u      = handle_u.Key;
                if (goal(u))
                {
                    var path = ReconstructPath(key, came_from, u);
                    return(new Weighted <IEnumerable <TNode> >(path, g_u));
                }
                open_lookup.Remove(key_u);
                open_queue.Remove(handle_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;
                    }
                    IPriorityQueueHandle <double, TNode> v_handle;
                    var g_uv = g_u + uv.Weight;
                    if (open_lookup.TryGetValue(key_v, out v_handle))
                    {
                        if (g_uv < v_handle.Key)
                        {
                            open_queue.UpdateKey(v_handle, g_uv);
                            came_from[key_v] = u;
                        }
                    }
                    else
                    {
                        open_lookup.Add(key_v, open_queue.Add(g_uv, v));
                        came_from[key_v] = u;
                    }
                }
            }
            return(null);
        }
コード例 #3
0
        public IEnumerable<Tuple<Word, int>> Derive()
        {
            var derivedWords = new HashSet<string>();
            var pq = new PairingHeap<Word, int>();

            pq.Add(new Word(Grammar.StartSymbol), 0);

            var rules = Grammar.Rules.OrderBy(r => r.WordToInsert.Length - r.WordToReplace.Length).ToArray();

            while (pq.Count > 0)
            {
                var elementToDerive = pq.Min;
                pq.Remove(elementToDerive);

                var wordToDerive = elementToDerive.Key;

                foreach (var nw in rules.SelectMany(rule => wordToDerive.ReplaceAll(rule.WordToReplace, rule.WordToInsert))
                        .Where(nw => !derivedWords.Contains(nw.ToString())))
                {
                    derivedWords.Add(nw.ToString());
                    pq.Add(nw, nw.Length);

                    yield return Tuple.Create(nw, wordToDerive.Length);
                }
            }
        }