有人实施过SMA *搜索算法吗?

时间:2009-12-12 23:55:02

标签: algorithm search artificial-intelligence a-star path-finding

我发现AIMA中的算法描述(Artificial Intelligence: A Modern Approach)根本不正确。 “必要”是什么意思?内存限制是多少?队列大小或处理过的节点?如果当前节点根本没有孩子怎么办?

我想知道这个算法本身是否正确。因为我搜索了互联网,但还没有人实现它。

感谢。

2 个答案:

答案 0 :(得分:3)

我已设法使用the PDF在C#中使用它实现图搜索。

我使用了3个列表 - 前沿(开放列表),叶子列表和"树分支"名单。

  • Frontier是PDF中提到的队列,它是从最佳到最差排序的公共优先级队列。

  • 叶子列表仅保留叶子,从最差到最好排序,当我们决定要忘记什么叶子时,我们将需要它。 SMA只会忘记离开,而不是整个分支。

  • 树分支列表保留完全展开的节点,其子节点都在内存中。我们需要它来测试州交叉点。

我已经使用快速二进制堆作为前沿和叶子列表,并使用哈希表作为树分支列表。

节点应保留以下附加信息:

  • 具有位置的后继迭代器(在后续列表中指向需要位置)。如果我们忘记了,我们绝对不能将我们的后继枚举重置为零,因为我们忘记了刚刚添加的节点。我使用IEnumerator,int用于位置,bool用于"完成"标志

  • 后继者名单。我们不可避免地需要这个用于f-cost向上传播。此外,我保留简单的继承状态列表 - 如[阻止,遗忘,存在]。需要跟踪被遗忘和被阻止的节点。 (被阻止 - 在图表中 - 由某个节点扩展得更快)

  • PDF中提到的两个F,我们现在的F,以及最好被遗忘的继任者F.

  • 节点深度

边界和叶子列表中的节点排序应该像这样:"如果我们有"完成"枚举标志,挑选最好忘记的继承者F,否则选择当前F,如果等于,选择最深的"。叶子列表使用完全相同的条件以相反的顺序排序。

基本算法大纲是这样的(类似于PDF):

  • 我们从边境选择最佳节点,如果它已经完成了#34; flag - 我们知道我们会记住,重置迭代器,在这种情况下我们必须重置最好被遗忘的继承者F(出于复杂的原因)。

  • 如果我们在列表中没有这个后继者(可以,当我们记得的时候) - 我们会生成它并按照PDF中的说明设置它。

  • 然后是最复杂的事情 - 我们测试边界或树分支列表中是否存在具有相同状态的节点。如果是的话 - 我将描述以后要做什么。如果不是,我们只需将子项添加到边界(并从叶子列表中删除父项)。

  • 在后续的枚举结束的所有情况下 - 我们进行所谓的f-costs备份,如果我们没有任何遗忘的节点(并且有一些后继者),我们删除当前节点从边界并将其添加到树枝列表。

如何忘记:我们从叶子列表中挑选第一片叶子(最糟糕的叶子),将其从边界移除,从父母的后继者列表中删除,更新(减少)父母最好的遗忘者#&# 39; s F,如果需要,如果父不在边界 - 我们将它从树枝列表中删除并将其添加到边界并将其添加到叶子列表中,如果它现在是叶子(不是'不再有接班人了。)

怎么做,如果我们生成了一个已经在前沿或树分支列表中的后继者。首先,我们需要对它进行更好的测试 - 我们比较两个节点的PathCost + H("原始" F)。请注意,我们无法比较备用的F - 这不起作用。如果它不是更好 - 我们只是将后继状态设置为阻止。如果是 - 可能会出现这样的情况:较差的节点是一个巨大的子树的根(太复杂,不能再解释)。在这种情况下,我们完全切断了子树,SMA一次忘记了一堆节点。在用更好的节点替换更糟糕的节点之后,我们从它的父级继承者列表中删除更糟糕的节点,从前沿,叶子列表甚至树分支列表(它甚至可能在那里!),将后继状态设置为阻止它的父母并且不要忘记检查更糟的节点的父节点是否现在阻止了所有节点 - 我们需要将它的F设置为无穷大,因为它变成了终端节点。

也许我没有最简单的实现,但它是唯一适合我的实现。我使用8个谜题进行测试 - 用最少的(n + 1) - 内存(计算起始节点)求解n步,并用传统的a-star检查解决方案的最优性。我花了20到30个小时试图找出所有细节 - 主要问题在于失败测试案例的复杂性 - 我已经得到了#34;用更好的节点取代了#34;逻辑错误仅在20多个步骤上进行,并对数千个随机种子进行了大量测试。还要注意优先级队列 - 我必须在很多情况下重新插入项目,导致F中的任何变化,最好忘记F,或者#34;完成" flag - 更改排序顺序。我最终检查了每个出列的二进制堆的一致性。摆脱最复杂的理解无法循环的错误的主要想法是检查,你不会在所有情况下减少F。这样F会不断增加。

我将在几周内分享工作实施资源。

答案 1 :(得分:2)

我认为this PDF是AIMA的SMA *部分,适用于没有该书的人。

我首先注意到来自维基百科的伪代码在该行中有一个相当明显的错误:

parent.successors.remove(parent);

应该是

parent.successors.remove(badNode);

(父母怎么可能成为自己的继任者?)

  

“必要”是什么意思?

如果其父级尚未进入队列,则必须将其添加到队列中。否则,我们最终会再次搜索此节点。

  

内存限制是多少?队列大小或处理过的节点?

队列将占用所有可用内存。处理的节点没有队列。这正是SMA *可以重新遍历节点并可能卡住的原因。

  

如果当前节点根本没有孩子怎么办?

如果节点没有子节点,则它是叶子节点。如果它是一个叶子节点,那么它就是一个终端节点。在这种情况下,如果它不是目标节点,我们将其f-cost设置为无穷大,并将该信息传播给其父节点。