$treeview $search $mathjax
TraDemGen Logo  1.00.2
$projectbrief
$projectbrief
$searchbox

pytrademgen.cpp

Go to the documentation of this file.
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 }