`A*` 从边界移除一个节点
`A*` removing a node from frontier
这是我写的一个A*
算法,在评价的时候被告知"Your implementation performs the goal test when a successor is added to the frontier, not when it's removed: this compromises optimality"。 "not when it's removed" 是什么意思?
这是我的代码:
def solve(problem, heuristic) :
"""
A* search algorithm finding the shortest path.
Returns:
A list of actions.
"""
s0 = problem.get_initial_state()
queue = PriorityQueue()
queue.push((0,s0,[]),0) # second 0 is priority
cost_so_far = dict()
cost_so_far[s0] = 0
while not queue.is_empty():
current_cost, s, actions = queue.pop()
for successor, action, cost in problem.get_successors(s):
new_cost = current_cost + cost
if problem.goal_test(successor):
return actions + [action]
else:
h = heuristic(successor, problem)
if successor not in cost_so_far or cost_so_far[successor] > new_cost + h:
cost_so_far[successor] = new_cost + h
queue.push((new_cost, successor, actions + [action]), new_cost + h)
修改版本(更新)
def solve(problem, heuristic) :
"""
A* search algorithm finding the shortest path.
Returns:
A list of actions.
"""
s0 = problem.get_initial_state()
queue = PriorityQueue()
queue.push((s0,[]),0) # 0 is the priority
cost_so_far = {s0:0}
while not queue.is_empty():
s, actions = queue.pop()
if problem.goal_test(s):
return actions
for successor, action, cost in problem.get_successors(s):
successor_cost = current_cost + cost
new_cost = successor_cost + heuristic(successor, problem)
if successor not in cost_so_far or cost_so_far[successor] > new_cost:
cost_so_far[successor] = new_cost
queue.push((successor, actions + [action]), new_cost)
来自维基百科,就在您引用之前:"the above pseudocode assumes that the heuristic function is monotonic"。
您的代码将在此图和启发式上给出错误答案(字母是节点,数字是成本):
Get from X to Z:
1 2
X - Y - Z
1 \ W / 3
h(X) = 2, h(Y) = 2, h(W) = 1, h(Z) = 0
节点将按X, W, Z, Y, Z
的顺序展开。但是,您的程序会在第一次找到 Z
后退出,并会报告成本为 4 的路径 X>W>Z
,这不是最优的。
假设您的图表如下所示:
9
S ----- G
\ /
1\ /1
\ /
W
您需要沿着最便宜的路径从起始节点 S
到达目标节点 G
。 S-G 边的成本为 9,而连接到航路点 W
的边每条成本为 2.
您的算法将查看 S
的邻居以将节点添加到边界,立即找到 G
和 return 昂贵的直接 S-G 路径,而不会找到通过航点 W
.
的路径
相反,当您 pop
来自优先级队列的节点时,您需要对节点执行目标测试。在这一点上,可以保证你找到了 cheapest 到节点的路径,而不仅仅是 some 到节点的路径。
这是我写的一个A*
算法,在评价的时候被告知"Your implementation performs the goal test when a successor is added to the frontier, not when it's removed: this compromises optimality"。 "not when it's removed" 是什么意思?
这是我的代码:
def solve(problem, heuristic) :
"""
A* search algorithm finding the shortest path.
Returns:
A list of actions.
"""
s0 = problem.get_initial_state()
queue = PriorityQueue()
queue.push((0,s0,[]),0) # second 0 is priority
cost_so_far = dict()
cost_so_far[s0] = 0
while not queue.is_empty():
current_cost, s, actions = queue.pop()
for successor, action, cost in problem.get_successors(s):
new_cost = current_cost + cost
if problem.goal_test(successor):
return actions + [action]
else:
h = heuristic(successor, problem)
if successor not in cost_so_far or cost_so_far[successor] > new_cost + h:
cost_so_far[successor] = new_cost + h
queue.push((new_cost, successor, actions + [action]), new_cost + h)
修改版本(更新)
def solve(problem, heuristic) :
"""
A* search algorithm finding the shortest path.
Returns:
A list of actions.
"""
s0 = problem.get_initial_state()
queue = PriorityQueue()
queue.push((s0,[]),0) # 0 is the priority
cost_so_far = {s0:0}
while not queue.is_empty():
s, actions = queue.pop()
if problem.goal_test(s):
return actions
for successor, action, cost in problem.get_successors(s):
successor_cost = current_cost + cost
new_cost = successor_cost + heuristic(successor, problem)
if successor not in cost_so_far or cost_so_far[successor] > new_cost:
cost_so_far[successor] = new_cost
queue.push((successor, actions + [action]), new_cost)
来自维基百科,就在您引用之前:"the above pseudocode assumes that the heuristic function is monotonic"。
您的代码将在此图和启发式上给出错误答案(字母是节点,数字是成本):
Get from X to Z:
1 2
X - Y - Z
1 \ W / 3
h(X) = 2, h(Y) = 2, h(W) = 1, h(Z) = 0
节点将按X, W, Z, Y, Z
的顺序展开。但是,您的程序会在第一次找到 Z
后退出,并会报告成本为 4 的路径 X>W>Z
,这不是最优的。
假设您的图表如下所示:
9
S ----- G
\ /
1\ /1
\ /
W
您需要沿着最便宜的路径从起始节点 S
到达目标节点 G
。 S-G 边的成本为 9,而连接到航路点 W
的边每条成本为 2.
您的算法将查看 S
的邻居以将节点添加到边界,立即找到 G
和 return 昂贵的直接 S-G 路径,而不会找到通过航点 W
.
相反,当您 pop
来自优先级队列的节点时,您需要对节点执行目标测试。在这一点上,可以保证你找到了 cheapest 到节点的路径,而不仅仅是 some 到节点的路径。