$treeview $search $mathjax
00001 00002 // ////////////////////////////////////////////////////////////////////// 00003 // Import section 00004 // ////////////////////////////////////////////////////////////////////// 00005 // STL 00006 #include <cassert> 00007 #include <string> 00008 #include <numeric> 00009 #include <algorithm> 00010 #include <cmath> 00011 // StdAir 00012 #include <stdair/basic/BasConst_Inventory.hpp> 00013 #include <stdair/bom/BomManager.hpp> 00014 #include <stdair/bom/SegmentCabin.hpp> 00015 #include <stdair/bom/FareFamily.hpp> 00016 #include <stdair/bom/BookingClass.hpp> 00017 #include <stdair/bom/BookingClassTypes.hpp> 00018 #include <stdair/service/Logger.hpp> 00019 // RMOL 00020 #include <rmol/basic/BasConst_General.hpp> 00021 #include <rmol/bom/Utilities.hpp> 00022 #include <rmol/bom/SegmentSnapshotTableHelper.hpp> 00023 00024 namespace RMOL { 00025 // //////////////////////////////////////////////////////////////////// 00026 void Utilities:: 00027 computeDistributionParameters (const stdair::UncDemVector_T& iVector, 00028 stdair::MeanValue_T& ioMean, 00029 stdair::StdDevValue_T& ioStdDev) { 00030 ioMean = 0.0; ioStdDev = 0.0; 00031 const stdair::NbOfSamples_T lNbOfSamples = iVector.size(); 00032 assert (lNbOfSamples > 1); 00033 00034 // Compute the mean 00035 for (stdair::UncDemVector_T::const_iterator itSample = iVector.begin(); 00036 itSample != iVector.end(); ++itSample) { 00037 //STDAIR_LOG_NOTIFICATION (*itSample); 00038 ioMean += *itSample; 00039 } 00040 ioMean /= lNbOfSamples; 00041 00042 // Compute the standard deviation 00043 for (stdair::UncDemVector_T::const_iterator itSample = iVector.begin(); 00044 itSample != iVector.end(); ++itSample) { 00045 const stdair::MeanValue_T& lSample = *itSample; 00046 ioStdDev += ((lSample - ioMean) * (lSample - ioMean)); 00047 } 00048 ioStdDev /= (lNbOfSamples - 1); 00049 ioStdDev = std::sqrt (ioStdDev); 00050 00051 // Sanity check 00052 if (ioStdDev == 0) { 00053 ioStdDev = 0.1; 00054 } 00055 } 00056 00057 // //////////////////////////////////////////////////////////////////// 00058 stdair::DCPList_T Utilities:: 00059 buildRemainingDCPList (const stdair::DTD_T& iDTD) { 00060 stdair::DCPList_T oDCPList; 00061 00062 const stdair::DCPList_T lWholeDCPList = stdair::DEFAULT_DCP_LIST; 00063 stdair::DCPList_T::const_iterator itDCP = lWholeDCPList.begin(); 00064 while (itDCP != lWholeDCPList.end()) { 00065 const stdair::DCP_T& lDCP = *itDCP; 00066 if (iDTD >= lDCP) { 00067 break; 00068 } 00069 ++itDCP; 00070 } 00071 assert (itDCP != lWholeDCPList.end()); 00072 00073 oDCPList.push_back (iDTD); 00074 ++itDCP; 00075 for (; itDCP != lWholeDCPList.end(); ++itDCP) { 00076 oDCPList.push_back (*itDCP); 00077 } 00078 00079 return oDCPList; 00080 } 00081 00082 // //////////////////////////////////////////////////////////////////// 00083 stdair::DCPList_T Utilities:: 00084 buildPastDCPList (const stdair::DTD_T& iDTD) { 00085 stdair::DCPList_T oDCPList; 00086 00087 const stdair::DCPList_T lWholeDCPList = stdair::DEFAULT_DCP_LIST; 00088 stdair::DCPList_T::const_iterator itDCP = lWholeDCPList.begin(); 00089 while (itDCP != lWholeDCPList.end()) { 00090 const stdair::DCP_T& lDCP = *itDCP; 00091 if (iDTD <= lDCP) { 00092 oDCPList.push_back (lDCP); 00093 ++itDCP; 00094 } else { 00095 break; 00096 } 00097 } 00098 00099 return oDCPList; 00100 } 00101 00102 // //////////////////////////////////////////////////////////////////// 00103 stdair::NbOfSegments_T Utilities:: 00104 getNbOfDepartedSimilarSegments (const stdair::SegmentCabin& iSegmentCabin, 00105 const stdair::Date_T& iEventDate) { 00106 stdair::DTD_T lDTD = 0; 00107 // Retrieve the guillotine block. 00108 const stdair::SegmentSnapshotTable& lSegmentSnapshotTable = 00109 iSegmentCabin.getSegmentSnapshotTable(); 00110 return SegmentSnapshotTableHelper:: 00111 getNbOfSegmentAlreadyPassedThisDTD (lSegmentSnapshotTable, lDTD, iEventDate); 00112 } 00113 00114 // //////////////////////////////////////////////////////////////////// 00115 stdair::BookingClassSellUpCurveMap_T Utilities:: 00116 computeSellUpFactorCurves (const stdair::FRAT5Curve_T& iFRAT5Curve, 00117 const stdair::BookingClassList_T& iBCList) { 00118 stdair::BookingClassSellUpCurveMap_T oBCSellUpFactorMap; 00119 00120 // Initialise a sell-up factor curve of 1.0 values 00121 stdair::SellUpCurve_T lBasedSellUpCurve; 00122 for (stdair::FRAT5Curve_T::const_iterator itFRAT5 = iFRAT5Curve.begin(); 00123 itFRAT5 != iFRAT5Curve.end(); ++itFRAT5) { 00124 const stdair::DTD_T& lDTD = itFRAT5->first; 00125 lBasedSellUpCurve.insert(stdair::SellUpCurve_T::value_type(lDTD, 1.0)); 00126 } 00127 00128 // Retrieve the classes from low to high and compute the distributions of 00129 // product-oriented and price-oriented demand. 00130 // Retrieve the lowest class. 00131 stdair::BookingClassList_T::const_reverse_iterator itCurrentClass = 00132 iBCList.rbegin(); 00133 assert (itCurrentClass != iBCList.rend()); 00134 00135 // If there is only one class in the cabin, all the sell-up factors 00136 // will be 1. 00137 stdair::BookingClass* lLowestBC_ptr = *itCurrentClass; 00138 assert (lLowestBC_ptr != NULL); 00139 const stdair::Yield_T& lLowestYield = lLowestBC_ptr->getYield(); 00140 bool insert = oBCSellUpFactorMap. 00141 insert (stdair::BookingClassSellUpCurveMap_T:: 00142 value_type(lLowestBC_ptr, lBasedSellUpCurve)).second; 00143 assert (insert == true); 00144 ++itCurrentClass; 00145 00146 // Compute the demand for higher class using the formula 00147 // Pro_sell_up_from_Q_to_F = e ^ ((y_F/y_Q - 1) * ln (0.5) / (FRAT5 - 1)) 00148 for (; itCurrentClass != iBCList.rend(); ++itCurrentClass) { 00149 stdair::BookingClass* lCurrentBC_ptr = *itCurrentClass; 00150 assert (lCurrentBC_ptr != NULL); 00151 const stdair::Yield_T& lCurrentYield = lCurrentBC_ptr->getYield(); 00152 00153 // Compute the sell-up factor curve for the current class. 00154 stdair::SellUpCurve_T lCurrentSellUpCurve; 00155 for (stdair::FRAT5Curve_T::const_iterator itFRAT5 = iFRAT5Curve.begin(); 00156 itFRAT5 != iFRAT5Curve.end(); ++itFRAT5) { 00157 const stdair::DTD_T& lDTD = itFRAT5->first; 00158 const stdair::FRAT5_T& lFRAT5 = itFRAT5->second; 00159 const double lSellUpCoef = log(0.5)/(lFRAT5-1); 00160 const stdair::SellupProbability_T lSellUpFactor = 00161 exp ((lCurrentYield/lLowestYield - 1.0) * lSellUpCoef); 00162 const bool isInsertionSuccessful = 00163 lCurrentSellUpCurve.insert (stdair::SellUpCurve_T::value_type(lDTD, lSellUpFactor)).second; 00164 assert (isInsertionSuccessful == true); 00165 } 00166 const bool isInsertionSuccessful = oBCSellUpFactorMap. 00167 insert (stdair::BookingClassSellUpCurveMap_T:: 00168 value_type(lCurrentBC_ptr, lCurrentSellUpCurve)).second; 00169 assert (isInsertionSuccessful == true); 00170 } 00171 return oBCSellUpFactorMap; 00172 } 00173 00174 00175 // //////////////////////////////////////////////////////////////////// 00176 stdair::BookingClassDispatchingCurveMap_T Utilities:: 00177 computeDispatchingFactorCurves (const stdair::FRAT5Curve_T& iFRAT5Curve, 00178 const stdair::BookingClassList_T& iBCList) { 00179 stdair::BookingClassDispatchingCurveMap_T oBCDispatchingFactorMap; 00180 00181 // Initialise a sell-up factor curve of 1.0 values 00182 stdair::DispatchingCurve_T lBasedDispatchingCurve; 00183 for (stdair::FRAT5Curve_T::const_iterator itFRAT5 = iFRAT5Curve.begin(); 00184 itFRAT5 != iFRAT5Curve.end(); ++itFRAT5) { 00185 const stdair::DTD_T& lDTD = itFRAT5->first; 00186 lBasedDispatchingCurve.insert(stdair::DispatchingCurve_T::value_type(lDTD, 1.0)); 00187 } 00188 00189 // Retrieve the classes from low to high and compute the distributions of 00190 // product-oriented and price-oriented demand. 00191 // Retrieve the lowest class. 00192 stdair::BookingClassList_T::const_reverse_iterator itCurrentClass = 00193 iBCList.rbegin(); 00194 assert (itCurrentClass != iBCList.rend()); 00195 stdair::BookingClassList_T::const_reverse_iterator itNextClass = 00196 itCurrentClass; ++itNextClass; 00197 00198 // If there is only one class in the cabin, all the sell-up factors 00199 // will be 1. 00200 stdair::BookingClass* lLowestBC_ptr = *itCurrentClass; 00201 assert (lLowestBC_ptr != NULL); 00202 const stdair::Yield_T& lLowestYield = lLowestBC_ptr->getYield(); 00203 if (itNextClass == iBCList.rend()) { 00204 bool insert = oBCDispatchingFactorMap. 00205 insert (stdair::BookingClassDispatchingCurveMap_T:: 00206 value_type(lLowestBC_ptr, lBasedDispatchingCurve)).second; 00207 assert (insert == true); 00208 } else { 00209 // Compute the demand for higher class using the formula 00210 // Pro_sell_up_from_Q_to_F = e ^ ((y_F/y_Q - 1) * ln (0.5) / (FRAT5 - 1)) 00211 for (; itNextClass != iBCList.rend(); ++itCurrentClass, ++itNextClass) { 00212 stdair::BookingClass* lCurrentBC_ptr = *itCurrentClass; 00213 stdair::BookingClass* lNextBC_ptr = *itNextClass; 00214 assert (lNextBC_ptr != NULL); 00215 const stdair::Yield_T& lNextYield = lNextBC_ptr->getYield(); 00216 00217 // Compute the sell-up factor curve for the current class. 00218 stdair::DispatchingCurve_T lCurrentDispatchingCurve; 00219 for (stdair::FRAT5Curve_T::const_iterator itFRAT5 = iFRAT5Curve.begin(); 00220 itFRAT5 != iFRAT5Curve.end(); ++itFRAT5) { 00221 const stdair::DTD_T& lDTD = itFRAT5->first; 00222 const stdair::FRAT5_T& lFRAT5 = itFRAT5->second; 00223 const double lDispatchingCoef = log(0.5)/(lFRAT5-1); 00224 double lDispatchingFactor = 00225 exp ((lNextYield/lLowestYield - 1.0) * lDispatchingCoef); 00226 stdair::DispatchingCurve_T::iterator itBasedDispatching = 00227 lBasedDispatchingCurve.find (lDTD); 00228 assert (itBasedDispatching != lBasedDispatchingCurve.end()); 00229 double& lBasedFactor = itBasedDispatching->second; 00230 bool insert = lCurrentDispatchingCurve.insert (stdair::DispatchingCurve_T::value_type(lDTD, lBasedFactor - lDispatchingFactor)).second; 00231 assert (insert == true); 00232 lBasedFactor = lDispatchingFactor; 00233 } 00234 bool insert = oBCDispatchingFactorMap. 00235 insert (stdair::BookingClassDispatchingCurveMap_T:: 00236 value_type(lCurrentBC_ptr, lCurrentDispatchingCurve)).second; 00237 assert (insert == true); 00238 } 00239 00240 // Compute the sell-up factor curve for the highest class (which is the 00241 // "current class") 00242 stdair::BookingClass* lCurrentBC_ptr = *itCurrentClass; 00243 bool insert = oBCDispatchingFactorMap. 00244 insert (stdair::BookingClassDispatchingCurveMap_T:: 00245 value_type(lCurrentBC_ptr, lBasedDispatchingCurve)).second; 00246 assert (insert == true); 00247 } 00248 return oBCDispatchingFactorMap; 00249 } 00250 00251 // //////////////////////////////////////////////////////////////////// 00252 void Utilities::dispatchDemandForecast 00253 (const stdair::BookingClassDispatchingCurveMap_T& iBCDispatchingCurveMap, 00254 const stdair::MeanValue_T& iMean, 00255 const stdair::StdDevValue_T& iStdDev, 00256 const stdair::DTD_T& iCurrentDCP) { 00257 for (stdair::BookingClassDispatchingCurveMap_T::const_iterator itBCDC = 00258 iBCDispatchingCurveMap.begin(); 00259 itBCDC != iBCDispatchingCurveMap.end(); ++itBCDC) { 00260 stdair::BookingClass* lBC_ptr = itBCDC->first; 00261 assert (lBC_ptr != NULL); 00262 const stdair::DispatchingCurve_T& lDispatchingCurve = itBCDC->second; 00263 stdair::DispatchingCurve_T::const_iterator itDispatchingFactor = 00264 lDispatchingCurve.find (iCurrentDCP); 00265 assert (itDispatchingFactor != lDispatchingCurve.end()); 00266 const double& lDF = itDispatchingFactor->second; 00267 00268 const stdair::MeanValue_T& lCurrentMean = lBC_ptr->getPriceDemMean(); 00269 const stdair::StdDevValue_T& lCurrentStdDev = lBC_ptr->getPriceDemStdDev(); 00270 00271 const stdair::MeanValue_T lAdditionalMean = iMean * lDF; 00272 const stdair::StdDevValue_T lAdditionalStdDev = iStdDev * std::sqrt (lDF); 00273 00274 const stdair::MeanValue_T lNewMean = lCurrentMean + lAdditionalMean; 00275 const stdair::StdDevValue_T lNewStdDev = 00276 std::sqrt (lCurrentStdDev * lCurrentStdDev 00277 + lAdditionalStdDev * lAdditionalStdDev); 00278 00279 lBC_ptr->setPriceDemMean (lNewMean); 00280 lBC_ptr->setPriceDemStdDev (lNewStdDev); 00281 } 00282 } 00283 00284 // //////////////////////////////////////////////////////////////////// 00285 void Utilities::dispatchDemandForecastForFA 00286 (const stdair::BookingClassSellUpCurveMap_T& iBCSellUpCurveMap, 00287 const stdair::MeanValue_T& iMean, 00288 const stdair::StdDevValue_T& iStdDev, 00289 const stdair::DTD_T& iCurrentDCP) { 00290 for (stdair::BookingClassSellUpCurveMap_T::const_iterator itBCSU = 00291 iBCSellUpCurveMap.begin(); 00292 itBCSU != iBCSellUpCurveMap.end(); ++itBCSU) { 00293 stdair::BookingClass* lBC_ptr = itBCSU->first; 00294 assert (lBC_ptr != NULL); 00295 const stdair::SellUpCurve_T& lSellUpCurve = itBCSU->second; 00296 stdair::SellUpCurve_T::const_iterator itSellUpFactor = 00297 lSellUpCurve.find (iCurrentDCP); 00298 assert (itSellUpFactor != lSellUpCurve.end()); 00299 const stdair::SellupProbability_T& lSU = itSellUpFactor->second; 00300 00301 const stdair::MeanValue_T& lCurrentMean = lBC_ptr->getCumuPriceDemMean(); 00302 const stdair::StdDevValue_T& lCurrentStdDev = 00303 lBC_ptr->getCumuPriceDemStdDev(); 00304 00305 const stdair::MeanValue_T lAdditionalMean = iMean * lSU; 00306 const stdair::StdDevValue_T lAdditionalStdDev = iStdDev * std::sqrt (lSU); 00307 00308 const stdair::MeanValue_T lNewMean = lCurrentMean + lAdditionalMean; 00309 const stdair::StdDevValue_T lNewStdDev = 00310 std::sqrt (lCurrentStdDev * lCurrentStdDev 00311 + lAdditionalStdDev * lAdditionalStdDev); 00312 00313 lBC_ptr->setCumuPriceDemMean (lNewMean); 00314 lBC_ptr->setCumuPriceDemStdDev (lNewStdDev); 00315 } 00316 } 00317 }