00001 #ifndef _pathfinder_astar_generic_cached_
00002 #define _pathfinder_astar_generic_cached_
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00032 #include "pathfinder.h"
00033
00034 #include <functional>
00035 #include <algorithm>
00036 #include <map>
00037
00038 namespace Pathfinder
00039 {
00040
00053 template <class NODETYPE, class DESTCOST, class GETNEIGHBORS, class COSTTYPE=double>
00054 class AStarGenericCached
00055 {
00056 public:
00057 AStarGenericCached();
00058 ~AStarGenericCached();
00059
00060
00074 const PathResult FindPath(const NODETYPE &start, const long startindex, const NODETYPE &goal, std::vector<NODETYPE> &finalpath, DESTCOST &destinationcost, GETNEIGHBORS &getneighbors);
00075
00076
00086 void InitializeStep(const NODETYPE &start, const long startindex, const NODETYPE &goal, DESTCOST &destcost, GETNEIGHBORS &getneighbors);
00087
00093 const PathResult Step();
00094
00102 void GetPath(std::vector<NODETYPE> &path);
00103
00107 void ClearCache();
00108
00116 void ClearCacheIndex(const long index);
00117
00121 class AddNeighborFunctor
00122 {
00123 public:
00124 AddNeighborFunctor(AStarGenericCached &astar):m_astargeneric(astar) {}
00132 inline void operator()(const NODETYPE &neighbor, const long neighborindex, const COSTTYPE &movecost)
00133 {
00134 m_astargeneric.AddNeighborCached(neighbor,neighborindex,movecost);
00135 }
00136 private:
00137 AStarGenericCached &m_astargeneric;
00138 };
00139
00143 class IGetNeighbors
00144 {
00145 public:
00146 virtual ~IGetNeighbors()=0;
00153 virtual void operator()(const NODETYPE &node, typename AStarGenericCached<NODETYPE,DESTCOST,GETNEIGHBORS,COSTTYPE>::AddNeighborFunctor &addneighborfunctor)=0;
00154 };
00155
00156 private:
00157
00158 AStarGenericCached(const AStarGenericCached &rhs);
00159 AStarGenericCached &operator=(const AStarGenericCached &rhs);
00160
00161 struct astarnode
00162 {
00163 NODETYPE m_node;
00164 astarnode *m_parent;
00165 COSTTYPE m_f;
00166 COSTTYPE m_g;
00167 COSTTYPE m_h;
00168 long m_index;
00169 };
00170
00171 struct astarnodecompare:public std::binary_function<astarnode *, astarnode *, bool>
00172 {
00173 inline bool operator()(const astarnode *left, const astarnode *right)
00174 {
00175 return right->m_f<left->m_f;
00176 }
00177 };
00178
00179 class astarallocator:public std::allocator<astarnode>
00180 {
00181 public:
00182 astarallocator()
00183 {
00184 m_mempos=0;
00185 m_mem.resize(1000,NULL);
00186 }
00187
00188 ~astarallocator()
00189 {
00190 for(std::vector<astarnode *>::size_type i=0; i<m_mempos; i++)
00191 {
00192 delete m_mem[i];
00193 }
00194 }
00195
00196 pointer allocate(size_type count)
00197 {
00198 return m_mempos>0 ? m_mem[--m_mempos] : new astarnode;
00199 }
00200
00201 void deallocate(pointer ptr, size_type count)
00202 {
00203 if(m_mempos==m_mem.size())
00204 {
00205 m_mem.resize(m_mem.size()+1000,NULL);
00206 }
00207 m_mem[m_mempos++]=ptr;
00208 }
00209
00210 private:
00211 std::vector<astarnode *> m_mem;
00212 typename std::vector<astarnode *>::size_type m_mempos;
00213 };
00214
00215 struct listelement
00216 {
00217 listelement():m_node(NULL),m_onopen(false),m_onclosed(false) {}
00218 astarnode *m_node;
00219 bool m_onopen;
00220 bool m_onclosed;
00221 };
00222
00223 void ClearOpenList();
00224 void ClearClosedList();
00225 void AddNeighborCached(const NODETYPE &neighbor, const long neighborindex, const COSTTYPE &movecost);
00226
00227 astarallocator m_astarnodeallocator;
00228
00229 std::vector<astarnode *> m_openlist;
00230 std::vector<astarnode *> m_closedlist;
00231 std::vector<listelement> m_helperlist;
00232 long m_helperliststartindex;
00233
00234 astarnode *m_currentnode;
00235 astarnode *m_astaropen;
00236 const NODETYPE *m_start;
00237 const NODETYPE *m_goal;
00238 DESTCOST *m_destinationcost;
00239 GETNEIGHBORS *m_getneighbors;
00240
00241 struct cacheelement
00242 {
00243 cacheelement():m_hascache(false) {}
00244 bool m_hascache;
00245 std::vector<std::pair<std::pair<NODETYPE,long> ,COSTTYPE> > m_neighbors;
00246 };
00247 std::vector<cacheelement> m_cache;
00248 long m_cachestartindex;
00249
00250 inline listelement &hl(const long index)
00251 {
00252 if(m_helperlist.size()==0)
00253 {
00254 m_helperlist.push_back(listelement());
00255 m_helperliststartindex=index;
00256 }
00257 else if(index<m_helperliststartindex)
00258 {
00259 m_helperlist.insert(m_helperlist.begin(),m_helperliststartindex-index,listelement());
00260 m_helperliststartindex=index;
00261 }
00262 else if(index-m_helperliststartindex>=m_helperlist.size())
00263 {
00264 m_helperlist.insert(m_helperlist.end(),((index-m_helperliststartindex)+1)-m_helperlist.size(),listelement());
00265 }
00266
00267 return m_helperlist[index-m_helperliststartindex];
00268 }
00269
00270 };
00271
00272 template <class NODETYPE, class DESTCOST, class GETNEIGHBORS, class COSTTYPE>
00273 AStarGenericCached<NODETYPE,DESTCOST,GETNEIGHBORS,COSTTYPE>::AStarGenericCached():
00274 m_currentnode(0),m_astaropen(0),m_goal(0),m_destinationcost(0),m_getneighbors(0),m_cachestartindex(0),m_helperliststartindex(0)
00275 {
00276
00277 }
00278
00279 template <class NODETYPE, class DESTCOST, class GETNEIGHBORS, class COSTTYPE>
00280 AStarGenericCached<NODETYPE,DESTCOST,GETNEIGHBORS,COSTTYPE>::~AStarGenericCached()
00281 {
00282 ClearOpenList();
00283 ClearClosedList();
00284 }
00285
00286 template <class NODETYPE, class DESTCOST, class GETNEIGHBORS, class COSTTYPE>
00287 void AStarGenericCached<NODETYPE,DESTCOST,GETNEIGHBORS,COSTTYPE>::AddNeighborCached(const NODETYPE &neighbor, const long neighborindex, const COSTTYPE &movecost)
00288 {
00289
00290 if(hl(neighborindex).m_onclosed==false)
00291 {
00292
00293
00294 m_astaropen=m_helperlist[neighborindex-m_helperliststartindex].m_node;
00295
00296
00297 if(m_astaropen!=NULL)
00298 {
00299 if(m_currentnode->m_g+movecost<m_astaropen->m_g)
00300 {
00301 m_astaropen->m_g=m_currentnode->m_g+movecost;
00302 m_astaropen->m_f=m_astaropen->m_g+m_astaropen->m_h;
00303 m_astaropen->m_parent=m_currentnode;
00304 std::make_heap(m_openlist.begin(),m_openlist.end(),astarnodecompare());
00305 }
00306 }
00307
00308 else
00309 {
00310 astarnode *newnode=m_astarnodeallocator.allocate(1);
00311 newnode->m_node=neighbor;
00312 newnode->m_parent=m_currentnode;
00313 newnode->m_g=m_currentnode->m_g+movecost;
00314 newnode->m_h=m_destinationcost->operator()(neighbor,*m_goal);
00315 newnode->m_f=newnode->m_g+newnode->m_h;
00316 newnode->m_index=neighborindex;
00317
00318 m_openlist.push_back(newnode);
00319 std::push_heap(m_openlist.begin(),m_openlist.end(),astarnodecompare());
00320 m_helperlist[neighborindex-m_helperliststartindex].m_onopen=true;
00321 m_helperlist[neighborindex-m_helperliststartindex].m_node=newnode;
00322 }
00323
00324 }
00325
00326 if(m_cache.size()==0)
00327 {
00328 m_cache.push_back(cacheelement());
00329 m_cachestartindex=m_currentnode->m_index;
00330 }
00331 else if(m_currentnode->m_index<m_cachestartindex)
00332 {
00333 m_cache.insert(m_cache.begin(),m_cachestartindex-m_currentnode->m_index,cacheelement());
00334 m_cachestartindex=m_currentnode->m_index;
00335 }
00336 else if(m_currentnode->m_index-m_cachestartindex>=m_cache.size())
00337 {
00338 m_cache.insert(m_cache.end(),((m_currentnode->m_index-m_cachestartindex)+1)-m_cache.size(),cacheelement());
00339 }
00340
00341 m_cache[m_currentnode->m_index-m_cachestartindex].m_hascache=true;
00342 m_cache[m_currentnode->m_index-m_cachestartindex].m_neighbors.push_back(std::pair<std::pair<NODETYPE,long> ,COSTTYPE>(std::pair<NODETYPE,long>(neighbor,neighborindex),movecost));
00343
00344 }
00345
00346 template <class NODETYPE, class DESTCOST, class GETNEIGHBORS, class COSTTYPE>
00347 void AStarGenericCached<NODETYPE,DESTCOST,GETNEIGHBORS,COSTTYPE>::ClearCache()
00348 {
00349 m_cache.clear();
00350 m_cachestartindex=0;
00351 }
00352
00353 template <class NODETYPE, class DESTCOST, class GETNEIGHBORS, class COSTTYPE>
00354 void AStarGenericCached<NODETYPE,DESTCOST,GETNEIGHBORS,COSTTYPE>::ClearCacheIndex(const long index)
00355 {
00356 if(index>=m_cachestartindex && index-m_cachestartindex<m_cache.size())
00357 {
00358 m_cache[index-m_cachestartindex].m_hascache=false;
00359 m_cache[index-m_cachestartindex].m_neighbors.clear();
00360 }
00361 }
00362
00363 template <class NODETYPE, class DESTCOST, class GETNEIGHBORS, class COSTTYPE>
00364 void AStarGenericCached<NODETYPE,DESTCOST,GETNEIGHBORS,COSTTYPE>::ClearClosedList()
00365 {
00366 for(std::vector<astarnode *>::iterator i=m_closedlist.begin(); i!=m_closedlist.end(); i++)
00367 {
00368 m_astarnodeallocator.deallocate((*i),1);
00369 }
00370 m_closedlist.clear();
00371 }
00372
00373 template <class NODETYPE, class DESTCOST, class GETNEIGHBORS, class COSTTYPE>
00374 void AStarGenericCached<NODETYPE,DESTCOST,GETNEIGHBORS,COSTTYPE>::ClearOpenList()
00375 {
00376 for(std::vector<astarnode *>::iterator i=m_openlist.begin(); i!=m_openlist.end(); i++)
00377 {
00378 m_astarnodeallocator.deallocate((*i),1);
00379 }
00380 m_openlist.clear();
00381 }
00382
00383 template <class NODETYPE, class DESTCOST, class GETNEIGHBORS, class COSTTYPE>
00384 const PathResult AStarGenericCached<NODETYPE,DESTCOST,GETNEIGHBORS,COSTTYPE>::FindPath(const NODETYPE &start, const long startindex, const NODETYPE &goal, std::vector<NODETYPE> &finalpath, DESTCOST &destinationcost, GETNEIGHBORS &getneighbors)
00385 {
00386
00387 ClearOpenList();
00388 ClearClosedList();
00389 m_helperlist.clear();
00390 m_helperliststartindex=0;
00391
00392 m_astaropen=0;
00393 m_goal=&goal;
00394 m_destinationcost=&destinationcost;
00395 AddNeighborFunctor anf(*this);
00396
00397
00398 m_currentnode=0;
00399 astarnode *newnode=m_astarnodeallocator.allocate(1);
00400 newnode->m_node=start;
00401 newnode->m_parent=NULL;
00402 newnode->m_g=destinationcost(start,goal);
00403 newnode->m_h=0;
00404 newnode->m_f=newnode->m_g+newnode->m_h;
00405 newnode->m_index=startindex;
00406
00407
00408 m_openlist.push_back(newnode);
00409 std::push_heap(m_openlist.begin(),m_openlist.end(),astarnodecompare());
00410 hl(newnode->m_index).m_node=newnode;
00411 m_helperlist[newnode->m_index-m_helperliststartindex].m_onopen=true;
00412
00413 while(m_openlist.size()>0)
00414 {
00415 m_currentnode=m_openlist.front();
00416 std::pop_heap(m_openlist.begin(),m_openlist.end(),astarnodecompare());
00417 m_openlist.pop_back();
00418 m_helperlist[m_currentnode->m_index-m_helperliststartindex].m_onopen=false;
00419
00420
00421 m_closedlist.push_back(m_currentnode);
00422 m_helperlist[m_currentnode->m_index-m_helperliststartindex].m_onclosed=true;
00423
00424 if(m_currentnode->m_node!=goal)
00425 {
00426
00427 if(m_currentnode->m_index>=m_cachestartindex && m_currentnode->m_index<m_cachestartindex+m_cache.size() && m_cache[m_currentnode->m_index-m_cachestartindex].m_hascache)
00428 {
00429 for(std::vector<std::pair<std::pair<NODETYPE,long> ,COSTTYPE> >::iterator i=m_cache[m_currentnode->m_index-m_cachestartindex].m_neighbors.begin(); i!=m_cache[m_currentnode->m_index-m_cachestartindex].m_neighbors.end(); i++)
00430 {
00431
00432 if(hl((*i).first.second).m_onclosed==false)
00433 {
00434
00435
00436 m_astaropen=m_helperlist[(*i).first.second-m_helperliststartindex].m_node;
00437
00438
00439 if(m_astaropen!=NULL)
00440 {
00441 if(m_currentnode->m_g+(*i).second<m_astaropen->m_g)
00442 {
00443 m_astaropen->m_g=m_currentnode->m_g+(*i).second;
00444 m_astaropen->m_f=m_astaropen->m_g+m_astaropen->m_h;
00445 m_astaropen->m_parent=m_currentnode;
00446 std::make_heap(m_openlist.begin(),m_openlist.end(),astarnodecompare());
00447 }
00448 }
00449
00450 else
00451 {
00452 astarnode *newnode=m_astarnodeallocator.allocate(1);
00453 newnode->m_node=(*i).first.first;
00454 newnode->m_parent=m_currentnode;
00455 newnode->m_g=m_currentnode->m_g+(*i).second;
00456 newnode->m_h=m_destinationcost->operator()((*i).first.first,*m_goal);
00457 newnode->m_f=newnode->m_g+newnode->m_h;
00458 newnode->m_index=(*i).first.second;
00459
00460 m_openlist.push_back(newnode);
00461 std::push_heap(m_openlist.begin(),m_openlist.end(),astarnodecompare());
00462 hl(newnode->m_index).m_onopen=true;
00463 m_helperlist[newnode->m_index-m_helperliststartindex].m_node=newnode;
00464 }
00465
00466 }
00467 }
00468 }
00469 else
00470 {
00471 getneighbors(m_currentnode->m_node,anf);
00472 }
00473 }
00474 else
00475 {
00476 finalpath.clear();
00477 while(m_currentnode)
00478 {
00479 finalpath.push_back(m_currentnode->m_node);
00480 m_currentnode=m_currentnode->m_parent;
00481 }
00482 return PATH_FOUND;
00483 }
00484
00485 }
00486
00487 return PATH_NOTFOUND;
00488 }
00489
00490 template <class NODETYPE, class DESTCOST, class GETNEIGHBORS, class COSTTYPE>
00491 void AStarGenericCached<NODETYPE,DESTCOST,GETNEIGHBORS,COSTTYPE>::GetPath(std::vector<NODETYPE> &path)
00492 {
00493 path.clear();
00494 astarnode *cnode=m_currentnode;
00495 while(cnode)
00496 {
00497 path.push_back(cnode->m_node);
00498 cnode=cnode->m_parent;
00499 }
00500 }
00501
00502 template <class NODETYPE, class DESTCOST, class GETNEIGHBORS, class COSTTYPE>
00503 void AStarGenericCached<NODETYPE,DESTCOST,GETNEIGHBORS,COSTTYPE>::InitializeStep(const NODETYPE &start, const long startindex, const NODETYPE &goal, DESTCOST &destinationcost, GETNEIGHBORS &getneighbors)
00504 {
00505 m_start=&start;
00506 m_goal=&goal;
00507 m_destinationcost=&destinationcost;
00508 m_getneighbors=&getneighbors;
00509
00510
00511 ClearOpenList();
00512 ClearClosedList();
00513 m_helperlist.clear();
00514 m_helperliststartindex=0;
00515
00516 m_astaropen=0;
00517 m_currentnode=0;
00518
00519 astarnode *newnode=m_astarnodeallocator.allocate(1);
00520 newnode->m_node=start;
00521 newnode->m_parent=NULL;
00522 newnode->m_g=destinationcost(start,goal);
00523 newnode->m_h=0;
00524 newnode->m_f=newnode->m_g+newnode->m_h;
00525 newnode->m_index=startindex;
00526
00527
00528 m_openlist.push_back(newnode);
00529 std::push_heap(m_openlist.begin(),m_openlist.end(),astarnodecompare());
00530 hl(newnode->m_index).m_node=newnode;
00531 m_helperlist[newnode->m_index-m_helperliststartindex].m_onopen=true;
00532
00533 }
00534
00535 template <class NODETYPE, class DESTCOST, class GETNEIGHBORS, class COSTTYPE>
00536 const PathResult AStarGenericCached<NODETYPE,DESTCOST,GETNEIGHBORS,COSTTYPE>::Step()
00537 {
00538 if(m_openlist.size()>0)
00539 {
00540
00541 m_currentnode=m_openlist.front();
00542 std::pop_heap(m_openlist.begin(),m_openlist.end(),astarnodecompare());
00543 m_openlist.pop_back();
00544 m_helperlist[m_currentnode->m_index-m_helperliststartindex].m_onopen=false;
00545
00546
00547 m_closedlist.push_back(m_currentnode);
00548 m_helperlist[m_currentnode->m_index-m_helperliststartindex].m_onclosed=true;
00549
00550 if(m_currentnode->m_node!=*m_goal)
00551 {
00552
00553 if(m_currentnode->m_index>=m_cachestartindex && m_currentnode->m_index<m_cachestartindex+m_cache.size() && m_cache[m_currentnode->m_index-m_cachestartindex].m_hascache)
00554 {
00555 for(std::vector<std::pair<std::pair<NODETYPE,long> ,COSTTYPE> >::iterator i=m_cache[m_currentnode->m_index-m_cachestartindex].m_neighbors.begin(); i!=m_cache[m_currentnode->m_index-m_cachestartindex].m_neighbors.end(); i++)
00556 {
00557
00558 if(hl((*i).first.second).m_onclosed==false)
00559 {
00560
00561
00562 m_astaropen=m_helperlist[(*i).first.second-m_helperliststartindex].m_node;
00563
00564
00565 if(m_astaropen!=NULL)
00566 {
00567 if(m_currentnode->m_g+(*i).second<m_astaropen->m_g)
00568 {
00569 m_astaropen->m_g=m_currentnode->m_g+(*i).second;
00570 m_astaropen->m_f=m_astaropen->m_g+m_astaropen->m_h;
00571 m_astaropen->m_parent=m_currentnode;
00572 std::make_heap(m_openlist.begin(),m_openlist.end(),astarnodecompare());
00573 }
00574 }
00575
00576 else
00577 {
00578 astarnode *newnode=m_astarnodeallocator.allocate(1);
00579 newnode->m_node=(*i).first.first;
00580 newnode->m_parent=m_currentnode;
00581 newnode->m_g=m_currentnode->m_g+(*i).second;
00582 newnode->m_h=m_destinationcost->operator()((*i).first.first,*m_goal);
00583 newnode->m_f=newnode->m_g+newnode->m_h;
00584 newnode->m_index=(*i).first.second;
00585
00586 m_openlist.push_back(newnode);
00587 std::push_heap(m_openlist.begin(),m_openlist.end(),astarnodecompare());
00588 hl(newnode->m_index).m_onopen=true;
00589 m_helperlist[newnode->m_index-m_helperliststartindex].m_node=newnode;
00590 }
00591
00592 }
00593 }
00594 }
00595 else
00596 {
00597 m_getneighbors->operator()(m_currentnode->m_node,AddNeighborFunctor(*this));
00598 }
00599 }
00600 else
00601 {
00602 return PATH_FOUND;
00603 }
00604
00605 return PATH_SEARCHING;
00606
00607 }
00608
00609 return PATH_NOTFOUND;
00610 }
00611
00612 }
00613
00614 #endif // _pathfinder_astar_generic_cached_