【问题标题】:Fastest cross-platform A* implementation?最快的跨平台 A* 实现?
【发布时间】:2023-03-29 08:04:01
【问题描述】:

有这么多可用的实现,使用小网格的 C++ 执行速度最快(CPU 密集度最低、二进制文件最小)、跨平台(Linux、Mac、Windows、iPhone)A* 实现是什么?

实现

谷歌返回:

还有其他人吗?

轮子

正如所问的,这个问题涉及重用(插入游戏),而不是重新发明(至少在性能被证明是一个问题之前)。结果可能是 Dijkstra 实现(或通用寻路算法)更适合,或者最快的实现不够快。我很欣赏替代算法的建议,但问题不是“我应该自己滚动 A* 吗?”

【问题讨论】:

    标签: c++ iphone algorithm a-star


    【解决方案1】:

    查看其他寻路算法(例如 Breath-First、Depth-First、Minimax、Negmax 等)并权衡您的场景的正面和负面。

    也提升has an A-star implementation。尝试关注these instructions 在 iPhone 上构建 boost,但它可能不适合你:它不是 boost 的“完整端口”,它可能会出错。

    以下内容来自Algorithms in a Nutshell(Java,不是 C++,但也许你想移植它):

    public Solution search( INode initial, INode goal ) {
      // Start from the initial state
      INodeSet open = StateStorageFactory.create( StateStorageFactory.TREE );
      INode copy = initial.copy();
      scoringFunction.score( copy );
      open.insert( copy );
    
      // Use Hashtable to store states we have already visited.
      INodeSet closed = StateStorageFactory.create( StateStorageFactory. HASH );
      while( !open.isEmpty() ) {
        // Remove node with smallest evaluation function and mark closed.
        INode n = open.remove();
    
        closed.insert( n );
    
        // Return if goal state reached.
        if( n.equals( goal ) ) { return new Solution( initial, n ); }
    
        // Compute successor moves and update OPEN/CLOSED lists.
        DepthTransition trans = (DepthTransition)n.storedData();
        int depth = 1;
    
        if( trans ! = null ) { depth = trans.depth + 1; }
    
        DoubleLinkedList<IMove> moves = n.validMoves();
    
        for( Iterator<IMove> it = moves.iterator(); it.hasNext(); ) {
          IMove move = it.next();
    
          // Make move and score the new board state.
          INode successor = n.copy();
          move.execute( successor );
    
          // Record previous move for solution trace and compute
          // evaluation function to see if we have improved upon
          // a state already closed
          successor.storedData( new DepthTransition( move, n, depth ) );
          scoringFunction.score( successor );
    
          // If already visited, see if we are revisiting with lower
          // cost. If not, just continue; otherwise, pull out of closed
          // and process
          INode past = closed.contains( successor );
    
          if( past ! = null ) {
            if( successor.score() >= past.score() ) {
              continue;
            }
    
            // we revisit with our lower cost.
            closed.remove( past );
          }
    
          // place into open.
          open.insert( successor );
        }
      }
    
      // No solution.
      return new Solution( initial, goal, false );
    }
    

    【讨论】:

    • 如果您使用仅标头库,则无需构建 Boost。如果您不使用 Dot 文件内容,则 Boost.Graph 仅是标题。我在 iPhone 上使用了几个 Boost 标头库,它们开箱即用。
    【解决方案2】:

    http://www.ceng.metu.edu.tr/~cuneyt/codes.html 有一个通用的 C++ A* 实现。看起来都是跨平台的标准C++。

    【讨论】:

      【解决方案3】:

      我有两条一般性建议:

      • 如果您的域被限制在一个网格中,也许您会通过搜索“寻路”而不是更通用的 A* 找到更好的结果。
      • 如果您的域不是严格搜索曲面上的路径,那么如果您花时间改进启发式算法而不是尝试优化算法本身,那么您的工作可以获得更多收益。

      【讨论】:

      • 我对第二个项目投了赞成票。第一个有点令人困惑,因为我认为“寻路”可以比“A*”更通用
      • A* 可用于任何类型的搜索问题,寻路是一个定义明确的领域:从表面的一个点导航到另一个点。
      • +1 表示第二点。启发式对于优化 A* 非常关键
      【解决方案4】:

      当您有可以使用的特定界限时,您通常最好自己编写算法。特别是您的小状态空间有助于优化预先花费内存以减少 CPU 时间,并且您使用网格而不是任意状态空间这一事实允许您执行诸如优化后继节点生成之类的事情,或者能够将在同一方格上结束的所有部分路径视为等效(普通的 A* 搜索不会也不能假设)。

      (PS。OpenSteer 是转向行为的集合,与 A* 无关,A* 是一种搜索算法,只是你可以在概念上使用一个、另一个或两者来遍历空间。一个不是在最合理的情况下替换另一个。)

      【讨论】:

        【解决方案5】:

        我建议你自己实现算法。按照伪代码:A* Search Algorithm,它应该是直截了当的。 “openset”应该实现为一个最小堆,这也是微不足道的;或者您可以使用 STL 中的 priority_queue。

        【讨论】:

        • 同意。 A* 本身并不是很复杂,通常可以针对特定情况进行优化。
        • 您不能使用 STL 中的priority_queue,因为它不允许更改已插入元素的优先级(并且强制堆重建效率极低)。对于像我这样的普通人来说,实现一个高效的 A* 不会花费大部分时间在列表中涉水并保持合理的内存消耗(例如通过避免将完整节点存储在封闭列表中)绝非易事。跨度>
        • @kuroineko 实际上您可以使用priority_queue,因为您在更改优先级时不需要 删除旧节点。您可以在开放集中再次插入具有更高优先级的节点,它将首先被选中并放入封闭集中(然后开放集中的“旧”节点将被丢弃,因为它已经在封闭集中设置)
        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2018-06-24
        • 2011-01-20
        • 1970-01-01
        • 2013-06-23
        • 2016-03-15
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多