我认为这与双向搜索的实现方式有关。
BFS 的伪代码如下所示:
until frontier.empty?
node <- frontier.pop()
add node to explored
for each child not in expored or frontier:
if child is goal then
return path
add child to frontier
想象一下像这样实现双向搜索:
until frontierForward.emtpy? or frontierBackward.empty?
node <- frontierForward.pop()
add node to exploredForward
for each child not in exporedForward or frontierForward:
if child in frontierBackward then
return pathForward + pathBackward
add child to frontierForward
Do something similar but now searching backwards
基本上,“前进”BFS 和“后退”BFS 的交替步骤。现在想象一个像这样的图表:
B-C-D
/ \
A E
\ /
F - G
BFS 的第一次向前和向后运行会给我们这样的状态:
1) expandedForward = A ; frontierForward = B, F
2) expandedBackward = E ; frontierBackward = D, G
现在算法从前向边界选择下一个要扩展的节点,然后选择 B。
3) expandedForward = A, B ; frontierForward = F, C
现在我们运行一个反向 BFS 并扩展节点 D。D 的子节点 C 位于前向边界,因此我们返回路径 A - B - C - D - E。
我认为这就是 Russel 和 Norvig 所指的。如果实施不考虑这种情况,它可能会给您一个不是最佳的解决方案。
它应该在确定它找到最佳解决方案之前完成扩展边界中具有相同“深度”的所有节点。或者可以按层而不是按节点交替前向和后向 BFS 搜索(向前扩展第 0 层中的所有节点,向后扩展第 0 层中的所有节点,向前扩展第 1 层中的所有节点等)