$treeview $search $mathjax
RMOL Logo  1.00.1
$projectbrief
$projectbrief
$searchbox

rmol/service/RMOL_Service.cpp

Go to the documentation of this file.
00001 // //////////////////////////////////////////////////////////////////////
00002 // Import section
00003 // //////////////////////////////////////////////////////////////////////
00004 // STL
00005 #include <cassert>
00006 // Boost
00007 #include <boost/make_shared.hpp>
00008 // StdAir
00009 #include <stdair/stdair_inventory_types.hpp>
00010 #include <stdair/basic/BasChronometer.hpp>
00011 #include <stdair/basic/ContinuousAttributeLite.hpp>
00012 #include <stdair/bom/BomManager.hpp>
00013 #include <stdair/bom/BomRetriever.hpp>
00014 #include <stdair/bom/BomRoot.hpp>
00015 #include <stdair/bom/Inventory.hpp>
00016 #include <stdair/bom/FlightDate.hpp>
00017 #include <stdair/bom/LegCabin.hpp>
00018 #include <stdair/bom/LegDate.hpp>
00019 #include <stdair/bom/YieldFeatures.hpp>
00020 #include <stdair/bom/AirportPair.hpp>
00021 #include <stdair/bom/PosChannel.hpp>
00022 #include <stdair/bom/DatePeriod.hpp>
00023 #include <stdair/bom/TimePeriod.hpp>
00024 #include <stdair/bom/AirlineClassList.hpp>
00025 #include <stdair/basic/BasConst_Request.hpp>
00026 #include <stdair/basic/BasConst_Inventory.hpp>
00027 #include <stdair/bom/Inventory.hpp>
00028 #include <stdair/bom/FlightDate.hpp>
00029 #include <stdair/bom/SegmentDate.hpp>
00030 #include <stdair/bom/SegmentCabin.hpp>
00031 #include <stdair/bom/BookingClass.hpp>
00032 #include <stdair/bom/OnDDate.hpp>
00033 #include <stdair/bom/OnDDateTypes.hpp>
00034 #include <stdair/command/CmdBomManager.hpp>
00035 #include <stdair/service/Logger.hpp>
00036 #include <stdair/STDAIR_Service.hpp>
00037 // RMOL
00038 #include <rmol/basic/BasConst_RMOL_Service.hpp>
00039 #include <rmol/factory/FacRmolServiceContext.hpp>
00040 #include <rmol/command/InventoryParser.hpp>
00041 #include <rmol/command/Optimiser.hpp>
00042 #include <rmol/command/PreOptimiser.hpp>
00043 #include <rmol/command/Forecaster.hpp>
00044 #include <rmol/service/RMOL_ServiceContext.hpp>
00045 #include <rmol/RMOL_Service.hpp>
00046 
00047 namespace RMOL {
00048 
00049   // ////////////////////////////////////////////////////////////////////
00050   RMOL_Service::RMOL_Service()
00051   : _rmolServiceContext (NULL),
00052     _previousForecastDate (stdair::Date_T (2000, 1, 1)) {
00053     assert (false);
00054   }
00055 
00056   // ////////////////////////////////////////////////////////////////////
00057   RMOL_Service::RMOL_Service (const RMOL_Service& iService) :
00058     _rmolServiceContext (NULL),
00059     _previousForecastDate (stdair::Date_T (2000, 1, 1)) {
00060     assert (false);
00061   }
00062 
00063   // ////////////////////////////////////////////////////////////////////
00064   RMOL_Service::RMOL_Service (const stdair::BasLogParams& iLogParams) :
00065     _rmolServiceContext (NULL),
00066     _previousForecastDate (stdair::Date_T (2000, 1, 1)) {
00067 
00068     // Initialise the STDAIR service handler
00069     stdair::STDAIR_ServicePtr_T lSTDAIR_Service_ptr =
00070       initStdAirService (iLogParams);
00071     
00072     // Initialise the service context
00073     initServiceContext();
00074 
00075     // Add the StdAir service context to the RMOL service context
00076     // \note RMOL owns the STDAIR service resources here.
00077     const bool ownStdairService = true;
00078     addStdAirService (lSTDAIR_Service_ptr, ownStdairService);
00079 
00080     // Initialise the (remaining of the) context
00081     initRmolService();
00082   }
00083 
00084   // ////////////////////////////////////////////////////////////////////
00085   RMOL_Service::RMOL_Service (const stdair::BasLogParams& iLogParams,
00086                               const stdair::BasDBParams& iDBParams) :
00087     _rmolServiceContext (NULL),
00088     _previousForecastDate (stdair::Date_T (2000, 1, 1)) {
00089 
00090     // Initialise the STDAIR service handler
00091     stdair::STDAIR_ServicePtr_T lSTDAIR_Service_ptr =
00092       initStdAirService (iLogParams, iDBParams);
00093     
00094     // Initialise the service context
00095     initServiceContext();
00096 
00097     // Add the StdAir service context to the RMOL service context
00098     // \note RMOL owns the STDAIR service resources here.
00099     const bool ownStdairService = true;
00100     addStdAirService (lSTDAIR_Service_ptr, ownStdairService);
00101 
00102     // Initialise the (remaining of the) context
00103     initRmolService();
00104   }
00105 
00106   // ////////////////////////////////////////////////////////////////////
00107   RMOL_Service::RMOL_Service (stdair::STDAIR_ServicePtr_T ioSTDAIRServicePtr)
00108     : _rmolServiceContext (NULL),
00109       _previousForecastDate (stdair::Date_T (2000, 1, 1)) {
00110     
00111     // Initialise the context
00112     initServiceContext();
00113     
00114     // Add the StdAir service context to the RMOL service context.
00115     // \note RMOL does not own the STDAIR service resources here.
00116     const bool doesNotOwnStdairService = false;
00117     addStdAirService (ioSTDAIRServicePtr, doesNotOwnStdairService);
00118 
00119     // Initialise the (remaining of the) context
00120     initRmolService();
00121   }
00122 
00123   // ////////////////////////////////////////////////////////////////////
00124   RMOL_Service::~RMOL_Service() {
00125     // Delete/Clean all the objects from memory
00126     finalise();
00127   }
00128 
00129   // ////////////////////////////////////////////////////////////////////
00130   void RMOL_Service::finalise() {
00131     assert (_rmolServiceContext != NULL);
00132     // Reset the (Boost.)Smart pointer pointing on the STDAIR_Service object.
00133     _rmolServiceContext->reset();
00134   }
00135 
00136   // ////////////////////////////////////////////////////////////////////
00137   void RMOL_Service::initServiceContext() {
00138     // Initialise the service context
00139     RMOL_ServiceContext& lRMOL_ServiceContext = 
00140       FacRmolServiceContext::instance().create();
00141     _rmolServiceContext = &lRMOL_ServiceContext;
00142   }
00143 
00144   // ////////////////////////////////////////////////////////////////////
00145   void RMOL_Service::
00146   addStdAirService (stdair::STDAIR_ServicePtr_T ioSTDAIR_Service_ptr,
00147                     const bool iOwnStdairService) {
00148 
00149     // Retrieve the RMOL service context
00150     assert (_rmolServiceContext != NULL);
00151     RMOL_ServiceContext& lRMOL_ServiceContext = *_rmolServiceContext;
00152 
00153     // Store the STDAIR service object within the (AIRINV) service context
00154     lRMOL_ServiceContext.setSTDAIR_Service (ioSTDAIR_Service_ptr,
00155                                             iOwnStdairService);
00156   }
00157 
00158   // ////////////////////////////////////////////////////////////////////
00159   stdair::STDAIR_ServicePtr_T RMOL_Service::
00160   initStdAirService (const stdair::BasLogParams& iLogParams) {
00161     
00169     stdair::STDAIR_ServicePtr_T lSTDAIR_Service_ptr = 
00170       boost::make_shared<stdair::STDAIR_Service> (iLogParams);
00171     
00172     return lSTDAIR_Service_ptr;
00173   }
00174 
00175   // //////////////////////////////////////////////////////////////////////
00176   stdair::STDAIR_ServicePtr_T RMOL_Service::
00177   initStdAirService (const stdair::BasLogParams& iLogParams,
00178                      const stdair::BasDBParams& iDBParams) {
00179 
00187     stdair::STDAIR_ServicePtr_T lSTDAIR_Service_ptr = 
00188       boost::make_shared<stdair::STDAIR_Service> (iLogParams, iDBParams);
00189     
00190     return lSTDAIR_Service_ptr;
00191   }
00192   
00193   // ////////////////////////////////////////////////////////////////////
00194   void RMOL_Service::initRmolService() {
00195     // Do nothing at this stage. A sample BOM tree may be built by
00196     // calling the buildSampleBom() method
00197   }
00198 
00199   // ////////////////////////////////////////////////////////////////////
00200   void RMOL_Service::
00201   parseAndLoad (const stdair::CabinCapacity_T& iCabinCapacity,
00202                 const stdair::Filename_T& iInputFileName) {
00203 
00204     // Retrieve the RMOL service context
00205     if (_rmolServiceContext == NULL) {
00206       throw stdair::NonInitialisedServiceException ("The RMOL service has not"
00207                                                     " been initialised");
00208     }
00209     assert (_rmolServiceContext != NULL);
00210     RMOL_ServiceContext& lRMOL_ServiceContext = *_rmolServiceContext; 
00211     const bool doesOwnStdairService =
00212       lRMOL_ServiceContext.getOwnStdairServiceFlag();
00213 
00214     // Retrieve the StdAir service object from the (RMOL) service context
00215     stdair::STDAIR_Service& lSTDAIR_Service =
00216       lRMOL_ServiceContext.getSTDAIR_Service();
00217     stdair::BomRoot& lPersistentBomRoot = 
00218       lSTDAIR_Service.getPersistentBomRoot();
00219 
00223     lSTDAIR_Service.buildDummyInventory (iCabinCapacity);
00224 
00228     InventoryParser::parseInputFileAndBuildBom (iInputFileName, 
00229                                                 lPersistentBomRoot);  
00230  
00246     buildComplementaryLinks (lPersistentBomRoot);
00247     
00252     if (doesOwnStdairService == true) {
00253  
00254       //
00255       clonePersistentBom ();
00256     }
00257   }
00258   
00259   // ////////////////////////////////////////////////////////////////////
00260   void RMOL_Service::buildSampleBom() {
00261 
00262     // Retrieve the RMOL service context
00263     if (_rmolServiceContext == NULL) {
00264       throw stdair::NonInitialisedServiceException ("The RMOL service has not"
00265                                                     " been initialised");
00266     }
00267     assert (_rmolServiceContext != NULL);
00268 
00269     // Retrieve the RMOL service context and whether it owns the Stdair
00270     // service
00271     RMOL_ServiceContext& lRMOL_ServiceContext = *_rmolServiceContext;
00272     const bool doesOwnStdairService =
00273       lRMOL_ServiceContext.getOwnStdairServiceFlag();
00274 
00275     // Retrieve the StdAir service object from the (RMOL) service context
00276     stdair::STDAIR_Service& lSTDAIR_Service =
00277       lRMOL_ServiceContext.getSTDAIR_Service();   
00278     stdair::BomRoot& lPersistentBomRoot = 
00279       lSTDAIR_Service.getPersistentBomRoot();
00280 
00285     if (doesOwnStdairService == true) {
00286       //
00287       lSTDAIR_Service.buildSampleBom();
00288     }
00289 
00305     buildComplementaryLinks (lPersistentBomRoot);
00306     
00311     if (doesOwnStdairService == true) {
00312  
00313       //
00314       clonePersistentBom ();
00315     }
00316   } 
00317 
00318   // ////////////////////////////////////////////////////////////////////
00319   void RMOL_Service::clonePersistentBom () {   
00320 
00321     // Retrieve the RMOL service context
00322     if (_rmolServiceContext == NULL) {
00323       throw stdair::NonInitialisedServiceException("The RMOL service has not "
00324                                                    "been initialised");
00325     }
00326     assert (_rmolServiceContext != NULL);
00327 
00328     // Retrieve the RMOL service context and whether it owns the Stdair
00329     // service
00330     RMOL_ServiceContext& lRMOL_ServiceContext = *_rmolServiceContext;
00331     const bool doesOwnStdairService =
00332       lRMOL_ServiceContext.getOwnStdairServiceFlag();
00333 
00334     // Retrieve the StdAir service object from the (RMOL) service context
00335     stdair::STDAIR_Service& lSTDAIR_Service =
00336       lRMOL_ServiceContext.getSTDAIR_Service();
00337  
00342     if (doesOwnStdairService == true) {
00343  
00344       //
00345       lSTDAIR_Service.clonePersistentBom ();
00346     }
00347 
00351     stdair::BomRoot& lBomRoot = 
00352       lSTDAIR_Service.getBomRoot();
00353     buildComplementaryLinks (lBomRoot); 
00354   }     
00355 
00356   // ////////////////////////////////////////////////////////////////////
00357   void RMOL_Service::buildComplementaryLinks (stdair::BomRoot& ioBomRoot) { 
00358 
00359     // Retrieve the RMOL service context
00360     if (_rmolServiceContext == NULL) {
00361       throw stdair::NonInitialisedServiceException("The RMOL service has not "
00362                                                    "been initialised");
00363     }
00364     assert (_rmolServiceContext != NULL);
00365 
00366     // Retrieve the RMOL service context and whether it owns the Stdair
00367     // service
00368     RMOL_ServiceContext& lRMOL_ServiceContext = *_rmolServiceContext;
00369 
00370     // Retrieve the StdAir service object from the (RMOL) service context
00371     stdair::STDAIR_Service& lSTDAIR_Service =
00372       lRMOL_ServiceContext.getSTDAIR_Service();
00373 
00378     lSTDAIR_Service.buildDummyLegSegmentAccesses (ioBomRoot);
00379   }   
00380 
00381   // ////////////////////////////////////////////////////////////////////
00382   void RMOL_Service::optimalOptimisationByMCIntegration (const int K) {
00383     assert (_rmolServiceContext != NULL);
00384     RMOL_ServiceContext& lRMOL_ServiceContext = *_rmolServiceContext;
00385 
00386     // Retrieve the StdAir service
00387     stdair::STDAIR_Service& lSTDAIR_Service =
00388       lRMOL_ServiceContext.getSTDAIR_Service();   
00389     // TODO: gsabatier
00390     // Replace the getPersistentBomRoot method by the getBomRoot method,
00391     // in order to work on the clone Bom root instead of the persistent one.
00392     // Does not work for now because virtual classes are not cloned.
00393     stdair::BomRoot& lBomRoot = lSTDAIR_Service.getPersistentBomRoot();
00394 
00395     //
00396     stdair::LegCabin& lLegCabin =
00397       stdair::BomRetriever::retrieveDummyLegCabin (lBomRoot);
00398 
00399     stdair::BasChronometer lOptimisationChronometer;
00400     lOptimisationChronometer.start();
00401 
00402     Optimiser::optimalOptimisationByMCIntegration (K, lLegCabin);
00403 
00404     const double lOptimisationMeasure = lOptimisationChronometer.elapsed();
00405     
00406     // DEBUG
00407     STDAIR_LOG_DEBUG ("Optimisation by Monte-Carlo performed in "
00408                       << lOptimisationMeasure);
00409     STDAIR_LOG_DEBUG ("Result: " << lLegCabin.displayVirtualClassList());
00410 
00411     std::ostringstream logStream;
00412     stdair::BidPriceVector_T lBidPriceVector = lLegCabin.getBidPriceVector();
00413     logStream << "Bid-Price Vector (BPV): ";
00414     const unsigned int size = lBidPriceVector.size();
00415     
00416     for (unsigned int i = 0; i < size - 1; ++i) {
00417       const double bidPrice = lBidPriceVector.at(i);
00418       logStream << std::fixed << std::setprecision (2) << bidPrice << ", ";
00419     }
00420     const double bidPrice = lBidPriceVector.at(size -1);
00421     logStream << std::fixed << std::setprecision (2) << bidPrice;
00422     STDAIR_LOG_DEBUG (logStream.str());
00423   }
00424 
00425   // ////////////////////////////////////////////////////////////////////
00426   void RMOL_Service::optimalOptimisationByDP() {
00427   }
00428   
00429   // ////////////////////////////////////////////////////////////////////
00430   void RMOL_Service::heuristicOptimisationByEmsr() {
00431     assert (_rmolServiceContext != NULL);
00432     RMOL_ServiceContext& lRMOL_ServiceContext = *_rmolServiceContext;
00433 
00434     // Retrieve the StdAir service
00435     stdair::STDAIR_Service& lSTDAIR_Service =
00436       lRMOL_ServiceContext.getSTDAIR_Service();    
00437     // TODO: gsabatier
00438     // Replace the getPersistentBomRoot method by the getBomRoot method,
00439     // in order to work on the clone Bom root instead of the persistent one.
00440     // Does not work for now because virtual classes are not cloned.
00441     stdair::BomRoot& lBomRoot = lSTDAIR_Service.getPersistentBomRoot();
00442 
00443     //
00444     stdair::LegCabin& lLegCabin =
00445       stdair::BomRetriever::retrieveDummyLegCabin (lBomRoot);
00446 
00447     stdair::BasChronometer lOptimisationChronometer;
00448     lOptimisationChronometer.start();
00449     
00450     Optimiser::heuristicOptimisationByEmsr (lLegCabin);
00451     
00452     const double lOptimisationMeasure = lOptimisationChronometer.elapsed();
00453     // DEBUG
00454     STDAIR_LOG_DEBUG ("Optimisation EMSR performed in "
00455                       << lOptimisationMeasure);
00456     STDAIR_LOG_DEBUG ("Result: " << lLegCabin.displayVirtualClassList());
00457 
00458     stdair::BidPriceVector_T lBidPriceVector = lLegCabin.getBidPriceVector();
00459     std::ostringstream logStream;
00460     logStream << "Bid-Price Vector (BPV): ";
00461     stdair::UnsignedIndex_T idx = 0;
00462     for (stdair::BidPriceVector_T::const_iterator itBP = lBidPriceVector.begin();
00463          itBP != lBidPriceVector.end(); ++itBP) {
00464       if (idx != 0) {
00465         logStream << ", ";
00466       }
00467       const stdair::BidPrice_T& lBidPrice = *itBP;
00468       logStream << std::fixed << std::setprecision (2) << lBidPrice;
00469     }
00470     // DEBUG
00471     STDAIR_LOG_DEBUG (logStream.str());
00472   }
00473 
00474   // ////////////////////////////////////////////////////////////////////
00475   void RMOL_Service::heuristicOptimisationByEmsrA() {
00476     assert (_rmolServiceContext != NULL);
00477     RMOL_ServiceContext& lRMOL_ServiceContext = *_rmolServiceContext;
00478 
00479     // Retrieve the StdAir service
00480     stdair::STDAIR_Service& lSTDAIR_Service =
00481       lRMOL_ServiceContext.getSTDAIR_Service();     
00482     // TODO: gsabatier
00483     // Replace the getPersistentBomRoot method by the getBomRoot method,
00484     // in order to work on the clone Bom root instead of the persistent one.
00485     // Does not work for now because virtual classes are not cloned. 
00486     stdair::BomRoot& lBomRoot = lSTDAIR_Service.getPersistentBomRoot();
00487 
00488     //
00489     stdair::LegCabin& lLegCabin =
00490       stdair::BomRetriever::retrieveDummyLegCabin (lBomRoot);
00491 
00492     Optimiser::heuristicOptimisationByEmsrA (lLegCabin);
00493 
00494     // DEBUG
00495     STDAIR_LOG_DEBUG ("Result: " << lLegCabin.displayVirtualClassList());
00496     
00497   }
00498 
00499   // ////////////////////////////////////////////////////////////////////
00500   void RMOL_Service::heuristicOptimisationByEmsrB() {
00501     assert (_rmolServiceContext != NULL);
00502     RMOL_ServiceContext& lRMOL_ServiceContext = *_rmolServiceContext;
00503 
00504     // Retrieve the StdAir service
00505     stdair::STDAIR_Service& lSTDAIR_Service =
00506       lRMOL_ServiceContext.getSTDAIR_Service();    
00507     // TODO: gsabatier
00508     // Replace the getPersistentBomRoot method by the getBomRoot method,
00509     // in order to work on the clone Bom root instead of the persistent one.
00510     // Does not work for now because virtual classes are not cloned.
00511     stdair::BomRoot& lBomRoot = lSTDAIR_Service.getPersistentBomRoot();
00512 
00513     //
00514     stdair::LegCabin& lLegCabin =
00515       stdair::BomRetriever::retrieveDummyLegCabin (lBomRoot);
00516 
00517     Optimiser::heuristicOptimisationByEmsrB (lLegCabin);
00518 
00519     // DEBUG
00520     STDAIR_LOG_DEBUG ("Result: " << lLegCabin.displayVirtualClassList());
00521   }
00522 
00523   // ////////////////////////////////////////////////////////////////////
00524   const stdair::SegmentCabin& RMOL_Service::
00525   retrieveDummySegmentCabin(const bool isForFareFamilies) {
00526     assert (_rmolServiceContext != NULL);
00527     RMOL_ServiceContext& lRMOL_ServiceContext = *_rmolServiceContext;
00528 
00529     // Retrieve the StdAir service
00530     stdair::STDAIR_Service& lSTDAIR_Service =
00531       lRMOL_ServiceContext.getSTDAIR_Service();
00532     // TODO: gsabatier
00533     // Replace the getPersistentBomRoot method by the getBomRoot method,
00534     // in order to work on the clone Bom root instead of the persistent one.
00535     // Does not work for now because virtual classes are not cloned.
00536     stdair::BomRoot& lBomRoot = lSTDAIR_Service.getPersistentBomRoot();
00537 
00538     const stdair::SegmentCabin& lSegmentCabin = 
00539       stdair::BomRetriever::retrieveDummySegmentCabin(lBomRoot, 
00540                                                       isForFareFamilies);
00541     return lSegmentCabin;
00542     
00543   }
00544 
00545   // ////////////////////////////////////////////////////////////////////
00546   bool RMOL_Service::
00547   optimise (stdair::FlightDate& ioFlightDate,
00548             const stdair::DateTime_T& iRMEventTime,
00549             const stdair::UnconstrainingMethod& iUnconstrainingMethod,
00550             const stdair::ForecastingMethod& iForecastingMethod, 
00551             const stdair::PreOptimisationMethod& iPreOptimisationMethod,
00552             const stdair::OptimisationMethod& iOptimisationMethod,
00553             const stdair::PartnershipTechnique& iPartnershipTechnique) {
00554 
00555     
00556     STDAIR_LOG_DEBUG ("Forecast & Optimisation");
00557     
00558     const stdair::PartnershipTechnique::EN_PartnershipTechnique& lPartnershipTechnique =
00559       iPartnershipTechnique.getTechnique();
00560     
00561     switch (lPartnershipTechnique) {      
00562     case stdair::PartnershipTechnique::NONE:{
00563       // DEBUG
00564       STDAIR_LOG_DEBUG ("Forecast");
00565       
00566       // 1. Forecasting
00567       const bool isForecasted = Forecaster::forecast (ioFlightDate,
00568                                                       iRMEventTime,
00569                                                       iUnconstrainingMethod,
00570                                                       iForecastingMethod);
00571       // DEBUG
00572       STDAIR_LOG_DEBUG ("Forecast successful: " << isForecasted);
00573 
00574       if (isForecasted == true) {
00575         // 2a. MRT or FA
00576         // DEBUG
00577         STDAIR_LOG_DEBUG ("Pre-optimise");
00578         
00579         const bool isPreOptimised =
00580           PreOptimiser::preOptimise (ioFlightDate, iPreOptimisationMethod);
00581         
00582         // DEBUG
00583         STDAIR_LOG_DEBUG ("Pre-Optimise successful: " << isPreOptimised);
00584 
00585         if (isPreOptimised == true) {
00586           // 2b. Optimisation
00587           // DEBUG
00588           STDAIR_LOG_DEBUG ("Optimise");
00589           const bool optimiseSucceeded = 
00590             Optimiser::optimise (ioFlightDate, iOptimisationMethod);
00591           // DEBUG
00592           STDAIR_LOG_DEBUG ("Optimise successful: " << optimiseSucceeded);
00593           return optimiseSucceeded ;
00594         }
00595       }
00596       break;
00597     }
00598     case stdair::PartnershipTechnique::RAE_DA:
00599     case stdair::PartnershipTechnique::IBP_DA:{
00600       if (_previousForecastDate < iRMEventTime.date()) {
00601         forecastOnD (iRMEventTime);
00602         resetDemandInformation (iRMEventTime);
00603         projectAggregatedDemandOnLegCabins (iRMEventTime);
00604         optimiseOnD (iRMEventTime);
00605       }
00606       break;
00607     }
00608     case stdair::PartnershipTechnique::RAE_YP:
00609     case stdair::PartnershipTechnique::IBP_YP:
00610     case stdair::PartnershipTechnique::IBP_YP_U:{
00611       if (_previousForecastDate < iRMEventTime.date()) {
00612         forecastOnD (iRMEventTime);
00613         resetDemandInformation (iRMEventTime);
00614         projectOnDDemandOnLegCabinsUsingYP (iRMEventTime);
00615         optimiseOnD (iRMEventTime);
00616       }
00617       break;
00618     }
00619     case stdair::PartnershipTechnique::RMC:{
00620       if (_previousForecastDate < iRMEventTime.date()) {
00621         forecastOnD (iRMEventTime);
00622         resetDemandInformation (iRMEventTime);        
00623         updateBidPrice (iRMEventTime);
00624         projectOnDDemandOnLegCabinsUsingDYP (iRMEventTime);
00625         optimiseOnDUsingRMCooperation (iRMEventTime);
00626       }
00627       break;
00628     }
00629     case stdair::PartnershipTechnique::A_RMC:{
00630       if (_previousForecastDate < iRMEventTime.date()) {
00631         forecastOnD (iRMEventTime);
00632         resetDemandInformation (iRMEventTime);        
00633         updateBidPrice (iRMEventTime);
00634         projectOnDDemandOnLegCabinsUsingDYP (iRMEventTime);
00635         optimiseOnDUsingAdvancedRMCooperation (iRMEventTime);
00636       }
00637       break;
00638     }
00639     default:{
00640       assert (false);
00641       break;
00642       }
00643     }
00644     return false;  
00645   }
00646   
00647   // ////////////////////////////////////////////////////////////////////
00648   void RMOL_Service::forecastOnD (const stdair::DateTime_T& iRMEventTime) {
00649 
00650     if (_rmolServiceContext == NULL) {
00651       throw stdair::NonInitialisedServiceException ("The Rmol service "
00652                                                     "has not been initialised");
00653     }
00654     assert (_rmolServiceContext != NULL);
00655     RMOL_ServiceContext& lRMOL_ServiceContext = *_rmolServiceContext;
00656 
00657     // Retrieve the bom root
00658     stdair::STDAIR_Service& lSTDAIR_Service =
00659       lRMOL_ServiceContext.getSTDAIR_Service();
00660     stdair::BomRoot& lBomRoot = lSTDAIR_Service.getBomRoot();
00661 
00662     // Retrieve the date from the RM event
00663     const stdair::Date_T lDate = iRMEventTime.date();
00664 
00665     _previousForecastDate = lDate;
00666 
00667     const stdair::InventoryList_T& lInventoryList =
00668       stdair::BomManager::getList<stdair::Inventory> (lBomRoot);
00669     assert (!lInventoryList.empty());
00670     for (stdair::InventoryList_T::const_iterator itInv = lInventoryList.begin();
00671          itInv != lInventoryList.end(); ++itInv) {
00672       const stdair::Inventory* lInventory_ptr = *itInv;
00673       assert (lInventory_ptr != NULL);
00674       const bool hasOnDDateList =
00675         stdair::BomManager::hasList<stdair::OnDDate> (*lInventory_ptr);
00676       if (hasOnDDateList == true) {
00677         const stdair::OnDDateList_T lOnDDateList =
00678           stdair::BomManager::getList<stdair::OnDDate> (*lInventory_ptr);
00679 
00680         for (stdair::OnDDateList_T::const_iterator itOD = lOnDDateList.begin();
00681              itOD != lOnDDateList.end(); ++itOD) {
00682           stdair::OnDDate* lOnDDate_ptr = *itOD;
00683           assert (lOnDDate_ptr != NULL);
00684           
00685           const stdair::Date_T& lDepartureDate = lOnDDate_ptr->getDate();
00686           stdair::DateOffset_T lDateOffset = lDepartureDate - lDate;
00687           stdair::DTD_T lDTD = short (lDateOffset.days());
00688           
00689           stdair::DCPList_T::const_iterator itDCP =
00690             std::find (stdair::DEFAULT_DCP_LIST.begin(),
00691                        stdair::DEFAULT_DCP_LIST.end(), lDTD);
00692           // Check if the forecast for this O&D date needs to be forecasted.
00693           if (itDCP != stdair::DEFAULT_DCP_LIST.end()) {
00694             // Retrieve the total forecast map.
00695             const stdair::CabinForecastMap_T& lTotalForecastMap =
00696               lOnDDate_ptr->getTotalForecastMap();
00697             
00698             // Browse the map and make a forecast for every cabin.
00699             for (stdair::CabinForecastMap_T::const_iterator itCF =
00700                    lTotalForecastMap.begin();
00701                  itCF != lTotalForecastMap.end(); ++itCF) {
00702               const stdair::CabinCode_T lCabinCode = itCF->first;
00703               stdair::YieldFeatures* lYieldFeatures_ptr =
00704                 getYieldFeatures(*lOnDDate_ptr, lCabinCode, lBomRoot);
00705               if (lYieldFeatures_ptr == NULL) {
00706                 STDAIR_LOG_ERROR ("Cannot find yield corresponding to "
00707                                   << "the O&D date"
00708                                   << lOnDDate_ptr->toString()
00709                                   << " Cabin " << lCabinCode);
00710                 assert (false);
00711               }
00712               forecastOnD (*lYieldFeatures_ptr, *lOnDDate_ptr, lCabinCode, lDTD,
00713                            lBomRoot);
00714             }
00715           }
00716         }
00717       }
00718     }    
00719   }
00720 
00721   // ///////////////////////////////////////////////////////////////////
00722   stdair::YieldFeatures* RMOL_Service::
00723   getYieldFeatures(const stdair::OnDDate& iOnDDate,
00724                    const stdair::CabinCode_T& iCabinCode,
00725                    stdair::BomRoot& iBomRoot) {
00726 
00727     const stdair::AirportCode_T& lOrigin = iOnDDate.getOrigin();
00728     const stdair::AirportCode_T& lDestination = iOnDDate.getDestination();
00729 
00730     const stdair::Date_T& lDepartureDate = iOnDDate.getDate();
00731     
00732     // Build the airport pair key out of O&D and get the airport pair object
00733     const stdair::AirportPairKey lAirportPairKey(lOrigin, lDestination);
00734     stdair::AirportPair* lAirportPair_ptr = stdair::BomManager::
00735       getObjectPtr<stdair::AirportPair> (iBomRoot,
00736                                          lAirportPairKey.toString());
00737     if (lAirportPair_ptr == NULL) {
00738       STDAIR_LOG_ERROR ("Cannot find yield corresponding to the airport "
00739                         << "pair: " << lAirportPairKey.toString());
00740       assert (false);
00741     }  
00742 
00743     // Retrieve the corresponding date period to lDepartureDate.
00744     const stdair::DatePeriodList_T lDatePeriodList =
00745       stdair::BomManager::getList<stdair::DatePeriod> (*lAirportPair_ptr);
00746     for (stdair::DatePeriodList_T::const_iterator itDatePeriod =
00747            lDatePeriodList.begin();
00748          itDatePeriod != lDatePeriodList.end(); ++itDatePeriod) {
00749       const stdair::DatePeriod* lDatePeriod_ptr = *itDatePeriod;
00750       assert (lDatePeriod_ptr != NULL);
00751       
00752       const bool isDepartureDateValid =
00753         lDatePeriod_ptr->isDepartureDateValid (lDepartureDate);
00754       
00755       if (isDepartureDateValid == true) {
00756         // Retrieve the PoS-Channel.
00757         // TODO: Use POS and Channel from demand instead of default
00758         const stdair::PosChannelKey lPosChannelKey (stdair::DEFAULT_POS,
00759                                                     stdair::DEFAULT_CHANNEL);
00760         stdair::PosChannel* lPosChannel_ptr = stdair::BomManager::
00761           getObjectPtr<stdair::PosChannel> (*lDatePeriod_ptr,
00762                                             lPosChannelKey.toString());
00763         if (lPosChannel_ptr == NULL) {
00764           STDAIR_LOG_ERROR ("Cannot find yield corresponding to the PoS-"
00765                             << "Channel: " << lPosChannelKey.toString());
00766           assert (false);
00767         }
00768         // Retrieve the yield features.
00769         const stdair::TimePeriodList_T lTimePeriodList = stdair::
00770           BomManager::getList<stdair::TimePeriod> (*lPosChannel_ptr);
00771         for (stdair::TimePeriodList_T::const_iterator itTimePeriod =
00772                lTimePeriodList.begin();
00773              itTimePeriod != lTimePeriodList.end(); ++itTimePeriod) {
00774           const stdair::TimePeriod* lTimePeriod_ptr = *itTimePeriod;
00775           assert (lTimePeriod_ptr != NULL);
00776           
00777           // TODO: Use trip type from demand instead of default value.
00778           const stdair::YieldFeaturesKey lYieldFeaturesKey (stdair::TRIP_TYPE_ONE_WAY,
00779                                                             iCabinCode);
00780           stdair::YieldFeatures* oYieldFeatures_ptr = stdair::BomManager::
00781             getObjectPtr<stdair::YieldFeatures>(*lTimePeriod_ptr,
00782                                                 lYieldFeaturesKey.toString());
00783           if (oYieldFeatures_ptr != NULL) {
00784             return oYieldFeatures_ptr;
00785           }
00786         }
00787       }
00788     }
00789     return NULL;
00790     
00791   }
00792 
00793   
00794   // ///////////////////////////////////////////////////////////////////
00795   void RMOL_Service::
00796   forecastOnD (const stdair::YieldFeatures& iYieldFeatures,
00797                stdair::OnDDate& iOnDDate,
00798                const stdair::CabinCode_T& iCabinCode,
00799                const stdair::DTD_T& iDTD,
00800                stdair::BomRoot& iBomRoot) {
00801 
00802     const stdair::AirlineClassListList_T lAirlineClassListList =
00803       stdair::BomManager::getList<stdair::AirlineClassList> (iYieldFeatures);
00804     assert (lAirlineClassListList.begin() != lAirlineClassListList.end());
00805 
00806     // Yield order check
00807     stdair::AirlineClassListList_T::const_iterator  itACL =
00808       lAirlineClassListList.begin();
00809     stdair::Yield_T lPreviousYield((*itACL)->getYield());
00810     ++itACL;
00811     for (; itACL != lAirlineClassListList.end(); ++itACL) {
00812       const stdair::AirlineClassList* lAirlineClassList = *itACL;
00813       const stdair::Yield_T& lYield = lAirlineClassList->getYield();
00814       if (lYield <= lPreviousYield) {
00815         lPreviousYield = lYield;
00816       }
00817       else{
00818         STDAIR_LOG_ERROR ("Yields should be given in a descendant order"
00819                           << " in the yield input file") ;
00820         assert (false);
00821       }
00822     }
00823     // Proportion factor list initialisation
00824     // Each element corresponds to a yield rule
00825     stdair::ProportionFactorList_T lProportionFactorList;
00826     stdair::ProportionFactor_T lPreviousProportionFactor = 0;
00827 
00828     // Retrieve the minimal willingness to pay associated to the demand
00829     const stdair::WTPDemandPair_T& lTotalForecast =
00830       iOnDDate.getTotalForecast (iCabinCode);
00831     const stdair::WTP_T& lMinWTP = lTotalForecast.first;
00832    
00833     // Retrieve the remaining percentage of booking requests
00834     const stdair::ContinuousAttributeLite<stdair::FloatDuration_T>
00835       lArrivalPattern (stdair::DEFAULT_DTD_PROB_MAP);
00836      
00837     STDAIR_LOG_DEBUG (lArrivalPattern.displayCumulativeDistribution());
00838     const stdair::Probability_T lRemainingProportion =
00839       lArrivalPattern.getRemainingProportion(-float(iDTD));
00840 
00841     // Compute the characteristics (mean and std dev) of the total
00842     // forecast demand to come
00843     const stdair::MeanStdDevPair_T lForecatsMeanStdDevPair =
00844       lTotalForecast.second;
00845     const stdair::MeanValue_T& lMeanValue =
00846       lForecatsMeanStdDevPair.first;
00847     const stdair::MeanValue_T& lRemainingMeanValue =
00848       lRemainingProportion*lMeanValue;
00849     const stdair::StdDevValue_T& lStdDevValue =
00850       lForecatsMeanStdDevPair.second;
00851     const stdair::StdDevValue_T& lRemainingStdDevValue =
00852       lRemainingProportion*lStdDevValue;
00853 
00854     // Retrieve the frat5 coef corresponding to the input dtd
00855     stdair::DTDFratMap_T::const_iterator itDFC =
00856       stdair::DEFAULT_DTD_FRAT5COEF_MAP.find(iDTD);
00857     if (itDFC == stdair::DEFAULT_DTD_FRAT5COEF_MAP.end()) {
00858       STDAIR_LOG_ERROR ("Cannot find frat5 coef for DTD = " << iDTD );
00859       assert (false);
00860     }
00861     stdair::RealNumber_T lFrat5Coef =
00862       stdair::DEFAULT_DTD_FRAT5COEF_MAP.at(iDTD);
00863 
00864     STDAIR_LOG_DEBUG ("Remaining proportion " << lRemainingProportion
00865                       << " Total " << lMeanValue
00866                       << " StdDev " << lStdDevValue
00867                       << "Frat5 Coef " << lFrat5Coef);
00868 
00869     std::ostringstream oStr;
00870     // Compute the "forecast demand to come" proportion by class
00871     itACL = lAirlineClassListList.begin();
00872     for (; itACL != lAirlineClassListList.end(); ++itACL) {
00873       const stdair::AirlineClassList* lAirlineClassList_ptr = *itACL;
00874       const stdair::Yield_T& lYield = lAirlineClassList_ptr->getYield();
00875       stdair::ProportionFactor_T lProportionFactor =
00876         exp ((lYield - lMinWTP)*log(0.5)/(lMinWTP*(lFrat5Coef-1.0)));
00877       // If the yield is smaller than minimal WTP, the factor is greater than 1.
00878       // In that case it should be modified and put to 1.
00879       lProportionFactor = std::min (lProportionFactor, 1.0);
00880       lProportionFactorList.push_back(lProportionFactor - lPreviousProportionFactor);      
00881       lPreviousProportionFactor = lProportionFactor;
00882       oStr << lAirlineClassList_ptr->toString() << lProportionFactor << " ";
00883     }
00884 
00885     STDAIR_LOG_DEBUG (oStr.str());
00886 
00887     // Sanity check
00888     assert (lAirlineClassListList.size() == lProportionFactorList.size());
00889 
00890     STDAIR_LOG_DEBUG ("Forecast for " << iOnDDate.describeKey()
00891                       << " " << iDTD << " days to departure");
00892 
00893     // store the forecast demand to come characteristics in the booking classes
00894     stdair::ProportionFactorList_T::const_iterator itPF =
00895       lProportionFactorList.begin();
00896     itACL = lAirlineClassListList.begin();
00897     for (; itACL != lAirlineClassListList.end(); ++itACL, ++itPF) {
00898       const stdair::AirlineClassList* lAirlineClassList_ptr = *itACL;
00899       const stdair::ProportionFactor_T& lProportionFactor = *itPF;
00900       stdair::MeanValue_T lMeanValue = lProportionFactor*lRemainingMeanValue;
00901       stdair::StdDevValue_T lStdDevValue =
00902         lProportionFactor*lRemainingStdDevValue;
00903       setOnDForecast(*lAirlineClassList_ptr, lMeanValue, lStdDevValue,
00904                      iOnDDate, iCabinCode, iBomRoot);
00905     }  
00906     
00907   }
00908 
00909   // ///////////////////////////////////////////////////////////////////
00910   void RMOL_Service::
00911   setOnDForecast (const stdair::AirlineClassList& iAirlineClassList,
00912                   const stdair::MeanValue_T& iMeanValue,
00913                   const stdair::StdDevValue_T& iStdDevValue,
00914                   stdair::OnDDate& iOnDDate,
00915                   const stdair::CabinCode_T& iCabinCode,
00916                   stdair::BomRoot& iBomRoot) {
00917     
00918     const stdair::AirportCode_T& lOrigin = iOnDDate.getOrigin();
00919     const stdair::AirportCode_T& lDestination = iOnDDate.getDestination();
00920 
00921     const stdair::Date_T& lDepartureDate = iOnDDate.getDate();
00922 
00923     const stdair::AirlineCodeList_T& lAirlineCodeList =
00924       iAirlineClassList.getAirlineCodeList();
00925 
00926     // Retrieve the class list (one class per airline)
00927     const stdair::ClassList_StringList_T& lClassList_StringList =
00928       iAirlineClassList.getClassCodeList();
00929     assert (!lClassList_StringList.empty());
00930     stdair::ClassCodeList_T lClassCodeList;
00931     for (stdair::ClassList_StringList_T::const_iterator itCL =
00932            lClassList_StringList.begin();
00933          itCL != lClassList_StringList.end(); ++itCL){
00934       const stdair::ClassList_String_T& lClassList_String = *itCL;
00935       assert (lClassList_String.size() > 0);
00936       stdair::ClassCode_T lFirstClass;
00937       lFirstClass.append (lClassList_String, 0, 1);
00938       lClassCodeList.push_back(lFirstClass);
00939     }
00940 
00941     // Sanity check
00942     assert (lAirlineCodeList.size() == lClassCodeList.size());
00943     assert (!lAirlineCodeList.empty());
00944 
00945     if (lAirlineCodeList.size() == 1) {
00946       // Store the forecast information in the case of a single segment
00947       stdair::AirlineCode_T lAirlineCode = lAirlineCodeList.front();
00948       stdair::ClassCode_T lClassCode = lClassCodeList.front();
00949       stdair::Yield_T lYield = iAirlineClassList.getYield();
00950       setOnDForecast(lAirlineCode, lDepartureDate, lOrigin,
00951                      lDestination, iCabinCode, lClassCode,
00952                      iMeanValue, iStdDevValue, lYield, iBomRoot);      
00953     } else {
00954       // Store the forecast information in the case of a multiple segment
00955       
00956       stdair::Yield_T lYield = iAirlineClassList.getYield();
00957       for (stdair::AirlineCodeList_T::const_iterator itAC =
00958              lAirlineCodeList.begin();
00959            itAC != lAirlineCodeList.end(); ++itAC) {
00960         const stdair::AirlineCode_T& lAirlineCode = *itAC;
00961         setOnDForecast(lAirlineCodeList, lAirlineCode, lDepartureDate, lOrigin,
00962                        lDestination, iCabinCode, lClassCodeList,
00963                        iMeanValue, iStdDevValue, lYield, iBomRoot);
00964       }      
00965     }
00966   }
00967 
00968   // ///////////////////////////////////////////////////////////////////
00969   void RMOL_Service::
00970   setOnDForecast (const stdair::AirlineCode_T& iAirlineCode,
00971                   const stdair::Date_T& iDepartureDate,
00972                   const stdair::AirportCode_T& iOrigin,
00973                   const stdair::AirportCode_T& iDestination,
00974                   const stdair::CabinCode_T& iCabinCode,
00975                   const stdair::ClassCode_T& iClassCode,
00976                   const stdair::MeanValue_T& iMeanValue,
00977                   const stdair::StdDevValue_T& iStdDevValue,
00978                   const stdair::Yield_T& iYield,
00979                   stdair::BomRoot& iBomRoot) {
00980     stdair::Inventory* lInventory_ptr = iBomRoot.getInventory(iAirlineCode);
00981     if (lInventory_ptr == NULL) {
00982       STDAIR_LOG_ERROR ("Cannot find the inventory corresponding"
00983                         << " to the airline" << iAirlineCode) ;
00984       assert(false);
00985     }
00986     const stdair::OnDDateList_T lOnDDateList =
00987       stdair::BomManager::getList<stdair::OnDDate> (*lInventory_ptr);
00988     assert (!lOnDDateList.empty());
00989     bool lFoundOnDDate = false;
00990     for (stdair::OnDDateList_T::const_iterator itOD = lOnDDateList.begin();
00991          itOD != lOnDDateList.end(); ++itOD) {
00992       stdair::OnDDate* lOnDDate_ptr = *itOD;
00993       assert (lOnDDate_ptr != NULL);
00994       const stdair::Date_T& lDepartureDate = lOnDDate_ptr->getDate();
00995       const stdair::AirportCode_T& lOrigin = lOnDDate_ptr->getOrigin();
00996       const stdair::AirportCode_T& lDestination = lOnDDate_ptr->getDestination();
00997       const bool hasSegmentDateList =
00998         stdair::BomManager::hasList<stdair::SegmentDate> (*lOnDDate_ptr);
00999       if (hasSegmentDateList == false) {
01000         STDAIR_LOG_ERROR ("The O&D date " << lOnDDate_ptr->describeKey()
01001                           << "has not been correctly initialized : SegmentDate list is missing");
01002         assert (false);
01003       }
01004       const stdair::SegmentDateList_T& lSegmentDateList =
01005         stdair::BomManager::getList<stdair::SegmentDate> (*lOnDDate_ptr);
01006       // Check if the the O&D date is the one we are looking for
01007       if (lDepartureDate == iDepartureDate && lOrigin == iOrigin &&
01008           lDestination == iDestination && lSegmentDateList.size() == 1) {       
01009         stdair::CabinClassPair_T lCabinClassPair (iCabinCode, iClassCode);
01010         stdair::CabinClassPairList_T lCabinClassPairList;
01011         lCabinClassPairList.push_back(lCabinClassPair);
01012         const stdair::MeanStdDevPair_T lMeanStdDevPair (iMeanValue, iStdDevValue);
01013         const stdair::WTPDemandPair_T lWTPDemandPair (iYield, lMeanStdDevPair);
01014         lOnDDate_ptr->setDemandInformation(lCabinClassPairList, lWTPDemandPair);
01015         lFoundOnDDate = true;
01016         STDAIR_LOG_DEBUG (iAirlineCode << " Class " << iClassCode
01017                           << " Mean " << iMeanValue
01018                           << " Std Dev " << iStdDevValue);
01019         break;
01020       }
01021     }
01022 
01023     if (!lFoundOnDDate) {
01024       STDAIR_LOG_ERROR ("Cannot find class " << iClassCode << " in cabin "
01025                         << iCabinCode << " for the segment "
01026                         << iOrigin << "-" << iDestination << " with"
01027                         << " the airline " << iAirlineCode);
01028       assert(false);
01029     }
01030   }
01031   
01032   // ///////////////////////////////////////////////////////////////////       
01033   void RMOL_Service::
01034   setOnDForecast (const stdair::AirlineCodeList_T& iAirlineCodeList,
01035                   const stdair::AirlineCode_T& iAirlineCode,
01036                   const stdair::Date_T& iDepartureDate,
01037                   const stdair::AirportCode_T& iOrigin,
01038                   const stdair::AirportCode_T& iDestination,
01039                   const stdair::CabinCode_T& iCabinCode,
01040                   const stdair::ClassCodeList_T& iClassCodeList,
01041                   const stdair::MeanValue_T& iMeanValue,
01042                   const stdair::StdDevValue_T& iStdDevValue,
01043                   const stdair::Yield_T& iYield,
01044                   stdair::BomRoot& iBomRoot) {    
01045     stdair::Inventory* lInventory_ptr = iBomRoot.getInventory(iAirlineCode);
01046     if (lInventory_ptr == NULL) {
01047       STDAIR_LOG_ERROR ("Cannot find the inventory corresponding"
01048                         << " to the airline" << iAirlineCode) ;
01049       assert(false);
01050     }
01051     const stdair::OnDDateList_T lOnDDateList =
01052       stdair::BomManager::getList<stdair::OnDDate> (*lInventory_ptr);
01053     assert (!lOnDDateList.empty());
01054     bool lFoundOnDDate = false;
01055     for (stdair::OnDDateList_T::const_iterator itOD = lOnDDateList.begin();
01056          itOD != lOnDDateList.end(); ++itOD) {
01057       stdair::OnDDate* lOnDDate_ptr = *itOD;
01058       assert (lOnDDate_ptr != NULL);
01059       const stdair::Date_T& lDepartureDate = lOnDDate_ptr->getDate();
01060       const stdair::AirportCode_T& lOrigin = lOnDDate_ptr->getOrigin();
01061       const stdair::AirportCode_T& lDestination = lOnDDate_ptr->getDestination();
01062       const bool hasSegmentDateList =
01063         stdair::BomManager::hasList<stdair::SegmentDate> (*lOnDDate_ptr);
01064       if (hasSegmentDateList == false) {
01065         STDAIR_LOG_ERROR ("The O&D date " << lOnDDate_ptr->describeKey()
01066                           << "has not been correctly initialized : SegmentDate list is missing");
01067         assert (false);
01068       }
01069       const stdair::SegmentDateList_T& lSegmentDateList =
01070         stdair::BomManager::getList<stdair::SegmentDate> (*lOnDDate_ptr);
01071       // Check if the O&D date might be the one we are looking for.
01072       // There still is a test to go through to see if the combination of airlines is right.
01073       if (lDepartureDate == iDepartureDate && lOrigin == iOrigin &&
01074           lDestination == iDestination && lSegmentDateList.size() == iAirlineCodeList.size()) {
01075         const stdair::SegmentDateList_T& lSegmentDateList =
01076           stdair::BomManager::getList<stdair::SegmentDate> (*lOnDDate_ptr);        
01077         stdair::AirlineCodeList_T::const_iterator itAC = iAirlineCodeList.begin();
01078         stdair::SegmentDateList_T::const_iterator itSD = lSegmentDateList.begin();
01079         for (;itAC != iAirlineCodeList.end(); ++itAC, ++itSD) {
01080           const stdair::AirlineCode_T lForecastAirlineCode = *itAC;
01081           const stdair::SegmentDate* lSegmentDate_ptr = *itSD;
01082           // Check if the operating airline is a different one and check if it
01083           // is the airline that we are looking for.
01084           const stdair::SegmentDate* lOperatingSegmentDate_ptr =
01085             lSegmentDate_ptr->getOperatingSegmentDate ();
01086           if (lOperatingSegmentDate_ptr != NULL) {
01087             const stdair::FlightDate* lOperatingFD_ptr =
01088               stdair::BomManager::getParentPtr<stdair::FlightDate>(*lOperatingSegmentDate_ptr);
01089             const stdair::AirlineCode_T lOperatingAirlineCode =
01090               lOperatingFD_ptr->getAirlineCode();
01091             if (lOperatingAirlineCode != lForecastAirlineCode) {
01092               break;
01093             }
01094           } else {
01095             const stdair::AirlineCode_T lOperatingAirlineCode =
01096               lOnDDate_ptr->getAirlineCode();
01097             if (lOperatingAirlineCode != lForecastAirlineCode) {
01098               break;
01099             }
01100           }          
01101         }
01102         if (itAC == iAirlineCodeList.end()) {lFoundOnDDate = true;}
01103       }
01104       if (lFoundOnDDate) {        
01105         stdair::CabinClassPairList_T lCabinClassPairList;
01106         for (stdair::ClassCodeList_T::const_iterator itCC = iClassCodeList.begin();
01107              itCC != iClassCodeList.end(); ++itCC) {
01108           const stdair::ClassCode_T lClassCode = *itCC;
01109           stdair::CabinClassPair_T lCabinClassPair (iCabinCode, lClassCode);
01110           lCabinClassPairList.push_back(lCabinClassPair);
01111         }
01112         const stdair::MeanStdDevPair_T lMeanStdDevPair (iMeanValue, iStdDevValue);
01113         const stdair::YieldDemandPair_T lYieldDemandPair (iYield, lMeanStdDevPair);
01114         lOnDDate_ptr->setDemandInformation(lCabinClassPairList, lYieldDemandPair);
01115         lFoundOnDDate = true;
01116         std::ostringstream oACStr;
01117         for (stdair::AirlineCodeList_T::const_iterator itAC = iAirlineCodeList.begin();
01118              itAC != iAirlineCodeList.end(); ++itAC) {
01119           if (itAC == iAirlineCodeList.begin()) {
01120             oACStr << *itAC;
01121           }
01122           else {
01123             oACStr << "-" << *itAC;
01124           }
01125         }
01126         std::ostringstream oCCStr;
01127         for (stdair::ClassCodeList_T::const_iterator itCC = iClassCodeList.begin();
01128              itCC != iClassCodeList.end(); ++itCC) {
01129           if (itCC == iClassCodeList.begin()) {
01130             oCCStr << *itCC;
01131           }
01132           else {
01133             oCCStr << "-" << *itCC;
01134           }
01135         }
01136         
01137         STDAIR_LOG_DEBUG (oACStr.str() << " Classes " << oCCStr.str()
01138                           << " Mean " << iMeanValue << " Std Dev " << iStdDevValue);        
01139         break;
01140       }
01141     }
01142     if (!lFoundOnDDate) {
01143       STDAIR_LOG_ERROR ("Cannot find the required multi-segment O&D date:  "
01144                         << iOrigin << "-" << iDestination << " " << iDepartureDate);
01145       assert(false);
01146     }
01147   }
01148   
01149   // ///////////////////////////////////////////////////////////////////
01150   void RMOL_Service::
01151   resetDemandInformation (const stdair::DateTime_T& iRMEventTime) {
01152     if (_rmolServiceContext == NULL) {
01153       throw stdair::NonInitialisedServiceException ("The Rmol service "
01154                                                     "has not been initialised");
01155     }
01156     assert (_rmolServiceContext != NULL);
01157     RMOL_ServiceContext& lRMOL_ServiceContext = *_rmolServiceContext;
01158     
01159     // Retrieve the bom root
01160     stdair::STDAIR_Service& lSTDAIR_Service =
01161       lRMOL_ServiceContext.getSTDAIR_Service();
01162     stdair::BomRoot& lBomRoot = lSTDAIR_Service.getBomRoot();
01163 
01164     const stdair::InventoryList_T lInventoryList =
01165       stdair::BomManager::getList<stdair::Inventory> (lBomRoot);
01166     assert (!lInventoryList.empty());
01167     for (stdair::InventoryList_T::const_iterator itInv = lInventoryList.begin();
01168          itInv != lInventoryList.end(); ++itInv) {
01169       const stdair::Inventory* lInventory_ptr = *itInv;
01170       assert (lInventory_ptr != NULL);
01171       resetDemandInformation (iRMEventTime, *lInventory_ptr);
01172     }
01173   }
01174 
01175   // ///////////////////////////////////////////////////////////////////
01176   void RMOL_Service::
01177   resetDemandInformation (const stdair::DateTime_T& iRMEventTime,
01178                           const stdair::Inventory& iInventory) {
01179     
01180     const stdair::FlightDateList_T lFlightDateList =
01181       stdair::BomManager::getList<stdair::FlightDate> (iInventory);
01182     assert (!lFlightDateList.empty());
01183     for (stdair::FlightDateList_T::const_iterator itFD = lFlightDateList.begin();
01184          itFD != lFlightDateList.end(); ++itFD) {
01185       const stdair::FlightDate* lFlightDate_ptr = *itFD;
01186       assert (lFlightDate_ptr != NULL);
01187       
01188       // Retrieve the date from the RM event
01189       const stdair::Date_T lDate = iRMEventTime.date();
01190       
01191       const stdair::Date_T& lDepartureDate = lFlightDate_ptr->getDepartureDate();
01192       stdair::DateOffset_T lDateOffset = lDepartureDate - lDate;
01193       stdair::DTD_T lDTD = short (lDateOffset.days());
01194       
01195       stdair::DCPList_T::const_iterator itDCP =
01196         std::find (stdair::DEFAULT_DCP_LIST.begin(), stdair::DEFAULT_DCP_LIST.end(), lDTD);
01197       // Check if the demand forecast info corresponding to this flight date needs to be reset.
01198       if (itDCP != stdair::DEFAULT_DCP_LIST.end()) {
01199         // Check if the flight date holds a list of leg dates.
01200         // If so, find all leg cabin and reset the forecast they are holding.
01201         const bool hasLegDateList =
01202           stdair::BomManager::hasList<stdair::LegDate> (*lFlightDate_ptr);
01203         if (hasLegDateList == true) {
01204           const stdair::LegDateList_T lLegDateList =
01205             stdair::BomManager::getList<stdair::LegDate> (*lFlightDate_ptr);
01206           assert (!lLegDateList.empty());
01207           for (stdair::LegDateList_T::const_iterator itLD = lLegDateList.begin();
01208                itLD != lLegDateList.end(); ++itLD) {
01209             const stdair::LegDate* lLegDate_ptr = *itLD;
01210             assert (lLegDate_ptr != NULL);
01211             const stdair::LegCabinList_T lLegCabinList =
01212               stdair::BomManager::getList<stdair::LegCabin> (*lLegDate_ptr);
01213             assert (!lLegCabinList.empty());
01214             for (stdair::LegCabinList_T::const_iterator itLC = lLegCabinList.begin();
01215                  itLC != lLegCabinList.end(); ++itLC) {
01216               stdair::LegCabin* lLegCabin_ptr = *itLC;
01217               assert (lLegCabin_ptr != NULL);
01218               lLegCabin_ptr->emptyYieldLevelDemandMap();
01219             }
01220           }
01221         }
01222       }
01223     }
01224   }
01225   
01226   // ///////////////////////////////////////////////////////////////////
01227   void RMOL_Service::projectAggregatedDemandOnLegCabins(const stdair::DateTime_T& iRMEventTime) {
01228 
01229     if (_rmolServiceContext == NULL) {
01230       throw stdair::NonInitialisedServiceException ("The Rmol service "
01231                                                     "has not been initialised");
01232     }
01233     assert (_rmolServiceContext != NULL);
01234     RMOL_ServiceContext& lRMOL_ServiceContext = *_rmolServiceContext;
01235     
01236     // Retrieve the bom root
01237     stdair::STDAIR_Service& lSTDAIR_Service =
01238       lRMOL_ServiceContext.getSTDAIR_Service();
01239     stdair::BomRoot& lBomRoot = lSTDAIR_Service.getBomRoot();
01240 
01241     // Retrieve the date from the RM event
01242     const stdair::Date_T lDate = iRMEventTime.date();
01243 
01244     const stdair::InventoryList_T lInventoryList =
01245       stdair::BomManager::getList<stdair::Inventory> (lBomRoot);
01246     assert (!lInventoryList.empty());
01247     for (stdair::InventoryList_T::const_iterator itInv = lInventoryList.begin();
01248          itInv != lInventoryList.end(); ++itInv) {
01249       const stdair::Inventory* lInventory_ptr = *itInv;
01250       assert (lInventory_ptr != NULL);
01251       const stdair::OnDDateList_T lOnDDateList =
01252         stdair::BomManager::getList<stdair::OnDDate> (*lInventory_ptr);
01253       assert (!lOnDDateList.empty());
01254       for (stdair::OnDDateList_T::const_iterator itOD = lOnDDateList.begin();
01255            itOD != lOnDDateList.end(); ++itOD) {
01256         stdair::OnDDate* lOnDDate_ptr = *itOD;
01257         assert (lOnDDate_ptr != NULL);
01258 
01259         const stdair::Date_T& lDepartureDate = lOnDDate_ptr->getDate();
01260         stdair::DateOffset_T lDateOffset = lDepartureDate - lDate;
01261         stdair::DTD_T lDTD = short (lDateOffset.days());
01262       
01263         stdair::DCPList_T::const_iterator itDCP =
01264           std::find (stdair::DEFAULT_DCP_LIST.begin(), stdair::DEFAULT_DCP_LIST.end(), lDTD);
01265         // Check if the forecast for this O&D date needs to be projected.
01266         if (itDCP != stdair::DEFAULT_DCP_LIST.end()) {
01267 
01268           // Browse the demand info map.
01269           const stdair::StringDemandStructMap_T& lStringDemandStructMap =
01270             lOnDDate_ptr->getDemandInfoMap ();
01271           for (stdair::StringDemandStructMap_T::const_iterator itStrDS = lStringDemandStructMap.begin();
01272                itStrDS != lStringDemandStructMap.end(); ++itStrDS) {
01273             std::string lCabinClassPath = itStrDS->first;
01274             const stdair::YieldDemandPair_T& lYieldDemandPair =
01275               itStrDS->second;
01276             const stdair::CabinClassPairList_T& lCabinClassPairList =
01277               lOnDDate_ptr->getCabinClassPairList(lCabinClassPath);
01278             const stdair::NbOfSegments_T& lNbOfSegments = lOnDDate_ptr->getNbOfSegments();
01279             // Sanity check
01280             assert (lCabinClassPairList.size() == lNbOfSegments);
01281             
01282             const stdair::SegmentDateList_T lOnDSegmentDateList =
01283               stdair::BomManager::getList<stdair::SegmentDate> (*lOnDDate_ptr);
01284             // Sanity check
01285             assert (lOnDSegmentDateList.size() == lNbOfSegments);
01286             stdair::CabinClassPairList_T::const_iterator itCCP = lCabinClassPairList.begin();
01287             stdair::SegmentDateList_T::const_iterator itSD = lOnDSegmentDateList.begin();
01288             for (; itSD != lOnDSegmentDateList.end(); ++itCCP, ++itSD) {
01289               const stdair::SegmentDate* lSegmentDate_ptr = *itSD;
01290               const stdair::SegmentDate* lOperatingSegmentDate_ptr =
01291                 lSegmentDate_ptr->getOperatingSegmentDate ();
01292               assert (lSegmentDate_ptr != NULL);
01293               // Only operated legs receive the demand information.
01294               if (lOperatingSegmentDate_ptr == NULL) {
01295                 const stdair::CabinCode_T lCabinCode = itCCP->first;
01296                 const stdair::ClassCode_T lClassCode = itCCP->second;
01297                 const stdair::SegmentCabin* lSegmentCabin_ptr =
01298                   stdair::BomManager::getObjectPtr<stdair::SegmentCabin> (*lSegmentDate_ptr,
01299                                                                           lCabinCode);
01300                 assert (lSegmentCabin_ptr != NULL);
01301                 // Retrieve the booking class (level of aggregation of demand).
01302                 // The yield of the class is assigned to all types of demand for it.
01303                 const stdair::BookingClass* lBookingClass_ptr =
01304                   stdair::BomManager::getObjectPtr<stdair::BookingClass> (*lSegmentCabin_ptr,
01305                                                                           lClassCode);
01306                 assert (lBookingClass_ptr != NULL);
01307                 const stdair::LegCabinList_T lLegCabinList =
01308                   stdair::BomManager::getList<stdair::LegCabin> (*lSegmentCabin_ptr);
01309                 assert (!lLegCabinList.empty());
01310                 const int lNbOfLegs = lLegCabinList.size();
01311                 // Determine the yield (equally distributed over legs).
01312                 const stdair::Yield_T& lYield = lBookingClass_ptr->getYield()/lNbOfLegs;
01313                 const stdair::MeanStdDevPair_T& lMeanStdDevPair =
01314                   lYieldDemandPair.second;
01315                 const stdair::MeanValue_T& lMeanValue = lMeanStdDevPair.first;
01316                 const stdair::StdDevValue_T& lStdDevValue = lMeanStdDevPair.second;
01317                 for (stdair::LegCabinList_T::const_iterator itLC = lLegCabinList.begin();
01318                      itLC != lLegCabinList.end(); ++itLC) {
01319                   stdair::LegCabin* lLegCabin_ptr = *itLC;
01320                   assert (lLegCabin_ptr != NULL);
01321                   lLegCabin_ptr->addDemandInformation (lYield, lMeanValue, lStdDevValue);
01322                 }
01323               }
01324             }
01325           }
01326         }
01327       }
01328     }
01329   }
01330 
01331   // ///////////////////////////////////////////////////////////////////
01332   void RMOL_Service::projectOnDDemandOnLegCabinsUsingYP(const stdair::DateTime_T& iRMEventTime) {
01333 
01334     if (_rmolServiceContext == NULL) {
01335       throw stdair::NonInitialisedServiceException ("The Rmol service "
01336                                                     "has not been initialised");
01337     }
01338     assert (_rmolServiceContext != NULL);
01339     RMOL_ServiceContext& lRMOL_ServiceContext = *_rmolServiceContext;
01340     
01341     // Retrieve the bom root
01342     stdair::STDAIR_Service& lSTDAIR_Service =
01343       lRMOL_ServiceContext.getSTDAIR_Service();
01344     stdair::BomRoot& lBomRoot = lSTDAIR_Service.getBomRoot();
01345 
01346     // Retrieve the date from the RM event
01347     const stdair::Date_T lDate = iRMEventTime.date();
01348 
01349     const stdair::InventoryList_T lInventoryList =
01350       stdair::BomManager::getList<stdair::Inventory> (lBomRoot);
01351     assert (!lInventoryList.empty());
01352     for (stdair::InventoryList_T::const_iterator itInv = lInventoryList.begin();
01353          itInv != lInventoryList.end(); ++itInv) {
01354       const stdair::Inventory* lInventory_ptr = *itInv;
01355       assert (lInventory_ptr != NULL);
01356       const stdair::OnDDateList_T lOnDDateList =
01357         stdair::BomManager::getList<stdair::OnDDate> (*lInventory_ptr);
01358       assert (!lOnDDateList.empty());
01359       for (stdair::OnDDateList_T::const_iterator itOD = lOnDDateList.begin();
01360            itOD != lOnDDateList.end(); ++itOD) {
01361         stdair::OnDDate* lOnDDate_ptr = *itOD;
01362         assert (lOnDDate_ptr != NULL);
01363 
01364         const stdair::Date_T& lDepartureDate = lOnDDate_ptr->getDate();
01365         stdair::DateOffset_T lDateOffset = lDepartureDate - lDate;
01366         stdair::DTD_T lDTD = short (lDateOffset.days());
01367       
01368         stdair::DCPList_T::const_iterator itDCP =
01369           std::find (stdair::DEFAULT_DCP_LIST.begin(), stdair::DEFAULT_DCP_LIST.end(), lDTD);
01370         // Check if the forecast for this O&D date needs to be projected.
01371         if (itDCP != stdair::DEFAULT_DCP_LIST.end()) {
01372 
01373           // Browse the demand info map.
01374           const stdair::StringDemandStructMap_T& lStringDemandStructMap =
01375             lOnDDate_ptr->getDemandInfoMap ();
01376           for (stdair::StringDemandStructMap_T::const_iterator itStrDS = lStringDemandStructMap.begin();
01377                itStrDS != lStringDemandStructMap.end(); ++itStrDS) {
01378             std::string lCabinClassPath = itStrDS->first;
01379             const stdair::YieldDemandPair_T& lYieldDemandPair =
01380               itStrDS->second;
01381             const stdair::CabinClassPairList_T& lCabinClassPairList =
01382               lOnDDate_ptr->getCabinClassPairList(lCabinClassPath);
01383             const stdair::NbOfSegments_T& lNbOfSegments = lOnDDate_ptr->getNbOfSegments();
01384             // Sanity check
01385             assert (lCabinClassPairList.size() == lNbOfSegments);
01386             
01387             const stdair::SegmentDateList_T lOnDSegmentDateList =
01388               stdair::BomManager::getList<stdair::SegmentDate> (*lOnDDate_ptr);
01389             // Sanity check
01390             assert (lOnDSegmentDateList.size() == lNbOfSegments);
01391             stdair::CabinClassPairList_T::const_iterator itCCP = lCabinClassPairList.begin();
01392             stdair::SegmentDateList_T::const_iterator itSD = lOnDSegmentDateList.begin();
01393             for (; itSD != lOnDSegmentDateList.end(); ++itCCP, ++itSD) {
01394               const stdair::SegmentDate* lSegmentDate_ptr = *itSD;
01395               assert (lSegmentDate_ptr != NULL);
01396               const stdair::SegmentDate* lOperatingSegmentDate_ptr =
01397                 lSegmentDate_ptr->getOperatingSegmentDate ();
01398               // Only operated legs receive the demand information.
01399               if (lOperatingSegmentDate_ptr == NULL) {
01400                 const stdair::CabinCode_T lCabinCode = itCCP->first;
01401                 const stdair::ClassCode_T lClassCode = itCCP->second;
01402                 const stdair::SegmentCabin* lSegmentCabin_ptr =
01403                   stdair::BomManager::getObjectPtr<stdair::SegmentCabin> (*lSegmentDate_ptr,
01404                                                                           lCabinCode);
01405                 assert (lSegmentCabin_ptr != NULL);
01406                 const stdair::LegCabinList_T lLegCabinList =
01407                   stdair::BomManager::getList<stdair::LegCabin> (*lSegmentCabin_ptr);
01408                 assert (!lLegCabinList.empty());
01409                 const int lNbOfLegs = lLegCabinList.size();
01410                 // Determine the yield (equally distributed over segments and then legs).
01411                 const stdair::MeanStdDevPair_T& lMeanStdDevPair =
01412                   lYieldDemandPair.second;
01413                 const stdair::Yield_T& lYield = lYieldDemandPair.first/(lNbOfLegs*lNbOfSegments);
01414                 const stdair::MeanValue_T& lMeanValue = lMeanStdDevPair.first;
01415                 const stdair::StdDevValue_T& lStdDevValue = lMeanStdDevPair.second;
01416                 for (stdair::LegCabinList_T::const_iterator itLC = lLegCabinList.begin();
01417                      itLC != lLegCabinList.end(); ++itLC) {
01418                   stdair::LegCabin* lLegCabin_ptr = *itLC;
01419                   assert (lLegCabin_ptr != NULL);
01420                   lLegCabin_ptr->addDemandInformation (lYield, lMeanValue, lStdDevValue);
01421                 }
01422               }
01423             }
01424           }
01425         }
01426       }
01427     }
01428   }
01429 
01430   // ///////////////////////////////////////////////////////////////////
01431   void RMOL_Service::optimiseOnD (const stdair::DateTime_T& iRMEventTime) {
01432 
01433     if (_rmolServiceContext == NULL) {
01434       throw stdair::NonInitialisedServiceException ("The Rmol service "
01435                                                     "has not been initialised");
01436     }
01437     assert (_rmolServiceContext != NULL);
01438     RMOL_ServiceContext& lRMOL_ServiceContext = *_rmolServiceContext;
01439 
01440     // Retrieve the bom root
01441     stdair::STDAIR_Service& lSTDAIR_Service =
01442       lRMOL_ServiceContext.getSTDAIR_Service();
01443     stdair::BomRoot& lBomRoot = lSTDAIR_Service.getBomRoot();
01444 
01445     // Retrieve the date from the RM event
01446     const stdair::Date_T lDate = iRMEventTime.date();
01447 
01448     const stdair::InventoryList_T& lInvList =
01449       stdair::BomManager::getList<stdair::Inventory> (lBomRoot);
01450     for (stdair::InventoryList_T::const_iterator itInv = lInvList.begin();
01451          itInv != lInvList.end(); ++itInv) {
01452       stdair::Inventory* lCurrentInv_ptr = *itInv;
01453       assert (lCurrentInv_ptr != NULL);
01454 
01455       const stdair::FlightDateList_T& lFlightDateList =
01456         stdair::BomManager::getList<stdair::FlightDate> (*lCurrentInv_ptr);
01457       for (stdair::FlightDateList_T::const_iterator itFlightDate =
01458              lFlightDateList.begin();
01459            itFlightDate != lFlightDateList.end(); ++itFlightDate) {
01460         stdair::FlightDate* lCurrentFlightDate_ptr = *itFlightDate;
01461         assert (lCurrentFlightDate_ptr != NULL);
01462 
01463         const stdair::Date_T& lCurrentDepartureDate = lCurrentFlightDate_ptr->getDepartureDate();
01464         stdair::DateOffset_T lDateOffset = lCurrentDepartureDate - lDate;
01465         stdair::DTD_T lDTD = short (lDateOffset.days());
01466       
01467         stdair::DCPList_T::const_iterator itDCP =
01468           std::find (stdair::DEFAULT_DCP_LIST.begin(), stdair::DEFAULT_DCP_LIST.end(), lDTD);
01469         // Check if the optimisation is needed.
01470         if (itDCP != stdair::DEFAULT_DCP_LIST.end()) {
01471           STDAIR_LOG_DEBUG ("Optimisation using O&D forecast: " << lCurrentInv_ptr->getAirlineCode()
01472                             << " Departure " << lCurrentDepartureDate << " DTD " << lDTD);
01473           Optimiser::optimiseUsingOnDForecast (*lCurrentFlightDate_ptr);
01474         }
01475       }
01476     }    
01477   }
01478 
01479   // ///////////////////////////////////////////////////////////////////
01480   void RMOL_Service::updateBidPrice (const stdair::DateTime_T& iRMEventTime) {
01481 
01482     if (_rmolServiceContext == NULL) {
01483       throw stdair::NonInitialisedServiceException ("The Rmol service "
01484                                                     "has not been initialised");
01485     }
01486     assert (_rmolServiceContext != NULL);
01487     RMOL_ServiceContext& lRMOL_ServiceContext = *_rmolServiceContext;
01488 
01489     // Retrieve the bom root
01490     stdair::STDAIR_Service& lSTDAIR_Service =
01491       lRMOL_ServiceContext.getSTDAIR_Service();
01492     stdair::BomRoot& lBomRoot = lSTDAIR_Service.getBomRoot();
01493 
01494     // Retrieve the date from the RM event
01495     const stdair::Date_T lDate = iRMEventTime.date();
01496 
01497     const stdair::InventoryList_T& lInvList =
01498       stdair::BomManager::getList<stdair::Inventory> (lBomRoot);
01499 
01500     for (stdair::InventoryList_T::const_iterator itInv = lInvList.begin();
01501          itInv != lInvList.end(); ++itInv) {
01502       stdair::Inventory* lCurrentInv_ptr = *itInv;
01503       assert (lCurrentInv_ptr != NULL);
01504       
01505       const stdair::FlightDateList_T& lFlightDateList =
01506         stdair::BomManager::getList<stdair::FlightDate> (*lCurrentInv_ptr);
01507       for (stdair::FlightDateList_T::const_iterator itFlightDate =
01508              lFlightDateList.begin();
01509            itFlightDate != lFlightDateList.end(); ++itFlightDate) {
01510         stdair::FlightDate* lCurrentFlightDate_ptr = *itFlightDate;
01511         assert (lCurrentFlightDate_ptr != NULL);
01512 
01513         const stdair::Date_T& lCurrentDepartureDate = lCurrentFlightDate_ptr->getDepartureDate();
01514         stdair::DateOffset_T lDateOffset = lCurrentDepartureDate - lDate;
01515         stdair::DTD_T lDTD = short (lDateOffset.days());
01516       
01517         stdair::DCPList_T::const_iterator itDCP =
01518           std::find (stdair::DEFAULT_DCP_LIST.begin(), stdair::DEFAULT_DCP_LIST.end(), lDTD);
01519         // Check if the operation is needed.
01520         if (itDCP != stdair::DEFAULT_DCP_LIST.end()) {
01521           updateBidPrice (*lCurrentFlightDate_ptr, lBomRoot);
01522         }
01523       }
01524     }
01525   }
01526 
01527   // ///////////////////////////////////////////////////////////////////
01528   void RMOL_Service::updateBidPrice (const stdair::FlightDate& iFlightDate,
01529                                           stdair::BomRoot& iBomRoot) {
01530     const stdair::SegmentDateList_T& lSegmentDateList =
01531       stdair::BomManager::getList<stdair::SegmentDate> (iFlightDate);
01532     const stdair::AirlineCode_T& lOptAC = iFlightDate.getAirlineCode();
01533     const std::string lFDKeyStr = iFlightDate.describeKey();
01534     
01535     for (stdair::SegmentDateList_T::const_iterator itSegmentDate = lSegmentDateList.begin();
01536          itSegmentDate != lSegmentDateList.end(); ++itSegmentDate) {
01537       stdair::SegmentDate* lSegmentDate_ptr = *itSegmentDate;
01538       assert (lSegmentDate_ptr != NULL);
01539       const bool hasSegmentDateList =
01540         stdair::BomManager::hasList<stdair::SegmentDate>(*lSegmentDate_ptr);
01541       if (hasSegmentDateList == true) {
01542         const stdair::LegDateList_T& lLegDateList =
01543           stdair::BomManager::getList<stdair::LegDate>(*lSegmentDate_ptr);
01544         // Get the list of marketing carriers segments.
01545         // These are part of maketing partners inventories images held by the operating airline.
01546         const stdair::SegmentDateList_T& lMktSegmentDateList =
01547           stdair::BomManager::getList<stdair::SegmentDate>(*lSegmentDate_ptr);
01548         for (stdair::SegmentDateList_T::const_iterator itMktSD = lMktSegmentDateList.begin();
01549              itMktSD != lMktSegmentDateList.end(); ++itMktSD) {
01550           // Get the marketing airline code.
01551           stdair::SegmentDate* lMktSD_ptr = *itMktSD;
01552           assert (lMktSD_ptr != NULL);
01553           stdair::FlightDate* lMktFD_ptr =
01554             stdair::BomManager::getParentPtr<stdair::FlightDate>(*lMktSD_ptr);
01555           assert (lMktFD_ptr != NULL);
01556           const stdair::AirlineCode_T& lMktAC = lMktFD_ptr->getAirlineCode();
01557           // Get the (real) marketer inventory.
01558           const stdair::Inventory* lMktInv_ptr =
01559             stdair::BomManager::getObjectPtr<stdair::Inventory>(iBomRoot,lMktAC);
01560           assert (lMktInv_ptr != NULL);
01561           // Get the image of the operating airline inventory held by the marketer.
01562           const stdair::Inventory* lOptInv_ptr =
01563             stdair::BomManager::getObjectPtr<stdair::Inventory>(*lMktInv_ptr,lOptAC);
01564           assert (lOptInv_ptr != NULL);
01565           // Find the image of the concerned flight date.
01566           const stdair::FlightDate* lOptFD_ptr =
01567             stdair::BomManager::getObjectPtr<stdair::FlightDate>(*lOptInv_ptr,lFDKeyStr);
01568           assert (lOptFD_ptr != NULL);
01569           // Browse the list of leg dates in the real operating inventory.
01570           // Retrieve the image of each leg date.
01571           for (stdair::LegDateList_T::const_iterator itLD = lLegDateList.begin();
01572                itLD != lLegDateList.end(); ++itLD) {
01573             const stdair::LegDate* lLD_ptr = *itLD;
01574             assert (lLD_ptr != NULL);
01575             const std::string lLDKeyStr = lLD_ptr->describeKey();
01576             stdair::LegDate* lOptLD_ptr =
01577               stdair::BomManager::getObjectPtr<stdair::LegDate>(*lOptFD_ptr,lLDKeyStr);
01578             assert (lOptLD_ptr != NULL);
01579             const stdair::LegCabinList_T& lLegCabinList_T =
01580               stdair::BomManager::getList<stdair::LegCabin>(*lLD_ptr);
01581             // Browse the list of leg cabins in the real operating inventory.
01582             // Retrieve the image of each leg cabin and update the bid price of the real and send it to the image.
01583             for (stdair::LegCabinList_T::const_iterator itLC = lLegCabinList_T.begin();
01584                  itLC != lLegCabinList_T.end(); ++itLC) {
01585               stdair::LegCabin* lLC_ptr = *itLC;
01586               assert (lLC_ptr != NULL);
01587               const std::string lLCKeyStr = lLC_ptr->describeKey();
01588               stdair::LegCabin* lOptLC_ptr =
01589                 stdair::BomManager::getObjectPtr<stdair::LegCabin>(*lOptLD_ptr, lLCKeyStr);
01590               assert (lOptLC_ptr != NULL);
01591               // Update the current bid price of the real leg.
01592               lLC_ptr->updateCurrentBidPrice();
01593               // Update the previous bid price (store the current).
01594               lOptLC_ptr->updatePreviousBidPrice();
01595               // Update the current bid price.
01596               lOptLC_ptr->setCurrentBidPrice (lLC_ptr->getCurrentBidPrice());
01597 
01598               STDAIR_LOG_DEBUG ("Update bid price of " << lLC_ptr->getFullerKey()
01599                                 << " : " << lOptLC_ptr->getCurrentBidPrice()
01600                                 << " Availability pool " << lLC_ptr->getAvailabilityPool());
01601             }
01602           }
01603         }
01604       }
01605     }
01606   }
01607 
01608   // ///////////////////////////////////////////////////////////////////
01609   void RMOL_Service::projectOnDDemandOnLegCabinsUsingDA(const stdair::DateTime_T& iRMEventTime) {
01610 
01611     if (_rmolServiceContext == NULL) {
01612       throw stdair::NonInitialisedServiceException ("The Rmol service "
01613                                                     "has not been initialised");
01614     }
01615     assert (_rmolServiceContext != NULL);
01616     RMOL_ServiceContext& lRMOL_ServiceContext = *_rmolServiceContext;
01617     
01618     // Retrieve the bom root
01619     stdair::STDAIR_Service& lSTDAIR_Service =
01620       lRMOL_ServiceContext.getSTDAIR_Service();
01621     stdair::BomRoot& lBomRoot = lSTDAIR_Service.getBomRoot();
01622 
01623     // Retrieve the date from the RM event
01624     const stdair::Date_T lDate = iRMEventTime.date();
01625 
01626     const stdair::InventoryList_T lInventoryList =
01627       stdair::BomManager::getList<stdair::Inventory> (lBomRoot);
01628     assert (!lInventoryList.empty());
01629     for (stdair::InventoryList_T::const_iterator itInv = lInventoryList.begin();
01630          itInv != lInventoryList.end(); ++itInv) {
01631       const stdair::Inventory* lInventory_ptr = *itInv;
01632       assert (lInventory_ptr != NULL);
01633       const stdair::OnDDateList_T lOnDDateList =
01634         stdair::BomManager::getList<stdair::OnDDate> (*lInventory_ptr);
01635       assert (!lOnDDateList.empty());
01636       for (stdair::OnDDateList_T::const_iterator itOD = lOnDDateList.begin();
01637            itOD != lOnDDateList.end(); ++itOD) {
01638         stdair::OnDDate* lOnDDate_ptr = *itOD;
01639         assert (lOnDDate_ptr != NULL);
01640 
01641         const stdair::Date_T& lDepartureDate = lOnDDate_ptr->getDate();
01642         stdair::DateOffset_T lDateOffset = lDepartureDate - lDate;
01643         stdair::DTD_T lDTD = short (lDateOffset.days());
01644       
01645         stdair::DCPList_T::const_iterator itDCP =
01646           std::find (stdair::DEFAULT_DCP_LIST.begin(), stdair::DEFAULT_DCP_LIST.end(), lDTD);
01647         // Check if the forecast for this O&D date needs to be projected.
01648         if (itDCP != stdair::DEFAULT_DCP_LIST.end()) {
01649 
01650           // Browse the demand info map.
01651           const stdair::StringDemandStructMap_T& lStringDemandStructMap =
01652             lOnDDate_ptr->getDemandInfoMap ();
01653           for (stdair::StringDemandStructMap_T::const_iterator itStrDS = lStringDemandStructMap.begin();
01654                itStrDS != lStringDemandStructMap.end(); ++itStrDS) {
01655             std::string lCabinClassPath = itStrDS->first;
01656             const stdair::YieldDemandPair_T& lYieldDemandPair = itStrDS->second;
01657             const stdair::CabinClassPairList_T& lCabinClassPairList =
01658               lOnDDate_ptr->getCabinClassPairList(lCabinClassPath);
01659             const stdair::NbOfSegments_T& lNbOfSegments = lOnDDate_ptr->getNbOfSegments();
01660             // Sanity check
01661             assert (lCabinClassPairList.size() == lNbOfSegments);
01662 
01663             //
01664             const stdair::SegmentDateList_T lOnDSegmentDateList =
01665               stdair::BomManager::getList<stdair::SegmentDate> (*lOnDDate_ptr);
01666             // Sanity check
01667             assert (lOnDSegmentDateList.size() == lNbOfSegments);
01668             stdair::CabinClassPairList_T::const_iterator itCCP = lCabinClassPairList.begin();
01669             stdair::SegmentDateList_T::const_iterator itSD = lOnDSegmentDateList.begin();
01670             // List of bid prices that will be used to easily compute displacement-ajusted yields.
01671             std::list<stdair::BidPrice_T> lBidPriceList;
01672             // The sum of bid prices that will be stored in the list above.
01673             stdair::BidPrice_T lTotalBidPrice = 0;
01674             // Retrieve the bid prices
01675             for (; itSD != lOnDSegmentDateList.end(); ++itCCP, ++itSD) {
01676               // Get the operating segment cabin (it holds the bid price information).
01677               const stdair::SegmentDate* lSegmentDate_ptr = *itSD;
01678               assert (lSegmentDate_ptr != NULL);
01679               // Get the operating airline code and check if it is the airline we are looking for.
01680               const stdair::SegmentDate* lOperatingSegmentDate_ptr =
01681                 lSegmentDate_ptr->getOperatingSegmentDate ();
01682               if (lOperatingSegmentDate_ptr != NULL) {
01683                 lSegmentDate_ptr = lOperatingSegmentDate_ptr;
01684               }
01685               const stdair::CabinCode_T lCabinCode = itCCP->first;
01686               const stdair::SegmentCabin* lSegmentCabin_ptr =
01687                 stdair::BomManager::getObjectPtr<stdair::SegmentCabin> (*lSegmentDate_ptr,
01688                                                                         lCabinCode);
01689               assert (lSegmentCabin_ptr != NULL);
01690               stdair::BidPrice_T lBidPrice = 0;
01691               const stdair::LegCabinList_T lLegCabinList =
01692                 stdair::BomManager::getList<stdair::LegCabin>(*lSegmentCabin_ptr);
01693               for (stdair::LegCabinList_T::const_iterator itLC = lLegCabinList.begin();
01694                    itLC != lLegCabinList.end(); ++itLC) {
01695                 const stdair::LegCabin* lLegCabin_ptr = *itLC;
01696                 assert (lLegCabin_ptr != NULL);
01697                 lBidPrice += lLegCabin_ptr->getCurrentBidPrice();
01698               }
01699               lBidPriceList.push_back (lBidPrice);
01700               lTotalBidPrice += lBidPrice;
01701             }            
01702             
01703             
01704             itCCP = lCabinClassPairList.begin();
01705             itSD = lOnDSegmentDateList.begin();
01706             std::list<stdair::BidPrice_T>::const_iterator itBP = lBidPriceList.begin();
01707             for (; itSD != lOnDSegmentDateList.end(); ++itCCP, ++itSD, ++itBP) {
01708               stdair::BidPrice_T lBidPrice = *itBP;
01709               stdair::BidPrice_T lComplementaryBidPrice = lTotalBidPrice - lBidPrice;
01710               const stdair::SegmentDate* lSegmentDate_ptr = *itSD;
01711               assert (lSegmentDate_ptr != NULL);
01712               const stdair::SegmentDate* lOperatingSegmentDate_ptr =
01713                 lSegmentDate_ptr->getOperatingSegmentDate ();
01714               // Only operated legs receive the demand information.
01715               if (lOperatingSegmentDate_ptr == NULL) {
01716                 const stdair::CabinCode_T lCabinCode = itCCP->first;
01717                 const stdair::ClassCode_T lClassCode = itCCP->second;
01718                 const stdair::SegmentCabin* lSegmentCabin_ptr =
01719                   stdair::BomManager::getObjectPtr<stdair::SegmentCabin> (*lSegmentDate_ptr,
01720                                                                           lCabinCode);
01721                 assert (lSegmentCabin_ptr != NULL);
01722                 const stdair::LegCabinList_T lLegCabinList =
01723                   stdair::BomManager::getList<stdair::LegCabin> (*lSegmentCabin_ptr);
01724                 assert (!lLegCabinList.empty());                
01725                 // Determine the displacement-adjusted yield.
01726                 // It is set to 100 (positive small value), if the computed value is negative.                
01727                 const stdair::Yield_T& lDAYield =
01728                   std::max(100., lYieldDemandPair.first - lComplementaryBidPrice);
01729                 
01730                                 
01731                 stdair::Yield_T lYield = lDAYield;
01732                 // In order to be protected against important variations of partners' bid price,
01733                 // the displacement adjusted yield is noy allowed to get out of a certain range.
01734                 // This range is here chosen to be from 80% to 100% of the (static rule) prorated yield.
01735                 /*
01736                 const int lNbOfLegs = lLegCabinList.size();
01737                 const stdair::Yield_T& lStaticProrationYield =
01738                   lDemandStruct.getYield()/(lNbOfLegs*lNbOfSegments); 
01739                 if (lDAYield < 0.8*lStaticProrationYield){
01740                   lYield = 0.8*lStaticProrationYield;
01741                 }
01742                 if (lDAYield > lStaticProrationYield) {
01743                   lYield = lStaticProrationYield;
01744                 }
01745                 */
01746                 const stdair::MeanStdDevPair_T& lMeanStdDevPair =
01747                   lYieldDemandPair.second;
01748                 const stdair::MeanValue_T& lMeanValue = lMeanStdDevPair.first;
01749                 const stdair::StdDevValue_T& lStdDevValue = lMeanStdDevPair.second;
01750                 for (stdair::LegCabinList_T::const_iterator itLC = lLegCabinList.begin();
01751                      itLC != lLegCabinList.end(); ++itLC) {
01752                   stdair::LegCabin* lLegCabin_ptr = *itLC;
01753                   assert (lLegCabin_ptr != NULL);
01754                   lLegCabin_ptr->addDemandInformation (lYield, lMeanValue, lStdDevValue);
01755                 }
01756               }
01757             }
01758           }
01759         }
01760       }
01761     }
01762   }
01763 
01764   // ///////////////////////////////////////////////////////////////////
01765   void RMOL_Service::projectOnDDemandOnLegCabinsUsingDYP(const stdair::DateTime_T& iRMEventTime) {
01766 
01767     if (_rmolServiceContext == NULL) {
01768       throw stdair::NonInitialisedServiceException ("The Rmol service "
01769                                                     "has not been initialised");
01770     }
01771     assert (_rmolServiceContext != NULL);
01772     RMOL_ServiceContext& lRMOL_ServiceContext = *_rmolServiceContext;
01773     
01774     // Retrieve the bom root
01775     stdair::STDAIR_Service& lSTDAIR_Service =
01776       lRMOL_ServiceContext.getSTDAIR_Service();
01777     stdair::BomRoot& lBomRoot = lSTDAIR_Service.getBomRoot();
01778     
01779     const stdair::InventoryList_T lInventoryList =
01780       stdair::BomManager::getList<stdair::Inventory> (lBomRoot);
01781     assert (!lInventoryList.empty());
01782     for (stdair::InventoryList_T::const_iterator itInv = lInventoryList.begin();
01783          itInv != lInventoryList.end(); ++itInv) {
01784       const stdair::Inventory* lInventory_ptr = *itInv;
01785       assert (lInventory_ptr != NULL);
01786       projectOnDDemandOnLegCabinsUsingDYP (iRMEventTime, *lInventory_ptr);
01787     }
01788   }
01789 
01790   // ///////////////////////////////////////////////////////////////////
01791   void RMOL_Service::projectOnDDemandOnLegCabinsUsingDYP(const stdair::DateTime_T& iRMEventTime,
01792                                                          const stdair::Inventory& iInventory) {
01793     
01794     const stdair::OnDDateList_T lOnDDateList =
01795       stdair::BomManager::getList<stdair::OnDDate> (iInventory);
01796     assert (!lOnDDateList.empty());
01797     for (stdair::OnDDateList_T::const_iterator itOD = lOnDDateList.begin();
01798          itOD != lOnDDateList.end(); ++itOD) {
01799       stdair::OnDDate* lOnDDate_ptr = *itOD;
01800       assert (lOnDDate_ptr != NULL);
01801       
01802       // Retrieve the date from the RM event
01803       const stdair::Date_T lDate = iRMEventTime.date();
01804 
01805       const stdair::Date_T& lDepartureDate = lOnDDate_ptr->getDate();
01806       stdair::DateOffset_T lDateOffset = lDepartureDate - lDate;
01807       stdair::DTD_T lDTD = short (lDateOffset.days());
01808       
01809       stdair::DCPList_T::const_iterator itDCP =
01810         std::find (stdair::DEFAULT_DCP_LIST.begin(), stdair::DEFAULT_DCP_LIST.end(), lDTD);
01811       // Check if the forecast for this O&D date needs to be projected.
01812       if (itDCP != stdair::DEFAULT_DCP_LIST.end()) {
01813         
01814         // Browse the demand info map.
01815         const stdair::StringDemandStructMap_T& lStringDemandStructMap =
01816           lOnDDate_ptr->getDemandInfoMap ();
01817         for (stdair::StringDemandStructMap_T::const_iterator itStrDS = lStringDemandStructMap.begin();
01818              itStrDS != lStringDemandStructMap.end(); ++itStrDS) {
01819           std::string lCabinClassPath = itStrDS->first;
01820           const stdair::YieldDemandPair_T& lYieldDemandPair = itStrDS->second;
01821           const stdair::CabinClassPairList_T& lCabinClassPairList =
01822             lOnDDate_ptr->getCabinClassPairList(lCabinClassPath);
01823           const stdair::NbOfSegments_T& lNbOfSegments = lOnDDate_ptr->getNbOfSegments();
01824           // Sanity check
01825           assert (lCabinClassPairList.size() == lNbOfSegments);
01826           
01827           //
01828           const stdair::SegmentDateList_T lOnDSegmentDateList =
01829               stdair::BomManager::getList<stdair::SegmentDate> (*lOnDDate_ptr);
01830           // Sanity check
01831           assert (lOnDSegmentDateList.size() == lNbOfSegments);
01832           stdair::CabinClassPairList_T::const_iterator itCCP = lCabinClassPairList.begin();
01833           stdair::SegmentDateList_T::const_iterator itSD = lOnDSegmentDateList.begin();
01834           // The sum of bid prices of all cabins.
01835           stdair::BidPrice_T lTotalBidPrice = 0;
01836           for (; itSD != lOnDSegmentDateList.end(); ++itCCP, ++itSD) {
01837             // Get the operating segment cabin (it holds the bid price information).
01838             const stdair::SegmentDate* lSegmentDate_ptr = *itSD;
01839             assert (lSegmentDate_ptr != NULL);
01840             // Get the operating airline code and check if it is the airline we are looking for.
01841             const stdair::SegmentDate* lOperatingSegmentDate_ptr =
01842               lSegmentDate_ptr->getOperatingSegmentDate ();
01843             if (lOperatingSegmentDate_ptr != NULL) {
01844               lSegmentDate_ptr = lOperatingSegmentDate_ptr;
01845             }
01846             const stdair::CabinCode_T lCabinCode = itCCP->first;
01847             const stdair::SegmentCabin* lSegmentCabin_ptr =
01848               stdair::BomManager::getObjectPtr<stdair::SegmentCabin> (*lSegmentDate_ptr,
01849                                                                       lCabinCode);
01850             assert (lSegmentCabin_ptr != NULL);
01851             const stdair::LegCabinList_T lLegCabinList =
01852               stdair::BomManager::getList<stdair::LegCabin>(*lSegmentCabin_ptr);
01853             for (stdair::LegCabinList_T::const_iterator itLC = lLegCabinList.begin();
01854                  itLC != lLegCabinList.end(); ++itLC) {
01855               const stdair::LegCabin* lLegCabin_ptr = *itLC;
01856               assert (lLegCabin_ptr != NULL);
01857               lTotalBidPrice += lLegCabin_ptr->getCurrentBidPrice();
01858             }
01859           }            
01860           
01861           
01862           itCCP = lCabinClassPairList.begin();
01863           itSD = lOnDSegmentDateList.begin();
01864           for (; itSD != lOnDSegmentDateList.end(); ++itCCP, ++itSD) {
01865             const stdair::SegmentDate* lSegmentDate_ptr = *itSD;
01866             assert (lSegmentDate_ptr != NULL);
01867             const stdair::SegmentDate* lOperatingSegmentDate_ptr =
01868               lSegmentDate_ptr->getOperatingSegmentDate ();
01869             // Only operated legs receive the demand information.
01870             if (lOperatingSegmentDate_ptr == NULL) {
01871               const stdair::CabinCode_T lCabinCode = itCCP->first;
01872               const stdair::ClassCode_T lClassCode = itCCP->second;
01873               const stdair::SegmentCabin* lSegmentCabin_ptr =
01874                 stdair::BomManager::getObjectPtr<stdair::SegmentCabin> (*lSegmentDate_ptr,
01875                                                                         lCabinCode);
01876               assert (lSegmentCabin_ptr != NULL);
01877               const stdair::LegCabinList_T lLegCabinList =
01878                 stdair::BomManager::getList<stdair::LegCabin> (*lSegmentCabin_ptr);
01879               assert (!lLegCabinList.empty());
01880               const stdair::Yield_T& lYield = lYieldDemandPair.first;            
01881               const stdair::MeanStdDevPair_T& lMeanStdDevPair =
01882                 lYieldDemandPair.second;
01883               const stdair::MeanValue_T& lMeanValue = lMeanStdDevPair.first;
01884               const stdair::StdDevValue_T& lStdDevValue = lMeanStdDevPair.second;
01885               for (stdair::LegCabinList_T::const_iterator itLC = lLegCabinList.begin();
01886                    itLC != lLegCabinList.end(); ++itLC) {
01887                 stdair::LegCabin* lLegCabin_ptr = *itLC;
01888                 assert (lLegCabin_ptr != NULL);
01889                 const stdair::BidPrice_T& lBidPrice = lLegCabin_ptr->getCurrentBidPrice();
01890                 const stdair::RealNumber_T lDynamicYieldProrationFactor = lBidPrice / lTotalBidPrice;
01891                 const stdair::Yield_T lProratedYield = lDynamicYieldProrationFactor*lYield;
01892                 lLegCabin_ptr->addDemandInformation (lProratedYield, lMeanValue, lStdDevValue);
01893                 
01894                 // STDAIR_LOG_DEBUG ("Addding demand information to leg-cabin " << lLegCabin_ptr->getFullerKey()
01895                 //                   << " Total yield " << lYield << " Proration factor "
01896                 //                   << lDynamicYieldProrationFactor << " Prorated yield " << lProratedYield
01897                 //                   << " Mean demand " << lMeanValue << " StdDev " << lStdDevValue);
01898               }
01899             }
01900           }
01901         }
01902       }
01903     }
01904   }
01905 
01906   // ///////////////////////////////////////////////////////////////////
01907   void RMOL_Service::optimiseOnDUsingRMCooperation (const stdair::DateTime_T& iRMEventTime) {
01908 
01909     if (_rmolServiceContext == NULL) {
01910       throw stdair::NonInitialisedServiceException ("The Rmol service "
01911                                                     "has not been initialised");
01912     }
01913     assert (_rmolServiceContext != NULL);
01914     RMOL_ServiceContext& lRMOL_ServiceContext = *_rmolServiceContext;
01915 
01916     // Retrieve the bom root
01917     stdair::STDAIR_Service& lSTDAIR_Service =
01918       lRMOL_ServiceContext.getSTDAIR_Service();
01919     stdair::BomRoot& lBomRoot = lSTDAIR_Service.getBomRoot();
01920 
01921     // Retrieve the date from the RM event
01922     const stdair::Date_T lDate = iRMEventTime.date();
01923 
01924     // Browse the list of inventories and optimise within each one independently.
01925     const stdair::InventoryList_T& lInvList =
01926       stdair::BomManager::getList<stdair::Inventory> (lBomRoot);
01927     for (stdair::InventoryList_T::const_iterator itInv = lInvList.begin();
01928          itInv != lInvList.end(); ++itInv) {
01929       stdair::Inventory* lCurrentInv_ptr = *itInv;
01930       assert (lCurrentInv_ptr != NULL);
01931       
01932       double lMaxBPVariation = 1.0;
01933       short lIterationCounter = 0;
01934       // Iterate until the variation is under the wanted level or the maximal number of iterations is reached.
01935       while (lMaxBPVariation > 0.01 && lIterationCounter < 10) {
01936         lMaxBPVariation = 0.0;
01937         lIterationCounter++;
01938         const stdair::FlightDateList_T& lFlightDateList =
01939           stdair::BomManager::getList<stdair::FlightDate> (*lCurrentInv_ptr);
01940         for (stdair::FlightDateList_T::const_iterator itFlightDate =
01941                lFlightDateList.begin();
01942              itFlightDate != lFlightDateList.end(); ++itFlightDate) {
01943           stdair::FlightDate* lCurrentFlightDate_ptr = *itFlightDate;
01944           assert (lCurrentFlightDate_ptr != NULL);
01945           
01946           const stdair::Date_T& lCurrentDepartureDate = lCurrentFlightDate_ptr->getDepartureDate();
01947           stdair::DateOffset_T lDateOffset = lCurrentDepartureDate - lDate;
01948           stdair::DTD_T lDTD = short (lDateOffset.days());
01949           
01950           stdair::DCPList_T::const_iterator itDCP =
01951             std::find (stdair::DEFAULT_DCP_LIST.begin(), stdair::DEFAULT_DCP_LIST.end(), lDTD);
01952           // Check if the optimisation is needed.
01953           if (itDCP != stdair::DEFAULT_DCP_LIST.end()) {
01954             const double lBPVariation = Optimiser::optimiseUsingOnDForecast (*lCurrentFlightDate_ptr);
01955             lMaxBPVariation = std::max(lMaxBPVariation, lBPVariation);
01956           }
01957         }
01958         // Update the prorated yields for the current inventory.
01959         resetDemandInformation (iRMEventTime, *lCurrentInv_ptr);
01960         projectOnDDemandOnLegCabinsUsingDYP (iRMEventTime, *lCurrentInv_ptr);
01961       }
01962     }
01963   }
01964 
01965    
01966   // ///////////////////////////////////////////////////////////////////
01967   void RMOL_Service::optimiseOnDUsingAdvancedRMCooperation (const stdair::DateTime_T& iRMEventTime) {
01968 
01969     if (_rmolServiceContext == NULL) {
01970       throw stdair::NonInitialisedServiceException ("The Rmol service "
01971                                                     "has not been initialised");
01972     }
01973     assert (_rmolServiceContext != NULL);
01974     RMOL_ServiceContext& lRMOL_ServiceContext = *_rmolServiceContext;
01975 
01976     // Retrieve the bom root
01977     stdair::STDAIR_Service& lSTDAIR_Service =
01978       lRMOL_ServiceContext.getSTDAIR_Service();
01979     stdair::BomRoot& lBomRoot = lSTDAIR_Service.getBomRoot();
01980     
01981     // Retrieve the date from the RM event
01982     const stdair::Date_T lDate = iRMEventTime.date();
01983 
01984     double lMaxBPVariation = 1.0;
01985     short lIterationCounter = 0;
01986     // Iterate until the variation is under the wanted level or the maximal number of iterations is reached.
01987     // Every iteration corresponds to the optimisation of the whole network. Bid prices are communicated
01988     // between partners at the end of each iteration.
01989     while (lMaxBPVariation > 0.01 && lIterationCounter < 50) {
01990       lMaxBPVariation = 0.0;
01991       lIterationCounter++;
01992 
01993       const stdair::InventoryList_T& lInvList =
01994         stdair::BomManager::getList<stdair::Inventory> (lBomRoot);
01995       for (stdair::InventoryList_T::const_iterator itInv = lInvList.begin();
01996            itInv != lInvList.end(); ++itInv) {
01997         stdair::Inventory* lCurrentInv_ptr = *itInv;
01998         assert (lCurrentInv_ptr != NULL);
01999         const stdair::FlightDateList_T& lFlightDateList =
02000           stdair::BomManager::getList<stdair::FlightDate> (*lCurrentInv_ptr);
02001         for (stdair::FlightDateList_T::const_iterator itFlightDate =
02002                lFlightDateList.begin();
02003              itFlightDate != lFlightDateList.end(); ++itFlightDate) {
02004           stdair::FlightDate* lCurrentFlightDate_ptr = *itFlightDate;
02005           assert (lCurrentFlightDate_ptr != NULL);
02006           
02007           const stdair::Date_T& lCurrentDepartureDate = lCurrentFlightDate_ptr->getDepartureDate();
02008           stdair::DateOffset_T lDateOffset = lCurrentDepartureDate - lDate;
02009           stdair::DTD_T lDTD = short (lDateOffset.days());
02010           
02011           stdair::DCPList_T::const_iterator itDCP =
02012             std::find (stdair::DEFAULT_DCP_LIST.begin(), stdair::DEFAULT_DCP_LIST.end(), lDTD);
02013           if (itDCP != stdair::DEFAULT_DCP_LIST.end()) {
02014             const double lBPVariation = Optimiser::optimiseUsingOnDForecast (*lCurrentFlightDate_ptr);
02015             lMaxBPVariation = std::max(lMaxBPVariation, lBPVariation);
02016           }
02017         }
02018       }
02019       // At the end of each iteration, communicate bid prices and compute displacement adjusted yields.
02020       updateBidPrice (iRMEventTime);
02021       resetDemandInformation (iRMEventTime);
02022       projectOnDDemandOnLegCabinsUsingDYP (iRMEventTime);
02023     }    
02024   }
02025 
02026 }