Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/algorithm/12.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Algorithm 重新访问A*算法:我必须检查开放列表还是封闭列表?_Algorithm_A Star - Fatal编程技术网

Algorithm 重新访问A*算法:我必须检查开放列表还是封闭列表?

Algorithm 重新访问A*算法:我必须检查开放列表还是封闭列表?,algorithm,a-star,Algorithm,A Star,我正在研究A*算法,关于重新访问有一些混乱 当我的教授解释A*时,他说如果我重新访问一个已经在封闭列表中的节点 我必须检查重新访问的成本与原始成本 若重新访问更便宜,我应该放弃封闭列表中的节点,并在其上添加重新访问的节点 所以伪代码是这样的: GeneralGraphSearch( v ) Prepare two empty lists: OPEN, CLOSED Insert v with Coste(v) into OPEN While forever If OPEN is empt

我正在研究A*算法,关于重新访问有一些混乱

当我的教授解释A*时,他说如果我重新访问一个已经在封闭列表中的节点

我必须检查重新访问的成本与原始成本

若重新访问更便宜,我应该放弃封闭列表中的节点,并在其上添加重新访问的节点

所以伪代码是这样的:

GeneralGraphSearch( v )
Prepare two empty lists: OPEN, CLOSED
Insert v with Coste(v) into OPEN
While forever
    If OPEN is empty, return failure
    while forever
       v = the node with the lowest cost in OPEN
       remove v from OPEN
       if v is not in CLOSED // v is not visited
        break 
       else if the new cost is cheaper than the cost of v in CLOSED
        remove v in CLOSED
        break
       end if
    end while
    If v is a goal, return success
    Insert v into CLOSED
    Expand v
    Insert all children of v with their costs into OPEN
end while
End
function A*(start, goal)
    // The set of nodes already evaluated.
    closedSet := {}
    // The set of currently discovered nodes that are not evaluated yet.
    // Initially, only the start node is known.
    openSet := {start}
    // For each node, which node it can most efficiently be reached from.
    // If a node can be reached from many nodes, cameFrom will eventually contain the
    // most efficient previous step.
    cameFrom := the empty map

    // For each node, the cost of getting from the start node to that node.
    gScore := map with default value of Infinity
    // The cost of going from start to start is zero.
    gScore[start] := 0 
    // For each node, the total cost of getting from the start node to the goal
    // by passing by that node. That value is partly known, partly heuristic.
    fScore := map with default value of Infinity
    // For the first node, that value is completely heuristic.
    fScore[start] := heuristic_cost_estimate(start, goal)

    while openSet is not empty
        current := the node in openSet having the lowest fScore[] value
        if current = goal
            return reconstruct_path(cameFrom, current)

        openSet.Remove(current)
        closedSet.Add(current)
        for each neighbor of current
            if neighbor in closedSet
                continue        // Ignore the neighbor which is already evaluated.
            // The distance from start to a neighbor
            tentative_gScore := gScore[current] + dist_between(current, neighbor)
            if neighbor not in openSet  // Discover a new node
                openSet.Add(neighbor)
            else if tentative_gScore >= gScore[neighbor]
                continue        // This is not a better path.

            // This path is the best until now. Record it!
            cameFrom[neighbor] := current
            gScore[neighbor] := tentative_gScore
            fScore[neighbor] := gScore[neighbor] + heuristic_cost_estimate(neighbor, goal)

    return failure

function reconstruct_path(cameFrom, current)
    total_path := [current]
    while current in cameFrom.Keys:
        current := cameFrom[current]
        total_path.append(current)
    return total_path
然而,当我查找wikipedia时,似乎他们只是忽略了一个节点,如果它已经在封闭列表中

相反,它们处理的是已在打开列表中的节点

他们的伪代码版本如下:

GeneralGraphSearch( v )
Prepare two empty lists: OPEN, CLOSED
Insert v with Coste(v) into OPEN
While forever
    If OPEN is empty, return failure
    while forever
       v = the node with the lowest cost in OPEN
       remove v from OPEN
       if v is not in CLOSED // v is not visited
        break 
       else if the new cost is cheaper than the cost of v in CLOSED
        remove v in CLOSED
        break
       end if
    end while
    If v is a goal, return success
    Insert v into CLOSED
    Expand v
    Insert all children of v with their costs into OPEN
end while
End
function A*(start, goal)
    // The set of nodes already evaluated.
    closedSet := {}
    // The set of currently discovered nodes that are not evaluated yet.
    // Initially, only the start node is known.
    openSet := {start}
    // For each node, which node it can most efficiently be reached from.
    // If a node can be reached from many nodes, cameFrom will eventually contain the
    // most efficient previous step.
    cameFrom := the empty map

    // For each node, the cost of getting from the start node to that node.
    gScore := map with default value of Infinity
    // The cost of going from start to start is zero.
    gScore[start] := 0 
    // For each node, the total cost of getting from the start node to the goal
    // by passing by that node. That value is partly known, partly heuristic.
    fScore := map with default value of Infinity
    // For the first node, that value is completely heuristic.
    fScore[start] := heuristic_cost_estimate(start, goal)

    while openSet is not empty
        current := the node in openSet having the lowest fScore[] value
        if current = goal
            return reconstruct_path(cameFrom, current)

        openSet.Remove(current)
        closedSet.Add(current)
        for each neighbor of current
            if neighbor in closedSet
                continue        // Ignore the neighbor which is already evaluated.
            // The distance from start to a neighbor
            tentative_gScore := gScore[current] + dist_between(current, neighbor)
            if neighbor not in openSet  // Discover a new node
                openSet.Add(neighbor)
            else if tentative_gScore >= gScore[neighbor]
                continue        // This is not a better path.

            // This path is the best until now. Record it!
            cameFrom[neighbor] := current
            gScore[neighbor] := tentative_gScore
            fScore[neighbor] := gScore[neighbor] + heuristic_cost_estimate(neighbor, goal)

    return failure

function reconstruct_path(cameFrom, current)
    total_path := [current]
    while current in cameFrom.Keys:
        current := cameFrom[current]
        total_path.append(current)
    return total_path
那么哪种方法是正确的


或者两者都是相同的?

编辑:实际上两者都是对的

然而,只有当您的hueristic仅可接受但不一致时,您才会使用professors算法,取自以下答案:

[维基百科的方法是最佳的]如果通往任何重复状态的最佳路径总是第一个被遵循。如果启发式函数具有一致性(也称为单性)属性,则此属性成立。如果对于每个节点n和n的每个后继节点n′,从n到达目标的估计成本不大于从n到达n′的阶跃成本加上从n到达目标的估计成本,则启发式函数是一致的

如果启发式函数仅仅是可接受的,那么[你的教授版本]是最优的,也就是说,它永远不会高估实现目标的成本

假设您的hueristic类似于欧几里德空间中的欧几里德距离(因此是一致的和可接受的),那么您不应该在闭合集中添加任何不是该节点最小成本值的内容。这样考虑一下,如果任意节点的代价可能无效,小于闭集中的代价,则会导致所有其他依赖路径步骤必须重新计算,并会破坏此算法的运行时复杂性

Wikipedia在这些情况下是正确的,这就是为什么您首先要将openset设置为优先级队列的全部原因。理想情况下,您的开放集是PQ,而封闭集是一个列表,它与您必须首先采取的步骤有关

您需要修改开放集中路径的成本的想法实际上意味着您需要一个具有删除功能的优先级队列,这在日志时间内是可能的,哈希表索引为二进制堆结构/配对堆/Fibonacci堆等(如何实现这一点的答案在别处找到)。这实际上成为IMO算法实现中最困难的部分,因为仅仅遵循算法并不能真正告诉您如何实现这一点,并且会让您陷入找出伪实现中缺少的部分的困境

您会注意到,其他实现将讨论删除密钥/更新密钥操作,这些操作在封闭集中没有意义,只有基于优先级队列的开放集