00001
00002
00003
00004
00005 #include <cassert>
00006 #include <sstream>
00007 #include <fstream>
00008 #include <vector>
00009 #include <list>
00010 #include <string>
00011
00012
00013 #include <boost/tokenizer.hpp>
00014
00015 #include <boost/program_options.hpp>
00016
00017 #include <boost/accumulators/accumulators.hpp>
00018 #include <boost/accumulators/statistics.hpp>
00019
00020
00021
00022 #include <stdair/stdair_basic_types.hpp>
00023 #include <stdair/basic/BasConst_General.hpp>
00024 #include <stdair/basic/ProgressStatusSet.hpp>
00025 #include <stdair/basic/DemandGenerationMethod.hpp>
00026 #include <stdair/bom/EventStruct.hpp>
00027 #include <stdair/bom/EventQueue.hpp>
00028 #include <stdair/bom/BookingRequestStruct.hpp>
00029 #include <stdair/bom/BomDisplay.hpp>
00030 #include <stdair/service/Logger.hpp>
00031
00032 #include <trademgen/TRADEMGEN_Service.hpp>
00033 #include <trademgen/config/trademgen-paths.hpp>
00034 #include <trademgen/config/trademgen-paths.hpp>
00035
00036
00037 namespace ba = boost::accumulators;
00038
00039
00040 typedef unsigned int NbOfRuns_T;
00041
00045 typedef ba::accumulator_set<double,
00046 ba::stats<ba::tag::min, ba::tag::max,
00047 ba::tag::mean (ba::immediate),
00048 ba::tag::sum,
00049 ba::tag::variance> > stat_acc_type;
00050
00051
00055 const stdair::Filename_T K_TRADEMGEN_DEFAULT_LOG_FILENAME ("trademgen.log");
00056
00060 const stdair::Filename_T K_TRADEMGEN_DEFAULT_INPUT_FILENAME (STDAIR_SAMPLE_DIR
00061 "/demand01.csv");
00062
00066 const stdair::Filename_T K_TRADEMGEN_DEFAULT_OUTPUT_FILENAME ("request.csv");
00067
00071 const stdair::DemandGenerationMethod
00072 K_TRADEMGEN_DEFAULT_DEMAND_GENERATION_METHOD =
00073 stdair::DemandGenerationMethod::POI_PRO;
00074
00078 const char K_TRADEMGEN_DEFAULT_DEMAND_GENERATION_METHOD_CHAR =
00079 K_TRADEMGEN_DEFAULT_DEMAND_GENERATION_METHOD.getMethodAsChar();
00080
00084 const stdair::RandomSeed_T K_TRADEMGEN_DEFAULT_RANDOM_SEED =
00085 stdair::DEFAULT_RANDOM_SEED;
00086
00090 const NbOfRuns_T K_TRADEMGEN_DEFAULT_RANDOM_DRAWS = 1;
00091
00096 const bool K_TRADEMGEN_DEFAULT_BUILT_IN_INPUT = false;
00097
00101 const int K_TRADEMGEN_EARLY_RETURN_STATUS = 99;
00102
00103
00107 void stat_display (std::ostream& oStream, const stat_acc_type& iStatAcc) {
00108
00109
00110 std::ios::fmtflags oldFlags = oStream.flags();
00111
00112
00113 oStream.setf (std::ios::fixed);
00114
00115
00116 oStream << "Statistics for the demand generation runs: " << std::endl;
00117 oStream << " minimum = " << ba::min (iStatAcc) << std::endl;
00118 oStream << " mean = " << ba::mean (iStatAcc) << std::endl;
00119 oStream << " maximum = " << ba::max (iStatAcc) << std::endl;
00120 oStream << " count = " << ba::count (iStatAcc) << std::endl;
00121 oStream << " variance = " << ba::variance (iStatAcc) << std::endl;
00122
00123
00124 oStream.flags (oldFlags);
00125 }
00126
00127
00128
00129 template<class T> std::ostream& operator<< (std::ostream& os,
00130 const std::vector<T>& v) {
00131 std::copy (v.begin(), v.end(), std::ostream_iterator<T> (std::cout, " "));
00132 return os;
00133 }
00134
00138 int readConfiguration (int argc, char* argv[], bool& ioIsBuiltin,
00139 stdair::RandomSeed_T& ioRandomSeed,
00140 NbOfRuns_T& ioRandomRuns,
00141 stdair::Filename_T& ioInputFilename,
00142 stdair::Filename_T& ioOutputFilename,
00143 stdair::Filename_T& ioLogFilename,
00144 stdair::DemandGenerationMethod& ioDemandGenerationMethod) {
00145
00146
00147 char lDemandGenerationMethodChar;
00148
00149
00150 ioIsBuiltin = K_TRADEMGEN_DEFAULT_BUILT_IN_INPUT;
00151
00152
00153 boost::program_options::options_description generic ("Generic options");
00154 generic.add_options()
00155 ("prefix", "print installation prefix")
00156 ("version,v", "print version string")
00157 ("help,h", "produce help message");
00158
00159
00160
00161 boost::program_options::options_description config ("Configuration");
00162 config.add_options()
00163 ("builtin,b",
00164 "The sample BOM tree can be either built-in or parsed from an input file. That latter must then be given with the -i/--input option")
00165 ("seed,s",
00166 boost::program_options::value<stdair::RandomSeed_T>(&ioRandomSeed)->default_value(K_TRADEMGEN_DEFAULT_RANDOM_SEED),
00167 "Seed for the random generation")
00168 ("draws,d",
00169 boost::program_options::value<NbOfRuns_T>(&ioRandomRuns)->default_value(K_TRADEMGEN_DEFAULT_RANDOM_DRAWS),
00170 "Number of runs for the demand generations")
00171 ("demandgeneration,G",
00172 boost::program_options::value< char >(&lDemandGenerationMethodChar)->default_value(K_TRADEMGEN_DEFAULT_DEMAND_GENERATION_METHOD_CHAR),
00173 "Method used to generate the demand (i.e., the booking requests): Poisson Process (P) or Order Statistics (S)")
00174 ("input,i",
00175 boost::program_options::value< std::string >(&ioInputFilename)->default_value(K_TRADEMGEN_DEFAULT_INPUT_FILENAME),
00176 "(CSV) input file for the demand distributions")
00177 ("output,o",
00178 boost::program_options::value< std::string >(&ioOutputFilename)->default_value(K_TRADEMGEN_DEFAULT_OUTPUT_FILENAME),
00179 "(CSV) output file for the generated requests")
00180 ("log,l",
00181 boost::program_options::value< std::string >(&ioLogFilename)->default_value(K_TRADEMGEN_DEFAULT_LOG_FILENAME),
00182 "Filepath for the logs")
00183 ;
00184
00185
00186
00187 boost::program_options::options_description hidden ("Hidden options");
00188 hidden.add_options()
00189 ("copyright",
00190 boost::program_options::value< std::vector<std::string> >(),
00191 "Show the copyright (license)");
00192
00193 boost::program_options::options_description cmdline_options;
00194 cmdline_options.add(generic).add(config).add(hidden);
00195
00196 boost::program_options::options_description config_file_options;
00197 config_file_options.add(config).add(hidden);
00198
00199 boost::program_options::options_description visible ("Allowed options");
00200 visible.add(generic).add(config);
00201
00202 boost::program_options::positional_options_description p;
00203 p.add ("copyright", -1);
00204
00205 boost::program_options::variables_map vm;
00206 boost::program_options::
00207 store (boost::program_options::command_line_parser (argc, argv).
00208 options (cmdline_options).positional(p).run(), vm);
00209
00210 std::ifstream ifs ("trademgen.cfg");
00211 boost::program_options::store (parse_config_file (ifs, config_file_options),
00212 vm);
00213 boost::program_options::notify (vm);
00214
00215 if (vm.count ("help")) {
00216 std::cout << visible << std::endl;
00217 return K_TRADEMGEN_EARLY_RETURN_STATUS;
00218 }
00219
00220 if (vm.count ("version")) {
00221 std::cout << PACKAGE_NAME << ", version " << PACKAGE_VERSION << std::endl;
00222 return K_TRADEMGEN_EARLY_RETURN_STATUS;
00223 }
00224
00225 if (vm.count ("prefix")) {
00226 std::cout << "Installation prefix: " << PREFIXDIR << std::endl;
00227 return K_TRADEMGEN_EARLY_RETURN_STATUS;
00228 }
00229
00230 if (vm.count ("builtin")) {
00231 ioIsBuiltin = true;
00232 }
00233 const std::string isBuiltinStr = (ioIsBuiltin == true)?"yes":"no";
00234 std::cout << "The BOM should be built-in? " << isBuiltinStr << std::endl;
00235
00236 if (ioIsBuiltin == false) {
00237
00238
00239 if (vm.count ("input")) {
00240 ioInputFilename = vm["input"].as< std::string >();
00241 std::cout << "Input filename is: " << ioInputFilename << std::endl;
00242
00243 } else {
00244
00245
00246 std::cerr << "Either one among the -b/--builtin and -i/--input "
00247 << "options must be specified" << std::endl;
00248 }
00249 }
00250
00251 if (vm.count ("output")) {
00252 ioOutputFilename = vm["output"].as< std::string >();
00253 std::cout << "Output filename is: " << ioOutputFilename << std::endl;
00254 }
00255
00256 if (vm.count ("log")) {
00257 ioLogFilename = vm["log"].as< std::string >();
00258 std::cout << "Log filename is: " << ioLogFilename << std::endl;
00259 }
00260
00261 if (vm.count ("demandgeneration")) {
00262 ioDemandGenerationMethod =
00263 stdair::DemandGenerationMethod (lDemandGenerationMethodChar);
00264 std::cout << "Date-time request generation method is: "
00265 << ioDemandGenerationMethod.describe() << std::endl;
00266 }
00267
00268
00269 std::cout << "The random generation seed is: " << ioRandomSeed << std::endl;
00270
00271
00272 std::cout << "The number of runs is: " << ioRandomRuns << std::endl;
00273
00274 return 0;
00275 }
00276
00277
00278 void generateDemand (TRADEMGEN::TRADEMGEN_Service& ioTrademgenService,
00279 const stdair::Filename_T& iOutputFilename,
00280 const NbOfRuns_T& iNbOfRuns,
00281 const stdair::DemandGenerationMethod& iDemandGenerationMethod) {
00282
00283
00284 std::ofstream output;
00285 output.open (iOutputFilename.c_str());
00286 output.clear();
00287
00288
00289 stat_acc_type lStatAccumulator;
00290
00291
00292
00293 const stdair::Count_T& lExpectedNbOfEventsToBeGenerated =
00294 ioTrademgenService.getExpectedTotalNumberOfRequestsToBeGenerated();
00295
00296
00297 boost::progress_display lProgressDisplay (lExpectedNbOfEventsToBeGenerated
00298 * iNbOfRuns);
00299
00300 for (NbOfRuns_T runIdx = 1; runIdx <= iNbOfRuns; ++runIdx) {
00301
00302 output << "Run number: " << runIdx << std::endl;
00303
00308 const stdair::Count_T& lActualNbOfEventsToBeGenerated =
00309 ioTrademgenService.generateFirstRequests (iDemandGenerationMethod);
00310
00311
00312 STDAIR_LOG_DEBUG ("[" << runIdx << "] Expected: "
00313 << lExpectedNbOfEventsToBeGenerated << ", actual: "
00314 << lActualNbOfEventsToBeGenerated);
00315
00323 while (ioTrademgenService.isQueueDone() == false) {
00324
00325
00326 stdair::EventStruct lEventStruct;
00327 stdair::ProgressStatusSet lProgressStatusSet =
00328 ioTrademgenService.popEvent (lEventStruct);
00329
00330
00331
00332
00333
00334
00335 const stdair::BookingRequestStruct& lPoppedRequest =
00336 lEventStruct.getBookingRequest();
00337
00338
00339 STDAIR_LOG_DEBUG ("[" << runIdx << "] Poped booking request: '"
00340 << lPoppedRequest.describe() << "'.");
00341
00342
00343
00344
00345
00346 const stdair::DemandGeneratorKey_T& lDemandStreamKey =
00347 lPoppedRequest.getDemandGeneratorKey();
00348
00349
00350 const bool stillHavingRequestsToBeGenerated = ioTrademgenService.
00351 stillHavingRequestsToBeGenerated (lDemandStreamKey,
00352 lProgressStatusSet,
00353 iDemandGenerationMethod);
00354
00355
00356 STDAIR_LOG_DEBUG (lProgressStatusSet.describe());
00357 STDAIR_LOG_DEBUG ("=> [" << lDemandStreamKey << "] is now processed. "
00358 << "Still generate events for that demand stream? "
00359 << stillHavingRequestsToBeGenerated);
00360
00361
00362
00363 if (stillHavingRequestsToBeGenerated == true) {
00364
00365 stdair::BookingRequestPtr_T lNextRequest_ptr =
00366 ioTrademgenService.generateNextRequest (lDemandStreamKey,
00367 iDemandGenerationMethod);
00368
00369 assert (lNextRequest_ptr != NULL);
00370
00371
00372 const stdair::Duration_T lDuration =
00373 lNextRequest_ptr->getRequestDateTime()
00374 - lPoppedRequest.getRequestDateTime();
00375 if (lDuration.total_milliseconds() < 0) {
00376 STDAIR_LOG_ERROR ("[" << lDemandStreamKey
00377 << "] The date-time of the generated event ("
00378 << lNextRequest_ptr->getRequestDateTime()
00379 << ") is lower than the date-time "
00380 << "of the current event ("
00381 << lPoppedRequest.getRequestDateTime() << ")");
00382 assert (false);
00383 }
00384
00385
00386 STDAIR_LOG_DEBUG ("[" << lDemandStreamKey << "] Added request: '"
00387 << lNextRequest_ptr->describe()
00388 << "'. Is queue done? "
00389 << ioTrademgenService.isQueueDone());
00390 }
00391
00392 STDAIR_LOG_DEBUG ("");
00393
00394
00395 ++lProgressDisplay;
00396 }
00397
00398
00399 lStatAccumulator (lActualNbOfEventsToBeGenerated);
00400
00401
00402 ioTrademgenService.reset();
00403 }
00404
00405
00406 STDAIR_LOG_DEBUG ("End of the demand generation. Following are some "
00407 "statistics for the " << iNbOfRuns << " runs.");
00408 std::ostringstream oStatStr;
00409 stat_display (oStatStr, lStatAccumulator);
00410 STDAIR_LOG_DEBUG (oStatStr.str());
00411
00412
00413 const std::string& lBOMStr = ioTrademgenService.csvDisplay();
00414 STDAIR_LOG_DEBUG (lBOMStr);
00415
00416
00417 output.close();
00418 }
00419
00420
00421
00422 int main (int argc, char* argv[]) {
00423
00424
00425 bool isBuiltin;
00426
00427
00428 stdair::RandomSeed_T lRandomSeed;
00429
00430
00431 NbOfRuns_T lNbOfRuns;
00432
00433
00434 stdair::Filename_T lInputFilename;
00435
00436
00437 stdair::Filename_T lOutputFilename;
00438
00439
00440 stdair::Filename_T lLogFilename;
00441
00442
00443 stdair::DemandGenerationMethod
00444 lDemandGenerationMethod (K_TRADEMGEN_DEFAULT_DEMAND_GENERATION_METHOD);
00445
00446
00447 const int lOptionParserStatus =
00448 readConfiguration (argc, argv, isBuiltin, lRandomSeed, lNbOfRuns,
00449 lInputFilename, lOutputFilename, lLogFilename,
00450 lDemandGenerationMethod);
00451
00452 if (lOptionParserStatus == K_TRADEMGEN_EARLY_RETURN_STATUS) {
00453 return 0;
00454 }
00455
00456
00457 std::ofstream logOutputFile;
00458
00459 logOutputFile.open (lLogFilename.c_str());
00460 logOutputFile.clear();
00461
00462
00463 const stdair::BasLogParams lLogParams (stdair::LOG::DEBUG, logOutputFile);
00464
00465
00466 TRADEMGEN::TRADEMGEN_Service trademgenService (lLogParams, lRandomSeed);
00467
00468
00469 if (isBuiltin == true) {
00470
00471 trademgenService.buildSampleBom();
00472
00473 } else {
00474
00475 trademgenService.parseAndLoad (lInputFilename);
00476 }
00477
00478
00479 generateDemand (trademgenService, lOutputFilename, lNbOfRuns,
00480 lDemandGenerationMethod);
00481
00482
00483 logOutputFile.close();
00484
00485
00486
00487
00488
00489
00490
00491
00492 return 0;
00493 }