TraDemGen Logo  1.00.4
C++ Simulated Travel Demand Generation Library
pytrademgen.cpp
Go to the documentation of this file.
1 // Boost Python
2 #include <boost/python.hpp>
3 // STL
4 #include <cassert>
5 #include <stdexcept>
6 #include <fstream>
7 #include <sstream>
8 #include <string>
9 // Boost Accumulators
10 #include <boost/accumulators/accumulators.hpp>
11 #include <boost/accumulators/statistics.hpp>
12 // StdAir
13 #include <stdair/stdair_basic_types.hpp>
14 #include <stdair/basic/ProgressStatusSet.hpp>
15 #include <stdair/basic/DemandGenerationMethod.hpp>
16 #include <stdair/bom/EventStruct.hpp>
17 #include <stdair/bom/BookingRequestStruct.hpp>
18 //#include <stdair/bom/BomDisplay.hpp>
19 #include <stdair/service/Logger.hpp>
20 // TraDemGen
23 
24 // Aliases for namespaces
25 namespace ba = boost::accumulators;
26 
27 // //////// Specific type definitions ///////
28 typedef unsigned int NbOfRuns_T;
29 
33 typedef ba::accumulator_set<double,
34  ba::stats<ba::tag::min, ba::tag::max,
35  ba::tag::mean (ba::immediate),
36  ba::tag::sum,
37  ba::tag::variance> > stat_acc_type;
38 
39 namespace TRADEMGEN {
40 
44  void stat_display (std::ostream& oStream, const stat_acc_type& iStatAcc) {
45 
46  // Store current formatting flags of the output stream
47  std::ios::fmtflags oldFlags = oStream.flags();
48 
49  //
50  oStream.setf (std::ios::fixed);
51 
52  //
53  oStream << "Statistics for the demand generation runs: " << std::endl;
54  oStream << " minimum = " << ba::min (iStatAcc) << std::endl;
55  oStream << " mean = " << ba::mean (iStatAcc) << std::endl;
56  oStream << " maximum = " << ba::max (iStatAcc) << std::endl;
57  oStream << " count = " << ba::count (iStatAcc) << std::endl;
58  oStream << " variance = " << ba::variance (iStatAcc) << std::endl;
59 
60  // Reset formatting flags of output stream
61  oStream.flags (oldFlags);
62  }
63 
67  struct Trademgener {
68  public:
72  std::string
73  trademgen (const NbOfRuns_T& iNbOfRuns,
74  const std::string& iDemandGenerationMethodString) {
75  std::ostringstream oStream;
76 
77  // Convert the input string into a demand generation method enumeration
78  const stdair::DemandGenerationMethod
79  iDemandGenerationMethod (iDemandGenerationMethodString);
80 
81  // Sanity check
82  if (_logOutputStream == NULL) {
83  oStream << "The log filepath is not valid." << std::endl;
84  return oStream.str();
85  }
86  assert (_logOutputStream != NULL);
87 
88  try {
89 
90  // DEBUG
91  *_logOutputStream << "Demand generation for " << iNbOfRuns << " runs, "
92  << "with the following method: "
93  << iDemandGenerationMethod << std::endl;
94 
95  if (_trademgenService == NULL) {
96  oStream << "The TraDemGen service has not been initialised, "
97  << "i.e., the init() method has not been called "
98  << "correctly on the Trademgener object. Please "
99  << "check that all the parameters are not empty and "
100  << "point to actual files.";
101  *_logOutputStream << oStream.str();
102  return oStream.str();
103  }
104  assert (_trademgenService != NULL);
105 
106  // Initialise the statistics collector/accumulator
107  stat_acc_type lStatAccumulator;
108 
109  // Retrieve the expected (mean value of the) number of events to be
110  // generated
111  const stdair::Count_T& lExpectedNbOfEventsToBeGenerated =
113 
114  // Initialise the (Boost) progress display object
115  boost::progress_display
116  lProgressDisplay (lExpectedNbOfEventsToBeGenerated * iNbOfRuns);
117 
118  for (NbOfRuns_T runIdx = 1; runIdx <= iNbOfRuns; ++runIdx) {
119  // /////////////////////////////////////////////////////
120  *_logOutputStream << "Run number: " << runIdx << std::endl;
121 
126  const stdair::Count_T& lActualNbOfEventsToBeGenerated =
127  _trademgenService->generateFirstRequests (iDemandGenerationMethod);
128 
129  // DEBUG
130  *_logOutputStream << "[" << runIdx << "] Expected: "
131  << lExpectedNbOfEventsToBeGenerated << ", actual: "
132  << lActualNbOfEventsToBeGenerated << std::endl;
133 
141  while (_trademgenService->isQueueDone() == false) {
142 
143  // Extract the next event from the event queue
144  stdair::EventStruct lEventStruct;
145  stdair::ProgressStatusSet lProgressStatusSet =
146  _trademgenService->popEvent (lEventStruct);
147 
148  // DEBUG
149  // STDAIR_LOG_DEBUG ("[" << runIdx << "] Poped event: '"
150  // << lEventStruct.describe() << "'.");
151 
152  // Extract the corresponding demand/booking request
153  const stdair::BookingRequestStruct& lPoppedRequest =
154  lEventStruct.getBookingRequest();
155 
156  // DEBUG
157  *_logOutputStream << "[" << runIdx << "] Poped booking request: '"
158  << lPoppedRequest.describe() << "'." << std::endl;
159 
160  // Dump the request into the dedicated CSV file
161  // stdair::BomDisplay::csvDisplay (output, lPoppedRequest);
162 
163  // Retrieve the corresponding demand stream key
164  const stdair::DemandGeneratorKey_T& lDemandStreamKey =
165  lPoppedRequest.getDemandGeneratorKey();
166 
167  // Assess whether more events should be generated for that
168  // demand stream
169  const bool stillHavingRequestsToBeGenerated = _trademgenService->
170  stillHavingRequestsToBeGenerated (lDemandStreamKey,
171  lProgressStatusSet,
172  iDemandGenerationMethod);
173 
174  // DEBUG
175  *_logOutputStream << lProgressStatusSet.describe() << std::endl;
176  *_logOutputStream << "=> [" << lDemandStreamKey
177  << "] is now processed. Still generate events "
178  << "for that demand stream? "
179  << stillHavingRequestsToBeGenerated << std::endl;
180 
181  // If there are still events to be generated for that demand
182  // stream, generate and add them to the event queue
183  if (stillHavingRequestsToBeGenerated == true) {
184 
185  stdair::BookingRequestPtr_T lNextRequest_ptr =
186  _trademgenService->generateNextRequest(lDemandStreamKey,
187  iDemandGenerationMethod);
188 
189  assert (lNextRequest_ptr != NULL);
190 
191  // Sanity check
192  const stdair::Duration_T lDuration =
193  lNextRequest_ptr->getRequestDateTime()
194  - lPoppedRequest.getRequestDateTime();
195  if (lDuration.total_milliseconds() < 0) {
196  *_logOutputStream << "[" << lDemandStreamKey
197  << "] The date-time of the generated event ("
198  << lNextRequest_ptr->getRequestDateTime()
199  << ") is lower than the date-time "
200  << "of the current event ("
201  << lPoppedRequest.getRequestDateTime()
202  << ")" << std::endl;
203  assert (false);
204  }
205 
206  // DEBUG
207  *_logOutputStream << "[" << lDemandStreamKey
208  << "] Added request: '"
209  << lNextRequest_ptr->describe()
210  << "'. Is queue done? "
211  << _trademgenService->isQueueDone()
212  << std::endl;
213  }
214  // DEBUG
215  *_logOutputStream << std::endl;
216 
217  // Update the progress display
218  ++lProgressDisplay;
219  }
220 
221  // Add the number of events to the statistics accumulator
222  lStatAccumulator (lActualNbOfEventsToBeGenerated);
223 
224  // Reset the service (including the event queue) for the next run
225  _trademgenService->reset();
226  }
227 
228  // DEBUG
229  *_logOutputStream << "End of the demand generation. Following are some "
230  << "statistics for the " << iNbOfRuns << " runs."
231  << std::endl;
232  std::ostringstream oStatStr;
233  stat_display (oStatStr, lStatAccumulator);
234  *_logOutputStream << oStatStr.str() << std::endl;
235 
236  // DEBUG
237  const std::string& lBOMStr = _trademgenService->csvDisplay();
238  *_logOutputStream << lBOMStr << std::endl;
239 
240  // DEBUG
241  *_logOutputStream << "TraDemGen output: "
242  << oStream.str() << std::endl;
243 
244  } catch (const stdair::RootException& eTrademgenError) {
245  oStream << "TraDemGen error: " << eTrademgenError.what() << std::endl;
246 
247  } catch (const std::exception& eStdError) {
248  oStream << "Error: " << eStdError.what() << std::endl;
249 
250  } catch (...) {
251  oStream << "Unknown error" << std::endl;
252  }
253 
254  //
255  oStream << "TraDemGen has completed the generation of the booking "
256  << "requests. See the log file for more details." << std::endl;
257 
258  return oStream.str();
259  }
260 
261  public:
263  Trademgener() : _trademgenService (NULL), _logOutputStream (NULL) {
264  }
265 
267  Trademgener (const Trademgener& iTrademgener)
268  : _trademgenService (iTrademgener._trademgenService),
269  _logOutputStream (iTrademgener._logOutputStream) {
270  }
271 
274  _trademgenService = NULL;
275  _logOutputStream = NULL;
276  }
277 
281  bool init (const std::string& iLogFilepath,
282  const stdair::RandomSeed_T& iRandomSeed, const bool isBuiltin,
283  const stdair::Filename_T& iDemandInputFilename) {
284  bool isEverythingOK = true;
285 
286  try {
287 
288  // Check that the file path given as input corresponds to an actual file
289  const bool isWriteable = (iLogFilepath.empty() == false);
290  // stdair::BasFileMgr::isWriteable (iLogFilepath);
291  if (isWriteable == false) {
292  isEverythingOK = false;
293  return isEverythingOK;
294  }
295 
296  // Set the log parameters
297  _logOutputStream = new std::ofstream;
298  assert (_logOutputStream != NULL);
299 
300  // Open and clean the log outputfile
301  _logOutputStream->open (iLogFilepath.c_str());
302  _logOutputStream->clear();
303 
304  // DEBUG
305  *_logOutputStream << "Python wrapper initialisation" << std::endl;
306  const stdair::BasLogParams lLogParams (stdair::LOG::DEBUG,
307  *_logOutputStream);
308 
309  // Initialise the context
310  _trademgenService = new TRADEMGEN_Service (lLogParams, iRandomSeed);
311  assert (_trademgenService != NULL);
312 
313  // Check wether or not a (CSV) input file should be read
314  if (isBuiltin == true) {
315  // Create a sample DemandStream object, and insert it within
316  // the BOM tree
317  _trademgenService->buildSampleBom();
318 
319  } else {
320  // Create the DemandStream objects, and insert them within
321  // the BOM tree
322  const DemandFilePath lDemandFilePath (iDemandInputFilename);
323  _trademgenService->parseAndLoad (lDemandFilePath);
324  }
325 
326  // DEBUG
327  *_logOutputStream << "Python wrapper initialised" << std::endl;
328 
329  } catch (const stdair::RootException& eTrademgenError) {
330  *_logOutputStream << "Trademgen error: " << eTrademgenError.what()
331  << std::endl;
332 
333  } catch (const std::exception& eStdError) {
334  *_logOutputStream << "Error: " << eStdError.what() << std::endl;
335 
336  } catch (...) {
337  *_logOutputStream << "Unknown error" << std::endl;
338  }
339 
340  return isEverythingOK;
341  }
342 
343  private:
345  TRADEMGEN_Service* _trademgenService;
346  std::ofstream* _logOutputStream;
347  };
348 
349 }
350 
351 // /////////////////////////////////////////////////////////////
352 BOOST_PYTHON_MODULE(pytrademgen) {
353  boost::python::class_<TRADEMGEN::Trademgener> ("Trademgener")
354  .def ("trademgen", &TRADEMGEN::Trademgener::trademgen)
355  .def ("init", &TRADEMGEN::Trademgener::init);
356 }
TRADEMGEN::TRADEMGEN_Service::popEvent
stdair::ProgressStatusSet popEvent(stdair::EventStruct &) const
Definition: TRADEMGEN_Service.cpp:713
TRADEMGEN::TRADEMGEN_Service::generateFirstRequests
stdair::Count_T generateFirstRequests(const stdair::DemandGenerationMethod &) const
Definition: TRADEMGEN_Service.cpp:663
BOOST_PYTHON_MODULE
BOOST_PYTHON_MODULE(pytrademgen)
Definition: pytrademgen.cpp:352
trademgen-paths.hpp
NbOfRuns_T
unsigned int NbOfRuns_T
Definition: pytrademgen.cpp:28
TRADEMGEN::TRADEMGEN_Service::isQueueDone
bool isQueueDone() const
Definition: TRADEMGEN_Service.cpp:729
NbOfRuns_T
unsigned int NbOfRuns_T
Definition: trademgen_generateDemand.cpp:38
TRADEMGEN::TRADEMGEN_Service
class holding the services related to Travel Demand Generation.
Definition: TRADEMGEN_Service.hpp:44
TRADEMGEN::TRADEMGEN_Service::reset
void reset() const
Definition: TRADEMGEN_Service.cpp:811
TRADEMGEN::Trademgener::init
bool init(const std::string &iLogFilepath, const stdair::RandomSeed_T &iRandomSeed, const bool isBuiltin, const stdair::Filename_T &iDemandInputFilename)
Definition: pytrademgen.cpp:281
TRADEMGEN::Trademgener::Trademgener
Trademgener()
Definition: pytrademgen.cpp:263
TRADEMGEN::Trademgener::~Trademgener
~Trademgener()
Definition: pytrademgen.cpp:273
TRADEMGEN::stat_display
void stat_display(std::ostream &oStream, const stat_acc_type &iStatAcc)
Definition: pytrademgen.cpp:44
TRADEMGEN::TRADEMGEN_Service::getExpectedTotalNumberOfRequestsToBeGenerated
const stdair::Count_T & getExpectedTotalNumberOfRequestsToBeGenerated() const
Definition: TRADEMGEN_Service.cpp:596
stat_acc_type
ba::accumulator_set< double, ba::stats< ba::tag::min, ba::tag::max, ba::tag::mean(ba::immediate), ba::tag::sum, ba::tag::variance > > stat_acc_type
Definition: trademgen_generateDemand.cpp:47
TRADEMGEN::TRADEMGEN_Service::csvDisplay
std::string csvDisplay() const
Definition: TRADEMGEN_Service.cpp:468
TRADEMGEN_Service.hpp
stat_acc_type
ba::accumulator_set< double, ba::stats< ba::tag::min, ba::tag::max, ba::tag::mean(ba::immediate), ba::tag::sum, ba::tag::variance > > stat_acc_type
Definition: pytrademgen.cpp:37
TRADEMGEN::TRADEMGEN_Service::buildSampleBom
void buildSampleBom()
Definition: TRADEMGEN_Service.cpp:310
TRADEMGEN::Trademgener::trademgen
std::string trademgen(const NbOfRuns_T &iNbOfRuns, const std::string &iDemandGenerationMethodString)
Definition: pytrademgen.cpp:73
TRADEMGEN::Trademgener::Trademgener
Trademgener(const Trademgener &iTrademgener)
Definition: pytrademgen.cpp:267
TRADEMGEN::Trademgener
Wrapper structure around the C++ API, so as to expose a Python API.
Definition: pytrademgen.cpp:67
TRADEMGEN::TRADEMGEN_Service::parseAndLoad
void parseAndLoad(const DemandFilePath &)
Definition: TRADEMGEN_Service.cpp:241
TRADEMGEN::TRADEMGEN_Service::generateNextRequest
stdair::BookingRequestPtr_T generateNextRequest(const stdair::DemandStreamKeyStr_T &, const stdair::DemandGenerationMethod &) const
Definition: TRADEMGEN_Service.cpp:689
TRADEMGEN::DemandFilePath
Definition: TRADEMGEN_Types.hpp:30
TRADEMGEN
Definition: BasConst.cpp:10