00001
00002
00003
00004
00005 #include <cassert>
00006 #include <sstream>
00007 #include <cmath>
00008
00009 #include <stdair/basic/BasConst_General.hpp>
00010 #include <stdair/basic/BasConst_Inventory.hpp>
00011 #include <stdair/basic/RandomGeneration.hpp>
00012 #include <stdair/bom/BomManager.hpp>
00013 #include <stdair/bom/FlightDate.hpp>
00014 #include <stdair/bom/LegDate.hpp>
00015 #include <stdair/bom/SegmentDate.hpp>
00016 #include <stdair/bom/LegCabin.hpp>
00017 #include <stdair/bom/SegmentCabin.hpp>
00018 #include <stdair/bom/GuillotineBlock.hpp>
00019 #include <stdair/bom/BookingClass.hpp>
00020 #include <stdair/service/Logger.hpp>
00021
00022 #include <rmol/basic/BasConst_Curves.hpp>
00023 #include <rmol/bom/Utilities.hpp>
00024 #include <rmol/bom/GuillotineBlockHelper.hpp>
00025 #include <rmol/bom/HistoricalBookingHolder.hpp>
00026 #include <rmol/bom/HistoricalBooking.hpp>
00027 #include <rmol/bom/EMDetruncator.hpp>
00028 #include <rmol/command/Forecaster.hpp>
00029 #include <rmol/command/Detruncator.hpp>
00030
00031 namespace RMOL {
00032
00033
00034 bool Forecaster::
00035 forecastUsingAdditivePickUp (stdair::FlightDate& ioFlightDate,
00036 const stdair::DateTime_T& iEventTime) {
00037
00038 const stdair::Date_T& lEventDate = iEventTime.date();
00039 stdair::Date_T lRefDate (2012, boost::gregorian::Jan, 01);
00040
00041
00042 bool isSucceeded = true;
00043 const stdair::SegmentDateList_T& lSDList =
00044 stdair::BomManager::getList<stdair::SegmentDate> (ioFlightDate);
00045 for (stdair::SegmentDateList_T::const_iterator itSD = lSDList.begin();
00046 itSD != lSDList.end(); ++itSD) {
00047 stdair::SegmentDate* lSD_ptr = *itSD;
00048 assert (lSD_ptr != NULL);
00049
00050 const stdair::Date_T& lBoardingDate = lSD_ptr->getBoardingDate();
00051 const stdair::DateOffset_T lSegmentDateOffset =
00052 lBoardingDate - lEventDate;
00053 const stdair::DTD_T lSegmentDTD = lSegmentDateOffset.days();
00054
00055
00056
00057
00058 stdair::DCPList_T lDCPList;
00059
00060 if (lEventDate < lRefDate) {
00061 lDCPList = Utilities::buildRemainingDCPList (lSegmentDTD);
00062 } else {
00063 lDCPList = Utilities::buildRemainingDCPList2 (lSegmentDTD);
00064 }
00065
00066
00067 const stdair::SegmentCabinList_T& lSCList =
00068 stdair::BomManager::getList<stdair::SegmentCabin> (*lSD_ptr);
00069 for (stdair::SegmentCabinList_T::const_iterator itSC = lSCList.begin();
00070 itSC != lSCList.end(); ++itSC) {
00071 stdair::SegmentCabin* lSC_ptr = *itSC;
00072 assert (lSC_ptr != NULL);
00073
00074
00075
00076
00077 bool isForecasted = forecastUsingAdditivePickUp (*lSC_ptr, lDCPList,
00078 lEventDate);
00079 if (isForecasted == false) {
00080 isSucceeded = false;
00081 }
00082 }
00083 }
00084
00085 return isSucceeded;
00086 }
00087
00088
00089 bool Forecaster::
00090 forecastUsingAdditivePickUp (stdair::SegmentCabin& ioSegmentCabin,
00091 const stdair::DCPList_T& iDCPList,
00092 const stdair::Date_T& iEventDate) {
00093
00094 stdair::NbOfSegments_T lNbOfDepartedSegments =
00095 Utilities::getNbOfDepartedSimilarSegments (ioSegmentCabin, iEventDate);
00096
00097 if (lNbOfDepartedSegments > 52) lNbOfDepartedSegments = 52;
00098
00099
00100 STDAIR_LOG_DEBUG ("Nb of similar departed segments: "
00101 << lNbOfDepartedSegments);
00102
00103
00104
00105
00106 stdair::DCPList_T::const_iterator itDCP = iDCPList.begin();
00107 assert (itDCP != iDCPList.end());
00108 const stdair::DCP_T& lCurrentDTD = *itDCP;
00109 if (iDCPList.size() == 1 || lNbOfDepartedSegments < 2) {
00110 setRemainingDemandForecastToZero (ioSegmentCabin);
00111 return false;
00112 } else {
00113
00114 UnconstrainedDemandVector_T lQEquivalentDemandVector (lNbOfDepartedSegments, 0.0);
00115 BookingClassUnconstrainedDemandVectorMap_T lBkgClassUncDemMap;
00116 const stdair::BookingClassList_T& lBCList =
00117 stdair::BomManager::getList<stdair::BookingClass> (ioSegmentCabin);
00118 for (stdair::BookingClassList_T::const_iterator itBC = lBCList.begin();
00119 itBC != lBCList.end(); ++itBC) {
00120 stdair::BookingClass* lBC_ptr = *itBC;
00121 assert (lBC_ptr != NULL);
00122 std::vector<stdair::NbOfRequests_T> lUncDemandVector (lNbOfDepartedSegments, 0.0);
00123 bool insertionSucceeded = lBkgClassUncDemMap.insert
00124 (BookingClassUnconstrainedDemandVectorMap_T::
00125 value_type (lBC_ptr, lUncDemandVector)).second;
00126 assert (insertionSucceeded == true);
00127 }
00128
00129
00130
00131 stdair::DCPList_T::const_iterator itNextDCP = itDCP; ++itNextDCP;
00132 for (; itNextDCP != iDCPList.end(); ++itDCP, ++itNextDCP) {
00133 const stdair::DCP_T& lCurrentDCP = *itDCP;
00134 const stdair::DCP_T& lNextDCP = *itNextDCP;
00135
00136
00137 STDAIR_LOG_DEBUG ("Unconstrain demand for "
00138 << ioSegmentCabin.describeKey()
00139 << " and the DCP's " << lCurrentDCP << ", "
00140 << lNextDCP);
00141 Detruncator::unconstrainUsingAdditivePickUp (ioSegmentCabin,
00142 lBkgClassUncDemMap,
00143 lQEquivalentDemandVector,
00144 lCurrentDCP-1, lNextDCP,
00145 iEventDate);
00146 STDAIR_LOG_DEBUG ("Detrucation successful");
00147 }
00148
00149
00150 FRAT5Curve_T::const_iterator itFRAT5 =
00151 DEFAULT_CUMULATIVE_FRAT5_CURVE.lower_bound (lCurrentDTD);
00152 assert (itFRAT5 != DEFAULT_CUMULATIVE_FRAT5_CURVE.end());
00153 const double lFRAT5Coef = itFRAT5->second;
00154 const double lSellUpCoef = -log(0.5) / (lFRAT5Coef - 1);
00155
00156 forecastUsingAdditivePickUp (ioSegmentCabin, lBkgClassUncDemMap,
00157 lQEquivalentDemandVector, lSellUpCoef);
00158 return true;
00159 }
00160 }
00161
00162
00163 void Forecaster::
00164 forecastUsingAdditivePickUp (stdair::SegmentCabin& ioSegmentCabin,
00165 const BookingClassUnconstrainedDemandVectorMap_T& iClassUncDemMap,
00166 const UnconstrainedDemandVector_T& iUncDemVector,
00167 const double& iSellUpFactor) {
00168 double lPriceOriMean; double lPriceOriStdDev;
00169 Utilities::computeDistributionParameters (iUncDemVector, lPriceOriMean,
00170 lPriceOriStdDev);
00171
00172
00173
00174
00175
00176
00177
00178 const stdair::BookingClassList_T& lBCList =
00179 stdair::BomManager::getList<stdair::BookingClass> (ioSegmentCabin);
00180 stdair::BookingClassList_T::const_reverse_iterator itCurrentClass =
00181 lBCList.rbegin();
00182 assert (itCurrentClass != lBCList.rend());
00183 stdair::BookingClassList_T::const_reverse_iterator itNextClass =
00184 itCurrentClass;
00185 ++itNextClass;
00186
00187
00188 if (itNextClass == lBCList.rend()) {
00189 stdair::BookingClass* lLowestBC_ptr = *itCurrentClass;
00190 lLowestBC_ptr->setMean (lPriceOriMean);
00191 lLowestBC_ptr->setStdDev (lPriceOriStdDev);
00192 } else {
00193
00194
00195 for (; itNextClass != lBCList.rend(); ++itCurrentClass, ++itNextClass) {
00196 stdair::BookingClass* lCurrentBC_ptr = *itCurrentClass;
00197 assert (lCurrentBC_ptr != NULL);
00198 const stdair::Yield_T& lCurrentYield = lCurrentBC_ptr->getYield();
00199 stdair::BookingClass* lNextBC_ptr = *itNextClass;
00200 assert (lNextBC_ptr != NULL);
00201 const stdair::Yield_T& lNextYield = lNextBC_ptr->getYield();
00202
00203
00204
00205 const double lSellUp =
00206 exp ((1.0 - lNextYield/lCurrentYield) * iSellUpFactor);
00207 const double lPriceOriDemMeanFrac = lPriceOriMean * (1.0 - lSellUp);
00208 const double lPriceOriDemStdDevFrac = lPriceOriStdDev * (1.0 - lSellUp);
00209
00210
00211
00212 BookingClassUnconstrainedDemandVectorMap_T::const_iterator itBCUD =
00213 iClassUncDemMap.find (lCurrentBC_ptr);
00214 assert (itBCUD != iClassUncDemMap.end());
00215 const UnconstrainedDemandVector_T& lDemandVector = itBCUD->second;
00216 double lMean; double lStdDev;
00217 Utilities::computeDistributionParameters(lDemandVector, lMean, lStdDev);
00218
00219
00220 lMean += lPriceOriDemMeanFrac;
00221 lStdDev = sqrt (lStdDev * lStdDev +
00222 lPriceOriDemStdDevFrac * lPriceOriDemStdDevFrac);
00223 lCurrentBC_ptr->setMean (lMean);
00224 lCurrentBC_ptr->setStdDev (lStdDev);
00225
00226
00227
00228
00229
00230
00231
00232 lPriceOriMean *= lSellUp;
00233 lPriceOriStdDev *= lSellUp;
00234 }
00235
00236
00237
00238 stdair::BookingClass* lCurrentBC_ptr = *itCurrentClass;
00239 assert (lCurrentBC_ptr != NULL);
00240 BookingClassUnconstrainedDemandVectorMap_T::const_iterator itBCUD =
00241 iClassUncDemMap.find (lCurrentBC_ptr);
00242 assert (itBCUD != iClassUncDemMap.end());
00243 const UnconstrainedDemandVector_T& lDemandVector = itBCUD->second;
00244 double lMean; double lStdDev;
00245 Utilities::computeDistributionParameters(lDemandVector, lMean, lStdDev);
00246
00247
00248 lMean += lPriceOriMean;
00249 lStdDev = sqrt (lStdDev * lStdDev + lPriceOriStdDev * lPriceOriStdDev);
00250 lCurrentBC_ptr->setMean (lMean);
00251 lCurrentBC_ptr->setStdDev (lStdDev);
00252
00253
00254
00255
00256
00257 }
00258 }
00259
00260
00261 void Forecaster::
00262 setRemainingDemandForecastToZero (const stdair::SegmentCabin& iSegmentCabin) {
00263
00264 const stdair::BookingClassList_T& lBCList =
00265 stdair::BomManager::getList<stdair::BookingClass> (iSegmentCabin);
00266 for (stdair::BookingClassList_T::const_iterator itBC = lBCList.begin();
00267 itBC != lBCList.end(); ++itBC) {
00268 stdair::BookingClass* lBC_ptr = *itBC;
00269 assert (lBC_ptr != NULL);
00270 lBC_ptr->setMean (0.0);
00271 }
00272 }
00273
00274
00275 bool Forecaster::
00276 forecastUsingMultiplicativePickUp (stdair::FlightDate& ioFlightDate,
00277 const stdair::DateTime_T& iEventTime) {
00278
00279 const stdair::Date_T& lEventDate = iEventTime.date();
00280
00281
00282 bool isSucceeded = true;
00283 const stdair::SegmentDateList_T& lSDList =
00284 stdair::BomManager::getList<stdair::SegmentDate> (ioFlightDate);
00285 for (stdair::SegmentDateList_T::const_iterator itSD = lSDList.begin();
00286 itSD != lSDList.end(); ++itSD) {
00287 stdair::SegmentDate* lSD_ptr = *itSD;
00288 assert (lSD_ptr != NULL);
00289
00290 const stdair::Date_T& lBoardingDate = lSD_ptr->getBoardingDate();
00291 const stdair::DateOffset_T lSegmentDateOffset =
00292 lBoardingDate - lEventDate;
00293 const stdair::DTD_T lSegmentDTD = lSegmentDateOffset.days();
00294
00295
00296 const stdair::SegmentCabinList_T& lSCList =
00297 stdair::BomManager::getList<stdair::SegmentCabin> (*lSD_ptr);
00298 for (stdair::SegmentCabinList_T::const_iterator itSC = lSCList.begin();
00299 itSC != lSCList.end(); ++itSC) {
00300 stdair::SegmentCabin* lSC_ptr = *itSC;
00301 assert (lSC_ptr != NULL);
00302
00303 bool isForecasted = forecastUsingMultiplicativePickUp (*lSC_ptr,
00304 lEventDate,
00305 lSegmentDTD);
00306 if (isForecasted == false) {
00307 isSucceeded = false;
00308 }
00309 }
00310 }
00311 return isSucceeded;
00312 }
00313
00314
00315 bool Forecaster::
00316 forecastUsingMultiplicativePickUp (stdair::SegmentCabin& ioSegmentCabin,
00317 const stdair::Date_T& iEventDate,
00318 const stdair::DTD_T& iSegmentDTD) {
00319
00320 const stdair::GuillotineBlock& lGuillotineBlock =
00321 ioSegmentCabin.getGuillotineBlock();
00322 stdair::NbOfSegments_T lNbOfAnteriorSimilarSegments =
00323 GuillotineBlockHelper::
00324 getNbOfSegmentAlreadyPassedThisDTD (lGuillotineBlock, iSegmentDTD,
00325 iEventDate) - 1;
00326
00327 stdair::NbOfSegments_T lNbOfDepartedSegments =
00328 Utilities::getNbOfDepartedSimilarSegments (ioSegmentCabin, iEventDate);
00329
00330 if (lNbOfDepartedSegments > 52) {
00331 lNbOfAnteriorSimilarSegments =
00332 lNbOfAnteriorSimilarSegments - lNbOfDepartedSegments + 52;
00333 }
00334
00335
00336 STDAIR_LOG_DEBUG ("Nb of anterior similar segments: "
00337 << lNbOfAnteriorSimilarSegments);
00338
00339
00340
00341 stdair::DCPList_T::const_reverse_iterator itLastDCP =
00342 stdair::DEFAULT_DCP_LIST.rbegin();
00343 assert (itLastDCP != stdair::DEFAULT_DCP_LIST.rend());
00344 const stdair::DCP_T& lLastDCP = *itLastDCP;
00345 if (lNbOfAnteriorSimilarSegments < 1.0 || iSegmentDTD <= lLastDCP) {
00346 setRemainingDemandForecastToZero (ioSegmentCabin);
00347 return false;
00348 } else {
00349
00350
00351 stdair::DCPList_T::const_iterator itDCP =stdair::DEFAULT_DCP_LIST.begin();
00352 assert (itDCP != stdair::DEFAULT_DCP_LIST.end());
00353 const stdair::DCP_T& lFirstDCP = *itDCP;
00354
00355
00356 stdair::NbOfSegments_T lNbOfUsableSegments =
00357 GuillotineBlockHelper::
00358 getNbOfSegmentAlreadyPassedThisDTD (lGuillotineBlock, lFirstDCP,
00359 iEventDate);
00360
00361 unsigned short lSize = lNbOfUsableSegments;
00362 if (lNbOfDepartedSegments > 52) {
00363 lSize = lNbOfUsableSegments - lNbOfDepartedSegments + 52;
00364 }
00365
00366 STDAIR_LOG_DEBUG ("Nb of usable similar segments: "
00367 << lNbOfUsableSegments);
00368
00369 UnconstrainedDemandVector_T lQEquivalentDemandVector (lSize, 0.0);
00370 stdair::NbOfBookings_T lCurrentSegmentQEquivalentDemand = 0.0;
00371 BookingClassUnconstrainedDemandVectorMap_T lBkgClassUncDemVectorMap;
00372 BookingClassUnconstrainedDemandMap_T lCurrentSegmentBkgClassDemMap;
00373 const stdair::BookingClassList_T& lBCList =
00374 stdair::BomManager::getList<stdair::BookingClass> (ioSegmentCabin);
00375 for (stdair::BookingClassList_T::const_iterator itBC = lBCList.begin();
00376 itBC != lBCList.end(); ++itBC) {
00377 stdair::BookingClass* lBC_ptr = *itBC;
00378 assert (lBC_ptr != NULL);
00379
00380 UnconstrainedDemandVector_T lUncDemandVector (lSize, 0.0);
00381 bool insertionSucceeded = lBkgClassUncDemVectorMap.
00382 insert (BookingClassUnconstrainedDemandVectorMap_T::
00383 value_type (lBC_ptr, lUncDemandVector)).second;
00384 assert (insertionSucceeded == true);
00385 insertionSucceeded =
00386 lCurrentSegmentBkgClassDemMap.
00387 insert (BookingClassUnconstrainedDemandMap_T::
00388 value_type (lBC_ptr, 0.0)).second;
00389 assert (insertionSucceeded == true);
00390 }
00391 Detruncator::
00392 retrieveUnconstrainedDemandForFirstDCP (ioSegmentCabin,
00393 lBkgClassUncDemVectorMap,
00394 lQEquivalentDemandVector,
00395 lFirstDCP, lNbOfUsableSegments,
00396 lSize);
00397
00398
00399 stdair::DCPList_T::const_iterator itNextDCP = itDCP; ++itNextDCP;
00400 while (itNextDCP != stdair::DEFAULT_DCP_LIST.end()) {
00401 const stdair::DCP_T& lCurrentDCP = *itDCP;
00402 const stdair::DCP_T& lNextDCP = *itNextDCP;
00403 if (lCurrentDCP <= iSegmentDTD) {
00404 break;
00405 }
00406 Detruncator::
00407 unconstrainUsingMultiplicativePickUp (ioSegmentCabin,
00408 lBkgClassUncDemVectorMap,
00409 lQEquivalentDemandVector,
00410 lCurrentDCP-1, lNextDCP,
00411 iEventDate,
00412 lNbOfDepartedSegments);
00413 ++itNextDCP; ++itDCP;
00414 }
00415
00416
00417
00418 lCurrentSegmentQEquivalentDemand =
00419 lQEquivalentDemandVector.at (lNbOfAnteriorSimilarSegments);
00420 BookingClassUnconstrainedDemandMap_T::iterator itBCUD =
00421 lCurrentSegmentBkgClassDemMap.begin();
00422 for (BookingClassUnconstrainedDemandVectorMap_T::iterator itBCUDV =
00423 lBkgClassUncDemVectorMap.begin();
00424 itBCUDV != lBkgClassUncDemVectorMap.end(); ++itBCUDV, ++itBCUD) {
00425 assert (itBCUD != lCurrentSegmentBkgClassDemMap.end());
00426 assert (itBCUD->first == itBCUDV->first);
00427 stdair::NbOfRequests_T& lUncDem = itBCUD->second;
00428 UnconstrainedDemandVector_T& lUncDemVector = itBCUDV->second;
00429 lUncDem = lUncDemVector.at (lNbOfAnteriorSimilarSegments);
00430 }
00431
00432
00433 const stdair::DCP_T& lCurrentDTD = *itDCP;
00434 for (; itNextDCP != stdair::DEFAULT_DCP_LIST.end(); ++itNextDCP, ++itDCP){
00435 const stdair::DCP_T& lCurrentDCP = *itDCP;
00436 const stdair::DCP_T& lNextDCP = *itNextDCP;
00437 forecastUsingMultiplicativePickUp (ioSegmentCabin,
00438 lBkgClassUncDemVectorMap,
00439 lQEquivalentDemandVector,
00440 lCurrentDCP-1, lNextDCP, iEventDate,
00441 lNbOfAnteriorSimilarSegments,
00442 lNbOfDepartedSegments);
00443 }
00444
00445
00446 lCurrentSegmentQEquivalentDemand =
00447 lQEquivalentDemandVector.at (lNbOfAnteriorSimilarSegments)
00448 - lCurrentSegmentQEquivalentDemand;
00449 itBCUD = lCurrentSegmentBkgClassDemMap.begin();
00450 for (BookingClassUnconstrainedDemandVectorMap_T::iterator itBCUDV =
00451 lBkgClassUncDemVectorMap.begin();
00452 itBCUDV != lBkgClassUncDemVectorMap.end(); ++itBCUDV, ++itBCUD) {
00453 assert (itBCUD != lCurrentSegmentBkgClassDemMap.end());
00454 assert (itBCUD->first == itBCUDV->first);
00455 stdair::NbOfRequests_T& lUncDem = itBCUD->second;
00456 UnconstrainedDemandVector_T& lUncDemVector = itBCUDV->second;
00457 lUncDem = lUncDemVector.at (lNbOfAnteriorSimilarSegments) - lUncDem;
00458 }
00459
00460
00461 FRAT5Curve_T::const_iterator itFRAT5 =
00462 DEFAULT_CUMULATIVE_FRAT5_CURVE.lower_bound (lCurrentDTD);
00463 assert (itFRAT5 != DEFAULT_CUMULATIVE_FRAT5_CURVE.end());
00464 const double lFRAT5Coef = itFRAT5->second;
00465 const double lSellUpCoef = -log(0.5) / (lFRAT5Coef - 1);
00466
00467 return forecastUsingMultiplicativePickUp(ioSegmentCabin,
00468 lCurrentSegmentBkgClassDemMap,
00469 lCurrentSegmentQEquivalentDemand,
00470 lSellUpCoef);
00471
00472 }
00473 }
00474
00475
00476 void Forecaster::forecastUsingMultiplicativePickUp
00477 (const stdair::SegmentCabin& iSegmentCabin,
00478 BookingClassUnconstrainedDemandVectorMap_T& ioBkgClassUncDemMap,
00479 UnconstrainedDemandVector_T& ioQEquivalentDemandVector,
00480 const stdair::DCP_T& iDCPBegin, const stdair::DCP_T& iDCPEnd,
00481 const stdair::Date_T& iCurrentDate,
00482 const stdair::NbOfSegments_T& iNbOfAnteriorSimilarSegments,
00483 const stdair::NbOfSegments_T& iNbOfDepartedSegments) {
00484
00485
00486 const stdair::GuillotineBlock& lGuillotineBlock =
00487 iSegmentCabin.getGuillotineBlock();
00488
00489
00490
00491 const stdair::NbOfSegments_T lNbOfUsableSegments = GuillotineBlockHelper::
00492 getNbOfSegmentAlreadyPassedThisDTD (lGuillotineBlock, iDCPEnd,
00493 iCurrentDate);
00494
00495 STDAIR_LOG_DEBUG ("Nb of usable similar segments: "
00496 << lNbOfUsableSegments);
00497
00498 if (lNbOfUsableSegments > 0) {
00499
00500
00501 for (BookingClassUnconstrainedDemandVectorMap_T::iterator itBCUDV =
00502 ioBkgClassUncDemMap.begin(); itBCUDV != ioBkgClassUncDemMap.end();
00503 ++itBCUDV) {
00504 stdair::BookingClass* lBC_ptr = itBCUDV->first;
00505 assert (lBC_ptr != NULL);
00506 const stdair::MapKey_T& lBCKey = lBC_ptr->describeKey();
00507 const stdair::BlockIndex_T& lBlockIdx =
00508 lGuillotineBlock.getBlockIndex (lBCKey);
00509 UnconstrainedDemandVector_T& lUncDemVector = itBCUDV->second;
00510
00511 STDAIR_LOG_DEBUG ("Unconstrain product-oriented bookings for "<<lBCKey);
00512 forecastUsingMultiplicativePickUp (lGuillotineBlock, lUncDemVector,
00513 iDCPBegin, iDCPEnd,
00514 lNbOfUsableSegments, lBlockIdx,
00515 iNbOfAnteriorSimilarSegments,
00516 iNbOfDepartedSegments);
00517 }
00518
00519
00520
00521 std::ostringstream lSCMapKey;
00522 lSCMapKey << stdair::DEFAULT_SEGMENT_CABIN_VALUE_TYPE
00523 << iSegmentCabin.describeKey();
00524 const stdair::BlockIndex_T& lCabinIdx =
00525 lGuillotineBlock.getBlockIndex (lSCMapKey.str());
00526
00527 STDAIR_LOG_DEBUG ("Unconstrain price-oriented bookings");
00528 forecastUsingMultiplicativePickUp (lGuillotineBlock,
00529 ioQEquivalentDemandVector,
00530 iDCPBegin, iDCPEnd,
00531 lNbOfUsableSegments, lCabinIdx,
00532 iNbOfAnteriorSimilarSegments,
00533 iNbOfDepartedSegments,
00534 iSegmentCabin, iCurrentDate);
00535 }
00536 }
00537
00538
00539 void Forecaster::forecastUsingMultiplicativePickUp
00540 (const stdair::GuillotineBlock& iGuillotineBlock,
00541 UnconstrainedDemandVector_T& ioUncDemVector,
00542 const stdair::DCP_T& iDCPBegin, const stdair::DCP_T& iDCPEnd,
00543 const stdair::NbOfSegments_T& iNbOfUsableSegments,
00544 const stdair::BlockIndex_T& iBlockIdx,
00545 const stdair::NbOfSegments_T& iNbOfAnteriorSimilarSegments,
00546 const stdair::NbOfSegments_T& iNbOfDepartedSegments) {
00547
00548 stdair::NbOfSegments_T lSegBegin = 0;
00549 if (iNbOfDepartedSegments > 52) {
00550 lSegBegin = iNbOfDepartedSegments - 52;
00551 }
00552
00553 stdair::ConstSegmentCabinDTDRangeSnapshotView_T lBookingView =
00554 iGuillotineBlock.getConstSegmentCabinDTDRangeProductAndPriceOrientedBookingSnapshotView (lSegBegin, iNbOfUsableSegments -1, iDCPEnd, iDCPBegin);
00555 stdair::ConstSegmentCabinDTDRangeSnapshotView_T lAvlView =
00556 iGuillotineBlock.getConstSegmentCabinDTDRangeAvailabilitySnapshotView (lSegBegin, iNbOfUsableSegments -1, iDCPEnd, iDCPBegin);
00557
00558
00559 const stdair::ValueTypeIndexMap_T& lVTIdxMap =
00560 iGuillotineBlock.getValueTypeIndexMap();
00561 const unsigned int lNbOfValueTypes = lVTIdxMap.size();
00562 HistoricalBookingHolder lHBHolder;
00563 std::vector<short> lDataIndexList;
00564 for (short i = 0; i < iNbOfUsableSegments-lSegBegin; ++i) {
00565 stdair::Flag_T lCensorshipFlag = false;
00566 stdair::NbOfBookings_T lNbOfHistoricalBkgs = 0.0;
00567 const short lNbOfDTDs = iDCPBegin - iDCPEnd + 1;
00568
00569
00570 for (short j = 0; j < lNbOfDTDs; ++j) {
00571
00572
00573
00574 if (lCensorshipFlag == false) {
00575 if (lAvlView[i*lNbOfValueTypes + iBlockIdx][j] < 1.0) {
00576 lCensorshipFlag = true;
00577 }
00578 }
00579
00580
00581
00582 lNbOfHistoricalBkgs += lBookingView[i*lNbOfValueTypes + iBlockIdx][j];
00583 }
00584
00585
00586
00587 stdair::NbOfRequests_T& lUncDemand = ioUncDemVector.at (i);
00588 if (lUncDemand < 1.0) {
00589 lUncDemand += lNbOfHistoricalBkgs;
00590 } else {
00591 double lBkgDemandFactor = lNbOfHistoricalBkgs / lUncDemand;
00592 HistoricalBooking lHistoricalBkg (lBkgDemandFactor, lCensorshipFlag);
00593 lHBHolder.addHistoricalBooking (lHistoricalBkg);
00594 lDataIndexList.push_back (i);
00595 }
00596
00597
00598 STDAIR_LOG_DEBUG ("Historical bkgs: " << lNbOfHistoricalBkgs
00599 << ", censored: " << lCensorshipFlag);
00600 }
00601
00602
00603 STDAIR_LOG_DEBUG ("Unconstrain by multiplicative pick-up using EM");
00604
00605
00606 Detruncator::unconstrainUsingMultiplicativePickUp (lHBHolder);
00607
00608
00609 short i = 0;
00610 for (std::vector<short>::iterator itIdx = lDataIndexList.begin();
00611 itIdx != lDataIndexList.end(); ++itIdx, ++i) {
00612 short lIdx = *itIdx;
00613 stdair::NbOfRequests_T& lPastDemand = ioUncDemVector.at (lIdx);
00614 const stdair::NbOfRequests_T& lUncDemandFactorOfThisPeriod =
00615 lHBHolder.getUnconstrainedDemand (i);
00616 lPastDemand *= (1+lUncDemandFactorOfThisPeriod);
00617 }
00618
00619
00620 if (lHBHolder.getNbOfFlights() > 0) {
00621 const stdair::NbOfRequests_T& lUncDemandFactorMean =
00622 lHBHolder.getDemandMean();
00623 stdair::NbOfRequests_T& lPastDemand =
00624 ioUncDemVector.at (iNbOfAnteriorSimilarSegments);
00625 lPastDemand *= (1+lUncDemandFactorMean);
00626 }
00627 }
00628
00629
00630 void Forecaster::forecastUsingMultiplicativePickUp
00631 (const stdair::GuillotineBlock& iGuillotineBlock,
00632 UnconstrainedDemandVector_T& ioUncDemVector,
00633 const stdair::DCP_T& iDCPBegin, const stdair::DCP_T& iDCPEnd,
00634 const stdair::NbOfSegments_T& iNbOfUsableSegments,
00635 const stdair::BlockIndex_T& iBlockIdx,
00636 const stdair::NbOfSegments_T& iNbOfAnteriorSimilarSegments,
00637 const stdair::NbOfSegments_T& iNbOfDepartedSegments,
00638 const stdair::SegmentCabin& iSegmentCabin,
00639 const stdair::Date_T& iCurrentDate) {
00640
00641 stdair::NbOfSegments_T lSegBegin = 0;
00642 if (iNbOfDepartedSegments > 52) {
00643 lSegBegin = iNbOfDepartedSegments - 52;
00644 }
00645
00646 stdair::ConstSegmentCabinDTDRangeSnapshotView_T lBookingView =
00647 iGuillotineBlock.getConstSegmentCabinDTDRangeProductAndPriceOrientedBookingSnapshotView (lSegBegin, iNbOfUsableSegments -1, iDCPEnd, iDCPBegin);
00648 stdair::ConstSegmentCabinDTDRangeSnapshotView_T lAvlView =
00649 iGuillotineBlock.getConstSegmentCabinDTDRangeAvailabilitySnapshotView (lSegBegin, iNbOfUsableSegments -1, iDCPEnd, iDCPBegin);
00650
00651
00652 const stdair::ValueTypeIndexMap_T& lVTIdxMap =
00653 iGuillotineBlock.getValueTypeIndexMap();
00654 const unsigned int lNbOfValueTypes = lVTIdxMap.size();
00655 HistoricalBookingHolder lHBHolder;
00656 std::vector<short> lDataIndexList;
00657 for (short i = 0; i < iNbOfUsableSegments-lSegBegin; ++i) {
00658 stdair::Flag_T lCensorshipFlag = false;
00659 stdair::NbOfBookings_T lNbOfHistoricalBkgs = 0.0;
00660 const short lNbOfDTDs = iDCPBegin - iDCPEnd + 1;
00661
00662
00663 for (short j = 0; j < lNbOfDTDs; ++j) {
00664
00665
00666
00667 if (lCensorshipFlag == false) {
00668 if (lAvlView[i*lNbOfValueTypes + iBlockIdx][j] < 1.0) {
00669 lCensorshipFlag = true;
00670 }
00671 }
00672
00673
00674
00675 lNbOfHistoricalBkgs += lBookingView[i*lNbOfValueTypes + iBlockIdx][j];
00676 }
00677
00678
00679
00680 stdair::NbOfRequests_T& lUncDemand = ioUncDemVector.at (i);
00681 if (lUncDemand < 1.0) {
00682 lUncDemand += lNbOfHistoricalBkgs;
00683 } else {
00684 double lBkgDemandFactor = lNbOfHistoricalBkgs / lUncDemand;
00685 HistoricalBooking lHistoricalBkg (lBkgDemandFactor, lCensorshipFlag);
00686 lHBHolder.addHistoricalBooking (lHistoricalBkg);
00687 lDataIndexList.push_back (i);
00688 }
00689
00690
00691 STDAIR_LOG_DEBUG ("Historical bkgs: " << lNbOfHistoricalBkgs
00692 << ", censored: " << lCensorshipFlag);
00693 }
00694
00695
00696 STDAIR_LOG_DEBUG ("Unconstrain by multiplicative pick-up using EM");
00697
00698
00699 Detruncator::unconstrainUsingMultiplicativePickUp (lHBHolder);
00700
00701
00702
00703 const stdair::SegmentDate& lSegmentDate = stdair::BomManager::
00704 getParent<stdair::SegmentDate, stdair::SegmentCabin> (iSegmentCabin);
00705 const stdair::FlightDate& lFlightDate = stdair::BomManager::
00706 getParent<stdair::FlightDate, stdair::SegmentDate> (lSegmentDate);
00707 const stdair::Date_T& lDepDate = lFlightDate.getDepartureDate();
00708 const boost::gregorian::date_duration lDD = lDepDate - iCurrentDate;
00709 const long lDTD = lDD.days();
00710 stdair::Date_T lRefDate (2012, boost::gregorian::Jan, 01);
00711 short i = 0;
00712 for (std::vector<short>::iterator itIdx = lDataIndexList.begin();
00713 itIdx != lDataIndexList.end(); ++itIdx, ++i) {
00714 short lIdx = *itIdx;
00715 stdair::NbOfRequests_T& lPastDemand = ioUncDemVector.at (lIdx);
00716 const stdair::NbOfRequests_T& lUncDemandFactorOfThisPeriod =
00717 lHBHolder.getUnconstrainedDemand (i);
00718 const double lUncDemThisPeriod =
00719 lPastDemand * lUncDemandFactorOfThisPeriod;
00720 const double lQEBkgThisPeriod =
00721 lPastDemand * lHBHolder.getHistoricalBooking (i);
00722 lPastDemand *= (1+lUncDemandFactorOfThisPeriod);
00723 if (lDepDate > lRefDate) {
00724 const stdair::DateOffset_T lDateOffset (7 *(52 - i) + 420);
00725 const stdair::Date_T lHDate = lDepDate - lDateOffset;
00726 STDAIR_LOG_NOTIFICATION (boost::gregorian::to_iso_string(lDepDate)
00727 << ";" << lDTD << ";" << iDCPBegin << ";"
00728 << iDCPEnd << ";"
00729 << boost::gregorian::to_iso_string (lHDate)
00730 << ";" << lUncDemThisPeriod);
00731 STDAIR_LOG_NOTIFICATION (boost::gregorian::to_iso_string(lDepDate)
00732 << ";" << lDTD << ";" << iDCPBegin << ";"
00733 << iDCPEnd << ";"
00734 << boost::gregorian::to_iso_string (lHDate)
00735 << ";" << lQEBkgThisPeriod);
00736 }
00737 }
00738
00739
00740 if (lHBHolder.getNbOfFlights() > 0) {
00741 const stdair::NbOfRequests_T& lUncDemandFactorMean =
00742 lHBHolder.getDemandMean();
00743 stdair::NbOfRequests_T& lPastDemand =
00744 ioUncDemVector.at (iNbOfAnteriorSimilarSegments);
00745 lPastDemand *= (1+lUncDemandFactorMean);
00746 }
00747 }
00748
00749
00750 bool Forecaster::
00751 forecastUsingMultiplicativePickUp (stdair::SegmentCabin& ioSegmentCabin,
00752 const BookingClassUnconstrainedDemandMap_T& iClassUncDemMap,
00753 const stdair::NbOfRequests_T& iUncDem,
00754 const double& iSellUpFactor) {
00755 double lPriceOriMean = iUncDem;
00756 double lPriceOriStdDev = sqrt (iUncDem);
00757
00758
00759 STDAIR_LOG_DEBUG ("Price-oriented demand: mean = " << lPriceOriMean
00760 << ", stddev = " << lPriceOriStdDev);
00761
00762
00763
00764
00765 const stdair::BookingClassList_T& lBCList =
00766 stdair::BomManager::getList<stdair::BookingClass> (ioSegmentCabin);
00767 stdair::BookingClassList_T::const_reverse_iterator itCurrentClass =
00768 lBCList.rbegin();
00769 assert (itCurrentClass != lBCList.rend());
00770 stdair::BookingClassList_T::const_reverse_iterator itNextClass =
00771 itCurrentClass;
00772 ++itNextClass;
00773
00774
00775 if (itNextClass == lBCList.rend()) {
00776 stdair::BookingClass* lLowestBC_ptr = *itCurrentClass;
00777 lLowestBC_ptr->setMean (lPriceOriMean);
00778 lLowestBC_ptr->setStdDev (lPriceOriStdDev);
00779 if (lPriceOriMean > 0) {
00780 return true;
00781 } else {
00782 return false;
00783 }
00784 } else {
00785 bool isSucceeded = false;
00786
00787
00788 for (; itNextClass != lBCList.rend(); ++itCurrentClass, ++itNextClass) {
00789 stdair::BookingClass* lCurrentBC_ptr = *itCurrentClass;
00790 assert (lCurrentBC_ptr != NULL);
00791 const stdair::Yield_T& lCurrentYield = lCurrentBC_ptr->getYield();
00792 stdair::BookingClass* lNextBC_ptr = *itNextClass;
00793 assert (lNextBC_ptr != NULL);
00794 const stdair::Yield_T& lNextYield = lNextBC_ptr->getYield();
00795
00796
00797
00798 const double lSellUp =
00799 exp ((1.0 - lNextYield/lCurrentYield) * iSellUpFactor);
00800 const double lPriceOriDemMeanFrac = lPriceOriMean * (1.0 - lSellUp);
00801 const double lPriceOriDemStdDevFrac = lPriceOriStdDev * (1.0 - lSellUp);
00802
00803
00804
00805 BookingClassUnconstrainedDemandMap_T::const_iterator itBCUD =
00806 iClassUncDemMap.find (lCurrentBC_ptr);
00807 assert (itBCUD != iClassUncDemMap.end());
00808 double lMean = itBCUD->second;
00809 double lStdDev = sqrt (lMean);
00810
00811
00812 lMean += lPriceOriDemMeanFrac;
00813 lStdDev = sqrt (lStdDev * lStdDev +
00814 lPriceOriDemStdDevFrac * lPriceOriDemStdDevFrac);
00815 lCurrentBC_ptr->setMean (lMean);
00816 lCurrentBC_ptr->setStdDev (lStdDev);
00817
00818 if (lMean > 0) {
00819 isSucceeded = true;
00820 }
00821
00822
00823 STDAIR_LOG_DEBUG ("Class " << lCurrentBC_ptr->describeKey()
00824 << ", mean = " << lMean
00825 << ", stddev = " << lStdDev);
00826
00827
00828 lPriceOriMean *= lSellUp;
00829 lPriceOriStdDev *= lSellUp;
00830 }
00831
00832
00833
00834 stdair::BookingClass* lCurrentBC_ptr = *itCurrentClass;
00835 assert (lCurrentBC_ptr != NULL);
00836 BookingClassUnconstrainedDemandMap_T::const_iterator itBCUD =
00837 iClassUncDemMap.find (lCurrentBC_ptr);
00838 assert (itBCUD != iClassUncDemMap.end());
00839 double lMean = itBCUD->second;
00840 double lStdDev = sqrt (lMean);
00841
00842
00843 lMean += lPriceOriMean;
00844 lStdDev = sqrt (lStdDev * lStdDev + lPriceOriStdDev * lPriceOriStdDev);
00845 lCurrentBC_ptr->setMean (lMean);
00846 lCurrentBC_ptr->setStdDev (lStdDev);
00847
00848 if (lMean > 0) {
00849 isSucceeded = true;
00850 }
00851
00852
00853 STDAIR_LOG_DEBUG ("Class " << lCurrentBC_ptr->describeKey()
00854 << ", mean = " << lMean
00855 << ", stddev = " << lStdDev);
00856 return isSucceeded;
00857 }
00858 }
00859
00860 }