【问题标题】:How to implement a best-first search in Haskell?如何在 Haskell 中实现最佳优先搜索?
【发布时间】:2014-07-23 05:54:21
【问题描述】:

有没有办法在 Haskell 中高效地进行最佳优先搜索?我想维护一个动态树。我有一个启发式函数,可以计算每个节点的数字和一个后继函数,它将返回一个节点的子节点列表。

在每一步,我都想采用具有最佳启发式的叶节点并将其替换为它的子节点。重复这个过程,直到我得到一个“足够好”的节点。

为此,我需要维护叶子的优先级队列。但是有没有一种方法可以有效地从优先级队列中的叶子到它在树中的位置,以便我可以修改树?

【问题讨论】:

  • 拉链或棱镜。虽然如果你让树实际上是可变的(例如,由一堆 IORef 组成),它们可能无济于事。
  • 我对棱镜不熟悉。至于拉链,它们在这里适用吗,因为我需要同时关注所有的叶子?

标签: haskell


【解决方案1】:

一个可能的答案是使用 Haskell 最隐秘的可变性形式:惰性。如果你懒惰地生成整个树(即使它是无限)然后根据你的优先级队列重复查看树中的不同点,那么你只会产生尽可能多的执行最佳优先搜索所需的树。

您仍然需要为重复遍历树的较低分支付费,但也许您可以通过某种方式更改搜索结构以做得更好。

【讨论】:

  • 你是在建议打结的方法吗?
  • 有潜力,但我想先了解更多关于确切算法的信息。即使没有打结,利用懒惰也是一个好主意。
【解决方案2】:

最好的首次搜索不需要显式树。只是优先级队列应该做。使队列的节点携带尽可能多的上下文来计算后继节点和成本函数。如果您真的需要树,那么正如其他人所说,拉链是要走的路。您会将拉链保留在优先级队列中,而不仅仅是树节点。由于优先级队列包含所有叶子,因此您不需要修改共享树。

【讨论】:

  • 完全正确。每一步都只是step (x:xs) | goodEnuf x = x | otherwise = merge (prioritized (children x)) xs
  • 但是这里的问题是一旦叶子被“修改”,更改应该传播到所有其他节点,这将是一个昂贵的操作。
【解决方案3】:

查看weighted-search 包,它实现了优先搜索单子。它允许您表达您想要的解决方案,并在途中添加weight 以指示您何时知道解决方案的费用增加了,并且该包将首先找到权重最小的解决方案。在您的情况下,创建要搜索的整棵树(可能是无限的),然后使用加权搜索来构造通过该树的所有路径并赋予它们权重。然后,您将首先获得权重最小的路径。

【讨论】:

    猜你喜欢
    • 2020-05-23
    • 1970-01-01
    • 2019-11-21
    • 2022-06-13
    • 1970-01-01
    • 2011-05-28
    • 2010-12-07
    • 2014-06-02
    • 2012-01-12
    相关资源
    最近更新 更多