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

rmol/command/Optimiser.cpp

Go to the documentation of this file.
00001 // //////////////////////////////////////////////////////////////////////
00002 // Import section
00003 // //////////////////////////////////////////////////////////////////////
00004 // STL
00005 #include <cassert>
00006 #include <sstream>
00007 // StdAir
00008 #include <stdair/basic/BasConst_General.hpp>
00009 #include <stdair/basic/RandomGeneration.hpp>
00010 #include <stdair/bom/BomManager.hpp>
00011 #include <stdair/bom/FlightDate.hpp>
00012 #include <stdair/bom/LegDate.hpp>
00013 #include <stdair/bom/SegmentDate.hpp>
00014 #include <stdair/bom/LegCabin.hpp>
00015 #include <stdair/bom/SegmentCabin.hpp>
00016 #include <stdair/bom/FareFamily.hpp>
00017 #include <stdair/bom/BookingClass.hpp>
00018 #include <stdair/service/Logger.hpp>
00019 // RMOL
00020 #include <rmol/basic/BasConst_General.hpp>
00021 #include <rmol/bom/MCOptimiser.hpp>
00022 #include <rmol/bom/Emsr.hpp>
00023 #include <rmol/bom/DPOptimiser.hpp>
00024 #include <rmol/command/Optimiser.hpp>
00025 
00026 namespace RMOL {
00027 
00028   // ////////////////////////////////////////////////////////////////////
00029   void Optimiser::
00030   optimalOptimisationByMCIntegration (const stdair::NbOfSamples_T& K,
00031                                       stdair::LegCabin& ioLegCabin) {
00032     // Retrieve the segment-cabin
00033     const stdair::SegmentCabinList_T lSegmentCabinList =
00034       stdair::BomManager::getList<stdair::SegmentCabin> (ioLegCabin);
00035     stdair::SegmentCabinList_T::const_iterator itSC = lSegmentCabinList.begin();
00036     assert (itSC != lSegmentCabinList.end());
00037     const stdair::SegmentCabin* lSegmentCabin_ptr = *itSC;
00038     assert (lSegmentCabin_ptr != NULL);
00039     
00040     // Retrieve the class list.
00041     const stdair::BookingClassList_T lBookingClassList =
00042       stdair::BomManager::getList<stdair::BookingClass> (*lSegmentCabin_ptr);
00043     stdair::RandomGeneration lSeedGenerator (stdair::DEFAULT_RANDOM_SEED);
00044 
00045     // Generate the demand samples for the booking classes.
00046     for (stdair::BookingClassList_T::const_iterator itBC =
00047            lBookingClassList.begin(); itBC != lBookingClassList.end(); ++itBC) {
00048       stdair::RandomSeed_T lRandomSeed =
00049         lSeedGenerator.generateUniform01 () * 1e9;
00050       stdair::BookingClass* lBookingClass_ptr = *itBC;
00051       assert (lBookingClass_ptr != NULL);
00052       lBookingClass_ptr->generateDemandSamples (K, lRandomSeed);
00053 
00054       // DEBUG
00055       //STDAIR_LOG_DEBUG ("Generating " << K << " demand samples for the class "
00056       //                   << lBookingClass_ptr->describeKey());
00057     }   
00058     
00059     // Call the class performing the actual algorithm
00060     MCOptimiser::optimalOptimisationByMCIntegration (ioLegCabin);
00061   }
00062 
00063   // ////////////////////////////////////////////////////////////////////
00064   void Optimiser::optimalOptimisationByDP (stdair::LegCabin& ioLegCabin) {
00065     DPOptimiser::optimalOptimisationByDP (ioLegCabin);
00066   }
00067 
00068   // ////////////////////////////////////////////////////////////////////
00069   void Optimiser::heuristicOptimisationByEmsr (stdair::LegCabin& ioLegCabin) {
00070     Emsr::heuristicOptimisationByEmsr (ioLegCabin);
00071   }
00072 
00073   // ////////////////////////////////////////////////////////////////////
00074   void Optimiser::heuristicOptimisationByEmsrA (stdair::LegCabin& ioLegCabin) {
00075     Emsr::heuristicOptimisationByEmsrA (ioLegCabin);
00076   }
00077   
00078   // ////////////////////////////////////////////////////////////////////
00079   void Optimiser::heuristicOptimisationByEmsrB (stdair::LegCabin& ioLegCabin) {
00080     Emsr::heuristicOptimisationByEmsrB (ioLegCabin);
00081   }
00082 
00083   // ////////////////////////////////////////////////////////////////////
00084   bool Optimiser::optimise (stdair::FlightDate& ioFlightDate,
00085                             const stdair::OptimisationMethod& iOptimisationMethod) {
00086     bool optimiseSucceeded = false;
00087     // Browse the leg-cabin list and build the virtual class list for
00088     // each cabin.
00089     const stdair::LegDateList_T& lLDList =
00090       stdair::BomManager::getList<stdair::LegDate> (ioFlightDate);
00091     for (stdair::LegDateList_T::const_iterator itLD = lLDList.begin();
00092          itLD != lLDList.end(); ++itLD) {
00093       stdair::LegDate* lLD_ptr = *itLD;
00094       assert (lLD_ptr != NULL);
00095       const bool isSucceeded = optimise(*lLD_ptr, iOptimisationMethod);
00096       // If at least one leg date is optimised, the optimisation is succeeded.
00097       if (isSucceeded == true) {
00098         optimiseSucceeded = true;
00099         // Do not return now because all leg dates need to be optimised.
00100       }
00101     }
00102     return optimiseSucceeded;
00103   }
00104 
00105   // ////////////////////////////////////////////////////////////////////
00106   bool Optimiser::
00107   optimise (stdair::LegDate& ioLegDate,
00108             const stdair::OptimisationMethod& iOptimisationMethod) {
00109     bool optimiseSucceeded = false;
00110     // Browse the leg-cabin list 
00111     const stdair::LegCabinList_T& lLCList =
00112       stdair::BomManager::getList<stdair::LegCabin> (ioLegDate);
00113     for (stdair::LegCabinList_T::const_iterator itLC = lLCList.begin();
00114          itLC != lLCList.end(); ++itLC) {
00115       stdair::LegCabin* lLC_ptr = *itLC;
00116       assert (lLC_ptr != NULL);
00117       const bool isSucceeded = optimise(*lLC_ptr, iOptimisationMethod);
00118       // If at least one leg cabin is optimised, the optimisation is succeeded.
00119       if (isSucceeded == true) {
00120         optimiseSucceeded = true;
00121         // Do not return now because all leg cabins need to be optimised.
00122       }
00123     }
00124     return optimiseSucceeded;
00125   }
00126 
00127   // ////////////////////////////////////////////////////////////////////
00128   bool Optimiser::
00129   optimise (stdair::LegCabin& ioLegCabin,
00130             const stdair::OptimisationMethod& iOptimisationMethod) {
00131     bool optimiseSucceeded = false;
00132     //
00133     // Build the virtual class list.
00134     bool hasVirtualClass = 
00135       buildVirtualClassListForLegBasedOptimisation (ioLegCabin);
00136     if (hasVirtualClass == true) {
00137       switch (iOptimisationMethod.getMethod()) {
00138       case stdair::OptimisationMethod::LEG_BASED_MC: {
00139         // Number of samples generated for the Monte Carlo integration.
00140         // It is important that number is greater than 100 (=10000 here).
00141         const stdair::NbOfSamples_T lNbOfSamples =
00142           DEFAULT_NUMBER_OF_DRAWS_FOR_MC_SIMULATION;
00143         optimalOptimisationByMCIntegration (lNbOfSamples, ioLegCabin);
00144         optimiseSucceeded = true;
00145         break;
00146       }
00147       case stdair::OptimisationMethod::LEG_BASED_EMSR_B: {
00148         heuristicOptimisationByEmsrB (ioLegCabin);
00149         optimiseSucceeded = true;
00150         break;
00151       }
00152       default: {
00153         assert (false);
00154           break;
00155       }
00156       }
00157     }
00158   
00159     return optimiseSucceeded;
00160   }
00161 
00162   // ////////////////////////////////////////////////////////////////////
00163   bool Optimiser::
00164   buildVirtualClassListForLegBasedOptimisation (stdair::LegCabin& ioLegCabin) {
00165     // The map holding all virtual classes to be created.
00166     stdair::VirtualClassMap_T lVirtualClassMap;
00167     bool isNotEmpty = false;
00168 
00169     // Retrieve the segment-cabin
00170     const stdair::SegmentCabinList_T& lSegmentCabinList =
00171       stdair::BomManager::getList<stdair::SegmentCabin> (ioLegCabin);
00172     stdair::SegmentCabinList_T::const_iterator itSC = lSegmentCabinList.begin();
00173     assert (itSC != lSegmentCabinList.end());
00174     const stdair::SegmentCabin* lSegmentCabin_ptr = *itSC;
00175     assert (lSegmentCabin_ptr != NULL);
00176     
00177     // Retrieve the class list.
00178     const stdair::BookingClassList_T lBookingClassList =
00179       stdair::BomManager::getList<stdair::BookingClass> (*lSegmentCabin_ptr);
00180 
00181     // Generate the demand samples for the booking classes.
00182     for (stdair::BookingClassList_T::const_iterator itBC =
00183            lBookingClassList.begin(); itBC != lBookingClassList.end(); ++itBC) {
00184       stdair::BookingClass* lBookingClass_ptr = *itBC;
00185       assert (lBookingClass_ptr != NULL);
00186 
00187       // If the demand forecast of the class is zero, there no need to create
00188       // a virtual class.
00189       // TODO: use float utils
00190       const stdair::NbOfRequests_T& lMean = lBookingClass_ptr->getMean();
00191       const stdair::StdDevValue_T& lStdDev = lBookingClass_ptr->getStdDev();
00192       if (lMean > 0.0) {
00193         const stdair::Yield_T& lYield = lBookingClass_ptr->getAdjustedYield();
00194         // TODO: use float utils
00195         assert (lYield >= 0.0);
00196         const stdair::Yield_T lRoundedYieldDouble = std::floor(lYield +0.5);
00197         const stdair::YieldLevel_T lRoundedYieldLevel = 
00198           static_cast<stdair::YieldLevel_T>(lRoundedYieldDouble);
00199         if (lRoundedYieldLevel > 0) {
00200           // If there is already a virtual class with this yield, add the current
00201           // booking class to its list and sum the two demand distributions.
00202           // Otherwise, create a new virtual class.
00203           stdair::VirtualClassMap_T::iterator itVCMap = 
00204             lVirtualClassMap.find(lRoundedYieldLevel);
00205           if (itVCMap == lVirtualClassMap.end()) {
00206             stdair::BookingClassList_T lBookingClassList;
00207             lBookingClassList.push_back(lBookingClass_ptr);
00208             stdair::VirtualClassStruct lVirtualClass (lBookingClassList);
00209             lVirtualClass.setYield (lRoundedYieldLevel);
00210             lVirtualClass.setMean (lMean);
00211             lVirtualClass.setStdDev (lStdDev);
00212 
00213             lVirtualClassMap.insert (stdair::VirtualClassMap_T::
00214                                   value_type (lRoundedYieldLevel, lVirtualClass));
00215           } else {
00216             stdair::VirtualClassStruct& lVirtualClass = itVCMap->second;
00217             const stdair::MeanValue_T& lVCMean = lVirtualClass.getMean();
00218             const stdair::StdDevValue_T& lVCStdDev = lVirtualClass.getStdDev();
00219             const stdair::MeanValue_T lNewMean = lVCMean + lMean;
00220             const stdair::StdDevValue_T lNewStdDev = 
00221               std::sqrt(lVCStdDev * lVCStdDev + lStdDev * lStdDev);
00222             lVirtualClass.setMean (lNewMean);
00223             lVirtualClass.setStdDev (lNewStdDev);
00224 
00225             lVirtualClass.addBookingClass(*lBookingClass_ptr);
00226           }
00227         }
00228       }
00229     }
00230 
00231     // Browse the virtual class map from high to low yield.
00232     ioLegCabin.emptyVirtualClassList();
00233     for (stdair::VirtualClassMap_T::reverse_iterator itVC =
00234            lVirtualClassMap.rbegin(); itVC != lVirtualClassMap.rend(); ++itVC) {
00235       stdair::VirtualClassStruct& lVC = itVC->second;
00236       
00237       ioLegCabin.addVirtualClass (lVC);
00238       if (isNotEmpty == false) {
00239         isNotEmpty = true;
00240       }
00241     }
00242     return isNotEmpty;
00243   }
00244   
00245   // ////////////////////////////////////////////////////////////////////
00246   double Optimiser::
00247   optimiseUsingOnDForecast (stdair::FlightDate& ioFlightDate,
00248                             const bool& iReduceFluctuations) {
00249     double lMaxBPVariation = 0.0;
00250     // Check if the flight date holds a list of leg dates.
00251     // If so, retieve it and optimise the cabins.
00252     const bool hasLegDateList =
00253       stdair::BomManager::hasList<stdair::LegDate> (ioFlightDate);
00254     if (hasLegDateList == true) {
00255       STDAIR_LOG_DEBUG ("Optimisation for the flight date: "
00256                         << ioFlightDate.toString());
00257       const stdair::LegDateList_T& lLDList =
00258         stdair::BomManager::getList<stdair::LegDate> (ioFlightDate);
00259       for (stdair::LegDateList_T::const_iterator itLD = lLDList.begin();
00260            itLD != lLDList.end(); ++itLD) {
00261         stdair::LegDate* lLD_ptr = *itLD;
00262         assert (lLD_ptr != NULL);
00263 
00264         //
00265         const stdair::LegCabinList_T& lLCList =
00266           stdair::BomManager::getList<stdair::LegCabin> (*lLD_ptr);
00267         for (stdair::LegCabinList_T::const_iterator itLC = lLCList.begin();
00268              itLC != lLCList.end(); ++itLC) {
00269           stdair::LegCabin* lLC_ptr = *itLC;
00270           assert (lLC_ptr != NULL);
00271           MCOptimiser::optimisationByMCIntegration (*lLC_ptr);
00272           const stdair::BidPrice_T& lCurrentBidPrice =
00273             lLC_ptr->getCurrentBidPrice();
00274           const stdair::BidPrice_T& lPreviousBidPrice =
00275             lLC_ptr->getPreviousBidPrice();
00276           assert (lPreviousBidPrice != 0);
00277           const double lBPVariation =
00278             std::abs((lCurrentBidPrice - lPreviousBidPrice)/lPreviousBidPrice);
00279           lMaxBPVariation = std::max(lMaxBPVariation, lBPVariation);
00280         }
00281       }
00282     }
00283     return lMaxBPVariation;
00284   }
00285 
00286 }