$treeview $search $mathjax
00001 // ////////////////////////////////////////////////////////////////////// 00002 // Import section 00003 // ////////////////////////////////////////////////////////////////////// 00004 // STL 00005 #include <cassert> 00006 #include <sstream> 00007 #include <cmath> 00008 // StdAir 00009 #include <stdair/basic/BasConst_General.hpp> 00010 #include <stdair/basic/BasConst_Inventory.hpp> 00011 #include <stdair/bom/BomManager.hpp> 00012 #include <stdair/bom/SegmentDate.hpp> 00013 #include <stdair/bom/SegmentCabin.hpp> 00014 #include <stdair/bom/SegmentSnapshotTable.hpp> 00015 #include <stdair/bom/FareFamily.hpp> 00016 #include <stdair/bom/BookingClass.hpp> 00017 #include <stdair/bom/Policy.hpp> 00018 #include <stdair/service/Logger.hpp> 00019 // RMOL 00020 #include <rmol/bom/Utilities.hpp> 00021 #include <rmol/bom/SegmentSnapshotTableHelper.hpp> 00022 #include <rmol/bom/HistoricalBookingHolder.hpp> 00023 #include <rmol/bom/HistoricalBooking.hpp> 00024 #include <rmol/bom/EMDetruncator.hpp> 00025 #include <rmol/command/OldQFF.hpp> 00026 #include <rmol/command/Detruncator.hpp> 00027 00028 namespace RMOL { 00029 // //////////////////////////////////////////////////////////////////// 00030 bool OldQFF:: 00031 forecast (stdair::SegmentCabin& ioSegmentCabin, 00032 const stdair::Date_T& iCurrentDate, 00033 const stdair::DTD_T& iCurrentDTD, 00034 const stdair::UnconstrainingMethod& iUnconstrainingMethod, 00035 const stdair::NbOfSegments_T& iNbOfDepartedSegments) { 00036 // Retrieve the snapshot table. 00037 const stdair::SegmentSnapshotTable& lSegmentSnapshotTable = 00038 ioSegmentCabin.getSegmentSnapshotTable(); 00039 00040 // Retrieve the FRAT5Curve. 00041 const stdair::FareFamilyList_T& lFFList = 00042 stdair::BomManager::getList<stdair::FareFamily>(ioSegmentCabin); 00043 stdair::FareFamilyList_T::const_reverse_iterator itFF = lFFList.rbegin(); 00044 assert (itFF != lFFList.rend()); 00045 stdair::FareFamily* lFF_ptr = *itFF; 00046 assert (lFF_ptr != NULL); 00047 const stdair::FRAT5Curve_T lFRAT5Curve = lFF_ptr->getFrat5Curve(); 00048 00049 // Retrieve the booking class list and compute the sell up curves 00050 // and the dispatching curves. 00051 const stdair::BookingClassList_T& lBCList = 00052 stdair::BomManager::getList<stdair::BookingClass>(ioSegmentCabin); 00053 const stdair::BookingClassSellUpCurveMap_T lBCSellUpCurveMap = 00054 Utilities::computeSellUpFactorCurves (lFRAT5Curve, lBCList); 00055 00056 // Retrieve the list of all policies and reset the demand forecast 00057 // for each one. 00058 const stdair::PolicyList_T& lPolicyList = 00059 stdair::BomManager::getList<stdair::Policy> (ioSegmentCabin); 00060 for (stdair::PolicyList_T::const_iterator itPolicy = lPolicyList.begin(); 00061 itPolicy != lPolicyList.end(); ++itPolicy) { 00062 stdair::Policy* lPolicy_ptr = *itPolicy; 00063 assert (lPolicy_ptr != NULL); 00064 lPolicy_ptr->resetDemandForecast(); 00065 } 00066 00067 // Browse all remaining DCP's and do unconstraining, forecasting 00068 // and dispatching. 00069 const stdair::DCPList_T lWholeDCPList = stdair::DEFAULT_DCP_LIST; 00070 stdair::DCPList_T::const_iterator itDCP = lWholeDCPList.begin(); 00071 stdair::DCPList_T::const_iterator itNextDCP = itDCP; ++itNextDCP; 00072 for (; itNextDCP != lWholeDCPList.end(); ++itDCP, ++itNextDCP) { 00073 const stdair::DCP_T& lCurrentDCP = *itDCP; 00074 const stdair::DCP_T& lNextDCP = *itNextDCP; 00075 00076 // The end of the interval is after the current DTD. 00077 if (lNextDCP < iCurrentDTD) { 00078 // Get the number of similar segments which has already passed the 00079 // (lNextDCP+1) 00080 const stdair::NbOfSegments_T& lNbOfUsableSegments = 00081 SegmentSnapshotTableHelper:: 00082 getNbOfSegmentAlreadyPassedThisDTD (lSegmentSnapshotTable, 00083 lNextDCP+1, 00084 iCurrentDate); 00085 stdair::NbOfSegments_T lSegmentBegin = 0; 00086 const stdair::NbOfSegments_T lSegmentEnd = lNbOfUsableSegments-1; 00087 if (iNbOfDepartedSegments > 52) { 00088 lSegmentBegin = iNbOfDepartedSegments - 52; 00089 } 00090 00091 // Retrieve the historical bookings and convert them to 00092 // Q-equivalent bookings. 00093 HistoricalBookingHolder lHBHolder; 00094 prepareHistoricalBooking (ioSegmentCabin, lSegmentSnapshotTable, 00095 lHBHolder, lCurrentDCP, lNextDCP, 00096 lSegmentBegin, lSegmentEnd, 00097 lBCSellUpCurveMap); 00098 00099 // Unconstrain the historical bookings. 00100 Detruncator::unconstrain (lHBHolder, iUnconstrainingMethod); 00101 00102 // Retrieve the historical unconstrained demand and perform the 00103 // forecasting. 00104 stdair::UncDemVector_T lUncDemVector; 00105 const short lNbOfHistoricalFlights = lHBHolder.getNbOfFlights(); 00106 for (short i = 0; i < lNbOfHistoricalFlights; ++i) { 00107 const stdair::NbOfBookings_T& lUncDemand = 00108 lHBHolder.getUnconstrainedDemand (i); 00109 lUncDemVector.push_back (lUncDemand); 00110 } 00111 stdair::MeanValue_T lMean = 0.0; 00112 stdair::StdDevValue_T lStdDev = 0.0; 00113 Utilities::computeDistributionParameters (lUncDemVector, 00114 lMean, lStdDev); 00115 00116 // Add the demand forecast to the fare family. 00117 const stdair::MeanValue_T& lCurrentMean = lFF_ptr->getMean(); 00118 const stdair::StdDevValue_T& lCurrentStdDev = lFF_ptr->getStdDev(); 00119 00120 const stdair::MeanValue_T lNewMean = lCurrentMean + lMean; 00121 const stdair::StdDevValue_T lNewStdDev = 00122 std::sqrt (lCurrentStdDev * lCurrentStdDev + lStdDev * lStdDev); 00123 00124 lFF_ptr->setMean (lNewMean); 00125 lFF_ptr->setStdDev (lNewStdDev); 00126 00127 // Dispatch the demand forecast to the policies. 00128 dispatchDemandForecastToPolicies (lPolicyList, lCurrentDCP, lMean, 00129 lStdDev, lBCSellUpCurveMap); 00130 } 00131 } 00132 00133 return true; 00134 } 00135 00136 // //////////////////////////////////////////////////////////////////// 00137 void OldQFF::prepareHistoricalBooking 00138 (const stdair::SegmentCabin& iSegmentCabin, 00139 const stdair::SegmentSnapshotTable& iSegmentSnapshotTable, 00140 HistoricalBookingHolder& ioHBHolder, 00141 const stdair::DCP_T& iDCPBegin, const stdair::DCP_T& iDCPEnd, 00142 const stdair::NbOfSegments_T& iSegmentBegin, 00143 const stdair::NbOfSegments_T& iSegmentEnd, 00144 const stdair::BookingClassSellUpCurveMap_T& iBCSellUpCurveMap) { 00145 00146 // Retrieve the segment-cabin index within the snapshot table 00147 std::ostringstream lSCMapKey; 00148 lSCMapKey << stdair::DEFAULT_SEGMENT_CABIN_VALUE_TYPE 00149 << iSegmentCabin.describeKey(); 00150 const stdair::ClassIndex_T& lCabinIdx = 00151 iSegmentSnapshotTable.getClassIndex (lSCMapKey.str()); 00152 00153 // Retrieve the gross daily booking and availability snapshots. 00154 const stdair::ConstSegmentCabinDTDRangeSnapshotView_T lPriceBookingView = 00155 iSegmentSnapshotTable.getConstSegmentCabinDTDRangePriceOrientedGrossBookingSnapshotView (iSegmentBegin, iSegmentEnd, iDCPEnd, iDCPBegin); 00156 const stdair::ConstSegmentCabinDTDRangeSnapshotView_T lProductBookingView = 00157 iSegmentSnapshotTable.getConstSegmentCabinDTDRangeProductOrientedGrossBookingSnapshotView (iSegmentBegin, iSegmentEnd, iDCPEnd, iDCPBegin); 00158 const stdair::ConstSegmentCabinDTDRangeSnapshotView_T lAvlView = 00159 iSegmentSnapshotTable.getConstSegmentCabinDTDRangeAvailabilitySnapshotView (iSegmentBegin, iSegmentEnd, iDCPEnd, iDCPBegin); 00160 00161 // Browse the list of segments and build the historical booking holder. 00162 const stdair::ClassIndexMap_T& lVTIdxMap = 00163 iSegmentSnapshotTable.getClassIndexMap(); 00164 const stdair::NbOfClasses_T lNbOfClasses = lVTIdxMap.size(); 00165 00166 for (short i = 0; i <= iSegmentEnd-iSegmentBegin; ++i) { 00167 stdair::Flag_T lCensorshipFlag = false; 00168 const short lNbOfDTDs = iDCPBegin - iDCPEnd + 1; 00169 const stdair::UnsignedIndex_T lAvlIdx = i*lNbOfClasses + lCabinIdx; 00170 00171 // Parse the DTDs during the period and compute the censorship flag 00172 for (short j = 0; j < lNbOfDTDs; ++j) { 00173 // Check if the data has been censored during this day. 00174 // STDAIR_LOG_DEBUG ("i: " << i << ", NbOfClasses: " << lNbOfClasses 00175 // << ", ClassIdx: " << iClassIdx << ", j: " << j); 00176 if (lAvlView[lAvlIdx][j] < 1.0) { 00177 lCensorshipFlag = true; 00178 break; 00179 } 00180 } 00181 00182 // Compute the Q-equivalent bookings 00183 stdair::NbOfBookings_T lNbOfHistoricalBkgs = 0.0; 00184 const stdair::BookingClassList_T& lBCList = 00185 stdair::BomManager::getList<stdair::BookingClass> (iSegmentCabin); 00186 for (short j = 0; j < lNbOfDTDs; ++j) { 00187 stdair::BookingClass* lLowestBC_ptr = NULL; 00188 stdair::NbOfBookings_T lNbOfBksOfTheDay = 0.0; 00189 for (stdair::BookingClassList_T::const_iterator itBC = lBCList.begin(); 00190 itBC != lBCList.end(); ++itBC) { 00191 stdair::BookingClass* lBC_ptr = *itBC; 00192 assert (lBC_ptr != NULL); 00193 00194 // Retrieve the number of bookings 00195 const stdair::ClassIndex_T& lClassIdx = 00196 iSegmentSnapshotTable.getClassIndex(lBC_ptr->describeKey()); 00197 const stdair::UnsignedIndex_T lIdx = i*lNbOfClasses + lClassIdx; 00198 const stdair::NbOfBookings_T lNbOfBookings = 00199 lPriceBookingView[lIdx][j] + lProductBookingView[lIdx][j]; 00200 lNbOfBksOfTheDay += lNbOfBookings; 00201 00202 if (lAvlView[lIdx][j] >= 1.0) { 00203 lLowestBC_ptr = lBC_ptr; 00204 } 00205 } 00206 00207 // Convert the number of bookings of the day to Q-equivalent 00208 // bookings using the sell-up probability of the lowest class 00209 // available of the day. 00210 if (lLowestBC_ptr != NULL) { 00211 stdair::BookingClassSellUpCurveMap_T::const_iterator itBCSUC = 00212 iBCSellUpCurveMap.find (lLowestBC_ptr); 00213 assert (itBCSUC != iBCSellUpCurveMap.end()); 00214 const stdair::SellUpCurve_T& lSellUpCurve = itBCSUC->second; 00215 stdair::SellUpCurve_T::const_iterator itSellUp = 00216 lSellUpCurve.find (iDCPBegin); 00217 assert (itSellUp != lSellUpCurve.end()); 00218 const stdair::SellupProbability_T& lSellUp = itSellUp->second; 00219 assert (lSellUp != 0); 00220 00221 lNbOfHistoricalBkgs += lNbOfBksOfTheDay/lSellUp; 00222 } 00223 } 00224 00225 HistoricalBooking lHistoricalBkg (lNbOfHistoricalBkgs, lCensorshipFlag); 00226 ioHBHolder.addHistoricalBooking (lHistoricalBkg); 00227 } 00228 } 00229 00230 // //////////////////////////////////////////////////////////////////// 00231 void OldQFF:: 00232 dispatchDemandForecastToPolicies (const stdair::PolicyList_T& iPolicyList, 00233 const stdair::DCP_T& iCurrentDCP, 00234 const stdair::MeanValue_T& iMean, 00235 const stdair::StdDevValue_T& iStdDev, 00236 const stdair::BookingClassSellUpCurveMap_T& iBCSellUpCurveMap) { 00237 for (stdair::PolicyList_T::const_iterator itPolicy = iPolicyList.begin(); 00238 itPolicy != iPolicyList.end(); ++itPolicy) { 00239 stdair::Policy* lPolicy_ptr = *itPolicy; 00240 assert (lPolicy_ptr != NULL); 00241 dispatchDemandForecastToPolicy (*lPolicy_ptr, 00242 iCurrentDCP, 00243 iMean, 00244 iStdDev, 00245 iBCSellUpCurveMap); 00246 } 00247 } 00248 00249 // //////////////////////////////////////////////////////////////////// 00250 void OldQFF:: 00251 dispatchDemandForecastToPolicy (stdair::Policy& ioPolicy, 00252 const stdair::DCP_T& iCurrentDCP, 00253 const stdair::MeanValue_T& iMean, 00254 const stdair::StdDevValue_T& iStdDev, 00255 const stdair::BookingClassSellUpCurveMap_T& iBCSellUpCurveMap) { 00256 const stdair::MeanValue_T& lPolicyDemand = ioPolicy.getDemand(); 00257 const stdair::StdDevValue_T& lPolicyStdDev = ioPolicy.getStdDev(); 00258 00259 // Browse the list of booking classes of the policy and use the 00260 // cumulative price-oriented demand forecast of each class. 00261 const bool hasAListOfBC = 00262 stdair::BomManager::hasList<stdair::BookingClass> (ioPolicy); 00263 if (hasAListOfBC == true) { 00264 const stdair::BookingClassList_T& lBCList = 00265 stdair::BomManager::getList<stdair::BookingClass> (ioPolicy); 00266 stdair::BookingClassList_T::const_reverse_iterator itCurrentBC = 00267 lBCList.rbegin(); 00268 assert(itCurrentBC != lBCList.rend()); 00269 stdair::BookingClass* lLowestBC_ptr = *itCurrentBC; 00270 assert (lLowestBC_ptr != NULL); 00271 const stdair::Yield_T& lLowestBCYield = lLowestBC_ptr->getYield(); 00272 // Retrieve the sell-up factor for the lowest class. 00273 stdair::BookingClassSellUpCurveMap_T::const_iterator itBCSU = 00274 iBCSellUpCurveMap.find (lLowestBC_ptr); 00275 assert (itBCSU != iBCSellUpCurveMap.end()); 00276 const stdair::SellUpCurve_T& lSellUpCurve = itBCSU->second; 00277 stdair::SellUpCurve_T::const_iterator itSellUpFactor = 00278 lSellUpCurve.find (iCurrentDCP); 00279 assert (itSellUpFactor != lSellUpCurve.end()); 00280 const stdair::SellupProbability_T& lSUToLowestClass = itSellUpFactor->second; 00281 00282 const stdair::MeanValue_T lAdditinalPolicyDemandMean = 00283 iMean * lSUToLowestClass; 00284 const stdair::StdDevValue_T lAdditinalPolicyDemandStdDev = 00285 iStdDev * std::sqrt (lSUToLowestClass); 00286 00287 const stdair::MeanValue_T lNewPolicyDemandMean = 00288 lPolicyDemand + lAdditinalPolicyDemandMean; 00289 const stdair::StdDevValue_T lNewPolicyDemandStdDev = 00290 std::sqrt (lPolicyStdDev*lPolicyStdDev 00291 + lAdditinalPolicyDemandStdDev * lAdditinalPolicyDemandStdDev); 00292 // 00293 ioPolicy.setDemand (lNewPolicyDemandMean); 00294 ioPolicy.setStdDev (lNewPolicyDemandStdDev); 00295 00296 ioPolicy.addYieldDemand (lLowestBCYield, 00297 lAdditinalPolicyDemandMean); 00298 00299 // Iterate other classes. 00300 stdair::BookingClassList_T::const_reverse_iterator itNextBC=itCurrentBC; 00301 ++itNextBC; 00302 for (; itNextBC != lBCList.rend(); ++itNextBC, ++itCurrentBC) { 00303 stdair::BookingClass* lCurrentBC_ptr = *itCurrentBC; 00304 assert (lCurrentBC_ptr != NULL); 00305 stdair::BookingClass* lNextBC_ptr = *itNextBC; 00306 assert (lNextBC_ptr != NULL); 00307 00308 // Retrieve the disutility for the current policy to the next one. 00309 const stdair::FareFamily& lCurrentFF = 00310 stdair::BomManager::getParent<stdair::FareFamily> (*lCurrentBC_ptr); 00311 const stdair::FFDisutilityCurve_T& lDisutilityCurve = 00312 lCurrentFF.getDisutilityCurve(); 00313 stdair::FFDisutilityCurve_T::const_iterator itDU = 00314 lDisutilityCurve.find (iCurrentDCP); 00315 assert (itDU != lDisutilityCurve.end()); 00316 const double& lDU = itDU->second; 00317 00318 // Retrieve the sell-up factor for the next class. 00319 stdair::BookingClassSellUpCurveMap_T::const_iterator itBCSUN = 00320 iBCSellUpCurveMap.find (lNextBC_ptr); 00321 assert (itBCSUN != iBCSellUpCurveMap.end()); 00322 const stdair::SellUpCurve_T& lSellUpCurveN = itBCSUN->second; 00323 stdair::SellUpCurve_T::const_iterator itSellUpFactorN = 00324 lSellUpCurveN.find (iCurrentDCP); 00325 assert (itSellUpFactorN != lSellUpCurveN.end()); 00326 const stdair::SellupProbability_T& lSUToNextClass = itSellUpFactorN->second; 00327 assert (lSUToNextClass > 0.0); 00328 assert(lSUToNextClass < lSUToLowestClass); 00329 00330 // Retrieve the yields of the two classes 00331 const stdair::Yield_T& lCurrentYield = lCurrentBC_ptr->getYield(); 00332 const stdair::Yield_T& lNextYield = lNextBC_ptr->getYield(); 00333 const double lBuyUpFactor = exp ((lCurrentYield-lNextYield)*lDU); 00334 00335 // Withdraw an amount demand forecast from the current class. This 00336 // amount of forecast will be added to the next class. 00337 const stdair::MeanValue_T lDemandForNextClass = 00338 iMean * lSUToNextClass * lBuyUpFactor; 00339 ioPolicy.addYieldDemand (lNextYield, lDemandForNextClass); 00340 ioPolicy.addYieldDemand (lCurrentYield, -lDemandForNextClass); 00341 } 00342 } 00343 } 00344 }