代码之家  ›  专栏  ›  技术社区  ›  Marc

A*寻路-欧几里德距离启发式表现比对角线距离差

  •  2
  • Marc  · 技术社区  · 8 年前

    我根据以下内容实现了A*寻路算法: https://www.redblobgames.com/pathfinding/a-star/introduction.html

    我的网格有很多障碍(超过一万个),而且非常大。我知道,为了获得一条最短路径,我需要实现一个可接受的启发式,这样就不会高估当前点与目标之间的距离。理论上,欧几里德距离必须始终小于或等于。然而,使用它,我根本得不到最短路径,因为使用对角线(切比雪夫或八进制)距离,我得到的路径更短。为什么会这样?我错过什么了吗? 代码如下:

    图表成本始终返回1

    图表邻居返回8个径向位置(如果有障碍,则返回较少)

    def a_star_search(graph, start, goal):
        frontier = PriorityQueue()
        frontier.put(start, 0)
        came_from = {}
        cost_so_far = {}
        came_from[start] = None
        cost_so_far[start] = 0
    
        while not frontier.empty():
            current = frontier.get()
    
            if current == goal:
                break
    
            for next in graph.neighbors(current):
                new_cost = cost_so_far[current] + graph.cost(current, next)
                if next not in cost_so_far or new_cost < cost_so_far[next]:
                    cost_so_far[next] = new_cost
                    priority = new_cost + heuristic(goal, next)
                    frontier.put(next, priority)
                    came_from[next] = current
    
        return get_path(came_from, start, goal)
    
    def heuristic(a, b):
        dx = abs(b[0] - a[0])
        dy = abs(b[1] - a[1])
        D = 1
        #with D2 = 1 it's even slower but more accurate
        D2 = math.sqrt(2)
        #Diagonal distance - this is more accurate
        #return D*(dx + dy) + (D2 - 2*D)*min(dx, dy)
        #Euclidean distance - this is faster and less accurate
        return math.sqrt(dx*dx + dy*dy)
    
    1 回复  |  直到 8 年前
        1
  •  5
  •   kutschkem    8 年前

    问题是,因为邻域都是8个相邻的网格点,并且它们之间的代价都是1,所以欧几里德距离高估了对角点之间的代价。

    对角线点之间的实际距离:1

    估计距离:sqrt(2)=1.41421356237

    所以欧几里德距离是 不可接受 为您的图表!