RMOL Logo  1.00.0
C++ library of Revenue Management and Optimisation classes and functions
 All Classes Namespaces Files Functions Variables Typedefs Friends Pages
NewQFF.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/NewQFF.hpp>
27 
28 namespace RMOL {
29  // ////////////////////////////////////////////////////////////////////
30  bool NewQFF::
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  // Browse the list of fare families and execute "Q-forecasting" within
41  // each fare family.
42  const stdair::FareFamilyList_T& lFFList =
43  stdair::BomManager::getList<stdair::FareFamily>(ioSegmentCabin);
44  for (stdair::FareFamilyList_T::const_iterator itFF = lFFList.begin();
45  itFF != lFFList.end(); ++itFF) {
46  stdair::FareFamily* lFF_ptr = *itFF;
47  assert (lFF_ptr != NULL);
48 
49  forecast (*lFF_ptr,
50  iCurrentDate,
51  iCurrentDTD,
52  iUnconstrainingMethod,
53  iNbOfDepartedSegments,
54  lSegmentSnapshotTable);
55  }
56 
57  // Dispatch the demand forecast to the policies.
58  dispatchDemandForecastToPolicies (ioSegmentCabin);
59 
60  return true;
61  }
62 
63  // ////////////////////////////////////////////////////////////////////
64  void NewQFF::
65  forecast (stdair::FareFamily& ioFareFamily,
66  const stdair::Date_T& iCurrentDate,
67  const stdair::DTD_T& iCurrentDTD,
68  const stdair::UnconstrainingMethod& iUnconstrainingMethod,
69  const stdair::NbOfSegments_T& iNbOfDepartedSegments,
70  const stdair::SegmentSnapshotTable& iSegmentSnapshotTable) {
71  // Retrieve the FRAT5Curve.
72  const stdair::FRAT5Curve_T& lFRAT5Curve = ioFareFamily.getFrat5Curve();
73 
74  // Retrieve the booking class list and compute the sell up curves
75  // and the dispatching curves.
76  const stdair::BookingClassList_T& lBCList =
77  stdair::BomManager::getList<stdair::BookingClass>(ioFareFamily);
78  const stdair::BookingClassSellUpCurveMap_T lBCSellUpCurveMap =
79  Utilities::computeSellUpFactorCurves (lFRAT5Curve, lBCList);
80  const stdair::BookingClassDispatchingCurveMap_T lBCDispatchingCurveMap =
81  Utilities::computeDispatchingFactorCurves (lFRAT5Curve, lBCList);
82 
83  // Browse all remaining DCP's and do unconstraining, forecasting
84  // and dispatching.
85  const stdair::DCPList_T lWholeDCPList = stdair::DEFAULT_DCP_LIST;
86  stdair::DCPList_T::const_iterator itDCP = lWholeDCPList.begin();
87  stdair::DCPList_T::const_iterator itNextDCP = itDCP; ++itNextDCP;
88  for (; itNextDCP != lWholeDCPList.end(); ++itDCP, ++itNextDCP) {
89  const stdair::DCP_T& lCurrentDCP = *itDCP;
90  const stdair::DCP_T& lNextDCP = *itNextDCP;
91 
92  // The end of the interval is after the current DTD.
93  if (lNextDCP < iCurrentDTD) {
94  // Get the number of similar segments which has already passed the
95  // (lNextDCP+1)
96  const stdair::NbOfSegments_T& lNbOfUsableSegments =
98  getNbOfSegmentAlreadyPassedThisDTD (iSegmentSnapshotTable,
99  lNextDCP+1,
100  iCurrentDate);
101  stdair::NbOfSegments_T lSegmentBegin = 0;
102  const stdair::NbOfSegments_T lSegmentEnd = lNbOfUsableSegments-1;
103  if (iNbOfDepartedSegments > 52) {
104  lSegmentBegin = iNbOfDepartedSegments - 52;
105  }
106 
107  // Retrieve the historical bookings and convert them to
108  // Q-equivalent bookings.
109  HistoricalBookingHolder lHBHolder;
110  preparePriceOrientedHistoricalBooking (ioFareFamily,
111  iSegmentSnapshotTable,
112  lHBHolder,
113  lCurrentDCP, lNextDCP,
114  lSegmentBegin, lSegmentEnd,
115  lBCSellUpCurveMap);
116 
117  // Unconstrain the historical bookings.
118  Detruncator::unconstrain (lHBHolder, iUnconstrainingMethod);
119 
120  // Retrieve the historical unconstrained demand and perform the
121  // forecasting.
122  stdair::UncDemVector_T lUncDemVector;
123  // Be careful, the getter returns the vector size,
124  // so there is no reference.
125  const short lNbOfHistoricalFlights = lHBHolder.getNbOfFlights();
126  for (short i = 0; i < lNbOfHistoricalFlights; ++i) {
127  const stdair::NbOfBookings_T& lUncDemand =
128  lHBHolder.getUnconstrainedDemand (i);
129  lUncDemVector.push_back (lUncDemand);
130  }
131  stdair::MeanValue_T lMean = 0.0;
132  stdair::StdDevValue_T lStdDev = 0.0;
134  lMean, lStdDev);
135 
136  // Dispatch the forecast to all the classes.
137  Utilities::dispatchDemandForecast (lBCDispatchingCurveMap,
138  lMean, lStdDev, lCurrentDCP);
139 
140  // Dispatch the forecast to all classes for Fare Adjustment or MRT.
141  // The sell-up probability will be used in this case.
142  Utilities::dispatchDemandForecastForFA (lBCSellUpCurveMap,
143  lMean, lStdDev, lCurrentDCP);
144 
145  // Add the demand forecast to the fare family.
146  const stdair::MeanValue_T& lCurrentMean = ioFareFamily.getMean();
147  const stdair::StdDevValue_T& lCurrentStdDev = ioFareFamily.getStdDev();
148 
149  const stdair::MeanValue_T lNewMean = lCurrentMean + lMean;
150  const stdair::StdDevValue_T lNewStdDev =
151  std::sqrt (lCurrentStdDev * lCurrentStdDev + lStdDev * lStdDev);
152 
153  ioFareFamily.setMean (lNewMean);
154  ioFareFamily.setStdDev (lNewStdDev);
155  }
156  }
157 
158  }
159 
160  // ////////////////////////////////////////////////////////////////////
161  void NewQFF::preparePriceOrientedHistoricalBooking
162  (const stdair::FareFamily& iFareFamily,
163  const stdair::SegmentSnapshotTable& iSegmentSnapshotTable,
164  HistoricalBookingHolder& ioHBHolder,
165  const stdair::DCP_T& iDCPBegin, const stdair::DCP_T& iDCPEnd,
166  const stdair::NbOfSegments_T& iSegmentBegin,
167  const stdair::NbOfSegments_T& iSegmentEnd,
168  const stdair::BookingClassSellUpCurveMap_T& iBCSellUpCurveMap) {
169 
170  // Retrieve the gross daily booking and availability snapshots.
171  const stdair::ConstSegmentCabinDTDRangeSnapshotView_T lPriceBookingView =
172  iSegmentSnapshotTable.getConstSegmentCabinDTDRangePriceOrientedGrossBookingSnapshotView (iSegmentBegin, iSegmentEnd, iDCPEnd, iDCPBegin);
173  const stdair::ConstSegmentCabinDTDRangeSnapshotView_T lProductBookingView =
174  iSegmentSnapshotTable.getConstSegmentCabinDTDRangeProductOrientedGrossBookingSnapshotView (iSegmentBegin, iSegmentEnd, iDCPEnd, iDCPBegin);
175  const stdair::ConstSegmentCabinDTDRangeSnapshotView_T lAvlView =
176  iSegmentSnapshotTable.getConstSegmentCabinDTDRangeAvailabilitySnapshotView (iSegmentBegin, iSegmentEnd, iDCPEnd, iDCPBegin);
177 
178  // Browse the list of segments and build the historical booking holder.
179  const stdair::ClassIndexMap_T& lVTIdxMap =
180  iSegmentSnapshotTable.getClassIndexMap();
181  const stdair::NbOfClasses_T lNbOfClasses = lVTIdxMap.size();
182 
183  for (short i = 0; i <= iSegmentEnd-iSegmentBegin; ++i) {
184  stdair::Flag_T lCensorshipFlag = false;
185  const short lNbOfDTDs = iDCPBegin - iDCPEnd + 1;
186 
187  // Parse the DTDs during the period and compute the censorship flag
188  for (short j = 0; j < lNbOfDTDs; ++j) {
189  // Check if the data has been censored during this day.
190  // STDAIR_LOG_DEBUG ("i: " << i << ", NbOfClasses: " << lNbOfClasses
191  // << ", ClassIdx: " << iClassIdx << ", j: " << j);
192  bool tempCensorship = true;
193  for (stdair::BookingClassSellUpCurveMap_T::const_iterator itBCSUC =
194  iBCSellUpCurveMap.begin();
195  itBCSUC != iBCSellUpCurveMap.end(); ++itBCSUC) {
196  const stdair::BookingClass* lBookingClass_ptr = itBCSUC->first;
197  assert (lBookingClass_ptr != NULL);
198  const stdair::ClassIndex_T& lClassIdx =
199  iSegmentSnapshotTable.getClassIndex(lBookingClass_ptr->describeKey());
200  const stdair::UnsignedIndex_T lAvlIdx = i*lNbOfClasses + lClassIdx;
201  if (lAvlView[lAvlIdx][j] >= 1.0) {
202  tempCensorship = false;
203  break;
204  }
205  }
206  if (tempCensorship == true) {
207  lCensorshipFlag = true;
208  break;
209  }
210  }
211 
212  // Compute the Q-equivalent bookings
213  stdair::NbOfBookings_T lNbOfHistoricalBkgs = 0.0;
214  for (stdair::BookingClassSellUpCurveMap_T::const_iterator itBCSUC =
215  iBCSellUpCurveMap.begin();
216  itBCSUC != iBCSellUpCurveMap.end(); ++itBCSUC) {
217  const stdair::BookingClass* lBookingClass_ptr = itBCSUC->first;
218  assert (lBookingClass_ptr != NULL);
219  const stdair::SellUpCurve_T& lSellUpCurve = itBCSUC->second;
220  stdair::SellUpCurve_T::const_iterator itSellUp =
221  lSellUpCurve.find (iDCPBegin);
222  assert (itSellUp != lSellUpCurve.end());
223  const stdair::SellupProbability_T& lSellUp = itSellUp->second;
224  assert (lSellUp != 0);
225 
226  // Retrieve the number of bookings
227  const stdair::ClassIndex_T& lClassIdx =
228  iSegmentSnapshotTable.getClassIndex(lBookingClass_ptr->describeKey());
229  const stdair::UnsignedIndex_T lIdx = i*lNbOfClasses + lClassIdx;
230 
231  stdair::NbOfBookings_T lNbOfBookings = 0.0;
232  for (short j = 0; j < lNbOfDTDs; ++j) {
233  lNbOfBookings +=
234  lPriceBookingView[lIdx][j] + lProductBookingView[lIdx][j];
235  }
236  const stdair::NbOfBookings_T lNbOfQEquivalentBkgs=lNbOfBookings/lSellUp;
237 
238  lNbOfHistoricalBkgs += lNbOfQEquivalentBkgs;
239  }
240 
241  HistoricalBooking lHistoricalBkg (lNbOfHistoricalBkgs, lCensorshipFlag);
242  ioHBHolder.addHistoricalBooking (lHistoricalBkg);
243  }
244  }
245 
246  // ////////////////////////////////////////////////////////////////////
247  void NewQFF::
248  dispatchDemandForecastToPolicies (const stdair::SegmentCabin& iSegmentCabin){
249  // Retrieve the list of policies.
250  const stdair::PolicyList_T& lPolicyList =
251  stdair::BomManager::getList<stdair::Policy> (iSegmentCabin);
252 
253  for (stdair::PolicyList_T::const_iterator itPolicy = lPolicyList.begin();
254  itPolicy != lPolicyList.end(); ++itPolicy) {
255  stdair::Policy* lPolicy_ptr = *itPolicy;
256  assert (lPolicy_ptr != NULL);
257  dispatchDemandForecastToPolicy(*lPolicy_ptr);
258  }
259  }
260 
261  // ////////////////////////////////////////////////////////////////////
262  void NewQFF::
263  dispatchDemandForecastToPolicy (stdair::Policy& ioPolicy){
264  // Reset the demand forecast of the policy
265  ioPolicy.resetDemandForecast();
266 
267  const stdair::MeanValue_T& lPolicyDemand = ioPolicy.getDemand();
268  const stdair::StdDevValue_T& lPolicyStdDev = ioPolicy.getStdDev();
269  stdair::MeanValue_T lNewPolicyDemand = lPolicyDemand;
270  stdair::MeanValue_T lNewPolicyStdDev = lPolicyStdDev;
271 
272  // Browse the list of booking classes of the policy and use the
273  // cumulative price-oriented demand forecast of each class.
274  const bool hasAListOfBC =
275  stdair::BomManager::hasList<stdair::BookingClass> (ioPolicy);
276  if (hasAListOfBC == true) {
277  const stdair::BookingClassList_T& lBCList =
278  stdair::BomManager::getList<stdair::BookingClass> (ioPolicy);
279  for (stdair::BookingClassList_T::const_iterator itBC = lBCList.begin();
280  itBC != lBCList.end(); ++itBC) {
281  const stdair::BookingClass* lBC_ptr = *itBC;
282  assert (lBC_ptr != NULL);
283  const stdair::Yield_T& lYield = lBC_ptr->getYield();
284  const stdair::MeanValue_T& lDemand = lBC_ptr->getCumuPriceDemMean();
285  const stdair::StdDevValue_T& lStdDev =
286  lBC_ptr->getCumuPriceDemStdDev();
287 
288  ioPolicy.addYieldDemand (lYield, lDemand);
289  lNewPolicyDemand += lDemand;
290  const stdair::StdDevValue_T lSquareNewPolicyStdDev =
291  lNewPolicyStdDev*lNewPolicyStdDev + lStdDev*lStdDev;
292  lNewPolicyStdDev =
293  std::sqrt (lSquareNewPolicyStdDev);
294  }
295  ioPolicy.setDemand(lNewPolicyDemand);
296  ioPolicy.setStdDev(lNewPolicyStdDev);
297  }
298  }
299 }