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