RMOL Logo  1.00.0
C++ library of Revenue Management and Optimisation classes and functions
 All Classes Namespaces Files Functions Variables Typedefs Friends Pages
OldQFF.cpp
Go to the documentation of this file.
1 // //////////////////////////////////////////////////////////////////////
2 // Import section
3 // //////////////////////////////////////////////////////////////////////
4 // STL
5 #include <cassert>
6 #include <sstream>
7 #include <cmath>
8 // StdAir
9 #include <stdair/basic/BasConst_General.hpp>
10 #include <stdair/basic/BasConst_Inventory.hpp>
11 #include <stdair/bom/BomManager.hpp>
12 #include <stdair/bom/SegmentDate.hpp>
13 #include <stdair/bom/SegmentCabin.hpp>
14 #include <stdair/bom/SegmentSnapshotTable.hpp>
15 #include <stdair/bom/FareFamily.hpp>
16 #include <stdair/bom/BookingClass.hpp>
17 #include <stdair/bom/Policy.hpp>
18 #include <stdair/service/Logger.hpp>
19 // RMOL
20 #include <rmol/bom/Utilities.hpp>
25 #include <rmol/command/OldQFF.hpp>
27 
28 namespace RMOL {
29  // ////////////////////////////////////////////////////////////////////
30  bool OldQFF::
31  forecast (stdair::SegmentCabin& ioSegmentCabin,
32  const stdair::Date_T& iCurrentDate,
33  const stdair::DTD_T& iCurrentDTD,
34  const stdair::UnconstrainingMethod& iUnconstrainingMethod,
35  const stdair::NbOfSegments_T& iNbOfDepartedSegments) {
36  // Retrieve the snapshot table.
37  const stdair::SegmentSnapshotTable& lSegmentSnapshotTable =
38  ioSegmentCabin.getSegmentSnapshotTable();
39 
40  // Retrieve the FRAT5Curve.
41  const stdair::FareFamilyList_T& lFFList =
42  stdair::BomManager::getList<stdair::FareFamily>(ioSegmentCabin);
43  stdair::FareFamilyList_T::const_reverse_iterator itFF = lFFList.rbegin();
44  assert (itFF != lFFList.rend());
45  stdair::FareFamily* lFF_ptr = *itFF;
46  assert (lFF_ptr != NULL);
47  const stdair::FRAT5Curve_T lFRAT5Curve = lFF_ptr->getFrat5Curve();
48 
49  // Retrieve the booking class list and compute the sell up curves
50  // and the dispatching curves.
51  const stdair::BookingClassList_T& lBCList =
52  stdair::BomManager::getList<stdair::BookingClass>(ioSegmentCabin);
53  const stdair::BookingClassSellUpCurveMap_T lBCSellUpCurveMap =
54  Utilities::computeSellUpFactorCurves (lFRAT5Curve, lBCList);
55 
56  // Retrieve the list of all policies and reset the demand forecast
57  // for each one.
58  const stdair::PolicyList_T& lPolicyList =
59  stdair::BomManager::getList<stdair::Policy> (ioSegmentCabin);
60  for (stdair::PolicyList_T::const_iterator itPolicy = lPolicyList.begin();
61  itPolicy != lPolicyList.end(); ++itPolicy) {
62  stdair::Policy* lPolicy_ptr = *itPolicy;
63  assert (lPolicy_ptr != NULL);
64  lPolicy_ptr->resetDemandForecast();
65  }
66 
67  // Browse all remaining DCP's and do unconstraining, forecasting
68  // and dispatching.
69  const stdair::DCPList_T lWholeDCPList = stdair::DEFAULT_DCP_LIST;
70  stdair::DCPList_T::const_iterator itDCP = lWholeDCPList.begin();
71  stdair::DCPList_T::const_iterator itNextDCP = itDCP; ++itNextDCP;
72  for (; itNextDCP != lWholeDCPList.end(); ++itDCP, ++itNextDCP) {
73  const stdair::DCP_T& lCurrentDCP = *itDCP;
74  const stdair::DCP_T& lNextDCP = *itNextDCP;
75 
76  // The end of the interval is after the current DTD.
77  if (lNextDCP < iCurrentDTD) {
78  // Get the number of similar segments which has already passed the
79  // (lNextDCP+1)
80  const stdair::NbOfSegments_T& lNbOfUsableSegments =
82  getNbOfSegmentAlreadyPassedThisDTD (lSegmentSnapshotTable,
83  lNextDCP+1,
84  iCurrentDate);
85  stdair::NbOfSegments_T lSegmentBegin = 0;
86  const stdair::NbOfSegments_T lSegmentEnd = lNbOfUsableSegments-1;
87  if (iNbOfDepartedSegments > 52) {
88  lSegmentBegin = iNbOfDepartedSegments - 52;
89  }
90 
91  // Retrieve the historical bookings and convert them to
92  // Q-equivalent bookings.
93  HistoricalBookingHolder lHBHolder;
94  prepareHistoricalBooking (ioSegmentCabin, lSegmentSnapshotTable,
95  lHBHolder, lCurrentDCP, lNextDCP,
96  lSegmentBegin, lSegmentEnd,
97  lBCSellUpCurveMap);
98 
99  // Unconstrain the historical bookings.
100  Detruncator::unconstrain (lHBHolder, iUnconstrainingMethod);
101 
102  // Retrieve the historical unconstrained demand and perform the
103  // forecasting.
104  stdair::UncDemVector_T lUncDemVector;
105  const short lNbOfHistoricalFlights = lHBHolder.getNbOfFlights();
106  for (short i = 0; i < lNbOfHistoricalFlights; ++i) {
107  const stdair::NbOfBookings_T& lUncDemand =
108  lHBHolder.getUnconstrainedDemand (i);
109  lUncDemVector.push_back (lUncDemand);
110  }
111  stdair::MeanValue_T lMean = 0.0;
112  stdair::StdDevValue_T lStdDev = 0.0;
114  lMean, lStdDev);
115 
116  // Add the demand forecast to the fare family.
117  const stdair::MeanValue_T& lCurrentMean = lFF_ptr->getMean();
118  const stdair::StdDevValue_T& lCurrentStdDev = lFF_ptr->getStdDev();
119 
120  const stdair::MeanValue_T lNewMean = lCurrentMean + lMean;
121  const stdair::StdDevValue_T lNewStdDev =
122  std::sqrt (lCurrentStdDev * lCurrentStdDev + lStdDev * lStdDev);
123 
124  lFF_ptr->setMean (lNewMean);
125  lFF_ptr->setStdDev (lNewStdDev);
126 
127  // Dispatch the demand forecast to the policies.
128  dispatchDemandForecastToPolicies (lPolicyList, lCurrentDCP, lMean,
129  lStdDev, lBCSellUpCurveMap);
130  }
131  }
132 
133  return true;
134  }
135 
136  // ////////////////////////////////////////////////////////////////////
137  void OldQFF::prepareHistoricalBooking
138  (const stdair::SegmentCabin& iSegmentCabin,
139  const stdair::SegmentSnapshotTable& iSegmentSnapshotTable,
140  HistoricalBookingHolder& ioHBHolder,
141  const stdair::DCP_T& iDCPBegin, const stdair::DCP_T& iDCPEnd,
142  const stdair::NbOfSegments_T& iSegmentBegin,
143  const stdair::NbOfSegments_T& iSegmentEnd,
144  const stdair::BookingClassSellUpCurveMap_T& iBCSellUpCurveMap) {
145 
146  // Retrieve the segment-cabin index within the snapshot table
147  std::ostringstream lSCMapKey;
148  lSCMapKey << stdair::DEFAULT_SEGMENT_CABIN_VALUE_TYPE
149  << iSegmentCabin.describeKey();
150  const stdair::ClassIndex_T& lCabinIdx =
151  iSegmentSnapshotTable.getClassIndex (lSCMapKey.str());
152 
153  // Retrieve the gross daily booking and availability snapshots.
154  const stdair::ConstSegmentCabinDTDRangeSnapshotView_T lPriceBookingView =
155  iSegmentSnapshotTable.getConstSegmentCabinDTDRangePriceOrientedGrossBookingSnapshotView (iSegmentBegin, iSegmentEnd, iDCPEnd, iDCPBegin);
156  const stdair::ConstSegmentCabinDTDRangeSnapshotView_T lProductBookingView =
157  iSegmentSnapshotTable.getConstSegmentCabinDTDRangeProductOrientedGrossBookingSnapshotView (iSegmentBegin, iSegmentEnd, iDCPEnd, iDCPBegin);
158  const stdair::ConstSegmentCabinDTDRangeSnapshotView_T lAvlView =
159  iSegmentSnapshotTable.getConstSegmentCabinDTDRangeAvailabilitySnapshotView (iSegmentBegin, iSegmentEnd, iDCPEnd, iDCPBegin);
160 
161  // Browse the list of segments and build the historical booking holder.
162  const stdair::ClassIndexMap_T& lVTIdxMap =
163  iSegmentSnapshotTable.getClassIndexMap();
164  const stdair::NbOfClasses_T lNbOfClasses = lVTIdxMap.size();
165 
166  for (short i = 0; i <= iSegmentEnd-iSegmentBegin; ++i) {
167  stdair::Flag_T lCensorshipFlag = false;
168  const short lNbOfDTDs = iDCPBegin - iDCPEnd + 1;
169  const stdair::UnsignedIndex_T lAvlIdx = i*lNbOfClasses + lCabinIdx;
170 
171  // Parse the DTDs during the period and compute the censorship flag
172  for (short j = 0; j < lNbOfDTDs; ++j) {
173  // Check if the data has been censored during this day.
174  // STDAIR_LOG_DEBUG ("i: " << i << ", NbOfClasses: " << lNbOfClasses
175  // << ", ClassIdx: " << iClassIdx << ", j: " << j);
176  if (lAvlView[lAvlIdx][j] < 1.0) {
177  lCensorshipFlag = true;
178  break;
179  }
180  }
181 
182  // Compute the Q-equivalent bookings
183  stdair::NbOfBookings_T lNbOfHistoricalBkgs = 0.0;
184  const stdair::BookingClassList_T& lBCList =
185  stdair::BomManager::getList<stdair::BookingClass> (iSegmentCabin);
186  for (short j = 0; j < lNbOfDTDs; ++j) {
187  stdair::BookingClass* lLowestBC_ptr = NULL;
188  stdair::NbOfBookings_T lNbOfBksOfTheDay = 0.0;
189  for (stdair::BookingClassList_T::const_iterator itBC = lBCList.begin();
190  itBC != lBCList.end(); ++itBC) {
191  stdair::BookingClass* lBC_ptr = *itBC;
192  assert (lBC_ptr != NULL);
193 
194  // Retrieve the number of bookings
195  const stdair::ClassIndex_T& lClassIdx =
196  iSegmentSnapshotTable.getClassIndex(lBC_ptr->describeKey());
197  const stdair::UnsignedIndex_T lIdx = i*lNbOfClasses + lClassIdx;
198  const stdair::NbOfBookings_T lNbOfBookings =
199  lPriceBookingView[lIdx][j] + lProductBookingView[lIdx][j];
200  lNbOfBksOfTheDay += lNbOfBookings;
201 
202  if (lAvlView[lIdx][j] >= 1.0) {
203  lLowestBC_ptr = lBC_ptr;
204  }
205  }
206 
207  // Convert the number of bookings of the day to Q-equivalent
208  // bookings using the sell-up probability of the lowest class
209  // available of the day.
210  if (lLowestBC_ptr != NULL) {
211  stdair::BookingClassSellUpCurveMap_T::const_iterator itBCSUC =
212  iBCSellUpCurveMap.find (lLowestBC_ptr);
213  assert (itBCSUC != iBCSellUpCurveMap.end());
214  const stdair::SellUpCurve_T& lSellUpCurve = itBCSUC->second;
215  stdair::SellUpCurve_T::const_iterator itSellUp =
216  lSellUpCurve.find (iDCPBegin);
217  assert (itSellUp != lSellUpCurve.end());
218  const stdair::SellupProbability_T& lSellUp = itSellUp->second;
219  assert (lSellUp != 0);
220 
221  lNbOfHistoricalBkgs += lNbOfBksOfTheDay/lSellUp;
222  }
223  }
224 
225  HistoricalBooking lHistoricalBkg (lNbOfHistoricalBkgs, lCensorshipFlag);
226  ioHBHolder.addHistoricalBooking (lHistoricalBkg);
227  }
228  }
229 
230  // ////////////////////////////////////////////////////////////////////
231  void OldQFF::
232  dispatchDemandForecastToPolicies (const stdair::PolicyList_T& iPolicyList,
233  const stdair::DCP_T& iCurrentDCP,
234  const stdair::MeanValue_T& iMean,
235  const stdair::StdDevValue_T& iStdDev,
236  const stdair::BookingClassSellUpCurveMap_T& iBCSellUpCurveMap) {
237  for (stdair::PolicyList_T::const_iterator itPolicy = iPolicyList.begin();
238  itPolicy != iPolicyList.end(); ++itPolicy) {
239  stdair::Policy* lPolicy_ptr = *itPolicy;
240  assert (lPolicy_ptr != NULL);
241  dispatchDemandForecastToPolicy (*lPolicy_ptr,
242  iCurrentDCP,
243  iMean,
244  iStdDev,
245  iBCSellUpCurveMap);
246  }
247  }
248 
249  // ////////////////////////////////////////////////////////////////////
250  void OldQFF::
251  dispatchDemandForecastToPolicy (stdair::Policy& ioPolicy,
252  const stdair::DCP_T& iCurrentDCP,
253  const stdair::MeanValue_T& iMean,
254  const stdair::StdDevValue_T& iStdDev,
255  const stdair::BookingClassSellUpCurveMap_T& iBCSellUpCurveMap) {
256  const stdair::MeanValue_T& lPolicyDemand = ioPolicy.getDemand();
257  const stdair::StdDevValue_T& lPolicyStdDev = ioPolicy.getStdDev();
258 
259  // Browse the list of booking classes of the policy and use the
260  // cumulative price-oriented demand forecast of each class.
261  const bool hasAListOfBC =
262  stdair::BomManager::hasList<stdair::BookingClass> (ioPolicy);
263  if (hasAListOfBC == true) {
264  const stdair::BookingClassList_T& lBCList =
265  stdair::BomManager::getList<stdair::BookingClass> (ioPolicy);
266  stdair::BookingClassList_T::const_reverse_iterator itCurrentBC =
267  lBCList.rbegin();
268  assert(itCurrentBC != lBCList.rend());
269  stdair::BookingClass* lLowestBC_ptr = *itCurrentBC;
270  assert (lLowestBC_ptr != NULL);
271  const stdair::Yield_T& lLowestBCYield = lLowestBC_ptr->getYield();
272  // Retrieve the sell-up factor for the lowest class.
273  stdair::BookingClassSellUpCurveMap_T::const_iterator itBCSU =
274  iBCSellUpCurveMap.find (lLowestBC_ptr);
275  assert (itBCSU != iBCSellUpCurveMap.end());
276  const stdair::SellUpCurve_T& lSellUpCurve = itBCSU->second;
277  stdair::SellUpCurve_T::const_iterator itSellUpFactor =
278  lSellUpCurve.find (iCurrentDCP);
279  assert (itSellUpFactor != lSellUpCurve.end());
280  const stdair::SellupProbability_T& lSUToLowestClass = itSellUpFactor->second;
281 
282  const stdair::MeanValue_T lAdditinalPolicyDemandMean =
283  iMean * lSUToLowestClass;
284  const stdair::StdDevValue_T lAdditinalPolicyDemandStdDev =
285  iStdDev * std::sqrt (lSUToLowestClass);
286 
287  const stdair::MeanValue_T lNewPolicyDemandMean =
288  lPolicyDemand + lAdditinalPolicyDemandMean;
289  const stdair::StdDevValue_T lNewPolicyDemandStdDev =
290  std::sqrt (lPolicyStdDev*lPolicyStdDev
291  + lAdditinalPolicyDemandStdDev * lAdditinalPolicyDemandStdDev);
292  //
293  ioPolicy.setDemand (lNewPolicyDemandMean);
294  ioPolicy.setStdDev (lNewPolicyDemandStdDev);
295 
296  ioPolicy.addYieldDemand (lLowestBCYield,
297  lAdditinalPolicyDemandMean);
298 
299  // Iterate other classes.
300  stdair::BookingClassList_T::const_reverse_iterator itNextBC=itCurrentBC;
301  ++itNextBC;
302  for (; itNextBC != lBCList.rend(); ++itNextBC, ++itCurrentBC) {
303  stdair::BookingClass* lCurrentBC_ptr = *itCurrentBC;
304  assert (lCurrentBC_ptr != NULL);
305  stdair::BookingClass* lNextBC_ptr = *itNextBC;
306  assert (lNextBC_ptr != NULL);
307 
308  // Retrieve the disutility for the current policy to the next one.
309  const stdair::FareFamily& lCurrentFF =
310  stdair::BomManager::getParent<stdair::FareFamily> (*lCurrentBC_ptr);
311  const stdair::FFDisutilityCurve_T& lDisutilityCurve =
312  lCurrentFF.getDisutilityCurve();
313  stdair::FFDisutilityCurve_T::const_iterator itDU =
314  lDisutilityCurve.find (iCurrentDCP);
315  assert (itDU != lDisutilityCurve.end());
316  const double& lDU = itDU->second;
317 
318  // Retrieve the sell-up factor for the next class.
319  stdair::BookingClassSellUpCurveMap_T::const_iterator itBCSUN =
320  iBCSellUpCurveMap.find (lNextBC_ptr);
321  assert (itBCSUN != iBCSellUpCurveMap.end());
322  const stdair::SellUpCurve_T& lSellUpCurveN = itBCSUN->second;
323  stdair::SellUpCurve_T::const_iterator itSellUpFactorN =
324  lSellUpCurveN.find (iCurrentDCP);
325  assert (itSellUpFactorN != lSellUpCurveN.end());
326  const stdair::SellupProbability_T& lSUToNextClass = itSellUpFactorN->second;
327  assert (lSUToNextClass > 0.0);
328  assert(lSUToNextClass < lSUToLowestClass);
329 
330  // Retrieve the yields of the two classes
331  const stdair::Yield_T& lCurrentYield = lCurrentBC_ptr->getYield();
332  const stdair::Yield_T& lNextYield = lNextBC_ptr->getYield();
333  const double lBuyUpFactor = exp ((lCurrentYield-lNextYield)*lDU);
334 
335  // Withdraw an amount demand forecast from the current class. This
336  // amount of forecast will be added to the next class.
337  const stdair::MeanValue_T lDemandForNextClass =
338  iMean * lSUToNextClass * lBuyUpFactor;
339  ioPolicy.addYieldDemand (lNextYield, lDemandForNextClass);
340  ioPolicy.addYieldDemand (lCurrentYield, -lDemandForNextClass);
341  }
342  }
343  }
344 }