寻找A *搜索的加速

时间:2012-03-07 22:38:38

标签: a-star

我在C#中有以下工作A *代码:

static bool AStar(
    IGraphNode start,
    Func<IGraphNode, bool> check,
    out List<IGraphNode> path)
{
    // Closed list. Hashset because O(1).
    var closed =
        new HashSet<IGraphNode>();
    // Binary heap which accepts multiple equivalent items.
    var frontier =
        new MultiHeap<IGraphNode>(
            (a, b) =>
            { return Math.Sign(a.TotalDistance - b.TotalDistance); }
            );
    // Some way to know how many multiple equivalent items there are.
    var references =
        new Dictionary<IGraphNode, int>();
    // Some way to know which parent a graph node has.
    var parents =
        new Dictionary<IGraphNode, IGraphNode>();

    // One new graph node in the frontier,
    frontier.Insert(start);
    // Count the reference.
    references[start] = 1;

    IGraphNode current = start;

    do
    {

        do
        {
            frontier.Get(out current);
            // If it's in the closed list or
            // there's other instances of it in the frontier,
            // and there's still nodes left in the frontier,
            // then that's not the best node.
        } while (
            (closed.Contains(current) ||
            (--references[current]) > 0) &&
            frontier.Count > 0
            );

        // If we have run out of options,
        if (closed.Contains(current) && frontier.Count == 0)
        {
            // then there's no path.
            path = null;
            return false;
        }


        closed.Add(current);
        foreach (var edge in current.Edges)
        {
            // If there's a chance of a better path
            // to this node,
            if (!closed.Contains(edge.End))
            {
                int count;
                // If the frontier doesn't contain this node,
                if (!references.TryGetValue(edge.End, out count) ||
                    count == 0)
                {
                    // Initialize it and insert it.
                    edge.End.PathDistance =
                        current.PathDistance + edge.Distance;
                    edge.End.EstimatedDistance = CalcDistance(edge.End);
                    parents[edge.End] = current;
                    frontier.Insert(edge.End);
                    references[edge.End] = 1;
                }
                else
                {
                    // If this path is better than the existing path,
                    if (current.PathDistance + edge.Distance <
                        edge.End.PathDistance)
                    {
                        // Use this path.
                        edge.End.PathDistance = current.PathDistance +
                            edge.Distance;
                        parents[edge.End] = current;
                        frontier.Insert(edge.End);
                        // Keeping track of multiples equivalent items.
                        ++references[edge.End];
                    }
                }
            }
        }
    } while (!check(current) && frontier.Count > 0);

    if (check(current))
    {
        path = new List<IGraphNode>();
        path.Add(current);
        while (current.PathDistance != 0)
        {
            current = parents[current];
            path.Add(current);
        }
        path.Reverse();
        return true;
    }

    // Yep, no path.
    path = null;
    return false;
}

如何让它更快?请没有代码样本;这是我自己设定的挑战。

编辑:为了澄清,我正在寻找适用于A *的任何建议,建议,链接等。代码只是一个例子。我没有要求代码样本,因为它们太容易实现所描述的技术。

感谢。

2 个答案:

答案 0 :(得分:2)

你看过this page还是this page了吗?他们提供了大量有用的优化技巧以及一般A *的一些重要信息。

答案 1 :(得分:0)

更改为使用随机可聚合队列作为堆结构。既然你想要编程挑战,我不会告诉你如何将递归的Meld方法改为不递归。这就是让速度超出这个结构的诀窍。更多信息在Gambin的论文“Randomized Meldable Priority Queues”中(在网上搜索)。