TvlSim Logo  1.00.0
C++ Simulated Travel-Oriented Distribution System Library
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
simulate.cpp
Go to the documentation of this file.
1 // STL
2 #include <cassert>
3 #include <iostream>
4 #include <sstream>
5 #include <fstream>
6 #include <vector>
7 #include <string>
8 // Boost (Extended STL)
9 #include <boost/tokenizer.hpp>
10 #include <boost/program_options.hpp>
11 // StdAir
12 #include <stdair/stdair_basic_types.hpp>
13 #include <stdair/basic/BasConst_General.hpp>
14 #include <stdair/basic/BasLogParams.hpp>
15 #include <stdair/basic/BasDBParams.hpp>
16 #include <stdair/basic/DemandGenerationMethod.hpp>
17 #include <stdair/service/Logger.hpp>
18 // SimFQT
19 #include <simfqt/SIMFQT_Types.hpp>
20 // TVLSIM
22 #include <tvlsim/config/tvlsim-paths.hpp>
23 
24 // //////// Type definitions ///////
28 typedef unsigned int NbOfRuns_T;
29 
33 typedef std::vector<std::string> WordList_T;
34 
35 
36 // //////// Constants //////
40 const std::string K_TVLSIM_DEFAULT_LOG_FILENAME ("simulate.log");
41 
46  "/rds01/schedule.csv");
47 
52  "/ond01.csv");
53 
58  "/frat5.csv");
63  "/ffDisutility.csv");
64 
69  "/rds01/yield.csv");
70 
75  "/rds01/fare.csv");
76 
81  "/rds01/demand.csv");
82 
87 
91 const stdair::RandomSeed_T K_TRADEMGEN_DEFAULT_RANDOM_SEED =
92  stdair::DEFAULT_RANDOM_SEED;
93 
98 
105 
109 const std::string K_TVLSIM_DEFAULT_QUERY_STRING ("my good old query");
110 
114 const std::string K_TVLSIM_DEFAULT_DB_USER ("tvlsim");
115 const std::string K_TVLSIM_DEFAULT_DB_PASSWD ("tvlsim");
116 const std::string K_TVLSIM_DEFAULT_DB_DBNAME ("sim_tvlsim");
117 const std::string K_TVLSIM_DEFAULT_DB_HOST ("localhost");
118 const std::string K_TVLSIM_DEFAULT_DB_PORT ("3306");
119 
120 
121 // //////////////////////////////////////////////////////////////////////
122 void tokeniseStringIntoWordList (const std::string& iPhrase,
123  WordList_T& ioWordList) {
124  // Empty the word list
125  ioWordList.clear();
126 
127  // Boost Tokeniser
128  typedef boost::tokenizer<boost::char_separator<char> > Tokeniser_T;
129 
130  // Define the separators
131  const boost::char_separator<char> lSepatorList(" .,;:|+-*/_=!@#$%`~^&(){}[]?'<>\"");
132 
133  // Initialise the phrase to be tokenised
134  Tokeniser_T lTokens (iPhrase, lSepatorList);
135  for (Tokeniser_T::const_iterator tok_iter = lTokens.begin();
136  tok_iter != lTokens.end(); ++tok_iter) {
137  const std::string& lTerm = *tok_iter;
138  ioWordList.push_back (lTerm);
139  }
140 
141 }
142 
143 // //////////////////////////////////////////////////////////////////////
144 std::string createStringFromWordList (const WordList_T& iWordList) {
145  std::ostringstream oStr;
146 
147  unsigned short idx = iWordList.size();
148  for (WordList_T::const_iterator itWord = iWordList.begin();
149  itWord != iWordList.end(); ++itWord, --idx) {
150  const std::string& lWord = *itWord;
151  oStr << lWord;
152  if (idx > 1) {
153  oStr << " ";
154  }
155  }
156 
157  return oStr.str();
158 }
159 
160 
161 // ///////// Parsing of Options & Configuration /////////
162 // A helper function to simplify the main part.
163 template<class T> std::ostream& operator<< (std::ostream& os,
164  const std::vector<T>& v) {
165  std::copy (v.begin(), v.end(), std::ostream_iterator<T> (std::cout, " "));
166  return os;
167 }
168 
171 
173 int readConfiguration (int argc, char* argv[],
174  bool& ioIsBuiltin, stdair::RandomSeed_T& ioRandomSeed,
175  NbOfRuns_T& ioRandomRuns, std::string& ioQueryString,
176  stdair::Filename_T& ioScheduleInputFilename,
177  stdair::Filename_T& ioOnDInputFilename,
178  stdair::Filename_T& ioFRAT5Filename,
179  stdair::Filename_T& ioFFDisutilityFilename,
180  stdair::Filename_T& ioYieldInputFilename,
181  stdair::Filename_T& ioFareInputFilename,
182  stdair::Filename_T& ioDemandInputFilename,
183  std::string& ioLogFilename,
184  stdair::DemandGenerationMethod& ioDemandGenerationMethod,
185  std::string& ioDBUser, std::string& ioDBPasswd,
186  std::string& ioDBHost, std::string& ioDBPort,
187  std::string& ioDBDBName) {
188 
189  // Demand generation method as a single char (e.g., 'P' or 'S').
190  char lDemandGenerationMethodChar;
191 
192  // Default for the built-in input
193  ioIsBuiltin = K_TVLSIM_DEFAULT_BUILT_IN_INPUT;
194 
195  // Initialise the travel query string, if that one is empty
196  if (ioQueryString.empty() == true) {
197  ioQueryString = K_TVLSIM_DEFAULT_QUERY_STRING;
198  }
199 
200  // Transform the query string into a list of words (STL strings)
201  WordList_T lWordList;
202  tokeniseStringIntoWordList (ioQueryString, lWordList);
203 
204  // Declare a group of options that will be allowed only on command line
205  boost::program_options::options_description generic ("Generic options");
206  generic.add_options()
207  ("prefix", "print installation prefix")
208  ("version,v", "print version string")
209  ("help,h", "produce help message");
210 
211  // Declare a group of options that will be allowed both on command
212  // line and in config file
213  boost::program_options::options_description config ("Configuration");
214  config.add_options()
215  ("builtin,b",
216  "The sample BOM tree can be either built-in or parsed from input files. In that latter case, the input files must be specified as well (e.g., -d/--demand, -s/--schedule, -o/--ond, -f/--fare, -y/--yield)")
217  ("seed,S",
218  boost::program_options::value<stdair::RandomSeed_T>(&ioRandomSeed)->default_value(K_TRADEMGEN_DEFAULT_RANDOM_SEED),
219  "Seed for the random generation")
220  ("runs,r",
221  boost::program_options::value<NbOfRuns_T>(&ioRandomRuns)->default_value(K_TRADEMGEN_DEFAULT_RANDOM_DRAWS),
222  "Number of simulation runs")
223  ("schedule,s",
224  boost::program_options::value< std::string >(&ioScheduleInputFilename)->default_value(K_TVLSIM_DEFAULT_SCHEDULE_INPUT_FILENAME),
225  "(CSV) input file for the schedules")
226  ("ond,o",
227  boost::program_options::value< std::string >(&ioOnDInputFilename)->default_value(K_TVLSIM_DEFAULT_OND_INPUT_FILENAME),
228  "(CSV) input file for the O&D definitions")
229  ("frat5,F",
230  boost::program_options::value< std::string >(&ioFRAT5Filename)->default_value(K_TVLSIM_DEFAULT_FRAT5_INPUT_FILENAME),
231  "(CSV) input file for the FRAT5 Curve")
232  ("ff_disutility,D",
233  boost::program_options::value< std::string >(&ioFFDisutilityFilename)->default_value(K_TVLSIM_DEFAULT_FF_DISUTILITY_INPUT_FILENAME),
234  "(CSV) input file for the FF disutility Curve")
235  ("yield,y",
236  boost::program_options::value< std::string >(&ioYieldInputFilename)->default_value(K_TVLSIM_DEFAULT_YIELD_INPUT_FILENAME),
237  "(CSV) input file for the yields")
238  ("fare,f",
239  boost::program_options::value< std::string >(&ioFareInputFilename)->default_value(K_TVLSIM_DEFAULT_FARE_INPUT_FILENAME),
240  "(CSV) input file for the fares")
241  ("demand,d",
242  boost::program_options::value< std::string >(&ioDemandInputFilename)->default_value(K_TVLSIM_DEFAULT_DEMAND_INPUT_FILENAME),
243  "(CSV) input file for the demand distributions")
244  ("log,l",
245  boost::program_options::value< std::string >(&ioLogFilename)->default_value(K_TVLSIM_DEFAULT_LOG_FILENAME),
246  "Filepath for the logs")
247  ("demandgeneration,G",
248  boost::program_options::value< char >(&lDemandGenerationMethodChar)->default_value(K_TVLSIM_DEMAND_GENERATION_METHOD_CHAR),
249  "Method used to generate the demand (i.e., booking requests): Poisson Process (e.g., P) or Statistics Order (e.g., S)")
250  ("user,u",
251  boost::program_options::value< std::string >(&ioDBUser)->default_value(K_TVLSIM_DEFAULT_DB_USER),
252  "SQL database hostname (e.g., tvlsim)")
253  ("passwd,p",
254  boost::program_options::value< std::string >(&ioDBPasswd)->default_value(K_TVLSIM_DEFAULT_DB_PASSWD),
255  "SQL database hostname (e.g., tvlsim)")
256  ("host,H",
257  boost::program_options::value< std::string >(&ioDBHost)->default_value(K_TVLSIM_DEFAULT_DB_HOST),
258  "SQL database hostname (e.g., localhost)")
259  ("port,P",
260  boost::program_options::value< std::string >(&ioDBPort)->default_value(K_TVLSIM_DEFAULT_DB_PORT),
261  "SQL database port (e.g., 3306)")
262  ("dbname,n",
263  boost::program_options::value< std::string >(&ioDBDBName)->default_value(K_TVLSIM_DEFAULT_DB_DBNAME),
264  "SQL database name (e.g., tvlsim)")
265  ("query,q",
266  boost::program_options::value< WordList_T >(&lWordList)->multitoken(),
267  "Query word list")
268  ;
269 
270  // Hidden options, will be allowed both on command line and
271  // in config file, but will not be shown to the user.
272  boost::program_options::options_description hidden ("Hidden options");
273  hidden.add_options()
274  ("copyright",
275  boost::program_options::value< std::vector<std::string> >(),
276  "Show the copyright (license)");
277 
278  boost::program_options::options_description cmdline_options;
279  cmdline_options.add(generic).add(config).add(hidden);
280 
281  boost::program_options::options_description config_file_options;
282  config_file_options.add(config).add(hidden);
283 
284  boost::program_options::options_description visible ("Allowed options");
285  visible.add(generic).add(config);
286 
287  boost::program_options::positional_options_description p;
288  p.add ("copyright", -1);
289 
290  boost::program_options::variables_map vm;
291  boost::program_options::
292  store (boost::program_options::command_line_parser (argc, argv).
293  options (cmdline_options).positional(p).run(), vm);
294 
295  std::ifstream ifs ("simulate.cfg");
296  boost::program_options::store (parse_config_file (ifs, config_file_options),
297  vm);
298  boost::program_options::notify (vm);
299 
300  if (vm.count ("help")) {
301  std::cout << visible << std::endl;
303  }
304 
305  if (vm.count ("version")) {
306  std::cout << PACKAGE_NAME << ", version " << PACKAGE_VERSION << std::endl;
308  }
309 
310  if (vm.count ("prefix")) {
311  std::cout << "Installation prefix: " << PREFIXDIR << std::endl;
313  }
314 
315  if (vm.count ("builtin")) {
316  ioIsBuiltin = true;
317  }
318  const std::string isBuiltinStr = (ioIsBuiltin == true)?"yes":"no";
319  std::cout << "The BOM should be built-in? " << isBuiltinStr << std::endl;
320 
321  //
322  std::ostringstream oErrorMessageStr;
323  oErrorMessageStr << "Either the -b/--builtin option, or the combination of "
324  << "the -d/--demand, -s/--schedule, -o/--ond, -f/--fare "
325  << "and -y/--yield options must be specified";
326 
327  if (ioIsBuiltin == false) {
328  if (vm.count ("schedule")) {
329  ioScheduleInputFilename = vm["schedule"].as< std::string >();
330  std::cout << "Schedule input filename is: " << ioScheduleInputFilename
331  << std::endl;
332 
333  } else {
334  // The built-in option is not selected. However, no schedule input file
335  // is specified
336  std::cerr << oErrorMessageStr.str() << std::endl;
337  }
338 
339  if (vm.count ("ond")) {
340  ioOnDInputFilename = vm["ond"].as< std::string >();
341  std::cout << "O&D input filename is: " << ioOnDInputFilename << std::endl;
342 
343  } else {
344  // The built-in option is not selected. However, no ond input file
345  // is specified
346  std::cerr << oErrorMessageStr.str() << std::endl;
347  }
348 
349  if (vm.count ("frat5")) {
350  ioFRAT5Filename = vm["frat5"].as< std::string >();
351  std::cout << "FRAT5 input filename is: " << ioFRAT5Filename << std::endl;
352 
353  } else {
354  // The built-in option is not selected. However, no frat5 input file
355  // is specified
356  std::cerr << oErrorMessageStr.str() << std::endl;
357  }
358 
359  if (vm.count ("ff_disutility")) {
360  ioFFDisutilityFilename = vm["ff_disutility"].as< std::string >();
361  std::cout << "FF disutility input filename is: "
362  << ioFFDisutilityFilename << std::endl;
363 
364  } else {
365  // The built-in option is not selected. However, no ff
366  // disutility input file is specified
367  std::cerr << oErrorMessageStr.str() << std::endl;
368  }
369 
370  if (vm.count ("yield")) {
371  ioYieldInputFilename = vm["yield"].as< std::string >();
372  std::cout << "Yield input filename is: " << ioYieldInputFilename << std::endl;
373 
374  } else {
375  // The built-in option is not selected. However, no yield input file
376  // is specified
377  std::cerr << oErrorMessageStr.str() << std::endl;
378  }
379 
380  if (vm.count ("fare")) {
381  ioFareInputFilename = vm["fare"].as< std::string >();
382  std::cout << "Fare input filename is: " << ioFareInputFilename << std::endl;
383 
384  } else {
385  // The built-in option is not selected. However, no fare input file
386  // is specified
387  std::cerr << oErrorMessageStr.str() << std::endl;
388  }
389 
390  if (vm.count ("demand")) {
391  ioDemandInputFilename = vm["demand"].as< std::string >();
392  std::cout << "Demand input filename is: " << ioDemandInputFilename
393  << std::endl;
394  } else {
395  // The built-in option is not selected. However, no demand input file
396  // is specified
397  std::cerr << oErrorMessageStr.str() << std::endl;
398  }
399  }
400 
401  if (vm.count ("log")) {
402  ioLogFilename = vm["log"].as< std::string >();
403  std::cout << "Log filename is: " << ioLogFilename << std::endl;
404  }
405 
406  //
407  if (vm.count ("demandgeneration")) {
408  ioDemandGenerationMethod =
409  stdair::DemandGenerationMethod (lDemandGenerationMethodChar);
410  std::cout << "Demand generation method is: "
411  << ioDemandGenerationMethod.describe() << std::endl;
412  }
413 
414  //
415  std::cout << "The random generation seed is: " << ioRandomSeed << std::endl;
416 
417  //
418  std::cout << "The number of simulation runs is: " << ioRandomRuns
419  << std::endl;
420 
421  //
422  if (vm.count ("user")) {
423  ioDBUser = vm["user"].as< std::string >();
424  std::cout << "SQL database user name is: " << ioDBUser << std::endl;
425  }
426 
427  if (vm.count ("passwd")) {
428  ioDBPasswd = vm["passwd"].as< std::string >();
429  //std::cout << "SQL database user password is: " << ioDBPasswd << std::endl;
430  }
431 
432  if (vm.count ("host")) {
433  ioDBHost = vm["host"].as< std::string >();
434  std::cout << "SQL database host name is: " << ioDBHost << std::endl;
435  }
436 
437  if (vm.count ("port")) {
438  ioDBPort = vm["port"].as< std::string >();
439  std::cout << "SQL database port number is: " << ioDBPort << std::endl;
440  }
441 
442  if (vm.count ("dbname")) {
443  ioDBDBName = vm["dbname"].as< std::string >();
444  std::cout << "SQL database name is: " << ioDBDBName << std::endl;
445  }
446 
447  //
448  ioQueryString = createStringFromWordList (lWordList);
449  std::cout << "The query string is: " << ioQueryString << std::endl;
450 
451  return 0;
452 }
453 
454 // ///////// M A I N ////////////
455 int main (int argc, char* argv[]) {
456 
457  // State whether the BOM tree should be built-in or parsed from an
458  // input file
459  bool isBuiltin;
460 
461  // Random generation seed
462  stdair::RandomSeed_T lRandomSeed;
463 
464  // Number of simulation runs to be performed
465  NbOfRuns_T lNbOfRuns;
466 
467  // Query
468  std::string lQuery;
469 
470  // Start date
471  stdair::Date_T lStartDate (2009, boost::gregorian::Feb, 01);
472 
473  // End date
474  stdair::Date_T lEndDate (2012, boost::gregorian::Mar, 02);
475 
476  // Schedule input file name
477  stdair::Filename_T lScheduleInputFilename;
478 
479  // O&D input filename
480  std::string lOnDInputFilename;
481 
482  // FRAT5 input filename
483  std::string lFRAT5InputFilename;
484 
485  // FF disutility input filename
486  std::string lFFDisutilityInputFilename;
487 
488  // Yield input filename
489  std::string lYieldInputFilename;
490 
491  // Fare input filename
492  std::string lFareInputFilename;
493 
494  // Demand input file name
495  stdair::Filename_T lDemandInputFilename;
496 
497  // Output log File
498  std::string lLogFilename;
499 
500  // Demand generation method.
501  stdair::DemandGenerationMethod
502  lDemandGenerationMethod (K_TVLSIM_DEMAND_GENERATION_METHOD_CHAR);
503 
504  // SQL database parameters
505  std::string lDBUser;
506  std::string lDBPasswd;
507  std::string lDBHost;
508  std::string lDBPort;
509  std::string lDBDBName;
510 
511  // Call the command-line option parser
512  const int lOptionParserStatus =
513  readConfiguration (argc, argv, isBuiltin, lRandomSeed, lNbOfRuns, lQuery,
514  lScheduleInputFilename, lOnDInputFilename,
515  lFRAT5InputFilename, lFFDisutilityInputFilename,
516  lYieldInputFilename, lFareInputFilename,
517  lDemandInputFilename, lLogFilename,
518  lDemandGenerationMethod,
519  lDBUser, lDBPasswd, lDBHost, lDBPort, lDBDBName);
520 
521  if (lOptionParserStatus == K_TVLSIM_EARLY_RETURN_STATUS) {
522  return 0;
523  }
524 
525  // Set the database parameters
526  stdair::BasDBParams lDBParams (lDBUser, lDBPasswd, lDBHost, lDBPort,
527  lDBDBName);
528 
529  // Set the log parameters
530  std::ofstream logOutputFile;
531  // open and clean the log outputfile
532  logOutputFile.open (lLogFilename.c_str());
533  logOutputFile.clear();
534 
535  // Initialise the simulation context
536  const stdair::BasLogParams lLogParams (stdair::LOG::DEBUG, logOutputFile);
537  TVLSIM::TVLSIM_Service tvlsimService (lLogParams, lDBParams, lStartDate, lEndDate,
538  lRandomSeed, lDemandGenerationMethod,
539  lNbOfRuns);
540 
541  // Check wether or not (CSV) input files should be read
542  if (isBuiltin == true) {
543  // Build the sample BOM tree
544  tvlsimService.buildSampleBom();
545 
546  } else {
547  // Build the BOM tree from parsing input files
548  stdair::ScheduleFilePath lScheduleFilePath (lScheduleInputFilename);
549  stdair::ODFilePath lODFilePath (lOnDInputFilename);
550  stdair::FRAT5FilePath lFRAT5FilePath (lFRAT5InputFilename);
551  stdair::FFDisutilityFilePath lFFDisutilityFilePath (lFFDisutilityInputFilename);
552  const SIMFQT::FareFilePath lFareFilePath (lFareInputFilename);
553  const AIRRAC::YieldFilePath lYieldFilePath (lYieldInputFilename);
554  const TRADEMGEN::DemandFilePath lDemandFilePath (lDemandInputFilename);
555  tvlsimService.setInputFiles (lScheduleFilePath, lODFilePath,
556  lFRAT5FilePath, lFFDisutilityFilePath,
557  lYieldFilePath, lFareFilePath,
558  lDemandFilePath);
559  tvlsimService.parseAndLoad ();
560  }
561 
562  // Initialise the snapshot and RM events
563  tvlsimService.initSnapshotAndRMEvents();
564 
565  // Perform a simulation
566  tvlsimService.simulate ();
567 
568 
569  // DEBUG
570  // Display the airlines stored in the database
571  tvlsimService.displayAirlineListFromDB();
572 
573  return 0;
574 }
575