Main   Class Hierarchy   Classes   Compound List   Files   Compound Members   File Members   Pages  

idastar.cpp

Go to the documentation of this file.
00001 //-----------------------------------------------------------------------------
00002 /** @file idastar.cpp
00003     @see idastar.h
00004 
00005     $Id: idastar_8cpp-source.html,v 1.1.1.1 2003/08/07 19:41:39 emarkus Exp $
00006     $Source: /usr/cvsroot/www_pathfind/libpathfind/0.1.0/doc/idastar_8cpp-source.html,v $
00007 */
00008 //-----------------------------------------------------------------------------
00009 
00010 #include "idastar.h"
00011 
00012 #include <iostream>
00013 #include <math.h>
00014 #include "util.h"
00015 
00016 using namespace std;
00017 using namespace PathFind;
00018 
00019 //-----------------------------------------------------------------------------
00020 
00021 IDAStar::IDAStar(Caching caching)
00022     : m_caching(caching),
00023       m_statistics(createStatistics()),
00024       m_branchingFactor(m_statistics.get("branching_factor"))
00025 {
00026 }
00027 
00028 bool IDAStar::checkCache(int nodeId, int f, int g, int iteration, int& fMin)
00029 {
00030     if (m_cache[nodeId].m_iter > 0) 
00031     {
00032         if ((m_cache[nodeId].m_g < g) ||
00033             ((m_cache[nodeId].m_g == g) && 
00034              (m_cache[nodeId].m_iter == iteration)))
00035         {
00036             fMin = INT_MAX;
00037             return true;
00038         }
00039 
00040         if ( m_caching == F_CACHING )
00041         {
00042             // Check if backed-up F-value causes an early termination.
00043             if ( m_cache[nodeId].m_f > m_fLimit )
00044             {
00045                 fMin = m_cache[nodeId].m_f;
00046                 return true;
00047             }
00048         }
00049 
00050     }
00051     return false;
00052 }
00053 
00054 StatisticsCollection IDAStar::createStatistics()
00055 {
00056     StatisticsCollection collection;
00057     collection.create("aborted");
00058     collection.create("cpu_time");
00059     collection.create("path_cost");
00060     collection.create("path_length");
00061     collection.create("branching_factor");
00062     collection.create("nodes_expanded");
00063     collection.create("nodes_visited");
00064     collection.create("iterations");
00065     return collection;
00066 }
00067 
00068 bool IDAStar::findPath(const Environment& env, int start, int target)
00069 {
00070     assert(env.isValidNodeId(start));
00071     assert(env.isValidNodeId(target));
00072     clock_t startTime = clock();
00073     m_statistics.clear();
00074     m_nodesExpanded = 0;
00075     m_nodesVisited = 0;
00076     m_env = &env;
00077     m_target = target;
00078     m_path.clear();
00079     m_abortSearch = false;
00080     m_visitedNodes.resize(env.getNumberNodes());
00081     fill(m_visitedNodes.begin(), m_visitedNodes.end(), ' ');
00082     if ( m_caching != NO_CACHING )
00083     {
00084         m_cache.clear();
00085         m_cache.resize(env.getNumberNodes());
00086     }
00087     findPathIdaStar(start);
00088     m_statistics.get("aborted").add(m_abortSearch ? 1 : 0);
00089     double timeDiff =
00090         static_cast<double>(clock() - startTime) / CLOCKS_PER_SEC;
00091     m_statistics.get("cpu_time").add(timeDiff);
00092     m_statistics.get("nodes_expanded").add(m_nodesExpanded);
00093     m_statistics.get("nodes_visited").add(m_nodesVisited);
00094     m_statistics.get("path_length").add(m_path.size());
00095     return true;
00096 }
00097 
00098 void IDAStar::findPathIdaStar(int start)
00099 {
00100     const int maxFLimit = m_env->getNumberNodes() * m_env->getMaxCost();
00101     int heuristic = m_env->getHeuristic(start, m_target);
00102     m_fLimit = heuristic;
00103     int minCost = m_env->getMinCost();
00104     unsigned int expectedMaxDepth =
00105         static_cast<unsigned int>(heuristic / minCost);
00106     if (m_successorStack.size() < expectedMaxDepth)
00107         m_successorStack.resize(expectedMaxDepth);
00108     int iteration = 1;
00109 
00110     while (true)
00111     {
00112         //cerr << "limit = " << m_fLimit << '\n';
00113         int fMin = INT_MAX;
00114         searchPathIdaStar(iteration, start, NO_NODE, 0, 0, fMin);
00115         if (m_path.size() > 0)
00116             break;
00117         if (fMin > maxFLimit)
00118             break;
00119         m_fLimit = fMin;
00120         ++iteration;
00121     }
00122     m_statistics.get("iterations").add(iteration);
00123 }
00124 
00125 const StatisticsCollection& IDAStar::getStatistics() const
00126 {
00127     return m_statistics;
00128 }
00129 
00130 void IDAStar::markVisitedNode(int nodeId, int iteration)
00131 {
00132     if (m_visitedNodes[nodeId] != ' ')
00133         return;
00134     m_visitedNodes[nodeId] = getVisitedNodeLabel(iteration);
00135 }
00136 
00137 bool IDAStar::searchPathIdaStar(int iteration, int node, int lastNode,
00138                                 int depth, int g, int& fMin)
00139 {
00140     ++m_nodesVisited;
00141     markVisitedNode(node, iteration);
00142     if (m_nodesLimit >= 0 && m_nodesVisited > m_nodesLimit)
00143     {
00144         m_abortSearch = true;
00145         fMin = INT_MAX;
00146         return false;
00147     }
00148     int f = g + m_env->getHeuristic(node, m_target);
00149     if (f > m_fLimit)
00150     {
00151         fMin = f;
00152         return false;
00153     }
00154     if (node == m_target)
00155     {
00156         m_statistics.get("path_cost").add(f);
00157         m_path.push_back(node);
00158         fMin = f;
00159         return true;
00160     }
00161 
00162     if (m_caching != NO_CACHING)
00163     {
00164         if (checkCache(node, f, g, iteration, fMin))
00165         {
00166             return false;
00167         }
00168         addCache(node, f, g, iteration);
00169     }
00170 
00171     ++m_nodesExpanded;
00172     assert(depth >= 0);
00173     if (m_successorStack.size() < static_cast<unsigned int>(depth + 1))
00174         m_successorStack.resize(depth + 1);
00175     vector<Environment::Successor>& successors = m_successorStack[depth];
00176     m_env->getSuccessors(node, lastNode, successors);
00177     int numberSuccessors = successors.size();
00178     m_branchingFactor.add(numberSuccessors);
00179     fMin = INT_MAX;
00180     for (int i = 0; i < numberSuccessors; ++i)
00181     {
00182         // Get reference on edge again, because resize could have changed it.
00183         const Environment::Successor& successor = m_successorStack[depth][i];
00184         int targetNodeId = successor.m_target;
00185         int fMinChild;
00186         if (targetNodeId == lastNode)
00187             continue;
00188         if (searchPathIdaStar(iteration, targetNodeId, node, depth + 1,
00189                               g + successor.m_cost, fMinChild))
00190         {
00191             if ( fMinChild < fMin )
00192                 fMin = fMinChild;
00193             m_path.push_back(node);
00194             return true;
00195         }
00196         if ( fMinChild < fMin )
00197             fMin = fMinChild;
00198 
00199         if (m_abortSearch)
00200             return false;
00201     }
00202 
00203     if ( m_caching == F_CACHING ) 
00204     {
00205         if ( fMin > m_cache[node].m_f )
00206             m_cache[node].m_f = fMin;
00207     }
00208     
00209     return false;
00210 }
00211 
00212 //-----------------------------------------------------------------------------


Generated on Thu Aug 7 13:04:49 2003 by Doxygen1.3.1