【问题标题】:Behavior trees in HaskellHaskell 中的行为树
【发布时间】:2012-05-18 11:47:18
【问题描述】:

我听说 Haskell 中存在用于树实现的策略,但我没有找到任何关于良好行为树替代方案的信息。

我的目标:给定一个表示状态的元组,将该元组提供给行为节点树的最佳模式是什么,每个行为节点都根据元组返回忙/错误/已完成/正在运行。该行为也可能改变元组(导致状态改变)。

嵌套节点可以根据其父节点的策略执行。例如,如果子节点返回“错误”,则不会评估更多子节点。另一种策略是即使返回错误状态也执行所有子节点。

我希望这是有道理的!

【问题讨论】:

  • 我不是 100% 确定我理解了这个问题,但您对 unfoldTree 感兴趣吗?
  • 您有一些参考资料或示例代码吗?有点不清楚你在问什么。

标签: haskell behavior-tree


【解决方案1】:

我们都被你的问题弄糊涂了,我可能不明白你说的“元组”是什么意思,但在黑暗中开枪:

我编写了一个名为 simple-actors 的小型库,用于 Actor Model concurrency。如果你能想象你需要通过“演员”在并发“频道”上监听并相互交流来完成什么,那么你可能有兴趣看看。

这里的文档顶部是binary search tree of actors 的一个示例(您的问题让我想到了这一点,抱歉,如果这一切都离题了)。

编辑:我应该提到我发现Behavior Trees 上的维基百科页面完全难以理解;也许熟悉企业术语的人可以提供帮助。

【讨论】:

    【解决方案2】:

    不幸的是,您似乎是一个很少有 Haskell 用户了解的领域的专家。关于这些技术,我所知道的只是我从非技术人员那里听到的关于不同业务规则引擎的内容,所以我可能不太了解,但我认为值得一试,因为其他人都被难住了。

    就前向链接推理系统,尤其是 Rete 算法而言,它们基本上已经具备功能性。他们在进行过程中迭代并向数据库添加更多知识,直到没有事情可做。如果您不允许任意效果,它将是一个简单的Control.Monad.State 端口;如果您需要任意效果,您可以使用状态单子变换器,而不是中级/高级 Haskellers 会被吓倒的东西。你可能会找到一些你可以使用的东西on the Haskell site,但如果你最终自己这样做了the Monad TransformersReal World Haskell 一章是必不可少的。

    我对行为树一无所知,但在 Wikipedia 上一目了然,它们在我看来就像 Rete 算法加上后台的并发进程。如果这甚至接近正确,那么您必须决定是否需要并发性或并行性。如果您对“神奇地”计算得更快的纯值感到满意(并且,通过扩展,所有内容都是用 Haskell 编写的),那么您可以不费吹灰之力地使用 Control.Parallel 中的东西,但您将无法(比如说)查询哪些进程正在运行,哪些没有。如果您真的需要不同的可观察行为,那么您将需要Control.Concurrent,它不那么神奇,所以需要更多记账。西蒙马洛写了a pretty nice tutorial关于你在那里的选择。你所描述的对我来说听起来比 Haskell 可以为你做的大多数很酷的东西都低级。如果您决定接受更高级别的接口,您可能会发现它更容易实现。我也不是这个主题的专家。

    【讨论】:

      【解决方案3】:

      由于没有找到 BT 实现,我自己开始在 Haskell 中实现某种 BT,如下所述:

      http://www.brainific.com/blog/2015/09/twisting-your-trees/

      并存储在这里:

      https://bitbucket.org/brainific/action-fw/src

      这里有具体的测试:

      https://bitbucket.org/brainific/action-fw/src/a6081b740dc4b8258f67f49df473458737fc4240/test/BehaviourTrees21Test.hs?at=master&fileviewer=file-view-default

      请注意一些与标准行业 BT 不同的功能:

      • 这些树是事件驱动的,与更常见的轮询树相比,它更像是一棵事件处理过程树;
      • 事件类型是通用的:成功/失败/运行状态只是另一种事件类型,由转换函数处理,因此您实际上可以轻松混合和匹配 BT 节点和 FSM 节点;
      • 事件节点不是静态的,而是在运行时从某些 Env 数据类型生成的(我没有进行深入的性能检查,但希望 Haskell RTS 在这里应该有所帮助);
      • 节点是通过代码指定的,因此它们可以比平时更奇特(其中一个可以产生计划过程并等待“继续”开始,在执行计划时中断默认的 BT 运行);
      • 尚未实现黑板或代理间消息(尽管添加地图和频道应该相当简单)。

      使用 Haskell 有一些问题(例如,我仍然不能弯曲类型系统来表示处理事件类型 T1 的树只能包含触发事件类型 T1 的子树),但可以提供一些具有很强表达能力的功能(例如循环作为无限惰性列表)。

      请注意,它仍然是 alpha 版甚至是 pre-alpha 版!我开始将它与 The Dark Mod (http://thedarkmod.com) 集成,我希望在其中验证我的假设。如果您最终感兴趣,请随时发送邮件。

      【讨论】:

        【解决方案4】:

        我最近发布了关于 hackage 的 smarties 行为树库

        https://hackage.haskell.org/package/smarties

        我确信在 haskell 中实现 BT 有其他很好的方法,但我对这个设计非常满意。注意 smarties 只支持 2 个节点状态 SUCCESS 和 FAIL。

        回答您的问题:

        将该元组提供给行为树的最佳模式是什么 每个返回忙/错误/已完成/正在运行的节点 元组。该行为也可能改变元组(导致状态 改变)。

        smarties 主要类型是一个 monad,它表示具有内部感知(状态)的节点序列。从这个意义上说,它与 State monad 非常相似。还有一些接口可以强制执行不可变的感知。

        嵌套节点可以根据其父节点的策略执行 节点。例如,如果子节点返回“错误”,则不再有子节点 节点将被评估。另一种策略是执行所有子 节点,即使返回错误状态。

        只要遇到 FAIL 节点,它就会将状态和最终输出短路。然而,它仍然运行剩余的节点来获取它的一元返回值,这对于在 BT 中组合逻辑非常有用。

        选择器(代表分支逻辑)因此通过传入节点单子列表并采用第一个具有成功状态的单子来实现。

        Monadic 语法在行为树中非常强大。您在树中的某个点读取状态,并稍后在树中使用它的值。这使得节点更容易组合!

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2018-05-25
          • 1970-01-01
          • 2014-04-30
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多