RMOL Logo  0.25.2
C++ library of Revenue Management and Optimisation classes and functions
rmol.cpp
Go to the documentation of this file.
00001 // STL
00002 #include <cassert>
00003 #include <iostream>
00004 #include <sstream>
00005 #include <fstream>
00006 #include <string>
00007 // Boost (Extended STL)
00008 #include <boost/date_time/posix_time/posix_time.hpp>
00009 #include <boost/date_time/gregorian/gregorian.hpp>
00010 #include <boost/program_options.hpp>
00011 // StdAir
00012 #include <stdair/service/Logger.hpp>
00013 // RMOL
00014 #include <rmol/RMOL_Service.hpp>
00015 #include <rmol/config/rmol-paths.hpp>
00016 
00017 // //////// Constants //////
00019 const std::string K_RMOL_DEFAULT_LOG_FILENAME ("rmol.log");
00020 
00023 const bool K_RMOL_DEFAULT_BUILT_IN_INPUT = false;
00024 
00026 const std::string K_RMOL_DEFAULT_INPUT_FILENAME (STDAIR_SAMPLE_DIR "/rm01.csv");
00027 
00029 const int K_RMOL_DEFAULT_RANDOM_DRAWS = 100000;
00030 
00032 const double K_RMOL_DEFAULT_CAPACITY = 500.0;
00033 
00043 const short K_RMOL_DEFAULT_METHOD = 0;
00044 
00045 // ///////// Parsing of Options & Configuration /////////
00046 // A helper function to simplify the main part.
00047 template<class T> std::ostream& operator<< (std::ostream& os,
00048                                             const std::vector<T>& v) {
00049   std::copy (v.begin(), v.end(), std::ostream_iterator<T> (std::cout, " ")); 
00050   return os;
00051 }
00052 
00054 const int K_RMOL_EARLY_RETURN_STATUS = 99;
00055 
00057 int readConfiguration(int argc, char* argv[], 
00058                       int& ioRandomDraws, double& ioCapacity, 
00059                       short& ioMethod, bool& ioIsBuiltin,
00060                       std::string& ioInputFilename, std::string& ioLogFilename){
00061 
00062   // Default for the built-in input
00063   ioIsBuiltin = K_RMOL_DEFAULT_BUILT_IN_INPUT;
00064     
00065   // Declare a group of options that will be allowed only on command line
00066   boost::program_options::options_description generic ("Generic options");
00067   generic.add_options()
00068     ("prefix", "print installation prefix")
00069     ("version,v", "print version string")
00070     ("help,h", "produce help message");
00071     
00072   // Declare a group of options that will be allowed both on command
00073   // line and in config file
00074   boost::program_options::options_description config ("Configuration");
00075   config.add_options()
00076     ("draws,d",
00077      boost::program_options::value<int>(&ioRandomDraws)->default_value(K_RMOL_DEFAULT_RANDOM_DRAWS), 
00078      "Number of to-be-generated random draws")
00079     ("capacity,c",
00080      boost::program_options::value<double>(&ioCapacity)->default_value(K_RMOL_DEFAULT_CAPACITY), 
00081      "Resource capacity (e.g., for a flight leg)")
00082     ("method,m",
00083      boost::program_options::value<short>(&ioMethod)->default_value(K_RMOL_DEFAULT_METHOD), 
00084      "Revenue Management method to be used (0 = Monte-Carlo, 1 = Dynamic Programming, 2 = EMSR, 3 = EMSR-a, 4 = EMSR-b)")
00085     ("builtin,b",
00086      "The cabin set up can be either built-in or parsed from an input file. That latter must then be given with the -i/--input option")
00087     ("input,i",
00088      boost::program_options::value< std::string >(&ioInputFilename)->default_value(K_RMOL_DEFAULT_INPUT_FILENAME),
00089      "(CSV) input file for the demand distribution parameters and resource (leg-cabin) capacities")
00090     ("log,l",
00091      boost::program_options::value< std::string >(&ioLogFilename)->default_value(K_RMOL_DEFAULT_LOG_FILENAME),
00092      "Filename for the logs")
00093     ;
00094 
00095   // Hidden options, will be allowed both on command line and
00096   // in config file, but will not be shown to the user.
00097   boost::program_options::options_description hidden ("Hidden options");
00098   hidden.add_options()
00099     ("copyright",
00100      boost::program_options::value< std::vector<std::string> >(),
00101      "Show the copyright (license)");
00102         
00103   boost::program_options::options_description cmdline_options;
00104   cmdline_options.add(generic).add(config).add(hidden);
00105 
00106   boost::program_options::options_description config_file_options;
00107   config_file_options.add(config).add(hidden);
00108 
00109   boost::program_options::options_description visible ("Allowed options");
00110   visible.add(generic).add(config);
00111         
00112   boost::program_options::positional_options_description p;
00113   p.add ("copyright", -1);
00114         
00115   boost::program_options::variables_map vm;
00116   boost::program_options::
00117     store (boost::program_options::command_line_parser (argc, argv).
00118            options (cmdline_options).positional(p).run(), vm);
00119 
00120   std::ifstream ifs ("rmol.cfg");
00121   boost::program_options::store (parse_config_file (ifs, config_file_options),
00122                                  vm);
00123   boost::program_options::notify (vm);
00124     
00125   if (vm.count ("help")) {
00126     std::cout << visible << std::endl;
00127     return K_RMOL_EARLY_RETURN_STATUS;
00128   }
00129 
00130   if (vm.count ("version")) {
00131     std::cout << PACKAGE_NAME << ", version " << PACKAGE_VERSION << std::endl;
00132     return K_RMOL_EARLY_RETURN_STATUS;
00133   }
00134 
00135   if (vm.count ("prefix")) {
00136     std::cout << "Installation prefix: " << PREFIXDIR << std::endl;
00137     return K_RMOL_EARLY_RETURN_STATUS;
00138   }
00139 
00140   if (vm.count ("builtin")) {
00141     ioIsBuiltin = true;
00142   }
00143   const std::string isBuiltinStr = (ioIsBuiltin == true)?"yes":"no";
00144   std::cout << "The BOM should be built-in? " << isBuiltinStr << std::endl;
00145 
00146   if (ioIsBuiltin == false) {
00147     if (vm.count ("input")) {
00148       ioInputFilename = vm["input"].as< std::string >();
00149       std::cout << "Input filename is: " << ioInputFilename << std::endl;
00150     }
00151   }
00152 
00153   if (vm.count ("log")) {
00154     ioLogFilename = vm["log"].as< std::string >();
00155     std::cout << "Log filename is: " << ioLogFilename << std::endl;
00156   }
00157 
00158   std::cout << "The number of random draws is: " << ioRandomDraws << std::endl;
00159   std::cout << "The resource capacity is: " << ioCapacity << std::endl;
00160   std::cout << "The optimisation method is: " << ioMethod << std::endl;
00161   std::cout << std::endl;
00162   
00163   return 0;
00164 }
00165 
00166 // /////////////////////////////////////////////////////
00167 void optimise (RMOL::RMOL_Service& rmolService,
00168                const short& iMethod, const int& iRandomDraws) {
00169 
00170   switch (iMethod) {
00171   case 0: {
00172     // Calculate the optimal protections by the Monte Carlo
00173     // Integration approach
00174     rmolService.optimalOptimisationByMCIntegration (iRandomDraws);
00175     break;
00176   }
00177   case 1: {
00178     // Calculate the optimal protections by DP.
00179     rmolService.optimalOptimisationByDP ();
00180     break;
00181   }
00182   case 2: {
00183     // Calculate the Bid-Price Vector by EMSR
00184     rmolService.heuristicOptimisationByEmsr ();
00185     break;
00186   }
00187   case 3: {
00188     // Calculate the protections by EMSR-a
00189     rmolService.heuristicOptimisationByEmsrA ();
00190     break;
00191   }
00192   case 4: {
00193     // Calculate the protections by EMSR-b
00194     rmolService.heuristicOptimisationByEmsrB ();
00195     break;
00196   }
00197   default: {
00198     rmolService.optimalOptimisationByMCIntegration (iRandomDraws);
00199   }
00200   }
00201 }
00202 
00203 // ///////// M A I N ////////////
00204 int main (int argc, char* argv[]) {
00205 
00206   // Number of random draws to be generated (best if greater than 100)
00207   int lRandomDraws = 0;
00208     
00209   // Cabin Capacity (it must be greater then 100 here)
00210   double lCapacity = 0.0;
00211 
00212   // Methods of optimisation (0 = Monte-Carlo, 1 = Dynamic Programming, 
00213   // 2 = EMSR, 3 = EMSR-a, 4 = EMSR-b)
00214   short lMethod = 0;   
00215     
00216   // Built-in
00217   bool isBuiltin;
00218     
00219   // Input file name
00220   std::string lInputFilename;
00221 
00222   // Output log File
00223   std::string lLogFilename;
00224 
00225   // Call the command-line option parser
00226   const int lOptionParserStatus = 
00227     readConfiguration (argc, argv, lRandomDraws, lCapacity, lMethod,
00228                        isBuiltin, lInputFilename, lLogFilename);
00229 
00230   if (lOptionParserStatus == K_RMOL_EARLY_RETURN_STATUS) {
00231     return 0;
00232   }
00233 
00234   // Set the log parameters
00235   std::ofstream logOutputFile;
00236   // Open and clean the log outputfile
00237   logOutputFile.open (lLogFilename.c_str());
00238   logOutputFile.clear();
00239 
00240   // Initialise the log stream
00241   const stdair::BasLogParams lLogParams (stdair::LOG::DEBUG, logOutputFile);
00242 
00243   // Initialise the RMOL service
00244   RMOL::RMOL_Service rmolService (lLogParams);
00245 
00246   if (isBuiltin == true) {
00247     // DEBUG
00248     STDAIR_LOG_DEBUG ("No input file has been given."
00249                       "A sample BOM tree will therefore be built.");
00250 
00251     // Build a sample BOM tree
00252     rmolService.buildSampleBom();
00253 
00254   } else {
00255     // DEBUG
00256     STDAIR_LOG_DEBUG ("RMOL will parse " << lInputFilename
00257                       << " and build the corresponding BOM tree.");
00258 
00259     //
00260     rmolService.parseAndLoad (lCapacity, lInputFilename);
00261   }
00262 
00263   // Launch the optimisation
00264   optimise (rmolService, lMethod, lRandomDraws);
00265 
00266   //
00267   logOutputFile.close();
00268 
00269   return 0;     
00270 }