RMOL Logo  0.25.3
C++ library of Revenue Management and Optimisation classes and functions
 All Classes Namespaces Files Functions Variables Typedefs Friends Macros Pages
RMOL_Service.cpp
Go to the documentation of this file.
1 // //////////////////////////////////////////////////////////////////////
2 // Import section
3 // //////////////////////////////////////////////////////////////////////
4 // STL
5 #include <cassert>
6 // Boost
7 #include <boost/make_shared.hpp>
8 // StdAir
9 #include <stdair/stdair_inventory_types.hpp>
10 #include <stdair/basic/BasChronometer.hpp>
11 #include <stdair/basic/ContinuousAttributeLite.hpp>
12 #include <stdair/bom/BomManager.hpp>
13 #include <stdair/bom/BomRetriever.hpp>
14 #include <stdair/bom/BomRoot.hpp>
15 #include <stdair/bom/Inventory.hpp>
16 #include <stdair/bom/FlightDate.hpp>
17 #include <stdair/bom/LegCabin.hpp>
18 #include <stdair/bom/LegDate.hpp>
19 #include <stdair/bom/YieldFeatures.hpp>
20 #include <stdair/bom/AirportPair.hpp>
21 #include <stdair/bom/PosChannel.hpp>
22 #include <stdair/bom/DatePeriod.hpp>
23 #include <stdair/bom/TimePeriod.hpp>
24 #include <stdair/bom/AirlineClassList.hpp>
25 #include <stdair/basic/BasConst_Request.hpp>
26 #include <stdair/basic/BasConst_Inventory.hpp>
27 #include <stdair/bom/Inventory.hpp>
28 #include <stdair/bom/FlightDate.hpp>
29 #include <stdair/bom/SegmentDate.hpp>
30 #include <stdair/bom/SegmentCabin.hpp>
31 #include <stdair/bom/BookingClass.hpp>
32 #include <stdair/bom/OnDDate.hpp>
33 #include <stdair/bom/OnDDateTypes.hpp>
34 #include <stdair/command/CmdBomManager.hpp>
35 #include <stdair/service/Logger.hpp>
36 #include <stdair/STDAIR_Service.hpp>
37 // RMOL
44 #include <rmol/RMOL_Service.hpp>
45 
46 namespace RMOL {
47 
48  // ////////////////////////////////////////////////////////////////////
49  RMOL_Service::RMOL_Service()
50  : _rmolServiceContext (NULL),
51  _previousForecastDate (stdair::Date_T (2000, 1, 1)) {
52  assert (false);
53  }
54 
55  // ////////////////////////////////////////////////////////////////////
56  RMOL_Service::RMOL_Service (const RMOL_Service& iService) :
57  _rmolServiceContext (NULL),
58  _previousForecastDate (stdair::Date_T (2000, 1, 1)) {
59  assert (false);
60  }
61 
62  // ////////////////////////////////////////////////////////////////////
63  RMOL_Service::RMOL_Service (const stdair::BasLogParams& iLogParams) :
64  _rmolServiceContext (NULL),
65  _previousForecastDate (stdair::Date_T (2000, 1, 1)) {
66 
67  // Initialise the STDAIR service handler
68  stdair::STDAIR_ServicePtr_T lSTDAIR_Service_ptr =
69  initStdAirService (iLogParams);
70 
71  // Initialise the service context
72  initServiceContext();
73 
74  // Add the StdAir service context to the RMOL service context
75  // \note RMOL owns the STDAIR service resources here.
76  const bool ownStdairService = true;
77  addStdAirService (lSTDAIR_Service_ptr, ownStdairService);
78 
79  // Initialise the (remaining of the) context
80  initRmolService();
81  }
82 
83  // ////////////////////////////////////////////////////////////////////
84  RMOL_Service::RMOL_Service (const stdair::BasLogParams& iLogParams,
85  const stdair::BasDBParams& iDBParams) :
86  _rmolServiceContext (NULL),
87  _previousForecastDate (stdair::Date_T (2000, 1, 1)) {
88 
89  // Initialise the STDAIR service handler
90  stdair::STDAIR_ServicePtr_T lSTDAIR_Service_ptr =
91  initStdAirService (iLogParams, iDBParams);
92 
93  // Initialise the service context
94  initServiceContext();
95 
96  // Add the StdAir service context to the RMOL service context
97  // \note RMOL owns the STDAIR service resources here.
98  const bool ownStdairService = true;
99  addStdAirService (lSTDAIR_Service_ptr, ownStdairService);
100 
101  // Initialise the (remaining of the) context
102  initRmolService();
103  }
104 
105  // ////////////////////////////////////////////////////////////////////
106  RMOL_Service::RMOL_Service (stdair::STDAIR_ServicePtr_T ioSTDAIRServicePtr)
107  : _rmolServiceContext (NULL),
108  _previousForecastDate (stdair::Date_T (2000, 1, 1)) {
109 
110  // Initialise the context
111  initServiceContext();
112 
113  // Add the StdAir service context to the RMOL service context.
114  // \note RMOL does not own the STDAIR service resources here.
115  const bool doesNotOwnStdairService = false;
116  addStdAirService (ioSTDAIRServicePtr, doesNotOwnStdairService);
117 
118  // Initialise the (remaining of the) context
119  initRmolService();
120  }
121 
122  // ////////////////////////////////////////////////////////////////////
124  // Delete/Clean all the objects from memory
125  finalise();
126  }
127 
128  // ////////////////////////////////////////////////////////////////////
129  void RMOL_Service::finalise() {
130  assert (_rmolServiceContext != NULL);
131  // Reset the (Boost.)Smart pointer pointing on the STDAIR_Service object.
132  _rmolServiceContext->reset();
133  }
134 
135  // ////////////////////////////////////////////////////////////////////
136  void RMOL_Service::initServiceContext() {
137  // Initialise the service context
138  RMOL_ServiceContext& lRMOL_ServiceContext =
140  _rmolServiceContext = &lRMOL_ServiceContext;
141  }
142 
143  // ////////////////////////////////////////////////////////////////////
144  void RMOL_Service::
145  addStdAirService (stdair::STDAIR_ServicePtr_T ioSTDAIR_Service_ptr,
146  const bool iOwnStdairService) {
147 
148  // Retrieve the RMOL service context
149  assert (_rmolServiceContext != NULL);
150  RMOL_ServiceContext& lRMOL_ServiceContext = *_rmolServiceContext;
151 
152  // Store the STDAIR service object within the (AIRINV) service context
153  lRMOL_ServiceContext.setSTDAIR_Service (ioSTDAIR_Service_ptr,
154  iOwnStdairService);
155  }
156 
157  // ////////////////////////////////////////////////////////////////////
158  stdair::STDAIR_ServicePtr_T RMOL_Service::
159  initStdAirService (const stdair::BasLogParams& iLogParams) {
160 
168  stdair::STDAIR_ServicePtr_T lSTDAIR_Service_ptr =
169  boost::make_shared<stdair::STDAIR_Service> (iLogParams);
170 
171  return lSTDAIR_Service_ptr;
172  }
173 
174  // //////////////////////////////////////////////////////////////////////
175  stdair::STDAIR_ServicePtr_T RMOL_Service::
176  initStdAirService (const stdair::BasLogParams& iLogParams,
177  const stdair::BasDBParams& iDBParams) {
178 
186  stdair::STDAIR_ServicePtr_T lSTDAIR_Service_ptr =
187  boost::make_shared<stdair::STDAIR_Service> (iLogParams, iDBParams);
188 
189  return lSTDAIR_Service_ptr;
190  }
191 
192  // ////////////////////////////////////////////////////////////////////
193  void RMOL_Service::initRmolService() {
194  // Do nothing at this stage. A sample BOM tree may be built by
195  // calling the buildSampleBom() method
196  }
197 
198  // ////////////////////////////////////////////////////////////////////
199  void RMOL_Service::
200  parseAndLoad (const stdair::CabinCapacity_T& iCabinCapacity,
201  const stdair::Filename_T& iInputFileName) {
202 
203  // Retrieve the RMOL service context
204  if (_rmolServiceContext == NULL) {
205  throw stdair::NonInitialisedServiceException ("The RMOL service has not"
206  " been initialised");
207  }
208  assert (_rmolServiceContext != NULL);
209  RMOL_ServiceContext& lRMOL_ServiceContext = *_rmolServiceContext;
210 
211  // Retrieve the StdAir service object from the (RMOL) service context
212  stdair::STDAIR_Service& lSTDAIR_Service =
213  lRMOL_ServiceContext.getSTDAIR_Service();
214  stdair::BomRoot& lBomRoot = lSTDAIR_Service.getBomRoot();
215 
216  // Build a dummy inventory with a leg-cabin which has the given capacity.
217  lSTDAIR_Service.buildDummyInventory (iCabinCapacity);
218 
219  // Complete the BOM tree with the optimisation problem specification
220  InventoryParser::parseInputFileAndBuildBom (iInputFileName, lBomRoot);
221  }
222 
223  // ////////////////////////////////////////////////////////////////////
225 
226  // Retrieve the RMOL service context
227  if (_rmolServiceContext == NULL) {
228  throw stdair::NonInitialisedServiceException ("The RMOL service has not"
229  " been initialised");
230  }
231  assert (_rmolServiceContext != NULL);
232 
233  // Retrieve the RMOL service context and whether it owns the Stdair
234  // service
235  RMOL_ServiceContext& lRMOL_ServiceContext = *_rmolServiceContext;
236  const bool doesOwnStdairService =
237  lRMOL_ServiceContext.getOwnStdairServiceFlag();
238 
239  // Retrieve the StdAir service object from the (RMOL) service context
240  stdair::STDAIR_Service& lSTDAIR_Service =
241  lRMOL_ServiceContext.getSTDAIR_Service();
242 
247  if (doesOwnStdairService == true) {
248  //
249  lSTDAIR_Service.buildSampleBom();
250  }
251 
269  }
270 
271  // ////////////////////////////////////////////////////////////////////
273  assert (_rmolServiceContext != NULL);
274  RMOL_ServiceContext& lRMOL_ServiceContext = *_rmolServiceContext;
275 
276  // Retrieve the StdAir service
277  stdair::STDAIR_Service& lSTDAIR_Service =
278  lRMOL_ServiceContext.getSTDAIR_Service();
279  stdair::BomRoot& lBomRoot = lSTDAIR_Service.getBomRoot();
280 
281  //
282  stdair::LegCabin& lLegCabin =
283  stdair::BomRetriever::retrieveDummyLegCabin (lBomRoot);
284 
285  stdair::BasChronometer lOptimisationChronometer;
286  lOptimisationChronometer.start();
287 
289 
290  const double lOptimisationMeasure = lOptimisationChronometer.elapsed();
291 
292  // DEBUG
293  STDAIR_LOG_DEBUG ("Optimisation by Monte-Carlo performed in "
294  << lOptimisationMeasure);
295  STDAIR_LOG_DEBUG ("Result: " << lLegCabin.displayVirtualClassList());
296 
297  std::ostringstream logStream;
298  stdair::BidPriceVector_T lBidPriceVector = lLegCabin.getBidPriceVector();
299  logStream << "Bid-Price Vector (BPV): ";
300  unsigned int size = lBidPriceVector.size();
301 
302  for (unsigned int i = 0; i < size - 1; ++i) {
303  const double bidPrice = lBidPriceVector.at(i);
304  logStream << std::fixed << std::setprecision (2) << bidPrice << ", ";
305  }
306  const double bidPrice = lBidPriceVector.at(size -1);
307  logStream << std::fixed << std::setprecision (2) << bidPrice;
308  STDAIR_LOG_DEBUG (logStream.str());
309  }
310 
311  // ////////////////////////////////////////////////////////////////////
313  }
314 
315  // ////////////////////////////////////////////////////////////////////
317  assert (_rmolServiceContext != NULL);
318  RMOL_ServiceContext& lRMOL_ServiceContext = *_rmolServiceContext;
319 
320  // Retrieve the StdAir service
321  stdair::STDAIR_Service& lSTDAIR_Service =
322  lRMOL_ServiceContext.getSTDAIR_Service();
323  stdair::BomRoot& lBomRoot = lSTDAIR_Service.getBomRoot();
324 
325  //
326  stdair::LegCabin& lLegCabin =
327  stdair::BomRetriever::retrieveDummyLegCabin (lBomRoot);
328 
329  stdair::BasChronometer lOptimisationChronometer;
330  lOptimisationChronometer.start();
331 
333 
334  const double lOptimisationMeasure = lOptimisationChronometer.elapsed();
335  // DEBUG
336  STDAIR_LOG_DEBUG ("Optimisation EMSR performed in "
337  << lOptimisationMeasure);
338  STDAIR_LOG_DEBUG ("Result: " << lLegCabin.displayVirtualClassList());
339 
340  stdair::BidPriceVector_T lBidPriceVector = lLegCabin.getBidPriceVector();
341  std::ostringstream logStream;
342  logStream << "Bid-Price Vector (BPV): ";
343  unsigned int idx = 0;
344  for (stdair::BidPriceVector_T::const_iterator itBP = lBidPriceVector.begin();
345  itBP != lBidPriceVector.end(); ++itBP) {
346  if (idx != 0) {
347  logStream << ", ";
348  }
349  const stdair::BidPrice_T& lBidPrice = *itBP;
350  logStream << std::fixed << std::setprecision (2) << lBidPrice;
351  }
352  // DEBUG
353  STDAIR_LOG_DEBUG (logStream.str());
354  }
355 
356  // ////////////////////////////////////////////////////////////////////
358  assert (_rmolServiceContext != NULL);
359  RMOL_ServiceContext& lRMOL_ServiceContext = *_rmolServiceContext;
360 
361  // Retrieve the StdAir service
362  stdair::STDAIR_Service& lSTDAIR_Service =
363  lRMOL_ServiceContext.getSTDAIR_Service();
364  stdair::BomRoot& lBomRoot = lSTDAIR_Service.getBomRoot();
365 
366  //
367  stdair::LegCabin& lLegCabin =
368  stdair::BomRetriever::retrieveDummyLegCabin (lBomRoot);
369 
371 
372  // DEBUG
373  STDAIR_LOG_DEBUG ("Result: " << lLegCabin.displayVirtualClassList());
374 
375  }
376 
377  // ////////////////////////////////////////////////////////////////////
379  assert (_rmolServiceContext != NULL);
380  RMOL_ServiceContext& lRMOL_ServiceContext = *_rmolServiceContext;
381 
382  // Retrieve the StdAir service
383  stdair::STDAIR_Service& lSTDAIR_Service =
384  lRMOL_ServiceContext.getSTDAIR_Service();
385  stdair::BomRoot& lBomRoot = lSTDAIR_Service.getBomRoot();
386 
387  //
388  stdair::LegCabin& lLegCabin =
389  stdair::BomRetriever::retrieveDummyLegCabin (lBomRoot);
390 
392 
393  // DEBUG
394  STDAIR_LOG_DEBUG ("Result: " << lLegCabin.displayVirtualClassList());
395  }
396 
397  // ////////////////////////////////////////////////////////////////////
398  bool RMOL_Service::
399  optimise (stdair::FlightDate& ioFlightDate,
400  const stdair::DateTime_T& iRMEventTime,
401  const stdair::ForecastingMethod& iForecastingMethod,
402  const stdair::PartnershipTechnique& iPartnershipTechnique) {
403 
404 
405  STDAIR_LOG_DEBUG ("Forecast & Optimisation");
406 
407  const stdair::PartnershipTechnique::EN_PartnershipTechnique& lPartnershipTechnique =
408  iPartnershipTechnique.getTechnique();
409 
410  switch (lPartnershipTechnique) {
411  case stdair::PartnershipTechnique::RAE_DA:
412  case stdair::PartnershipTechnique::IBP_DA:{
413  if (_previousForecastDate < iRMEventTime.date()) {
414  forecastOnD (iRMEventTime);
415  resetDemandInformation (iRMEventTime);
416  projectAggregatedDemandOnLegCabins (iRMEventTime);
417  optimiseOnD (iRMEventTime);
418  }
419  break;
420  }
421  case stdair::PartnershipTechnique::RAE_YP:
422  case stdair::PartnershipTechnique::IBP_YP:
423  case stdair::PartnershipTechnique::IBP_YP_U:{
424  if (_previousForecastDate < iRMEventTime.date()) {
425  forecastOnD (iRMEventTime);
426  resetDemandInformation (iRMEventTime);
427  projectOnDDemandOnLegCabinsUsingYP (iRMEventTime);
428  optimiseOnD (iRMEventTime);
429  }
430  break;
431  }
432  case stdair::PartnershipTechnique::RMC:{
433  if (_previousForecastDate < iRMEventTime.date()) {
434  forecastOnD (iRMEventTime);
435  resetDemandInformation (iRMEventTime);
436  updateBidPrice (iRMEventTime);
438  optimiseOnDUsingRMCooperation (iRMEventTime);
439  }
440  break;
441  }
442  case stdair::PartnershipTechnique::A_RMC:{
443  if (_previousForecastDate < iRMEventTime.date()) {
444  forecastOnD (iRMEventTime);
445  resetDemandInformation (iRMEventTime);
446  updateBidPrice (iRMEventTime);
449  }
450  break;
451  }
452  case stdair::PartnershipTechnique::NONE:{
453  // DEBUG
454  STDAIR_LOG_DEBUG ("Forecast");
455 
456  // 1. Forecast
457  bool isForecasted = false;
458  const stdair::ForecastingMethod::EN_ForecastingMethod& lForecastingMethod=
459  iForecastingMethod.getMethod();
460  switch (lForecastingMethod) {
461  case stdair::ForecastingMethod::ADD_PK: {
462  isForecasted = Forecaster::forecastUsingAdditivePickUp (ioFlightDate,
463  iRMEventTime);
464  break;
465  }
466  case stdair::ForecastingMethod::MUL_PK: {
467  isForecasted =
469  iRMEventTime);
470  break;
471  }
472  default: {
473  assert (false);
474  break;
475  }
476  }
477 
478  // DEBUG
479  STDAIR_LOG_DEBUG ("Forecast successful: " << isForecasted);
480 
481  // 2. Optimisation
482  if (isForecasted == true) {
483  // DEBUG
484  STDAIR_LOG_DEBUG ("Optimise");
485 
486  Optimiser::optimise (ioFlightDate);
487  return true;
488  }
489  break;
490  }
491  default:{
492  assert (false);
493  break;
494  }
495  }
496  return false;
497  }
498 
499  // ////////////////////////////////////////////////////////////////////
500  void RMOL_Service::forecastOnD (const stdair::DateTime_T& iRMEventTime) {
501 
502  if (_rmolServiceContext == NULL) {
503  throw stdair::NonInitialisedServiceException ("The Rmol service "
504  "has not been initialised");
505  }
506  assert (_rmolServiceContext != NULL);
507  RMOL_ServiceContext& lRMOL_ServiceContext = *_rmolServiceContext;
508 
509  // Retrieve the bom root
510  stdair::STDAIR_Service& lSTDAIR_Service =
511  lRMOL_ServiceContext.getSTDAIR_Service();
512  stdair::BomRoot& lBomRoot = lSTDAIR_Service.getBomRoot();
513 
514  // Retrieve the date from the RM event
515  const stdair::Date_T lDate = iRMEventTime.date();
516 
517  _previousForecastDate = lDate;
518 
519  const stdair::InventoryList_T& lInventoryList =
520  stdair::BomManager::getList<stdair::Inventory> (lBomRoot);
521  assert (!lInventoryList.empty());
522  for (stdair::InventoryList_T::const_iterator itInv = lInventoryList.begin();
523  itInv != lInventoryList.end(); ++itInv) {
524  const stdair::Inventory* lInventory_ptr = *itInv;
525  assert (lInventory_ptr != NULL);
526  if (stdair::BomManager::hasList<stdair::OnDDate> (*lInventory_ptr)) {
527  const stdair::OnDDateList_T lOnDDateList =
528  stdair::BomManager::getList<stdair::OnDDate> (*lInventory_ptr);
529 
530  for (stdair::OnDDateList_T::const_iterator itOD = lOnDDateList.begin();
531  itOD != lOnDDateList.end(); ++itOD) {
532  stdair::OnDDate* lOnDDate_ptr = *itOD;
533  assert (lOnDDate_ptr != NULL);
534 
535  const stdair::Date_T& lDepartureDate = lOnDDate_ptr->getDate();
536  stdair::DateOffset_T lDateOffset = lDepartureDate - lDate;
537  stdair::DTD_T lDTD = short (lDateOffset.days());
538 
539  stdair::DCPList_T::const_iterator itDCP =
540  std::find (stdair::DEFAULT_DCP_LIST.begin(),
541  stdair::DEFAULT_DCP_LIST.end(), lDTD);
542  // Check if the forecast for this O&D date needs to be forecasted.
543  if (itDCP != stdair::DEFAULT_DCP_LIST.end()) {
544  // Retrieve the total forecast map.
545  const stdair::CabinForecastMap_T& lTotalForecastMap =
546  lOnDDate_ptr->getTotalForecastMap();
547 
548  // Browse the map and make a forecast for every cabin.
549  for (stdair::CabinForecastMap_T::const_iterator itCF =
550  lTotalForecastMap.begin();
551  itCF != lTotalForecastMap.end(); ++itCF) {
552  const stdair::CabinCode_T lCabinCode = itCF->first;
553  stdair::YieldFeatures* lYieldFeatures_ptr =
554  getYieldFeatures(*lOnDDate_ptr, lCabinCode, lBomRoot);
555  if (lYieldFeatures_ptr == NULL) {
556  STDAIR_LOG_ERROR ("Cannot find yield corresponding to "
557  << "the O&D date"
558  << lOnDDate_ptr->toString()
559  << " Cabin " << lCabinCode);
560  assert (false);
561  }
562  forecastOnD (*lYieldFeatures_ptr, *lOnDDate_ptr, lCabinCode, lDTD,
563  lBomRoot);
564  }
565  }
566  }
567  }
568  }
569  }
570 
571  // ///////////////////////////////////////////////////////////////////
572  stdair::YieldFeatures* RMOL_Service::
573  getYieldFeatures(const stdair::OnDDate& iOnDDate,
574  const stdair::CabinCode_T& iCabinCode,
575  stdair::BomRoot& iBomRoot) {
576 
577  const stdair::AirportCode_T& lOrigin = iOnDDate.getOrigin();
578  const stdair::AirportCode_T& lDestination = iOnDDate.getDestination();
579 
580  const stdair::Date_T& lDepartureDate = iOnDDate.getDate();
581 
582  // Build the airport pair key out of O&D and get the airport pair object
583  const stdair::AirportPairKey lAirportPairKey(lOrigin, lDestination);
584  stdair::AirportPair* lAirportPair_ptr = stdair::BomManager::
585  getObjectPtr<stdair::AirportPair> (iBomRoot,
586  lAirportPairKey.toString());
587  if (lAirportPair_ptr == NULL) {
588  STDAIR_LOG_ERROR ("Cannot find yield corresponding to the airport "
589  << "pair: " << lAirportPairKey.toString());
590  assert (false);
591  }
592 
593  // Retrieve the corresponding date period to lDepartureDate.
594  const stdair::DatePeriodList_T lDatePeriodList =
595  stdair::BomManager::getList<stdair::DatePeriod> (*lAirportPair_ptr);
596  for (stdair::DatePeriodList_T::const_iterator itDatePeriod =
597  lDatePeriodList.begin();
598  itDatePeriod != lDatePeriodList.end(); ++itDatePeriod) {
599  const stdair::DatePeriod* lDatePeriod_ptr = *itDatePeriod;
600  assert (lDatePeriod_ptr != NULL);
601 
602  const bool isDepartureDateValid =
603  lDatePeriod_ptr->isDepartureDateValid (lDepartureDate);
604 
605  if (isDepartureDateValid == true) {
606  // Retrieve the PoS-Channel.
607  // TODO: Use POS and Channel from demand instead of default
608  const stdair::PosChannelKey lPosChannelKey (stdair::DEFAULT_POS,
609  stdair::DEFAULT_CHANNEL);
610  stdair::PosChannel* lPosChannel_ptr = stdair::BomManager::
611  getObjectPtr<stdair::PosChannel> (*lDatePeriod_ptr,
612  lPosChannelKey.toString());
613  if (lPosChannel_ptr == NULL) {
614  STDAIR_LOG_ERROR ("Cannot find yield corresponding to the PoS-"
615  << "Channel: " << lPosChannelKey.toString());
616  assert (false);
617  }
618  // Retrieve the yield features.
619  const stdair::TimePeriodList_T lTimePeriodList = stdair::
620  BomManager::getList<stdair::TimePeriod> (*lPosChannel_ptr);
621  for (stdair::TimePeriodList_T::const_iterator itTimePeriod =
622  lTimePeriodList.begin();
623  itTimePeriod != lTimePeriodList.end(); ++itTimePeriod) {
624  const stdair::TimePeriod* lTimePeriod_ptr = *itTimePeriod;
625  assert (lTimePeriod_ptr != NULL);
626 
627  // TODO: Use trip type from demand instead of default value.
628  const stdair::YieldFeaturesKey lYieldFeaturesKey (stdair::TRIP_TYPE_ONE_WAY,
629  iCabinCode);
630  stdair::YieldFeatures* oYieldFeatures_ptr = stdair::BomManager::
631  getObjectPtr<stdair::YieldFeatures>(*lTimePeriod_ptr,
632  lYieldFeaturesKey.toString());
633  if (oYieldFeatures_ptr != NULL) {
634  return oYieldFeatures_ptr;
635  }
636  }
637  }
638  }
639  return NULL;
640 
641  }
642 
643 
644  // ///////////////////////////////////////////////////////////////////
645  void RMOL_Service::
646  forecastOnD (const stdair::YieldFeatures& iYieldFeatures,
647  stdair::OnDDate& iOnDDate,
648  const stdair::CabinCode_T& iCabinCode,
649  const stdair::DTD_T& iDTD,
650  stdair::BomRoot& iBomRoot) {
651 
652  const stdair::AirlineClassListList_T lAirlineClassListList =
653  stdair::BomManager::getList<stdair::AirlineClassList> (iYieldFeatures);
654  assert (lAirlineClassListList.begin() != lAirlineClassListList.end());
655 
656  // Yield order check
657  stdair::AirlineClassListList_T::const_iterator itACL =
658  lAirlineClassListList.begin();
659  stdair::Yield_T lPreviousYield((*itACL)->getYield());
660  ++itACL;
661  for (; itACL != lAirlineClassListList.end(); ++itACL) {
662  const stdair::AirlineClassList* lAirlineClassList = *itACL;
663  const stdair::Yield_T& lYield = lAirlineClassList->getYield();
664  if (lYield <= lPreviousYield) {
665  lPreviousYield = lYield;
666  }
667  else{
668  STDAIR_LOG_ERROR ("Yields should be given in a descendant order"
669  << " in the yield input file") ;
670  assert (false);
671  }
672  }
673  // Proportion factor list initialisation
674  // Each element corresponds to a yield rule
675  stdair::ProportionFactorList_T lProportionFactorList;
676  stdair::ProportionFactor_T lPreviousProportionFactor = 0;
677 
678  // Retrieve the minimal willingness to pay associated to the demand
679  const stdair::WTPDemandPair_T& lTotalForecast =
680  iOnDDate.getTotalForecast (iCabinCode);
681  const stdair::WTP_T& lMinWTP = lTotalForecast.first;
682 
683  // Retrieve the remaining percentage of booking requests
684  const stdair::ContinuousAttributeLite<stdair::FloatDuration_T>
685  lArrivalPattern (stdair::DEFAULT_DTD_PROB_MAP);
686 
687  STDAIR_LOG_DEBUG (lArrivalPattern.displayCumulativeDistribution());
688  const stdair::Probability_T lRemainingProportion =
689  lArrivalPattern.getRemainingProportion(-float(iDTD));
690 
691  // Compute the characteristics (mean and std dev) of the total
692  // forecast demand to come
693  const stdair::MeanStdDevPair_T lForecatsMeanStdDevPair =
694  lTotalForecast.second;
695  const stdair::MeanValue_T& lMeanValue =
696  lForecatsMeanStdDevPair.first;
697  const stdair::MeanValue_T& lRemainingMeanValue =
698  lRemainingProportion*lMeanValue;
699  const stdair::StdDevValue_T& lStdDevValue =
700  lForecatsMeanStdDevPair.second;
701  const stdair::StdDevValue_T& lRemainingStdDevValue =
702  lRemainingProportion*lStdDevValue;
703 
704  // Retrieve the frat5 coef corresponding to the input dtd
705  stdair::DTDFratMap_T::const_iterator itDFC =
706  stdair::DEFAULT_DTD_FRAT5COEF_MAP.find(iDTD);
707  if (itDFC == stdair::DEFAULT_DTD_FRAT5COEF_MAP.end()) {
708  STDAIR_LOG_ERROR ("Cannot find frat5 coef for DTD = " << iDTD );
709  assert (false);
710  }
711  stdair::RealNumber_T lFrat5Coef =
712  stdair::DEFAULT_DTD_FRAT5COEF_MAP.at(iDTD);
713 
714  STDAIR_LOG_DEBUG ("Remaining proportion " << lRemainingProportion
715  << " Total " << lMeanValue
716  << " StdDev " << lStdDevValue
717  << "Frat5 Coef " << lFrat5Coef);
718 
719  std::ostringstream oStr;
720  // Compute the "forecast demand to come" proportion by class
721  itACL = lAirlineClassListList.begin();
722  for (; itACL != lAirlineClassListList.end(); ++itACL) {
723  const stdair::AirlineClassList* lAirlineClassList_ptr = *itACL;
724  const stdair::Yield_T& lYield = lAirlineClassList_ptr->getYield();
725  stdair::ProportionFactor_T lProportionFactor =
726  exp ((lYield - lMinWTP)*log(0.5)/(lMinWTP*(lFrat5Coef-1.0)));
727  // If the yield is smaller than minimal WTP, the factor is greater than 1.
728  // In that case it should be modified and put to 1.
729  lProportionFactor = std::min (lProportionFactor, 1.0);
730  lProportionFactorList.push_back(lProportionFactor - lPreviousProportionFactor);
731  lPreviousProportionFactor = lProportionFactor;
732  oStr << lAirlineClassList_ptr->toString() << lProportionFactor << " ";
733  }
734 
735  STDAIR_LOG_DEBUG (oStr.str());
736 
737  // Sanity check
738  assert (lAirlineClassListList.size() == lProportionFactorList.size());
739 
740  STDAIR_LOG_DEBUG ("Forecast for " << iOnDDate.describeKey()
741  << " " << iDTD << " days to departure");
742 
743  // store the forecast demand to come characteristics in the booking classes
744  stdair::ProportionFactorList_T::const_iterator itPF =
745  lProportionFactorList.begin();
746  itACL = lAirlineClassListList.begin();
747  for (; itACL != lAirlineClassListList.end(); ++itACL, ++itPF) {
748  const stdair::AirlineClassList* lAirlineClassList_ptr = *itACL;
749  const stdair::ProportionFactor_T& lProportionFactor = *itPF;
750  stdair::MeanValue_T lMeanValue = lProportionFactor*lRemainingMeanValue;
751  stdair::StdDevValue_T lStdDevValue =
752  lProportionFactor*lRemainingStdDevValue;
753  setOnDForecast(*lAirlineClassList_ptr, lMeanValue, lStdDevValue,
754  iOnDDate, iCabinCode, iBomRoot);
755  }
756 
757  }
758 
759  // ///////////////////////////////////////////////////////////////////
760  void RMOL_Service::
761  setOnDForecast (const stdair::AirlineClassList& iAirlineClassList,
762  const stdair::MeanValue_T& iMeanValue,
763  const stdair::StdDevValue_T& iStdDevValue,
764  stdair::OnDDate& iOnDDate,
765  const stdair::CabinCode_T& iCabinCode,
766  stdair::BomRoot& iBomRoot) {
767 
768  const stdair::AirportCode_T& lOrigin = iOnDDate.getOrigin();
769  const stdair::AirportCode_T& lDestination = iOnDDate.getDestination();
770 
771  const stdair::Date_T& lDepartureDate = iOnDDate.getDate();
772 
773  const stdair::AirlineCodeList_T& lAirlineCodeList =
774  iAirlineClassList.getAirlineCodeList();
775 
776  // Retrieve the class list (one class per airline)
777  const stdair::ClassList_StringList_T& lClassList_StringList =
778  iAirlineClassList.getClassCodeList();
779  assert (!lClassList_StringList.empty());
780  stdair::ClassCodeList_T lClassCodeList;
781  for (stdair::ClassList_StringList_T::const_iterator itCL =
782  lClassList_StringList.begin();
783  itCL != lClassList_StringList.end(); ++itCL){
784  const stdair::ClassList_String_T& lClassList_String = *itCL;
785  assert (lClassList_String.size() > 0);
786  stdair::ClassCode_T lFirstClass;
787  lFirstClass.append (lClassList_String, 0, 1);
788  lClassCodeList.push_back(lFirstClass);
789  }
790 
791  // Sanity check
792  assert (lAirlineCodeList.size() == lClassCodeList.size());
793  assert (!lAirlineCodeList.empty());
794 
795  if (lAirlineCodeList.size() == 1) {
796  // Store the forecast information in the case of a single segment
797  stdair::AirlineCode_T lAirlineCode = lAirlineCodeList.front();
798  stdair::ClassCode_T lClassCode = lClassCodeList.front();
799  stdair::Yield_T lYield = iAirlineClassList.getYield();
800  setOnDForecast(lAirlineCode, lDepartureDate, lOrigin,
801  lDestination, iCabinCode, lClassCode,
802  iMeanValue, iStdDevValue, lYield, iBomRoot);
803  } else {
804  // Store the forecast information in the case of a multiple segment
805 
806  stdair::Yield_T lYield = iAirlineClassList.getYield();
807  for (stdair::AirlineCodeList_T::const_iterator itAC =
808  lAirlineCodeList.begin();
809  itAC != lAirlineCodeList.end(); ++itAC) {
810  const stdair::AirlineCode_T& lAirlineCode = *itAC;
811  setOnDForecast(lAirlineCodeList, lAirlineCode, lDepartureDate, lOrigin,
812  lDestination, iCabinCode, lClassCodeList,
813  iMeanValue, iStdDevValue, lYield, iBomRoot);
814  }
815  }
816  }
817 
818  // ///////////////////////////////////////////////////////////////////
819  void RMOL_Service::
820  setOnDForecast (const stdair::AirlineCode_T& iAirlineCode,
821  const stdair::Date_T& iDepartureDate,
822  const stdair::AirportCode_T& iOrigin,
823  const stdair::AirportCode_T& iDestination,
824  const stdair::CabinCode_T& iCabinCode,
825  const stdair::ClassCode_T& iClassCode,
826  const stdair::MeanValue_T& iMeanValue,
827  const stdair::StdDevValue_T& iStdDevValue,
828  const stdair::Yield_T& iYield,
829  stdair::BomRoot& iBomRoot) {
830  stdair::Inventory* lInventory_ptr = iBomRoot.getInventory(iAirlineCode);
831  if (lInventory_ptr == NULL) {
832  STDAIR_LOG_ERROR ("Cannot find the inventory corresponding"
833  << " to the airline" << iAirlineCode) ;
834  assert(false);
835  }
836  const stdair::OnDDateList_T lOnDDateList =
837  stdair::BomManager::getList<stdair::OnDDate> (*lInventory_ptr);
838  assert (!lOnDDateList.empty());
839  bool lFoundOnDDate = false;
840  for (stdair::OnDDateList_T::const_iterator itOD = lOnDDateList.begin();
841  itOD != lOnDDateList.end(); ++itOD) {
842  stdair::OnDDate* lOnDDate_ptr = *itOD;
843  assert (lOnDDate_ptr != NULL);
844  const stdair::Date_T& lDepartureDate = lOnDDate_ptr->getDate();
845  const stdair::AirportCode_T& lOrigin = lOnDDate_ptr->getOrigin();
846  const stdair::AirportCode_T& lDestination = lOnDDate_ptr->getDestination();
847  if (!stdair::BomManager::hasList<stdair::SegmentDate> (*lOnDDate_ptr)) {
848  STDAIR_LOG_ERROR ("The O&D date " << lOnDDate_ptr->describeKey()
849  << "has not been correctly initialized : SegmentDate list is missing");
850  assert (false);
851  }
852  const stdair::SegmentDateList_T& lSegmentDateList =
853  stdair::BomManager::getList<stdair::SegmentDate> (*lOnDDate_ptr);
854  // Check if the the O&D date is the one we are looking for
855  if (lDepartureDate == iDepartureDate && lOrigin == iOrigin &&
856  lDestination == iDestination && lSegmentDateList.size() == 1) {
857  stdair::CabinClassPair_T lCabinClassPair (iCabinCode, iClassCode);
858  stdair::CabinClassPairList_T lCabinClassPairList;
859  lCabinClassPairList.push_back(lCabinClassPair);
860  const stdair::MeanStdDevPair_T lMeanStdDevPair (iMeanValue, iStdDevValue);
861  const stdair::WTPDemandPair_T lWTPDemandPair (iYield, lMeanStdDevPair);
862  lOnDDate_ptr->setDemandInformation(lCabinClassPairList, lWTPDemandPair);
863  lFoundOnDDate = true;
864  STDAIR_LOG_DEBUG (iAirlineCode << " Class " << iClassCode
865  << " Mean " << iMeanValue
866  << " Std Dev " << iStdDevValue);
867  break;
868  }
869  }
870 
871  if (!lFoundOnDDate) {
872  STDAIR_LOG_ERROR ("Cannot find class " << iClassCode << " in cabin "
873  << iCabinCode << " for the segment "
874  << iOrigin << "-" << iDestination << " with"
875  << " the airline " << iAirlineCode);
876  assert(false);
877  }
878  }
879 
880  // ///////////////////////////////////////////////////////////////////
881  void RMOL_Service::
882  setOnDForecast (const stdair::AirlineCodeList_T& iAirlineCodeList,
883  const stdair::AirlineCode_T& iAirlineCode,
884  const stdair::Date_T& iDepartureDate,
885  const stdair::AirportCode_T& iOrigin,
886  const stdair::AirportCode_T& iDestination,
887  const stdair::CabinCode_T& iCabinCode,
888  const stdair::ClassCodeList_T& iClassCodeList,
889  const stdair::MeanValue_T& iMeanValue,
890  const stdair::StdDevValue_T& iStdDevValue,
891  const stdair::Yield_T& iYield,
892  stdair::BomRoot& iBomRoot) {
893  stdair::Inventory* lInventory_ptr = iBomRoot.getInventory(iAirlineCode);
894  if (lInventory_ptr == NULL) {
895  STDAIR_LOG_ERROR ("Cannot find the inventory corresponding"
896  << " to the airline" << iAirlineCode) ;
897  assert(false);
898  }
899  const stdair::OnDDateList_T lOnDDateList =
900  stdair::BomManager::getList<stdair::OnDDate> (*lInventory_ptr);
901  assert (!lOnDDateList.empty());
902  bool lFoundOnDDate = false;
903  for (stdair::OnDDateList_T::const_iterator itOD = lOnDDateList.begin();
904  itOD != lOnDDateList.end(); ++itOD) {
905  stdair::OnDDate* lOnDDate_ptr = *itOD;
906  assert (lOnDDate_ptr != NULL);
907  const stdair::Date_T& lDepartureDate = lOnDDate_ptr->getDate();
908  const stdair::AirportCode_T& lOrigin = lOnDDate_ptr->getOrigin();
909  const stdair::AirportCode_T& lDestination = lOnDDate_ptr->getDestination();
910  if (!stdair::BomManager::hasList<stdair::SegmentDate> (*lOnDDate_ptr)) {
911  STDAIR_LOG_ERROR ("The O&D date " << lOnDDate_ptr->describeKey()
912  << "has not been correctly initialized : SegmentDate list is missing");
913  assert (false);
914  }
915  const stdair::SegmentDateList_T& lSegmentDateList =
916  stdair::BomManager::getList<stdair::SegmentDate> (*lOnDDate_ptr);
917  // Check if the O&D date might be the one we are looking for.
918  // There still is a test to go through to see if the combination of airlines is right.
919  if (lDepartureDate == iDepartureDate && lOrigin == iOrigin &&
920  lDestination == iDestination && lSegmentDateList.size() == iAirlineCodeList.size()) {
921  const stdair::SegmentDateList_T& lSegmentDateList =
922  stdair::BomManager::getList<stdair::SegmentDate> (*lOnDDate_ptr);
923  stdair::AirlineCodeList_T::const_iterator itAC = iAirlineCodeList.begin();
924  stdair::SegmentDateList_T::const_iterator itSD = lSegmentDateList.begin();
925  for (;itAC != iAirlineCodeList.end(); ++itAC, ++itSD) {
926  const stdair::AirlineCode_T lForecastAirlineCode = *itAC;
927  const stdair::SegmentDate* lSegmentDate_ptr = *itSD;
928  // Check if the operating airline is a different one and check if it
929  // is the airline that we are looking for.
930  const stdair::SegmentDate* lOperatingSegmentDate_ptr =
931  lSegmentDate_ptr->getOperatingSegmentDate ();
932  if (lOperatingSegmentDate_ptr != NULL) {
933  const stdair::FlightDate* lOperatingFD_ptr =
934  stdair::BomManager::getParentPtr<stdair::FlightDate>(*lOperatingSegmentDate_ptr);
935  const stdair::AirlineCode_T lOperatingAirlineCode =
936  lOperatingFD_ptr->getAirlineCode();
937  if (lOperatingAirlineCode != lForecastAirlineCode) {
938  break;
939  }
940  } else {
941  const stdair::AirlineCode_T lOperatingAirlineCode =
942  lOnDDate_ptr->getAirlineCode();
943  if (lOperatingAirlineCode != lForecastAirlineCode) {
944  break;
945  }
946  }
947  }
948  if (itAC == iAirlineCodeList.end()) {lFoundOnDDate = true;}
949  }
950  if (lFoundOnDDate) {
951  stdair::CabinClassPairList_T lCabinClassPairList;
952  for (stdair::ClassCodeList_T::const_iterator itCC = iClassCodeList.begin();
953  itCC != iClassCodeList.end(); ++itCC) {
954  const stdair::ClassCode_T lClassCode = *itCC;
955  stdair::CabinClassPair_T lCabinClassPair (iCabinCode, lClassCode);
956  lCabinClassPairList.push_back(lCabinClassPair);
957  }
958  const stdair::MeanStdDevPair_T lMeanStdDevPair (iMeanValue, iStdDevValue);
959  const stdair::YieldDemandPair_T lYieldDemandPair (iYield, lMeanStdDevPair);
960  lOnDDate_ptr->setDemandInformation(lCabinClassPairList, lYieldDemandPair);
961  lFoundOnDDate = true;
962  std::ostringstream oACStr;
963  for (stdair::AirlineCodeList_T::const_iterator itAC = iAirlineCodeList.begin();
964  itAC != iAirlineCodeList.end(); ++itAC) {
965  if (itAC == iAirlineCodeList.begin()) {
966  oACStr << *itAC;
967  }
968  else {
969  oACStr << "-" << *itAC;
970  }
971  }
972  std::ostringstream oCCStr;
973  for (stdair::ClassCodeList_T::const_iterator itCC = iClassCodeList.begin();
974  itCC != iClassCodeList.end(); ++itCC) {
975  if (itCC == iClassCodeList.begin()) {
976  oCCStr << *itCC;
977  }
978  else {
979  oCCStr << "-" << *itCC;
980  }
981  }
982 
983  STDAIR_LOG_DEBUG (oACStr.str() << " Classes " << oCCStr.str()
984  << " Mean " << iMeanValue << " Std Dev " << iStdDevValue);
985  break;
986  }
987  }
988  if (!lFoundOnDDate) {
989  STDAIR_LOG_ERROR ("Cannot find the required multi-segment O&D date: "
990  << iOrigin << "-" << iDestination << " " << iDepartureDate);
991  assert(false);
992  }
993  }
994 
995  // ///////////////////////////////////////////////////////////////////
996  void RMOL_Service::
997  resetDemandInformation (const stdair::DateTime_T& iRMEventTime) {
998  if (_rmolServiceContext == NULL) {
999  throw stdair::NonInitialisedServiceException ("The Rmol service "
1000  "has not been initialised");
1001  }
1002  assert (_rmolServiceContext != NULL);
1003  RMOL_ServiceContext& lRMOL_ServiceContext = *_rmolServiceContext;
1004 
1005  // Retrieve the bom root
1006  stdair::STDAIR_Service& lSTDAIR_Service =
1007  lRMOL_ServiceContext.getSTDAIR_Service();
1008  stdair::BomRoot& lBomRoot = lSTDAIR_Service.getBomRoot();
1009 
1010  const stdair::InventoryList_T lInventoryList =
1011  stdair::BomManager::getList<stdair::Inventory> (lBomRoot);
1012  assert (!lInventoryList.empty());
1013  for (stdair::InventoryList_T::const_iterator itInv = lInventoryList.begin();
1014  itInv != lInventoryList.end(); ++itInv) {
1015  const stdair::Inventory* lInventory_ptr = *itInv;
1016  assert (lInventory_ptr != NULL);
1017  resetDemandInformation (iRMEventTime, *lInventory_ptr);
1018  }
1019  }
1020 
1021  // ///////////////////////////////////////////////////////////////////
1022  void RMOL_Service::
1023  resetDemandInformation (const stdair::DateTime_T& iRMEventTime,
1024  const stdair::Inventory& iInventory) {
1025 
1026  const stdair::FlightDateList_T lFlightDateList =
1027  stdair::BomManager::getList<stdair::FlightDate> (iInventory);
1028  assert (!lFlightDateList.empty());
1029  for (stdair::FlightDateList_T::const_iterator itFD = lFlightDateList.begin();
1030  itFD != lFlightDateList.end(); ++itFD) {
1031  const stdair::FlightDate* lFlightDate_ptr = *itFD;
1032  assert (lFlightDate_ptr != NULL);
1033 
1034  // Retrieve the date from the RM event
1035  const stdair::Date_T lDate = iRMEventTime.date();
1036 
1037  const stdair::Date_T& lDepartureDate = lFlightDate_ptr->getDepartureDate();
1038  stdair::DateOffset_T lDateOffset = lDepartureDate - lDate;
1039  stdair::DTD_T lDTD = short (lDateOffset.days());
1040 
1041  stdair::DCPList_T::const_iterator itDCP =
1042  std::find (stdair::DEFAULT_DCP_LIST.begin(), stdair::DEFAULT_DCP_LIST.end(), lDTD);
1043  // Check if the demand forecast info corresponding to this flight date needs to be reset.
1044  if (itDCP != stdair::DEFAULT_DCP_LIST.end()) {
1045  // Check if the flight date holds a list of leg dates.
1046  // If so, find all leg cabin and reset the forecast they are holding.
1047  if (stdair::BomManager::hasList<stdair::LegDate> (*lFlightDate_ptr)) {
1048  const stdair::LegDateList_T lLegDateList =
1049  stdair::BomManager::getList<stdair::LegDate> (*lFlightDate_ptr);
1050  assert (!lLegDateList.empty());
1051  for (stdair::LegDateList_T::const_iterator itLD = lLegDateList.begin();
1052  itLD != lLegDateList.end(); ++itLD) {
1053  const stdair::LegDate* lLegDate_ptr = *itLD;
1054  assert (lLegDate_ptr != NULL);
1055  const stdair::LegCabinList_T lLegCabinList =
1056  stdair::BomManager::getList<stdair::LegCabin> (*lLegDate_ptr);
1057  assert (!lLegCabinList.empty());
1058  for (stdair::LegCabinList_T::const_iterator itLC = lLegCabinList.begin();
1059  itLC != lLegCabinList.end(); ++itLC) {
1060  stdair::LegCabin* lLegCabin_ptr = *itLC;
1061  assert (lLegCabin_ptr != NULL);
1062  lLegCabin_ptr->emptyYieldLevelDemandMap();
1063  }
1064  }
1065  }
1066  }
1067  }
1068  }
1069 
1070  // ///////////////////////////////////////////////////////////////////
1071  void RMOL_Service::projectAggregatedDemandOnLegCabins(const stdair::DateTime_T& iRMEventTime) {
1072 
1073  if (_rmolServiceContext == NULL) {
1074  throw stdair::NonInitialisedServiceException ("The Rmol service "
1075  "has not been initialised");
1076  }
1077  assert (_rmolServiceContext != NULL);
1078  RMOL_ServiceContext& lRMOL_ServiceContext = *_rmolServiceContext;
1079 
1080  // Retrieve the bom root
1081  stdair::STDAIR_Service& lSTDAIR_Service =
1082  lRMOL_ServiceContext.getSTDAIR_Service();
1083  stdair::BomRoot& lBomRoot = lSTDAIR_Service.getBomRoot();
1084 
1085  // Retrieve the date from the RM event
1086  const stdair::Date_T lDate = iRMEventTime.date();
1087 
1088  const stdair::InventoryList_T lInventoryList =
1089  stdair::BomManager::getList<stdair::Inventory> (lBomRoot);
1090  assert (!lInventoryList.empty());
1091  for (stdair::InventoryList_T::const_iterator itInv = lInventoryList.begin();
1092  itInv != lInventoryList.end(); ++itInv) {
1093  const stdair::Inventory* lInventory_ptr = *itInv;
1094  assert (lInventory_ptr != NULL);
1095  const stdair::OnDDateList_T lOnDDateList =
1096  stdair::BomManager::getList<stdair::OnDDate> (*lInventory_ptr);
1097  assert (!lOnDDateList.empty());
1098  for (stdair::OnDDateList_T::const_iterator itOD = lOnDDateList.begin();
1099  itOD != lOnDDateList.end(); ++itOD) {
1100  stdair::OnDDate* lOnDDate_ptr = *itOD;
1101  assert (lOnDDate_ptr != NULL);
1102 
1103  const stdair::Date_T& lDepartureDate = lOnDDate_ptr->getDate();
1104  stdair::DateOffset_T lDateOffset = lDepartureDate - lDate;
1105  stdair::DTD_T lDTD = short (lDateOffset.days());
1106 
1107  stdair::DCPList_T::const_iterator itDCP =
1108  std::find (stdair::DEFAULT_DCP_LIST.begin(), stdair::DEFAULT_DCP_LIST.end(), lDTD);
1109  // Check if the forecast for this O&D date needs to be projected.
1110  if (itDCP != stdair::DEFAULT_DCP_LIST.end()) {
1111 
1112  // Browse the demand info map.
1113  const stdair::StringDemandStructMap_T& lStringDemandStructMap =
1114  lOnDDate_ptr->getDemandInfoMap ();
1115  for (stdair::StringDemandStructMap_T::const_iterator itStrDS = lStringDemandStructMap.begin();
1116  itStrDS != lStringDemandStructMap.end(); ++itStrDS) {
1117  std::string lCabinClassPath = itStrDS->first;
1118  const stdair::YieldDemandPair_T& lYieldDemandPair =
1119  itStrDS->second;
1120  const stdair::CabinClassPairList_T& lCabinClassPairList =
1121  lOnDDate_ptr->getCabinClassPairList(lCabinClassPath);
1122  const unsigned int lNbOfSegments = lOnDDate_ptr->getNbOfSegments();
1123  // Sanity check
1124  assert (lCabinClassPairList.size() == lNbOfSegments);
1125 
1126  const stdair::SegmentDateList_T lOnDSegmentDateList =
1127  stdair::BomManager::getList<stdair::SegmentDate> (*lOnDDate_ptr);
1128  // Sanity check
1129  assert (lOnDSegmentDateList.size() == lNbOfSegments);
1130  stdair::CabinClassPairList_T::const_iterator itCCP = lCabinClassPairList.begin();
1131  stdair::SegmentDateList_T::const_iterator itSD = lOnDSegmentDateList.begin();
1132  for (; itSD != lOnDSegmentDateList.end(); ++itCCP, ++itSD) {
1133  const stdair::SegmentDate* lSegmentDate_ptr = *itSD;
1134  const stdair::SegmentDate* lOperatingSegmentDate_ptr =
1135  lSegmentDate_ptr->getOperatingSegmentDate ();
1136  assert (lSegmentDate_ptr != NULL);
1137  // Only operated legs receive the demand information.
1138  if (lOperatingSegmentDate_ptr == NULL) {
1139  const stdair::CabinCode_T lCabinCode = itCCP->first;
1140  const stdair::ClassCode_T lClassCode = itCCP->second;
1141  const stdair::SegmentCabin* lSegmentCabin_ptr =
1142  stdair::BomManager::getObjectPtr<stdair::SegmentCabin> (*lSegmentDate_ptr,
1143  lCabinCode);
1144  assert (lSegmentCabin_ptr != NULL);
1145  // Retrieve the booking class (level of aggregation of demand).
1146  // The yield of the class is assigned to all types of demand for it.
1147  const stdair::BookingClass* lBookingClass_ptr =
1148  stdair::BomManager::getObjectPtr<stdair::BookingClass> (*lSegmentCabin_ptr,
1149  lClassCode);
1150  assert (lBookingClass_ptr != NULL);
1151  const stdair::LegCabinList_T lLegCabinList =
1152  stdair::BomManager::getList<stdair::LegCabin> (*lSegmentCabin_ptr);
1153  assert (!lLegCabinList.empty());
1154  const int lNbOfLegs = lLegCabinList.size();
1155  // Determine the yield (equally distributed over legs).
1156  const stdair::Yield_T& lYield = lBookingClass_ptr->getYield()/lNbOfLegs;
1157  const stdair::MeanStdDevPair_T& lMeanStdDevPair =
1158  lYieldDemandPair.second;
1159  const stdair::MeanValue_T& lMeanValue = lMeanStdDevPair.first;
1160  const stdair::StdDevValue_T& lStdDevValue = lMeanStdDevPair.second;
1161  for (stdair::LegCabinList_T::const_iterator itLC = lLegCabinList.begin();
1162  itLC != lLegCabinList.end(); ++itLC) {
1163  stdair::LegCabin* lLegCabin_ptr = *itLC;
1164  assert (lLegCabin_ptr != NULL);
1165  lLegCabin_ptr->addDemandInformation (lYield, lMeanValue, lStdDevValue);
1166  }
1167  }
1168  }
1169  }
1170  }
1171  }
1172  }
1173  }
1174 
1175  // ///////////////////////////////////////////////////////////////////
1176  void RMOL_Service::projectOnDDemandOnLegCabinsUsingYP(const stdair::DateTime_T& iRMEventTime) {
1177 
1178  if (_rmolServiceContext == NULL) {
1179  throw stdair::NonInitialisedServiceException ("The Rmol service "
1180  "has not been initialised");
1181  }
1182  assert (_rmolServiceContext != NULL);
1183  RMOL_ServiceContext& lRMOL_ServiceContext = *_rmolServiceContext;
1184 
1185  // Retrieve the bom root
1186  stdair::STDAIR_Service& lSTDAIR_Service =
1187  lRMOL_ServiceContext.getSTDAIR_Service();
1188  stdair::BomRoot& lBomRoot = lSTDAIR_Service.getBomRoot();
1189 
1190  // Retrieve the date from the RM event
1191  const stdair::Date_T lDate = iRMEventTime.date();
1192 
1193  const stdair::InventoryList_T lInventoryList =
1194  stdair::BomManager::getList<stdair::Inventory> (lBomRoot);
1195  assert (!lInventoryList.empty());
1196  for (stdair::InventoryList_T::const_iterator itInv = lInventoryList.begin();
1197  itInv != lInventoryList.end(); ++itInv) {
1198  const stdair::Inventory* lInventory_ptr = *itInv;
1199  assert (lInventory_ptr != NULL);
1200  const stdair::OnDDateList_T lOnDDateList =
1201  stdair::BomManager::getList<stdair::OnDDate> (*lInventory_ptr);
1202  assert (!lOnDDateList.empty());
1203  for (stdair::OnDDateList_T::const_iterator itOD = lOnDDateList.begin();
1204  itOD != lOnDDateList.end(); ++itOD) {
1205  stdair::OnDDate* lOnDDate_ptr = *itOD;
1206  assert (lOnDDate_ptr != NULL);
1207 
1208  const stdair::Date_T& lDepartureDate = lOnDDate_ptr->getDate();
1209  stdair::DateOffset_T lDateOffset = lDepartureDate - lDate;
1210  stdair::DTD_T lDTD = short (lDateOffset.days());
1211 
1212  stdair::DCPList_T::const_iterator itDCP =
1213  std::find (stdair::DEFAULT_DCP_LIST.begin(), stdair::DEFAULT_DCP_LIST.end(), lDTD);
1214  // Check if the forecast for this O&D date needs to be projected.
1215  if (itDCP != stdair::DEFAULT_DCP_LIST.end()) {
1216 
1217  // Browse the demand info map.
1218  const stdair::StringDemandStructMap_T& lStringDemandStructMap =
1219  lOnDDate_ptr->getDemandInfoMap ();
1220  for (stdair::StringDemandStructMap_T::const_iterator itStrDS = lStringDemandStructMap.begin();
1221  itStrDS != lStringDemandStructMap.end(); ++itStrDS) {
1222  std::string lCabinClassPath = itStrDS->first;
1223  const stdair::YieldDemandPair_T& lYieldDemandPair =
1224  itStrDS->second;
1225  const stdair::CabinClassPairList_T& lCabinClassPairList =
1226  lOnDDate_ptr->getCabinClassPairList(lCabinClassPath);
1227  const unsigned int lNbOfSegments = lOnDDate_ptr->getNbOfSegments();
1228  // Sanity check
1229  assert (lCabinClassPairList.size() == lNbOfSegments);
1230 
1231  const stdair::SegmentDateList_T lOnDSegmentDateList =
1232  stdair::BomManager::getList<stdair::SegmentDate> (*lOnDDate_ptr);
1233  // Sanity check
1234  assert (lOnDSegmentDateList.size() == lNbOfSegments);
1235  stdair::CabinClassPairList_T::const_iterator itCCP = lCabinClassPairList.begin();
1236  stdair::SegmentDateList_T::const_iterator itSD = lOnDSegmentDateList.begin();
1237  for (; itSD != lOnDSegmentDateList.end(); ++itCCP, ++itSD) {
1238  const stdair::SegmentDate* lSegmentDate_ptr = *itSD;
1239  assert (lSegmentDate_ptr != NULL);
1240  const stdair::SegmentDate* lOperatingSegmentDate_ptr =
1241  lSegmentDate_ptr->getOperatingSegmentDate ();
1242  // Only operated legs receive the demand information.
1243  if (lOperatingSegmentDate_ptr == NULL) {
1244  const stdair::CabinCode_T lCabinCode = itCCP->first;
1245  const stdair::ClassCode_T lClassCode = itCCP->second;
1246  const stdair::SegmentCabin* lSegmentCabin_ptr =
1247  stdair::BomManager::getObjectPtr<stdair::SegmentCabin> (*lSegmentDate_ptr,
1248  lCabinCode);
1249  assert (lSegmentCabin_ptr != NULL);
1250  const stdair::LegCabinList_T lLegCabinList =
1251  stdair::BomManager::getList<stdair::LegCabin> (*lSegmentCabin_ptr);
1252  assert (!lLegCabinList.empty());
1253  const int lNbOfLegs = lLegCabinList.size();
1254  // Determine the yield (equally distributed over segments and then legs).
1255  const stdair::MeanStdDevPair_T& lMeanStdDevPair =
1256  lYieldDemandPair.second;
1257  const stdair::Yield_T& lYield = lYieldDemandPair.first/(lNbOfLegs*lNbOfSegments);
1258  const stdair::MeanValue_T& lMeanValue = lMeanStdDevPair.first;
1259  const stdair::StdDevValue_T& lStdDevValue = lMeanStdDevPair.second;
1260  for (stdair::LegCabinList_T::const_iterator itLC = lLegCabinList.begin();
1261  itLC != lLegCabinList.end(); ++itLC) {
1262  stdair::LegCabin* lLegCabin_ptr = *itLC;
1263  assert (lLegCabin_ptr != NULL);
1264  lLegCabin_ptr->addDemandInformation (lYield, lMeanValue, lStdDevValue);
1265  }
1266  }
1267  }
1268  }
1269  }
1270  }
1271  }
1272  }
1273 
1274  // ///////////////////////////////////////////////////////////////////
1275  void RMOL_Service::optimiseOnD (const stdair::DateTime_T& iRMEventTime) {
1276 
1277  if (_rmolServiceContext == NULL) {
1278  throw stdair::NonInitialisedServiceException ("The Rmol service "
1279  "has not been initialised");
1280  }
1281  assert (_rmolServiceContext != NULL);
1282  RMOL_ServiceContext& lRMOL_ServiceContext = *_rmolServiceContext;
1283 
1284  // Retrieve the bom root
1285  stdair::STDAIR_Service& lSTDAIR_Service =
1286  lRMOL_ServiceContext.getSTDAIR_Service();
1287  stdair::BomRoot& lBomRoot = lSTDAIR_Service.getBomRoot();
1288 
1289  // Retrieve the date from the RM event
1290  const stdair::Date_T lDate = iRMEventTime.date();
1291 
1292  const stdair::InventoryList_T& lInvList =
1293  stdair::BomManager::getList<stdair::Inventory> (lBomRoot);
1294  for (stdair::InventoryList_T::const_iterator itInv = lInvList.begin();
1295  itInv != lInvList.end(); ++itInv) {
1296  stdair::Inventory* lCurrentInv_ptr = *itInv;
1297  assert (lCurrentInv_ptr != NULL);
1298 
1299  const stdair::FlightDateList_T& lFlightDateList =
1300  stdair::BomManager::getList<stdair::FlightDate> (*lCurrentInv_ptr);
1301  for (stdair::FlightDateList_T::const_iterator itFlightDate =
1302  lFlightDateList.begin();
1303  itFlightDate != lFlightDateList.end(); ++itFlightDate) {
1304  stdair::FlightDate* lCurrentFlightDate_ptr = *itFlightDate;
1305  assert (lCurrentFlightDate_ptr != NULL);
1306 
1307  const stdair::Date_T& lCurrentDepartureDate = lCurrentFlightDate_ptr->getDepartureDate();
1308  stdair::DateOffset_T lDateOffset = lCurrentDepartureDate - lDate;
1309  stdair::DTD_T lDTD = short (lDateOffset.days());
1310 
1311  stdair::DCPList_T::const_iterator itDCP =
1312  std::find (stdair::DEFAULT_DCP_LIST.begin(), stdair::DEFAULT_DCP_LIST.end(), lDTD);
1313  // Check if the optimisation is needed.
1314  if (itDCP != stdair::DEFAULT_DCP_LIST.end()) {
1315  STDAIR_LOG_DEBUG ("Optimisation using O&D forecast: " << lCurrentInv_ptr->getAirlineCode()
1316  << " Departure " << lCurrentDepartureDate << " DTD " << lDTD);
1317  Optimiser::optimiseUsingOnDForecast (*lCurrentFlightDate_ptr);
1318  }
1319  }
1320  }
1321  }
1322 
1323  // ///////////////////////////////////////////////////////////////////
1324  void RMOL_Service::updateBidPrice (const stdair::DateTime_T& iRMEventTime) {
1325 
1326  if (_rmolServiceContext == NULL) {
1327  throw stdair::NonInitialisedServiceException ("The Rmol service "
1328  "has not been initialised");
1329  }
1330  assert (_rmolServiceContext != NULL);
1331  RMOL_ServiceContext& lRMOL_ServiceContext = *_rmolServiceContext;
1332 
1333  // Retrieve the bom root
1334  stdair::STDAIR_Service& lSTDAIR_Service =
1335  lRMOL_ServiceContext.getSTDAIR_Service();
1336  stdair::BomRoot& lBomRoot = lSTDAIR_Service.getBomRoot();
1337 
1338  // Retrieve the date from the RM event
1339  const stdair::Date_T lDate = iRMEventTime.date();
1340 
1341  const stdair::InventoryList_T& lInvList =
1342  stdair::BomManager::getList<stdair::Inventory> (lBomRoot);
1343 
1344  for (stdair::InventoryList_T::const_iterator itInv = lInvList.begin();
1345  itInv != lInvList.end(); ++itInv) {
1346  stdair::Inventory* lCurrentInv_ptr = *itInv;
1347  assert (lCurrentInv_ptr != NULL);
1348 
1349  const stdair::FlightDateList_T& lFlightDateList =
1350  stdair::BomManager::getList<stdair::FlightDate> (*lCurrentInv_ptr);
1351  for (stdair::FlightDateList_T::const_iterator itFlightDate =
1352  lFlightDateList.begin();
1353  itFlightDate != lFlightDateList.end(); ++itFlightDate) {
1354  stdair::FlightDate* lCurrentFlightDate_ptr = *itFlightDate;
1355  assert (lCurrentFlightDate_ptr != NULL);
1356 
1357  const stdair::Date_T& lCurrentDepartureDate = lCurrentFlightDate_ptr->getDepartureDate();
1358  stdair::DateOffset_T lDateOffset = lCurrentDepartureDate - lDate;
1359  stdair::DTD_T lDTD = short (lDateOffset.days());
1360 
1361  stdair::DCPList_T::const_iterator itDCP =
1362  std::find (stdair::DEFAULT_DCP_LIST.begin(), stdair::DEFAULT_DCP_LIST.end(), lDTD);
1363  // Check if the operation is needed.
1364  if (itDCP != stdair::DEFAULT_DCP_LIST.end()) {
1365  updateBidPrice (*lCurrentFlightDate_ptr, lBomRoot);
1366  }
1367  }
1368  }
1369  }
1370 
1371  // ///////////////////////////////////////////////////////////////////
1372  void RMOL_Service::updateBidPrice (const stdair::FlightDate& iFlightDate,
1373  stdair::BomRoot& iBomRoot) {
1374  const stdair::SegmentDateList_T& lSegmentDateList =
1375  stdair::BomManager::getList<stdair::SegmentDate> (iFlightDate);
1376  const stdair::AirlineCode_T& lOptAC = iFlightDate.getAirlineCode();
1377  const std::string lFDKeyStr = iFlightDate.describeKey();
1378 
1379  for (stdair::SegmentDateList_T::const_iterator itSegmentDate = lSegmentDateList.begin();
1380  itSegmentDate != lSegmentDateList.end(); ++itSegmentDate) {
1381  stdair::SegmentDate* lSegmentDate_ptr = *itSegmentDate;
1382  assert (lSegmentDate_ptr != NULL);
1383  if (stdair::BomManager::hasList<stdair::SegmentDate>(*lSegmentDate_ptr)) {
1384  const stdair::LegDateList_T& lLegDateList =
1385  stdair::BomManager::getList<stdair::LegDate>(*lSegmentDate_ptr);
1386  // Get the list of marketing carriers segments.
1387  // These are part of maketing partners inventories images held by the operating airline.
1388  const stdair::SegmentDateList_T& lMktSegmentDateList =
1389  stdair::BomManager::getList<stdair::SegmentDate>(*lSegmentDate_ptr);
1390  for (stdair::SegmentDateList_T::const_iterator itMktSD = lMktSegmentDateList.begin();
1391  itMktSD != lMktSegmentDateList.end(); ++itMktSD) {
1392  // Get the marketing airline code.
1393  stdair::SegmentDate* lMktSD_ptr = *itMktSD;
1394  assert (lMktSD_ptr != NULL);
1395  stdair::FlightDate* lMktFD_ptr =
1396  stdair::BomManager::getParentPtr<stdair::FlightDate>(*lMktSD_ptr);
1397  assert (lMktFD_ptr != NULL);
1398  const stdair::AirlineCode_T& lMktAC = lMktFD_ptr->getAirlineCode();
1399  // Get the (real) marketer inventory.
1400  const stdair::Inventory* lMktInv_ptr =
1401  stdair::BomManager::getObjectPtr<stdair::Inventory>(iBomRoot,lMktAC);
1402  assert (lMktInv_ptr != NULL);
1403  // Get the image of the operating airline inventory held by the marketer.
1404  const stdair::Inventory* lOptInv_ptr =
1405  stdair::BomManager::getObjectPtr<stdair::Inventory>(*lMktInv_ptr,lOptAC);
1406  assert (lOptInv_ptr != NULL);
1407  // Find the image of the concerned flight date.
1408  const stdair::FlightDate* lOptFD_ptr =
1409  stdair::BomManager::getObjectPtr<stdair::FlightDate>(*lOptInv_ptr,lFDKeyStr);
1410  assert (lOptFD_ptr != NULL);
1411  // Browse the list of leg dates in the real operating inventory.
1412  // Retrieve the image of each leg date.
1413  for (stdair::LegDateList_T::const_iterator itLD = lLegDateList.begin();
1414  itLD != lLegDateList.end(); ++itLD) {
1415  const stdair::LegDate* lLD_ptr = *itLD;
1416  assert (lLD_ptr != NULL);
1417  const std::string lLDKeyStr = lLD_ptr->describeKey();
1418  stdair::LegDate* lOptLD_ptr =
1419  stdair::BomManager::getObjectPtr<stdair::LegDate>(*lOptFD_ptr,lLDKeyStr);
1420  assert (lOptLD_ptr != NULL);
1421  const stdair::LegCabinList_T& lLegCabinList_T =
1422  stdair::BomManager::getList<stdair::LegCabin>(*lLD_ptr);
1423  // Browse the list of leg cabins in the real operating inventory.
1424  // Retrieve the image of each leg cabin and update the bid price of the real and send it to the image.
1425  for (stdair::LegCabinList_T::const_iterator itLC = lLegCabinList_T.begin();
1426  itLC != lLegCabinList_T.end(); ++itLC) {
1427  stdair::LegCabin* lLC_ptr = *itLC;
1428  assert (lLC_ptr != NULL);
1429  const std::string lLCKeyStr = lLC_ptr->describeKey();
1430  stdair::LegCabin* lOptLC_ptr =
1431  stdair::BomManager::getObjectPtr<stdair::LegCabin>(*lOptLD_ptr, lLCKeyStr);
1432  assert (lOptLC_ptr != NULL);
1433  // Update the current bid price of the real leg.
1434  lLC_ptr->updateCurrentBidPrice();
1435  // Update the previous bid price (store the current).
1436  lOptLC_ptr->updatePreviousBidPrice();
1437  // Update the current bid price.
1438  lOptLC_ptr->setCurrentBidPrice (lLC_ptr->getCurrentBidPrice());
1439 
1440  STDAIR_LOG_DEBUG ("Update bid price of " << lLC_ptr->getFullerKey()
1441  << " : " << lOptLC_ptr->getCurrentBidPrice()
1442  << " Availability pool " << lLC_ptr->getAvailabilityPool());
1443  }
1444  }
1445  }
1446  }
1447  }
1448  }
1449 
1450  // ///////////////////////////////////////////////////////////////////
1451  void RMOL_Service::projectOnDDemandOnLegCabinsUsingDA(const stdair::DateTime_T& iRMEventTime) {
1452 
1453  if (_rmolServiceContext == NULL) {
1454  throw stdair::NonInitialisedServiceException ("The Rmol service "
1455  "has not been initialised");
1456  }
1457  assert (_rmolServiceContext != NULL);
1458  RMOL_ServiceContext& lRMOL_ServiceContext = *_rmolServiceContext;
1459 
1460  // Retrieve the bom root
1461  stdair::STDAIR_Service& lSTDAIR_Service =
1462  lRMOL_ServiceContext.getSTDAIR_Service();
1463  stdair::BomRoot& lBomRoot = lSTDAIR_Service.getBomRoot();
1464 
1465  // Retrieve the date from the RM event
1466  const stdair::Date_T lDate = iRMEventTime.date();
1467 
1468  const stdair::InventoryList_T lInventoryList =
1469  stdair::BomManager::getList<stdair::Inventory> (lBomRoot);
1470  assert (!lInventoryList.empty());
1471  for (stdair::InventoryList_T::const_iterator itInv = lInventoryList.begin();
1472  itInv != lInventoryList.end(); ++itInv) {
1473  const stdair::Inventory* lInventory_ptr = *itInv;
1474  assert (lInventory_ptr != NULL);
1475  const stdair::OnDDateList_T lOnDDateList =
1476  stdair::BomManager::getList<stdair::OnDDate> (*lInventory_ptr);
1477  assert (!lOnDDateList.empty());
1478  for (stdair::OnDDateList_T::const_iterator itOD = lOnDDateList.begin();
1479  itOD != lOnDDateList.end(); ++itOD) {
1480  stdair::OnDDate* lOnDDate_ptr = *itOD;
1481  assert (lOnDDate_ptr != NULL);
1482 
1483  const stdair::Date_T& lDepartureDate = lOnDDate_ptr->getDate();
1484  stdair::DateOffset_T lDateOffset = lDepartureDate - lDate;
1485  stdair::DTD_T lDTD = short (lDateOffset.days());
1486 
1487  stdair::DCPList_T::const_iterator itDCP =
1488  std::find (stdair::DEFAULT_DCP_LIST.begin(), stdair::DEFAULT_DCP_LIST.end(), lDTD);
1489  // Check if the forecast for this O&D date needs to be projected.
1490  if (itDCP != stdair::DEFAULT_DCP_LIST.end()) {
1491 
1492  // Browse the demand info map.
1493  const stdair::StringDemandStructMap_T& lStringDemandStructMap =
1494  lOnDDate_ptr->getDemandInfoMap ();
1495  for (stdair::StringDemandStructMap_T::const_iterator itStrDS = lStringDemandStructMap.begin();
1496  itStrDS != lStringDemandStructMap.end(); ++itStrDS) {
1497  std::string lCabinClassPath = itStrDS->first;
1498  const stdair::YieldDemandPair_T& lYieldDemandPair = itStrDS->second;
1499  const stdair::CabinClassPairList_T& lCabinClassPairList =
1500  lOnDDate_ptr->getCabinClassPairList(lCabinClassPath);
1501  const unsigned int lNbOfSegments = lOnDDate_ptr->getNbOfSegments();
1502  // Sanity check
1503  assert (lCabinClassPairList.size() == lNbOfSegments);
1504 
1505  //
1506  const stdair::SegmentDateList_T lOnDSegmentDateList =
1507  stdair::BomManager::getList<stdair::SegmentDate> (*lOnDDate_ptr);
1508  // Sanity check
1509  assert (lOnDSegmentDateList.size() == lNbOfSegments);
1510  stdair::CabinClassPairList_T::const_iterator itCCP = lCabinClassPairList.begin();
1511  stdair::SegmentDateList_T::const_iterator itSD = lOnDSegmentDateList.begin();
1512  // List of bid prices that will be used to easily compute displacement-ajusted yields.
1513  std::list<stdair::BidPrice_T> lBidPriceList;
1514  // The sum of bid prices that will be stored in the list above.
1515  stdair::BidPrice_T lTotalBidPrice = 0;
1516  // Retrieve the bid prices
1517  for (; itSD != lOnDSegmentDateList.end(); ++itCCP, ++itSD) {
1518  // Get the operating segment cabin (it holds the bid price information).
1519  const stdair::SegmentDate* lSegmentDate_ptr = *itSD;
1520  assert (lSegmentDate_ptr != NULL);
1521  // Get the operating airline code and check if it is the airline we are looking for.
1522  const stdair::SegmentDate* lOperatingSegmentDate_ptr =
1523  lSegmentDate_ptr->getOperatingSegmentDate ();
1524  if (lOperatingSegmentDate_ptr != NULL) {
1525  lSegmentDate_ptr = lOperatingSegmentDate_ptr;
1526  }
1527  const stdair::CabinCode_T lCabinCode = itCCP->first;
1528  const stdair::SegmentCabin* lSegmentCabin_ptr =
1529  stdair::BomManager::getObjectPtr<stdair::SegmentCabin> (*lSegmentDate_ptr,
1530  lCabinCode);
1531  assert (lSegmentCabin_ptr != NULL);
1532  stdair::BidPrice_T lBidPrice = 0;
1533  const stdair::LegCabinList_T lLegCabinList =
1534  stdair::BomManager::getList<stdair::LegCabin>(*lSegmentCabin_ptr);
1535  for (stdair::LegCabinList_T::const_iterator itLC = lLegCabinList.begin();
1536  itLC != lLegCabinList.end(); ++itLC) {
1537  const stdair::LegCabin* lLegCabin_ptr = *itLC;
1538  assert (lLegCabin_ptr != NULL);
1539  lBidPrice += lLegCabin_ptr->getCurrentBidPrice();
1540  }
1541  lBidPriceList.push_back (lBidPrice);
1542  lTotalBidPrice += lBidPrice;
1543  }
1544 
1545 
1546  itCCP = lCabinClassPairList.begin();
1547  itSD = lOnDSegmentDateList.begin();
1548  std::list<stdair::BidPrice_T>::const_iterator itBP = lBidPriceList.begin();
1549  for (; itSD != lOnDSegmentDateList.end(); ++itCCP, ++itSD, ++itBP) {
1550  stdair::BidPrice_T lBidPrice = *itBP;
1551  stdair::BidPrice_T lComplementaryBidPrice = lTotalBidPrice - lBidPrice;
1552  const stdair::SegmentDate* lSegmentDate_ptr = *itSD;
1553  assert (lSegmentDate_ptr != NULL);
1554  const stdair::SegmentDate* lOperatingSegmentDate_ptr =
1555  lSegmentDate_ptr->getOperatingSegmentDate ();
1556  // Only operated legs receive the demand information.
1557  if (lOperatingSegmentDate_ptr == NULL) {
1558  const stdair::CabinCode_T lCabinCode = itCCP->first;
1559  const stdair::ClassCode_T lClassCode = itCCP->second;
1560  const stdair::SegmentCabin* lSegmentCabin_ptr =
1561  stdair::BomManager::getObjectPtr<stdair::SegmentCabin> (*lSegmentDate_ptr,
1562  lCabinCode);
1563  assert (lSegmentCabin_ptr != NULL);
1564  const stdair::LegCabinList_T lLegCabinList =
1565  stdair::BomManager::getList<stdair::LegCabin> (*lSegmentCabin_ptr);
1566  assert (!lLegCabinList.empty());
1567  // Determine the displacement-adjusted yield.
1568  // It is set to 100 (positive small value), if the computed value is negative.
1569  const stdair::Yield_T& lDAYield =
1570  std::max(100., lYieldDemandPair.first - lComplementaryBidPrice);
1571 
1572 
1573  stdair::Yield_T lYield = lDAYield;
1574  // In order to be protected against important variations of partners' bid price,
1575  // the displacement adjusted yield is noy allowed to get out of a certain range.
1576  // This range is here chosen to be from 80% to 100% of the (static rule) prorated yield.
1577  /*
1578  const int lNbOfLegs = lLegCabinList.size();
1579  const stdair::Yield_T& lStaticProrationYield =
1580  lDemandStruct.getYield()/(lNbOfLegs*lNbOfSegments);
1581  if (lDAYield < 0.8*lStaticProrationYield){
1582  lYield = 0.8*lStaticProrationYield;
1583  }
1584  if (lDAYield > lStaticProrationYield) {
1585  lYield = lStaticProrationYield;
1586  }
1587  */
1588  const stdair::MeanStdDevPair_T& lMeanStdDevPair =
1589  lYieldDemandPair.second;
1590  const stdair::MeanValue_T& lMeanValue = lMeanStdDevPair.first;
1591  const stdair::StdDevValue_T& lStdDevValue = lMeanStdDevPair.second;
1592  for (stdair::LegCabinList_T::const_iterator itLC = lLegCabinList.begin();
1593  itLC != lLegCabinList.end(); ++itLC) {
1594  stdair::LegCabin* lLegCabin_ptr = *itLC;
1595  assert (lLegCabin_ptr != NULL);
1596  lLegCabin_ptr->addDemandInformation (lYield, lMeanValue, lStdDevValue);
1597  }
1598  }
1599  }
1600  }
1601  }
1602  }
1603  }
1604  }
1605 
1606  // ///////////////////////////////////////////////////////////////////
1607  void RMOL_Service::projectOnDDemandOnLegCabinsUsingDYP(const stdair::DateTime_T& iRMEventTime) {
1608 
1609  if (_rmolServiceContext == NULL) {
1610  throw stdair::NonInitialisedServiceException ("The Rmol service "
1611  "has not been initialised");
1612  }
1613  assert (_rmolServiceContext != NULL);
1614  RMOL_ServiceContext& lRMOL_ServiceContext = *_rmolServiceContext;
1615 
1616  // Retrieve the bom root
1617  stdair::STDAIR_Service& lSTDAIR_Service =
1618  lRMOL_ServiceContext.getSTDAIR_Service();
1619  stdair::BomRoot& lBomRoot = lSTDAIR_Service.getBomRoot();
1620 
1621  const stdair::InventoryList_T lInventoryList =
1622  stdair::BomManager::getList<stdair::Inventory> (lBomRoot);
1623  assert (!lInventoryList.empty());
1624  for (stdair::InventoryList_T::const_iterator itInv = lInventoryList.begin();
1625  itInv != lInventoryList.end(); ++itInv) {
1626  const stdair::Inventory* lInventory_ptr = *itInv;
1627  assert (lInventory_ptr != NULL);
1628  projectOnDDemandOnLegCabinsUsingDYP (iRMEventTime, *lInventory_ptr);
1629  }
1630  }
1631 
1632  // ///////////////////////////////////////////////////////////////////
1633  void RMOL_Service::projectOnDDemandOnLegCabinsUsingDYP(const stdair::DateTime_T& iRMEventTime,
1634  const stdair::Inventory& iInventory) {
1635 
1636  const stdair::OnDDateList_T lOnDDateList =
1637  stdair::BomManager::getList<stdair::OnDDate> (iInventory);
1638  assert (!lOnDDateList.empty());
1639  for (stdair::OnDDateList_T::const_iterator itOD = lOnDDateList.begin();
1640  itOD != lOnDDateList.end(); ++itOD) {
1641  stdair::OnDDate* lOnDDate_ptr = *itOD;
1642  assert (lOnDDate_ptr != NULL);
1643 
1644  // Retrieve the date from the RM event
1645  const stdair::Date_T lDate = iRMEventTime.date();
1646 
1647  const stdair::Date_T& lDepartureDate = lOnDDate_ptr->getDate();
1648  stdair::DateOffset_T lDateOffset = lDepartureDate - lDate;
1649  stdair::DTD_T lDTD = short (lDateOffset.days());
1650 
1651  stdair::DCPList_T::const_iterator itDCP =
1652  std::find (stdair::DEFAULT_DCP_LIST.begin(), stdair::DEFAULT_DCP_LIST.end(), lDTD);
1653  // Check if the forecast for this O&D date needs to be projected.
1654  if (itDCP != stdair::DEFAULT_DCP_LIST.end()) {
1655 
1656  // Browse the demand info map.
1657  const stdair::StringDemandStructMap_T& lStringDemandStructMap =
1658  lOnDDate_ptr->getDemandInfoMap ();
1659  for (stdair::StringDemandStructMap_T::const_iterator itStrDS = lStringDemandStructMap.begin();
1660  itStrDS != lStringDemandStructMap.end(); ++itStrDS) {
1661  std::string lCabinClassPath = itStrDS->first;
1662  const stdair::YieldDemandPair_T& lYieldDemandPair = itStrDS->second;
1663  const stdair::CabinClassPairList_T& lCabinClassPairList =
1664  lOnDDate_ptr->getCabinClassPairList(lCabinClassPath);
1665  const unsigned int lNbOfSegments = lOnDDate_ptr->getNbOfSegments();
1666  // Sanity check
1667  assert (lCabinClassPairList.size() == lNbOfSegments);
1668 
1669  //
1670  const stdair::SegmentDateList_T lOnDSegmentDateList =
1671  stdair::BomManager::getList<stdair::SegmentDate> (*lOnDDate_ptr);
1672  // Sanity check
1673  assert (lOnDSegmentDateList.size() == lNbOfSegments);
1674  stdair::CabinClassPairList_T::const_iterator itCCP = lCabinClassPairList.begin();
1675  stdair::SegmentDateList_T::const_iterator itSD = lOnDSegmentDateList.begin();
1676  // The sum of bid prices of all cabins.
1677  stdair::BidPrice_T lTotalBidPrice = 0;
1678  for (; itSD != lOnDSegmentDateList.end(); ++itCCP, ++itSD) {
1679  // Get the operating segment cabin (it holds the bid price information).
1680  const stdair::SegmentDate* lSegmentDate_ptr = *itSD;
1681  assert (lSegmentDate_ptr != NULL);
1682  // Get the operating airline code and check if it is the airline we are looking for.
1683  const stdair::SegmentDate* lOperatingSegmentDate_ptr =
1684  lSegmentDate_ptr->getOperatingSegmentDate ();
1685  if (lOperatingSegmentDate_ptr != NULL) {
1686  lSegmentDate_ptr = lOperatingSegmentDate_ptr;
1687  }
1688  const stdair::CabinCode_T lCabinCode = itCCP->first;
1689  const stdair::SegmentCabin* lSegmentCabin_ptr =
1690  stdair::BomManager::getObjectPtr<stdair::SegmentCabin> (*lSegmentDate_ptr,
1691  lCabinCode);
1692  assert (lSegmentCabin_ptr != NULL);
1693  const stdair::LegCabinList_T lLegCabinList =
1694  stdair::BomManager::getList<stdair::LegCabin>(*lSegmentCabin_ptr);
1695  for (stdair::LegCabinList_T::const_iterator itLC = lLegCabinList.begin();
1696  itLC != lLegCabinList.end(); ++itLC) {
1697  const stdair::LegCabin* lLegCabin_ptr = *itLC;
1698  assert (lLegCabin_ptr != NULL);
1699  lTotalBidPrice += lLegCabin_ptr->getCurrentBidPrice();
1700  }
1701  }
1702 
1703 
1704  itCCP = lCabinClassPairList.begin();
1705  itSD = lOnDSegmentDateList.begin();
1706  for (; itSD != lOnDSegmentDateList.end(); ++itCCP, ++itSD) {
1707  const stdair::SegmentDate* lSegmentDate_ptr = *itSD;
1708  assert (lSegmentDate_ptr != NULL);
1709  const stdair::SegmentDate* lOperatingSegmentDate_ptr =
1710  lSegmentDate_ptr->getOperatingSegmentDate ();
1711  // Only operated legs receive the demand information.
1712  if (lOperatingSegmentDate_ptr == NULL) {
1713  const stdair::CabinCode_T lCabinCode = itCCP->first;
1714  const stdair::ClassCode_T lClassCode = itCCP->second;
1715  const stdair::SegmentCabin* lSegmentCabin_ptr =
1716  stdair::BomManager::getObjectPtr<stdair::SegmentCabin> (*lSegmentDate_ptr,
1717  lCabinCode);
1718  assert (lSegmentCabin_ptr != NULL);
1719  const stdair::LegCabinList_T lLegCabinList =
1720  stdair::BomManager::getList<stdair::LegCabin> (*lSegmentCabin_ptr);
1721  assert (!lLegCabinList.empty());
1722  const stdair::Yield_T& lYield = lYieldDemandPair.first;
1723  const stdair::MeanStdDevPair_T& lMeanStdDevPair =
1724  lYieldDemandPair.second;
1725  const stdair::MeanValue_T& lMeanValue = lMeanStdDevPair.first;
1726  const stdair::StdDevValue_T& lStdDevValue = lMeanStdDevPair.second;
1727  for (stdair::LegCabinList_T::const_iterator itLC = lLegCabinList.begin();
1728  itLC != lLegCabinList.end(); ++itLC) {
1729  stdair::LegCabin* lLegCabin_ptr = *itLC;
1730  assert (lLegCabin_ptr != NULL);
1731  const stdair::BidPrice_T& lBidPrice = lLegCabin_ptr->getCurrentBidPrice();
1732  const stdair::RealNumber_T lDynamicYieldProrationFactor = lBidPrice / lTotalBidPrice;
1733  const stdair::Yield_T lProratedYield = lDynamicYieldProrationFactor*lYield;
1734  lLegCabin_ptr->addDemandInformation (lProratedYield, lMeanValue, lStdDevValue);
1735 
1736  // STDAIR_LOG_DEBUG ("Addding demand information to leg-cabin " << lLegCabin_ptr->getFullerKey()
1737  // << " Total yield " << lYield << " Proration factor "
1738  // << lDynamicYieldProrationFactor << " Prorated yield " << lProratedYield
1739  // << " Mean demand " << lMeanValue << " StdDev " << lStdDevValue);
1740  }
1741  }
1742  }
1743  }
1744  }
1745  }
1746  }
1747 
1748  // ///////////////////////////////////////////////////////////////////
1749  void RMOL_Service::optimiseOnDUsingRMCooperation (const stdair::DateTime_T& iRMEventTime) {
1750 
1751  if (_rmolServiceContext == NULL) {
1752  throw stdair::NonInitialisedServiceException ("The Rmol service "
1753  "has not been initialised");
1754  }
1755  assert (_rmolServiceContext != NULL);
1756  RMOL_ServiceContext& lRMOL_ServiceContext = *_rmolServiceContext;
1757 
1758  // Retrieve the bom root
1759  stdair::STDAIR_Service& lSTDAIR_Service =
1760  lRMOL_ServiceContext.getSTDAIR_Service();
1761  stdair::BomRoot& lBomRoot = lSTDAIR_Service.getBomRoot();
1762 
1763  // Retrieve the date from the RM event
1764  const stdair::Date_T lDate = iRMEventTime.date();
1765 
1766  // Browse the list of inventories and optimise within each one independently.
1767  const stdair::InventoryList_T& lInvList =
1768  stdair::BomManager::getList<stdair::Inventory> (lBomRoot);
1769  for (stdair::InventoryList_T::const_iterator itInv = lInvList.begin();
1770  itInv != lInvList.end(); ++itInv) {
1771  stdair::Inventory* lCurrentInv_ptr = *itInv;
1772  assert (lCurrentInv_ptr != NULL);
1773 
1774  double lMaxBPVariation = 1.0;
1775  short lIterationCounter = 0;
1776  // Iterate until the variation is under the wanted level or the maximal number of iterations is reached.
1777  while (lMaxBPVariation > 0.01 && lIterationCounter < 10) {
1778  lMaxBPVariation = 0.0;
1779  lIterationCounter++;
1780  const stdair::FlightDateList_T& lFlightDateList =
1781  stdair::BomManager::getList<stdair::FlightDate> (*lCurrentInv_ptr);
1782  for (stdair::FlightDateList_T::const_iterator itFlightDate =
1783  lFlightDateList.begin();
1784  itFlightDate != lFlightDateList.end(); ++itFlightDate) {
1785  stdair::FlightDate* lCurrentFlightDate_ptr = *itFlightDate;
1786  assert (lCurrentFlightDate_ptr != NULL);
1787 
1788  const stdair::Date_T& lCurrentDepartureDate = lCurrentFlightDate_ptr->getDepartureDate();
1789  stdair::DateOffset_T lDateOffset = lCurrentDepartureDate - lDate;
1790  stdair::DTD_T lDTD = short (lDateOffset.days());
1791 
1792  stdair::DCPList_T::const_iterator itDCP =
1793  std::find (stdair::DEFAULT_DCP_LIST.begin(), stdair::DEFAULT_DCP_LIST.end(), lDTD);
1794  // Check if the optimisation is needed.
1795  if (itDCP != stdair::DEFAULT_DCP_LIST.end()) {
1796  const double lBPVariation = Optimiser::optimiseUsingOnDForecast (*lCurrentFlightDate_ptr);
1797  lMaxBPVariation = std::max(lMaxBPVariation, lBPVariation);
1798  }
1799  }
1800  // Update the prorated yields for the current inventory.
1801  resetDemandInformation (iRMEventTime, *lCurrentInv_ptr);
1802  projectOnDDemandOnLegCabinsUsingDYP (iRMEventTime, *lCurrentInv_ptr);
1803  }
1804  }
1805  }
1806 
1807 
1808  // ///////////////////////////////////////////////////////////////////
1809  void RMOL_Service::optimiseOnDUsingAdvancedRMCooperation (const stdair::DateTime_T& iRMEventTime) {
1810 
1811  if (_rmolServiceContext == NULL) {
1812  throw stdair::NonInitialisedServiceException ("The Rmol service "
1813  "has not been initialised");
1814  }
1815  assert (_rmolServiceContext != NULL);
1816  RMOL_ServiceContext& lRMOL_ServiceContext = *_rmolServiceContext;
1817 
1818  // Retrieve the bom root
1819  stdair::STDAIR_Service& lSTDAIR_Service =
1820  lRMOL_ServiceContext.getSTDAIR_Service();
1821  stdair::BomRoot& lBomRoot = lSTDAIR_Service.getBomRoot();
1822 
1823  // Retrieve the date from the RM event
1824  const stdair::Date_T lDate = iRMEventTime.date();
1825 
1826  double lMaxBPVariation = 1.0;
1827  short lIterationCounter = 0;
1828  // Iterate until the variation is under the wanted level or the maximal number of iterations is reached.
1829  // Every iteration corresponds to the optimisation of the whole network. Bid prices are communicated
1830  // between partners at the end of each iteration.
1831  while (lMaxBPVariation > 0.01 && lIterationCounter < 50) {
1832  lMaxBPVariation = 0.0;
1833  lIterationCounter++;
1834 
1835  const stdair::InventoryList_T& lInvList =
1836  stdair::BomManager::getList<stdair::Inventory> (lBomRoot);
1837  for (stdair::InventoryList_T::const_iterator itInv = lInvList.begin();
1838  itInv != lInvList.end(); ++itInv) {
1839  stdair::Inventory* lCurrentInv_ptr = *itInv;
1840  assert (lCurrentInv_ptr != NULL);
1841  const stdair::FlightDateList_T& lFlightDateList =
1842  stdair::BomManager::getList<stdair::FlightDate> (*lCurrentInv_ptr);
1843  for (stdair::FlightDateList_T::const_iterator itFlightDate =
1844  lFlightDateList.begin();
1845  itFlightDate != lFlightDateList.end(); ++itFlightDate) {
1846  stdair::FlightDate* lCurrentFlightDate_ptr = *itFlightDate;
1847  assert (lCurrentFlightDate_ptr != NULL);
1848 
1849  const stdair::Date_T& lCurrentDepartureDate = lCurrentFlightDate_ptr->getDepartureDate();
1850  stdair::DateOffset_T lDateOffset = lCurrentDepartureDate - lDate;
1851  stdair::DTD_T lDTD = short (lDateOffset.days());
1852 
1853  stdair::DCPList_T::const_iterator itDCP =
1854  std::find (stdair::DEFAULT_DCP_LIST.begin(), stdair::DEFAULT_DCP_LIST.end(), lDTD);
1855  if (itDCP != stdair::DEFAULT_DCP_LIST.end()) {
1856  const double lBPVariation = Optimiser::optimiseUsingOnDForecast (*lCurrentFlightDate_ptr);
1857  lMaxBPVariation = std::max(lMaxBPVariation, lBPVariation);
1858  }
1859  }
1860  }
1861  // At the end of each iteration, communicate bid prices and compute displacement adjusted yields.
1862  updateBidPrice (iRMEventTime);
1863  resetDemandInformation (iRMEventTime);
1864  projectOnDDemandOnLegCabinsUsingDYP (iRMEventTime);
1865  }
1866  }
1867 
1868 }