2010-01-21 66 views
14

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

实现

谷歌返回:

任何其他方面?

轮子

的问题,如要求,涉及到重复使用(插入游戏),而不是再造(至少是在显示性能是一个问题)。可能会发现Dijkstra实现(或通用寻路算法)更适合,或者最快的实现速度不够快。我很欣赏替代算法的建议,但问题不是“我应该推出自己的A *吗?”

回答

6

看看其他的路径寻找算法(如呼吸优先,深度优先,Minimax,Negmax等),并衡量您的情况的积极和消极。

Boost也has an A-star implementation。尝试遵循these instructions以在iPhone上提升效果,但它可能无法适用于您:它不是提升的“完整端口”,可能会出错。

以下是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); 
} 
+1

如果您使用仅标头库,则不需要构建Boost。如果您不使用Dot文件,则Boost.Graph仅为标题。我在iPhone上使用了几个Boost头文件库,它们可以很好地工作。 – 2011-10-24 18:33:33

5

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

+0

同意。 A *本身并不是很复杂,并且通常可以针对特定情况进行优化。 – 2010-01-21 17:22:42

+0

你不能使用STL中的'priority_queue',因为它不允许改变已经插入的元素的优先级(并且强制堆重建非常低效)。对于像我这样的凡人来说,实现一个高效的A *并不会花费大部分时间来浏览列表并且保持合理的内存消耗(例如通过避免将完整的节点存储在封闭列表中)是非常简单的。 – 2014-09-03 12:22:51

+0

@kuroineko实际上您可以使用'priority_queue',因为您在更改优先级时不需要_need_来删除旧节点。您可以再次在开放集合中再次插入具有更高优先级的节点,并且将首先选取它并放入封闭集合中(之后,打开集合中的“旧”节点将稍后被丢弃,因为它已经处于关闭状态设置) – cyril 2016-02-08 14:19:08

6

当您有特定的边界可以使用时,通常您最好自己编写算法。特别是,您的小型状态空间适合优化,预先花费内存以减少CPU时间,并且您使用网格而不是任意状态空间的事实允许您执行诸如优化后续节点生成等事情,或者能够处理所有以相同网格平方结束的部分路径(这是普通的A *搜索不会也不能假设的)。 (PS.OpenSteer,一个转向行为的集合,与A *无关,它是一种搜索算法,除了你可以在概念上使用一个,另一个或两者来遍历一个空间,其中一个并不是这样,吨另在最合理的情况下更换)

5

我有两点建议一般件:

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

我投了第二个子弹。第一个有点令人困惑,因为我认为“寻路”可能比“A *”更通用 – 2010-01-21 17:31:43

+1

A *可用于任何类型的搜索问题,路径寻找是一个明确定义的域:从一个点表面到另一个。 – fortran 2010-01-21 22:02:08

+1

第二点。启发式对优化非常重要A * – lalitm 2010-02-05 15:12:41