00001 //----------------------------------------------------------------------------- 00002 /** @file experiments.cpp 00003 Example program loading tiling maps from files. 00004 00005 $Id: experiments_8cpp-source.html,v 1.1.1.1 2003/08/07 19:41:38 emarkus Exp $ 00006 $Source: /usr/cvsroot/www_pathfind/libpathfind/0.1.0/doc/experiments_8cpp-source.html,v $ 00007 */ 00008 //----------------------------------------------------------------------------- 00009 00010 #include <memory> 00011 #include "pathfind.h" 00012 #include <iostream> 00013 #include <fstream> 00014 #include <sstream> 00015 00016 using namespace std; 00017 using namespace PathFind; 00018 00019 //----------------------------------------------------------------------------- 00020 00021 static const int s_numberRuns = 400; 00022 static const long long int s_nodesLimit = 100000000L; 00023 00024 //----------------------------------------------------------------------------- 00025 00026 typedef enum {A_STAR, FRINGE, IDA_STAR} SearchAlgorithm; 00027 00028 //----------------------------------------------------------------------------- 00029 00030 void printHeader(SearchAlgorithm searchAlgorithm, Tiling::Type type, 00031 const char* name) 00032 { 00033 cout << "==============================================================\n"; 00034 switch (searchAlgorithm) 00035 { 00036 case A_STAR: 00037 cout << "A_STAR"; 00038 break; 00039 case FRINGE: 00040 cout << "FRINGE"; 00041 break; 00042 case IDA_STAR: 00043 cout << "IDA_STAR"; 00044 break; 00045 } 00046 cout << " "; 00047 switch (type) 00048 { 00049 case Tiling::TILE: 00050 cout << "TILE"; 00051 break; 00052 case Tiling::OCTILE: 00053 cout << "OCTILE"; 00054 break; 00055 case Tiling::OCTILE_UNICOST: 00056 cout << "OCTILE_UNICOST"; 00057 break; 00058 case Tiling::HEX: 00059 cout << "HEX"; 00060 break; 00061 } 00062 cout << " "; 00063 cout << name; 00064 cout << '\n'; 00065 cout << "==============================================================\n"; 00066 } 00067 00068 StatisticsCollection 00069 runExperiment(SearchAlgorithm searchAlgorithm, Search* search, 00070 const Tiling& tiling, vector< pair<int,int> >& paths, 00071 const int fileIndex, int numberRuns, const char *fileName) 00072 { 00073 //printHeader(searchAlgorithm, tiling.getType(), fileName); 00074 //cout << tiling.getWidth() << "x" << tiling.getHeight() << '\n'; 00075 00076 SearchUtils searchUtils; 00077 StatisticsCollection statistics = search->createStatistics(); 00078 00079 if ( numberRuns > s_numberRuns ) 00080 numberRuns = s_numberRuns; 00081 00082 clock_t startTime = clock(); 00083 for (int runIndex = 0; runIndex < numberRuns; ++runIndex) 00084 { 00085 // Choose random start and target 00086 int start, target; 00087 start = paths[runIndex].first; 00088 target = paths[runIndex].second; 00089 00090 //searchUtils.findRandomStartTarget(tiling, start, target); 00091 //cout << "Run " << runIndex << ":\n"; 00092 //tiling.printFormatted(cout, start, target); 00093 //cout << '\n'; 00094 00095 // Do the search 00096 search->findPath(tiling, start, target); 00097 //cout << '\n'; 00098 //const vector<int>& path = search->getPath(); 00099 //tiling.printFormatted(cout, path); 00100 //cout << '\n'; 00101 //tiling.printPathAndLabels(cout, path, search->getVisitedNodes()); 00102 //cout << '\n'; 00103 00104 // Accumulate statistics 00105 const StatisticsCollection& searchStatistics = search->getStatistics(); 00106 00107 cout << " " << fileIndex; 00108 cout << " " << runIndex; 00109 cout << " " << start; 00110 cout << " " << target; 00111 cout << " " << tiling.getHeuristic(start,target); 00112 cout << " " << searchStatistics.get("path_cost").getMean(); 00113 cout << " " << search->getPath().size(); 00114 cout << " " << searchStatistics.get("nodes_expanded").getMean(); 00115 cout << " " << searchStatistics.get("cpu_time").getMean(); 00116 cout << " " << searchStatistics.get("iterations").getMean(); 00117 00118 cout << '\n'; 00119 00120 statistics.add(searchStatistics); 00121 } 00122 00123 statistics.create("cpu_time_avg"); 00124 double timeDiff = 00125 static_cast<double>(clock() - startTime) / CLOCKS_PER_SEC; 00126 statistics.get("cpu_time_avg").add( timeDiff / numberRuns ); 00127 // cout << "cpu_time_avg = " << timeDiff / numberRuns << endl; 00128 statistics.print(cout); 00129 00130 return statistics; 00131 } 00132 00133 00134 /** Generates a file with random passable start/target locations 00135 for a given map file. 00136 */ 00137 void generatePaths( const char *filename ) 00138 { 00139 ifstream file(filename); 00140 LineReader reader(file); 00141 Tiling tiling(reader); 00142 00143 string outfile; 00144 outfile = (outfile + filename) + ".paths"; 00145 ofstream out(outfile.c_str()); 00146 SearchUtils searchUtils; 00147 for (int runIndex = 0; runIndex < s_numberRuns; ++runIndex) 00148 { 00149 // Choose random start and target 00150 int start, target; 00151 searchUtils.findRandomStartTarget(tiling, start, target); 00152 out << runIndex << " " << start << " " << target << "\n"; 00153 } 00154 00155 out.close(); 00156 } 00157 00158 00159 int main(int argc, char *argv[]) 00160 { 00161 try 00162 { 00163 00164 if ( argc == 1 ) 00165 { 00166 cerr << 00167 "Usage: experiments [RUN_ASTAR|RUN_FRINGE|RUN_IDASTAR" 00168 "|RUN_IDASTAR_f|RUN_IDASTAR_F|GEN_PATHS]"; 00169 cerr << " <mapfiles>" << endl; 00170 exit(EXIT_FAILURE); 00171 } 00172 00173 SearchAlgorithm searchAlgorithm = A_STAR; 00174 string command = argv[1]; 00175 IDAStar::Caching caching = IDAStar::NO_CACHING; 00176 00177 if ( command == "RUN_ASTAR" ) 00178 { 00179 searchAlgorithm = A_STAR; 00180 } 00181 else if (command == "RUN_FRINGE") 00182 { 00183 searchAlgorithm = FRINGE; 00184 } 00185 else if ( command == "RUN_IDASTAR" ) 00186 { 00187 searchAlgorithm = IDA_STAR; 00188 caching = IDAStar::NO_CACHING; 00189 } 00190 else if ( command == "RUN_IDASTAR_f" ) 00191 { 00192 searchAlgorithm = IDA_STAR; 00193 caching = IDAStar::f_CACHING; 00194 } 00195 else if ( command == "RUN_IDASTAR_F" ) 00196 { 00197 searchAlgorithm = IDA_STAR; 00198 caching = IDAStar::F_CACHING; 00199 } 00200 else if ( command == "GEN_PATHS" ) 00201 { 00202 for ( int i=2 ; i<argc ; i++ ) 00203 { 00204 generatePaths( argv[i] ); 00205 } 00206 exit(EXIT_SUCCESS); 00207 } 00208 else 00209 { 00210 cerr << "Unknown command '" << command << "'" << endl; 00211 exit(EXIT_FAILURE); 00212 } 00213 00214 // Run either A_STAR or IDA_STAR experiments. 00215 StatisticsCollection *statisticsSum = 0; 00216 auto_ptr<Search> search; 00217 switch (searchAlgorithm) 00218 { 00219 case A_STAR: 00220 search.reset(new AStar<>()); 00221 break; 00222 case FRINGE: 00223 search.reset(new FringeSearch<>()); 00224 break; 00225 case IDA_STAR: 00226 search.reset(new IDAStar(caching)); 00227 break; 00228 } 00229 search->setNodesLimit(s_nodesLimit); 00230 for ( int i=2 ; i<argc ; i++ ) { 00231 // Read in map when constucting tiling object. 00232 ifstream file(argv[i]); 00233 LineReader reader(file); 00234 Tiling tiling(reader); 00235 00236 // Read in start/target states to do pathfinding on. 00237 string pathfileName; 00238 pathfileName = (pathfileName + argv[i]) + ".paths"; 00239 ifstream pathfile(pathfileName.c_str()); 00240 if ( !pathfile ) { 00241 cerr << "Could not open pathfile " << pathfileName << endl; 00242 exit(1); 00243 } 00244 vector< pair<int,int> > paths(100); 00245 int vidx, idx, start, target; 00246 vidx = 0; 00247 while ( pathfile >> idx >> start >> target ) 00248 { 00249 pair<int,int> path; 00250 path.first = start; 00251 path.second = target; 00252 00253 paths[vidx++] = path; 00254 if ( vidx >= (int) paths.size() ) 00255 paths.resize(2*paths.size()); 00256 } 00257 00258 // ... now ready to run experiments 00259 StatisticsCollection statistics = 00260 runExperiment(searchAlgorithm, search.get(), tiling, paths, 00261 i-1, vidx, argv[i]); 00262 00263 // gather statstic, need to create it the first time. 00264 if ( statisticsSum == 0 ) 00265 statisticsSum = new StatisticsCollection(statistics); 00266 else 00267 statisticsSum->add(statistics); 00268 } 00269 cout << '\n'; 00270 if ( argc > 2 ) 00271 { 00272 statisticsSum->print(cout); 00273 } 00274 } 00275 catch (const exception& e) 00276 { 00277 cerr << "Error: " << e.what() << '\n'; 00278 return -1; 00279 } 00280 return 0; 00281 } 00282 00283 //-----------------------------------------------------------------------------