Performance 如何在大空间尺度上加速A*算法?

Performance 如何在大空间尺度上加速A*算法?,performance,algorithm,a-star,netlogo,Performance,Algorithm,A Star,Netlogo,从中,我编写了一个A*算法,使用网络中的节点定义成本最低的路径。代码似乎可以工作,但在大空间尺度上使用时速度太慢。我的风景有1000个补丁x 1000个补丁,1个补丁=1个像素。即使我将它减少到400个补丁x 400个补丁,1个补丁=1个像素,它仍然太慢(我无法修改低于400个补丁x 400个补丁的风景)。代码如下: to find-path [ source-node destination-node] let search-done? false let search-path [] l

从中,我编写了一个A*算法,使用网络中的节点定义成本最低的路径。代码似乎可以工作,但在大空间尺度上使用时速度太慢。我的风景有1000个补丁x 1000个补丁,1个补丁=1个像素。即使我将它减少到400个补丁x 400个补丁,1个补丁=1个像素,它仍然太慢(我无法修改低于400个补丁x 400个补丁的风景)。代码如下:

to find-path [ source-node destination-node] 

let search-done? false
let search-path []
let current-node 0
set list-open []
set list-closed []  
let list-links-with-nodes-in-list-closed []
let list-links []

set list-open lput source-node list-open
while [ search-done? != true]
[    
ifelse length list-open != 0
[
  set list-open sort-by [[f] of ?1 < [f] of ?2] list-open 
  set current-node item 0 list-open 
  set list-open remove-item 0 list-open 
  set list-closed lput current-node list-closed
  ask current-node
  [  
    if parent-node != 0[
    set list-links-with-nodes-in-list-closed lput link-with parent-node list-links-with-nodes-in-list-closed 
    ]
    ifelse any? (nodes-on neighbors4) with [ (xcor = [ xcor ] of destination-node) and (ycor = [ycor] of destination-node)]
    [
      set search-done? true 
    ]
    [        
      ask (nodes-on neighbors4) with [ (not member? self list-closed) and (self != parent-node) ]  
      [  
        if not member? self list-open and self != source-node and self != destination-node
        [
          set list-open lput self list-open
          set parent-node current-node
          set list-links sentence (list-links-with-nodes-in-list-closed) (link-with parent-node)
          set g sum (map [ [link-cost] of ? ] list-links)
          set h distance destination-node 
          set f (g + h)
        ]
      ]
    ]
  ]
]

[
  user-message( "A path from the source to the destination does not exist." )
  report []
 ]
]
set search-path lput current-node search-path
let temp first search-path
while [ temp != source-node ]
[
 ask temp
[
  set color red
]
set search-path lput [parent-node] of temp search-path 
set temp [parent-node] of temp 
]
set search-path fput destination-node search-path
set search-path reverse search-path  
print search-path
end
查找路径[源节点目标节点] 让搜索完成?假的 让搜索路径[] 让当前节点0 将列表设置为打开[] 已关闭集合列表[] 让列表链接与列表中的节点关闭[] 让我们列出链接[] 设置列表打开lput源节点列表打开 而[搜索完成?!=真] [ ifelse长度列表打开!=0 [ 将列表打开排序设置为1的[[f]个列表打开 将当前节点项0列表设置为打开 设置列表打开删除项目0列表打开 设置列表关闭lput当前节点列表关闭 询问当前节点 [ 如果父节点!=0[ 设置列表中节点处于关闭状态的列表链接列表中节点处于关闭状态的父节点列表链接 ] ifelse any?(邻居4上的节点)具有[(xcor=[xcor]目标节点)和(ycor=[ycor]目标节点)] [ 设置搜索完成?为真 ] [ 使用[(非成员?自我列表已关闭)和(自我!=父节点)] [ 如果不是成员?自列表打开且自!=源节点和自!=目标节点 [ 设置列表打开lput自我列表打开 将父节点设置为当前节点 设置列表链接语句(列表中节点的列表链接已关闭)(与父节点的链接) 设置g总和(映射[?]列表链接的[链接成本]) 设置h距离目标节点 集合f(g+h) ] ] ] ] ] [ 用户消息(“从源到目标的路径不存在。”) 报告[] ] ] 设置搜索路径lput当前节点搜索路径 让我们先搜索路径 而[temp!=源节点] [ 询问临时工 [ 设置颜色为红色 ] 设置临时搜索路径的搜索路径lput[父节点] 设置temp的temp[父节点] ] 设置搜索路径fput目标节点搜索路径 设置搜索路径反向搜索路径 打印搜索路径 结束 不幸的是,我不知道如何加速这段代码。是否有一种在大空间尺度上快速计算最小成本路径的解决方案


非常感谢您的帮助。

很好奇,所以我测试了我的A*和这是我的结果

迷宫1280 x 800 x 32位像素

  • 如您所见,它花费了约23毫秒
  • 无多线程(AMD 3.2GHz)
  • 我发现的最慢路径约为44毫秒(几乎填满了整个地图)
我想这已经足够快了

以下是我的A*类的来源:

//---------------------------------------------------------------------------
//---------------------------------------------------------------------------
//---------------------------------------------------------------------------
常量DWORD A_星_空间=0xFFFFFF;
常数DWORD A_星_墙=0xFFFFFE;
//---------------------------------------------------------------------------
A级明星
{
公众:
//变数
DWORD**map;//map[ys][xs]
int xs,ys;//映射解析xs*ysHeight);
对于(y=0;yScanLine[y],x=0;xSetSize(xs,ys);
对于(y=0;yScanLine[y],x=0;x>1)&0x7F)+0x00404040;
p[x]=c;
}
}
//---------------------------------------------------------------------------
void A_star::compute(int x0,int y0,int x1,int y1)
{
整数x,y,xmin,xmax,ymin,ymax,xx,yy;
德沃德一世,j,e;
//[清除以前的路径]

对于(y=0;y如果您计划多次重复使用同一地图,某种形式的预处理通常是最佳的。实际上,您计算出一些公共点之间的最短距离,并将它们作为边添加到图形中,这通常有助于a*更快地找到解决方案。尽管它更难实现


例如,您可以对英国地图中的所有高速公路路线执行此操作,因此搜索算法只需查找到高速公路的路线,以及从高速公路交叉口到目的地的路线。

a*是两种启发式算法;Dijkstra算法和贪婪搜索。Dijkstra算法搜索最短路径。贪婪搜索寻找最便宜的路径h、 Dijkstra的算法速度非常慢,因为它不冒风险。乘以贪婪搜索的效果,冒更多的风险

例如,如果
A*=Dijkstra+Greedy
,那么更快的
A*=Dijkstra+1.1*Greedy
。无论您如何优化内存访问或代码,它都不会修复解决问题的错误方法。让您的A*更贪婪,它将专注于找到解决方案,而不是完美的解决方案

注:


在标准A*中,它将寻求完美的解决方案,直到遇到障碍。显示了不同的搜索启发法;注意贪婪搜索的速度(A*跳到2:22,贪婪搜索跳到4:40)。当我第一次开始使用a*时,我自己也遇到了类似的问题,上面修改的a*I大纲成倍地提高了我的性能。故事的寓意是:使用正确的工具完成工作。

TL;DR:在节点列表(图表)中只包括重要的补丁(或代理)!

加快速度的一种方法是不要搜索每个网格空间。A*是一种图形搜索,但似乎大多数程序员只是将网格中的每个点都转储到图形中。这不是必需的。使用稀疏搜索图形,而不是搜索屏幕上的每个点,可以加快速度

即使在一个复杂的迷宫中,你也可以通过在图表中只包含角点和交叉点来加快速度。不要将走廊网格添加到开放列表中——向前搜索以找到下一个角点或交叉点
// init
A_star map;
Graphics::TBitmap *maze=new Graphics::TBitmap;
maze->LoadFromFile("maze.bmp");
maze->HandleType=bmDIB;
maze->PixelFormat=pf32bit;
map.set(maze,0); // walls are 0x00000000 (black)
// this can be called repetitive without another init
map.compute(x0,y0,x1,y1); // map.px[map.ps],map.py[map.ps] holds the path
map.get(maze,0); // this is just for drawing the result map back to bitmap for viewing
Greedy Search = distance from end
Dijkstra's Algorithm = distance from start