$treeview $search $mathjax
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 }