$treeview $search $mathjax
00001 // STL 00002 #include <cassert> 00003 #include <stdexcept> 00004 #include <fstream> 00005 #include <sstream> 00006 #include <string> 00007 #include <list> 00008 #include <vector> 00009 // Boost Python 00010 #include <boost/python.hpp> 00011 // Boost Accumulators 00012 #include <boost/accumulators/accumulators.hpp> 00013 #include <boost/accumulators/statistics.hpp> 00014 // StdAir 00015 #include <stdair/stdair_basic_types.hpp> 00016 #include <stdair/basic/BasConst_General.hpp> 00017 #include <stdair/basic/ProgressStatusSet.hpp> 00018 #include <stdair/basic/DemandGenerationMethod.hpp> 00019 #include <stdair/bom/EventStruct.hpp> 00020 #include <stdair/bom/BookingRequestStruct.hpp> 00021 #include <stdair/bom/BomDisplay.hpp> 00022 #include <stdair/service/Logger.hpp> 00023 // TraDemGen 00024 #include <trademgen/TRADEMGEN_Service.hpp> 00025 #include <trademgen/config/trademgen-paths.hpp> 00026 00027 // Aliases for namespaces 00028 namespace ba = boost::accumulators; 00029 00030 // //////// Specific type definitions /////// 00031 typedef unsigned int NbOfRuns_T; 00032 00036 typedef ba::accumulator_set<double, 00037 ba::stats<ba::tag::min, ba::tag::max, 00038 ba::tag::mean (ba::immediate), 00039 ba::tag::sum, 00040 ba::tag::variance> > stat_acc_type; 00041 00042 namespace TRADEMGEN { 00043 00047 void stat_display (std::ostream& oStream, const stat_acc_type& iStatAcc) { 00048 00049 // Store current formatting flags of the output stream 00050 std::ios::fmtflags oldFlags = oStream.flags(); 00051 00052 // 00053 oStream.setf (std::ios::fixed); 00054 00055 // 00056 oStream << "Statistics for the demand generation runs: " << std::endl; 00057 oStream << " minimum = " << ba::min (iStatAcc) << std::endl; 00058 oStream << " mean = " << ba::mean (iStatAcc) << std::endl; 00059 oStream << " maximum = " << ba::max (iStatAcc) << std::endl; 00060 oStream << " count = " << ba::count (iStatAcc) << std::endl; 00061 oStream << " variance = " << ba::variance (iStatAcc) << std::endl; 00062 00063 // Reset formatting flags of output stream 00064 oStream.flags (oldFlags); 00065 } 00066 00070 struct Trademgener { 00071 public: 00075 std::string 00076 trademgen (const NbOfRuns_T& iNbOfRuns, 00077 const std::string& iDemandGenerationMethodString) { 00078 std::ostringstream oStream; 00079 00080 // Convert the input string into a demand generation method enumeration 00081 const stdair::DemandGenerationMethod 00082 iDemandGenerationMethod (iDemandGenerationMethodString); 00083 00084 // Sanity check 00085 if (_logOutputStream == NULL) { 00086 oStream << "The log filepath is not valid." << std::endl; 00087 return oStream.str(); 00088 } 00089 assert (_logOutputStream != NULL); 00090 00091 try { 00092 00093 // DEBUG 00094 *_logOutputStream << "Demand generation for " << iNbOfRuns << " runs, " 00095 << "with the following method: " 00096 << iDemandGenerationMethod << std::endl; 00097 00098 if (_trademgenService == NULL) { 00099 oStream << "The TraDemGen service has not been initialised, " 00100 << "i.e., the init() method has not been called " 00101 << "correctly on the Trademgener object. Please " 00102 << "check that all the parameters are not empty and " 00103 << "point to actual files."; 00104 *_logOutputStream << oStream.str(); 00105 return oStream.str(); 00106 } 00107 assert (_trademgenService != NULL); 00108 00109 // Initialise the statistics collector/accumulator 00110 stat_acc_type lStatAccumulator; 00111 00112 // Retrieve the expected (mean value of the) number of events to be 00113 // generated 00114 const stdair::Count_T& lExpectedNbOfEventsToBeGenerated = 00115 _trademgenService->getExpectedTotalNumberOfRequestsToBeGenerated(); 00116 00117 // Initialise the (Boost) progress display object 00118 boost::progress_display 00119 lProgressDisplay (lExpectedNbOfEventsToBeGenerated * iNbOfRuns); 00120 00121 for (NbOfRuns_T runIdx = 1; runIdx <= iNbOfRuns; ++runIdx) { 00122 // ///////////////////////////////////////////////////// 00123 *_logOutputStream << "Run number: " << runIdx << std::endl; 00124 00129 const stdair::Count_T& lActualNbOfEventsToBeGenerated = 00130 _trademgenService->generateFirstRequests (iDemandGenerationMethod); 00131 00132 // DEBUG 00133 *_logOutputStream << "[" << runIdx << "] Expected: " 00134 << lExpectedNbOfEventsToBeGenerated << ", actual: " 00135 << lActualNbOfEventsToBeGenerated << std::endl; 00136 00144 while (_trademgenService->isQueueDone() == false) { 00145 00146 // Extract the next event from the event queue 00147 stdair::EventStruct lEventStruct; 00148 stdair::ProgressStatusSet lProgressStatusSet = 00149 _trademgenService->popEvent (lEventStruct); 00150 00151 // DEBUG 00152 // STDAIR_LOG_DEBUG ("[" << runIdx << "] Poped event: '" 00153 // << lEventStruct.describe() << "'."); 00154 00155 // Extract the corresponding demand/booking request 00156 const stdair::BookingRequestStruct& lPoppedRequest = 00157 lEventStruct.getBookingRequest(); 00158 00159 // DEBUG 00160 *_logOutputStream << "[" << runIdx << "] Poped booking request: '" 00161 << lPoppedRequest.describe() << "'." << std::endl; 00162 00163 // Dump the request into the dedicated CSV file 00164 // stdair::BomDisplay::csvDisplay (output, lPoppedRequest); 00165 00166 // Retrieve the corresponding demand stream key 00167 const stdair::DemandGeneratorKey_T& lDemandStreamKey = 00168 lPoppedRequest.getDemandGeneratorKey(); 00169 00170 // Assess whether more events should be generated for that 00171 // demand stream 00172 const bool stillHavingRequestsToBeGenerated = _trademgenService-> 00173 stillHavingRequestsToBeGenerated (lDemandStreamKey, 00174 lProgressStatusSet, 00175 iDemandGenerationMethod); 00176 00177 // DEBUG 00178 *_logOutputStream << lProgressStatusSet.describe() << std::endl; 00179 *_logOutputStream << "=> [" << lDemandStreamKey 00180 << "] is now processed. Still generate events " 00181 << "for that demand stream? " 00182 << stillHavingRequestsToBeGenerated << std::endl; 00183 00184 // If there are still events to be generated for that demand 00185 // stream, generate and add them to the event queue 00186 if (stillHavingRequestsToBeGenerated == true) { 00187 00188 stdair::BookingRequestPtr_T lNextRequest_ptr = 00189 _trademgenService->generateNextRequest(lDemandStreamKey, 00190 iDemandGenerationMethod); 00191 00192 assert (lNextRequest_ptr != NULL); 00193 00194 // Sanity check 00195 const stdair::Duration_T lDuration = 00196 lNextRequest_ptr->getRequestDateTime() 00197 - lPoppedRequest.getRequestDateTime(); 00198 if (lDuration.total_milliseconds() < 0) { 00199 *_logOutputStream << "[" << lDemandStreamKey 00200 << "] The date-time of the generated event (" 00201 << lNextRequest_ptr->getRequestDateTime() 00202 << ") is lower than the date-time " 00203 << "of the current event (" 00204 << lPoppedRequest.getRequestDateTime() 00205 << ")" << std::endl; 00206 assert (false); 00207 } 00208 00209 // DEBUG 00210 *_logOutputStream << "[" << lDemandStreamKey 00211 << "] Added request: '" 00212 << lNextRequest_ptr->describe() 00213 << "'. Is queue done? " 00214 << _trademgenService->isQueueDone() 00215 << std::endl; 00216 } 00217 // DEBUG 00218 *_logOutputStream << std::endl; 00219 00220 // Update the progress display 00221 ++lProgressDisplay; 00222 } 00223 00224 // Add the number of events to the statistics accumulator 00225 lStatAccumulator (lActualNbOfEventsToBeGenerated); 00226 00227 // Reset the service (including the event queue) for the next run 00228 _trademgenService->reset(); 00229 } 00230 00231 // DEBUG 00232 *_logOutputStream << "End of the demand generation. Following are some " 00233 << "statistics for the " << iNbOfRuns << " runs." 00234 << std::endl; 00235 std::ostringstream oStatStr; 00236 stat_display (oStatStr, lStatAccumulator); 00237 *_logOutputStream << oStatStr.str() << std::endl; 00238 00239 // DEBUG 00240 const std::string& lBOMStr = _trademgenService->csvDisplay(); 00241 *_logOutputStream << lBOMStr << std::endl; 00242 00243 // DEBUG 00244 *_logOutputStream << "TraDemGen output: " 00245 << oStream.str() << std::endl; 00246 00247 } catch (const stdair::RootException& eTrademgenError) { 00248 oStream << "TraDemGen error: " << eTrademgenError.what() << std::endl; 00249 00250 } catch (const std::exception& eStdError) { 00251 oStream << "Error: " << eStdError.what() << std::endl; 00252 00253 } catch (...) { 00254 oStream << "Unknown error" << std::endl; 00255 } 00256 00257 // 00258 oStream << "TraDemGen has completed the generation of the booking " 00259 << "requests. See the log file for more details." << std::endl; 00260 00261 return oStream.str(); 00262 } 00263 00264 public: 00266 Trademgener() : _trademgenService (NULL), _logOutputStream (NULL) { 00267 } 00268 00270 Trademgener (const Trademgener& iTrademgener) 00271 : _trademgenService (iTrademgener._trademgenService), 00272 _logOutputStream (iTrademgener._logOutputStream) { 00273 } 00274 00276 ~Trademgener() { 00277 _trademgenService = NULL; 00278 _logOutputStream = NULL; 00279 } 00280 00284 bool init (const std::string& iLogFilepath, 00285 const stdair::RandomSeed_T& iRandomSeed, const bool isBuiltin, 00286 const stdair::Filename_T& iDemandInputFilename) { 00287 bool isEverythingOK = true; 00288 00289 try { 00290 00291 // Check that the file path given as input corresponds to an actual file 00292 const bool isWriteable = (iLogFilepath.empty() == false); 00293 // stdair::BasFileMgr::isWriteable (iLogFilepath); 00294 if (isWriteable == false) { 00295 isEverythingOK = false; 00296 return isEverythingOK; 00297 } 00298 00299 // Set the log parameters 00300 _logOutputStream = new std::ofstream; 00301 assert (_logOutputStream != NULL); 00302 00303 // Open and clean the log outputfile 00304 _logOutputStream->open (iLogFilepath.c_str()); 00305 _logOutputStream->clear(); 00306 00307 // DEBUG 00308 *_logOutputStream << "Python wrapper initialisation" << std::endl; 00309 const stdair::BasLogParams lLogParams (stdair::LOG::DEBUG, 00310 *_logOutputStream); 00311 00312 // Initialise the context 00313 _trademgenService = new TRADEMGEN_Service (lLogParams, iRandomSeed); 00314 assert (_trademgenService != NULL); 00315 00316 // Check wether or not a (CSV) input file should be read 00317 if (isBuiltin == true) { 00318 // Create a sample DemandStream object, and insert it within 00319 // the BOM tree 00320 _trademgenService->buildSampleBom(); 00321 00322 } else { 00323 // Create the DemandStream objects, and insert them within 00324 // the BOM tree 00325 const DemandFilePath lDemandFilePath (iDemandInputFilename); 00326 _trademgenService->parseAndLoad (lDemandFilePath); 00327 } 00328 00329 // DEBUG 00330 *_logOutputStream << "Python wrapper initialised" << std::endl; 00331 00332 } catch (const stdair::RootException& eTrademgenError) { 00333 *_logOutputStream << "Trademgen error: " << eTrademgenError.what() 00334 << std::endl; 00335 00336 } catch (const std::exception& eStdError) { 00337 *_logOutputStream << "Error: " << eStdError.what() << std::endl; 00338 00339 } catch (...) { 00340 *_logOutputStream << "Unknown error" << std::endl; 00341 } 00342 00343 return isEverythingOK; 00344 } 00345 00346 private: 00348 TRADEMGEN_Service* _trademgenService; 00349 std::ofstream* _logOutputStream; 00350 }; 00351 00352 } 00353 00354 // ///////////////////////////////////////////////////////////// 00355 BOOST_PYTHON_MODULE(libpytrademgen) { 00356 boost::python::class_<TRADEMGEN::Trademgener> ("Trademgener") 00357 .def ("trademgen", &TRADEMGEN::Trademgener::trademgen) 00358 .def ("init", &TRADEMGEN::Trademgener::init); 00359 }