RMOL Logo  1.00.0
C++ library of Revenue Management and Optimisation classes and functions
 All Classes Namespaces Files Functions Variables Typedefs Friends Pages
Utilities.cpp
Go to the documentation of this file.
1 
2 // //////////////////////////////////////////////////////////////////////
3 // Import section
4 // //////////////////////////////////////////////////////////////////////
5 // STL
6 #include <cassert>
7 #include <string>
8 #include <numeric>
9 #include <algorithm>
10 #include <cmath>
11 // StdAir
12 #include <stdair/basic/BasConst_Inventory.hpp>
13 #include <stdair/bom/BomManager.hpp>
14 #include <stdair/bom/SegmentCabin.hpp>
15 #include <stdair/bom/FareFamily.hpp>
16 #include <stdair/bom/BookingClass.hpp>
17 #include <stdair/bom/BookingClassTypes.hpp>
18 #include <stdair/service/Logger.hpp>
19 // RMOL
21 #include <rmol/bom/Utilities.hpp>
23 
24 namespace RMOL {
25  // ////////////////////////////////////////////////////////////////////
26  void Utilities::
27  computeDistributionParameters (const stdair::UncDemVector_T& iVector,
28  stdair::MeanValue_T& ioMean,
29  stdair::StdDevValue_T& ioStdDev) {
30  ioMean = 0.0; ioStdDev = 0.0;
31  const stdair::NbOfSamples_T lNbOfSamples = iVector.size();
32  assert (lNbOfSamples > 1);
33 
34  // Compute the mean
35  for (stdair::UncDemVector_T::const_iterator itSample = iVector.begin();
36  itSample != iVector.end(); ++itSample) {
37  //STDAIR_LOG_NOTIFICATION (*itSample);
38  ioMean += *itSample;
39  }
40  ioMean /= lNbOfSamples;
41 
42  // Compute the standard deviation
43  for (stdair::UncDemVector_T::const_iterator itSample = iVector.begin();
44  itSample != iVector.end(); ++itSample) {
45  const stdair::MeanValue_T& lSample = *itSample;
46  ioStdDev += ((lSample - ioMean) * (lSample - ioMean));
47  }
48  ioStdDev /= (lNbOfSamples - 1);
49  ioStdDev = std::sqrt (ioStdDev);
50 
51  // Sanity check
52  if (ioStdDev == 0) {
53  ioStdDev = 0.1;
54  }
55  }
56 
57  // ////////////////////////////////////////////////////////////////////
58  stdair::DCPList_T Utilities::
59  buildRemainingDCPList (const stdair::DTD_T& iDTD) {
60  stdair::DCPList_T oDCPList;
61 
62  const stdair::DCPList_T lWholeDCPList = stdair::DEFAULT_DCP_LIST;
63  stdair::DCPList_T::const_iterator itDCP = lWholeDCPList.begin();
64  while (itDCP != lWholeDCPList.end()) {
65  const stdair::DCP_T& lDCP = *itDCP;
66  if (iDTD >= lDCP) {
67  break;
68  }
69  ++itDCP;
70  }
71  assert (itDCP != lWholeDCPList.end());
72 
73  oDCPList.push_back (iDTD);
74  ++itDCP;
75  for (; itDCP != lWholeDCPList.end(); ++itDCP) {
76  oDCPList.push_back (*itDCP);
77  }
78 
79  return oDCPList;
80  }
81 
82  // ////////////////////////////////////////////////////////////////////
83  stdair::DCPList_T Utilities::
84  buildPastDCPList (const stdair::DTD_T& iDTD) {
85  stdair::DCPList_T oDCPList;
86 
87  const stdair::DCPList_T lWholeDCPList = stdair::DEFAULT_DCP_LIST;
88  stdair::DCPList_T::const_iterator itDCP = lWholeDCPList.begin();
89  while (itDCP != lWholeDCPList.end()) {
90  const stdair::DCP_T& lDCP = *itDCP;
91  if (iDTD <= lDCP) {
92  oDCPList.push_back (lDCP);
93  ++itDCP;
94  } else {
95  break;
96  }
97  }
98 
99  return oDCPList;
100  }
101 
102  // ////////////////////////////////////////////////////////////////////
103  stdair::NbOfSegments_T Utilities::
104  getNbOfDepartedSimilarSegments (const stdair::SegmentCabin& iSegmentCabin,
105  const stdair::Date_T& iEventDate) {
106  stdair::DTD_T lDTD = 0;
107  // Retrieve the guillotine block.
108  const stdair::SegmentSnapshotTable& lSegmentSnapshotTable =
109  iSegmentCabin.getSegmentSnapshotTable();
111  getNbOfSegmentAlreadyPassedThisDTD (lSegmentSnapshotTable, lDTD, iEventDate);
112  }
113 
114  // ////////////////////////////////////////////////////////////////////
115  stdair::BookingClassSellUpCurveMap_T Utilities::
116  computeSellUpFactorCurves (const stdair::FRAT5Curve_T& iFRAT5Curve,
117  const stdair::BookingClassList_T& iBCList) {
118  stdair::BookingClassSellUpCurveMap_T oBCSellUpFactorMap;
119 
120  // Initialise a sell-up factor curve of 1.0 values
121  stdair::SellUpCurve_T lBasedSellUpCurve;
122  for (stdair::FRAT5Curve_T::const_iterator itFRAT5 = iFRAT5Curve.begin();
123  itFRAT5 != iFRAT5Curve.end(); ++itFRAT5) {
124  const stdair::DTD_T& lDTD = itFRAT5->first;
125  lBasedSellUpCurve.insert(stdair::SellUpCurve_T::value_type(lDTD, 1.0));
126  }
127 
128  // Retrieve the classes from low to high and compute the distributions of
129  // product-oriented and price-oriented demand.
130  // Retrieve the lowest class.
131  stdair::BookingClassList_T::const_reverse_iterator itCurrentClass =
132  iBCList.rbegin();
133  assert (itCurrentClass != iBCList.rend());
134 
135  // If there is only one class in the cabin, all the sell-up factors
136  // will be 1.
137  stdair::BookingClass* lLowestBC_ptr = *itCurrentClass;
138  assert (lLowestBC_ptr != NULL);
139  const stdair::Yield_T& lLowestYield = lLowestBC_ptr->getYield();
140  bool insert = oBCSellUpFactorMap.
141  insert (stdair::BookingClassSellUpCurveMap_T::
142  value_type(lLowestBC_ptr, lBasedSellUpCurve)).second;
143  assert (insert == true);
144  ++itCurrentClass;
145 
146  // Compute the demand for higher class using the formula
147  // Pro_sell_up_from_Q_to_F = e ^ ((y_F/y_Q - 1) * ln (0.5) / (FRAT5 - 1))
148  for (; itCurrentClass != iBCList.rend(); ++itCurrentClass) {
149  stdair::BookingClass* lCurrentBC_ptr = *itCurrentClass;
150  assert (lCurrentBC_ptr != NULL);
151  const stdair::Yield_T& lCurrentYield = lCurrentBC_ptr->getYield();
152 
153  // Compute the sell-up factor curve for the current class.
154  stdair::SellUpCurve_T lCurrentSellUpCurve;
155  for (stdair::FRAT5Curve_T::const_iterator itFRAT5 = iFRAT5Curve.begin();
156  itFRAT5 != iFRAT5Curve.end(); ++itFRAT5) {
157  const stdair::DTD_T& lDTD = itFRAT5->first;
158  const stdair::FRAT5_T& lFRAT5 = itFRAT5->second;
159  const double lSellUpCoef = log(0.5)/(lFRAT5-1);
160  const stdair::SellupProbability_T lSellUpFactor =
161  exp ((lCurrentYield/lLowestYield - 1.0) * lSellUpCoef);
162  const bool isInsertionSuccessful =
163  lCurrentSellUpCurve.insert (stdair::SellUpCurve_T::value_type(lDTD, lSellUpFactor)).second;
164  assert (isInsertionSuccessful == true);
165  }
166  const bool isInsertionSuccessful = oBCSellUpFactorMap.
167  insert (stdair::BookingClassSellUpCurveMap_T::
168  value_type(lCurrentBC_ptr, lCurrentSellUpCurve)).second;
169  assert (isInsertionSuccessful == true);
170  }
171  return oBCSellUpFactorMap;
172  }
173 
174 
175  // ////////////////////////////////////////////////////////////////////
176  stdair::BookingClassDispatchingCurveMap_T Utilities::
177  computeDispatchingFactorCurves (const stdair::FRAT5Curve_T& iFRAT5Curve,
178  const stdair::BookingClassList_T& iBCList) {
179  stdair::BookingClassDispatchingCurveMap_T oBCDispatchingFactorMap;
180 
181  // Initialise a sell-up factor curve of 1.0 values
182  stdair::DispatchingCurve_T lBasedDispatchingCurve;
183  for (stdair::FRAT5Curve_T::const_iterator itFRAT5 = iFRAT5Curve.begin();
184  itFRAT5 != iFRAT5Curve.end(); ++itFRAT5) {
185  const stdair::DTD_T& lDTD = itFRAT5->first;
186  lBasedDispatchingCurve.insert(stdair::DispatchingCurve_T::value_type(lDTD, 1.0));
187  }
188 
189  // Retrieve the classes from low to high and compute the distributions of
190  // product-oriented and price-oriented demand.
191  // Retrieve the lowest class.
192  stdair::BookingClassList_T::const_reverse_iterator itCurrentClass =
193  iBCList.rbegin();
194  assert (itCurrentClass != iBCList.rend());
195  stdair::BookingClassList_T::const_reverse_iterator itNextClass =
196  itCurrentClass; ++itNextClass;
197 
198  // If there is only one class in the cabin, all the sell-up factors
199  // will be 1.
200  stdair::BookingClass* lLowestBC_ptr = *itCurrentClass;
201  assert (lLowestBC_ptr != NULL);
202  const stdair::Yield_T& lLowestYield = lLowestBC_ptr->getYield();
203  if (itNextClass == iBCList.rend()) {
204  bool insert = oBCDispatchingFactorMap.
205  insert (stdair::BookingClassDispatchingCurveMap_T::
206  value_type(lLowestBC_ptr, lBasedDispatchingCurve)).second;
207  assert (insert == true);
208  } else {
209  // Compute the demand for higher class using the formula
210  // Pro_sell_up_from_Q_to_F = e ^ ((y_F/y_Q - 1) * ln (0.5) / (FRAT5 - 1))
211  for (; itNextClass != iBCList.rend(); ++itCurrentClass, ++itNextClass) {
212  stdair::BookingClass* lCurrentBC_ptr = *itCurrentClass;
213  stdair::BookingClass* lNextBC_ptr = *itNextClass;
214  assert (lNextBC_ptr != NULL);
215  const stdair::Yield_T& lNextYield = lNextBC_ptr->getYield();
216 
217  // Compute the sell-up factor curve for the current class.
218  stdair::DispatchingCurve_T lCurrentDispatchingCurve;
219  for (stdair::FRAT5Curve_T::const_iterator itFRAT5 = iFRAT5Curve.begin();
220  itFRAT5 != iFRAT5Curve.end(); ++itFRAT5) {
221  const stdair::DTD_T& lDTD = itFRAT5->first;
222  const stdair::FRAT5_T& lFRAT5 = itFRAT5->second;
223  const double lDispatchingCoef = log(0.5)/(lFRAT5-1);
224  double lDispatchingFactor =
225  exp ((lNextYield/lLowestYield - 1.0) * lDispatchingCoef);
226  stdair::DispatchingCurve_T::iterator itBasedDispatching =
227  lBasedDispatchingCurve.find (lDTD);
228  assert (itBasedDispatching != lBasedDispatchingCurve.end());
229  double& lBasedFactor = itBasedDispatching->second;
230  bool insert = lCurrentDispatchingCurve.insert (stdair::DispatchingCurve_T::value_type(lDTD, lBasedFactor - lDispatchingFactor)).second;
231  assert (insert == true);
232  lBasedFactor = lDispatchingFactor;
233  }
234  bool insert = oBCDispatchingFactorMap.
235  insert (stdair::BookingClassDispatchingCurveMap_T::
236  value_type(lCurrentBC_ptr, lCurrentDispatchingCurve)).second;
237  assert (insert == true);
238  }
239 
240  // Compute the sell-up factor curve for the highest class (which is the
241  // "current class")
242  stdair::BookingClass* lCurrentBC_ptr = *itCurrentClass;
243  bool insert = oBCDispatchingFactorMap.
244  insert (stdair::BookingClassDispatchingCurveMap_T::
245  value_type(lCurrentBC_ptr, lBasedDispatchingCurve)).second;
246  assert (insert == true);
247  }
248  return oBCDispatchingFactorMap;
249  }
250 
251  // ////////////////////////////////////////////////////////////////////
253  (const stdair::BookingClassDispatchingCurveMap_T& iBCDispatchingCurveMap,
254  const stdair::MeanValue_T& iMean,
255  const stdair::StdDevValue_T& iStdDev,
256  const stdair::DTD_T& iCurrentDCP) {
257  for (stdair::BookingClassDispatchingCurveMap_T::const_iterator itBCDC =
258  iBCDispatchingCurveMap.begin();
259  itBCDC != iBCDispatchingCurveMap.end(); ++itBCDC) {
260  stdair::BookingClass* lBC_ptr = itBCDC->first;
261  assert (lBC_ptr != NULL);
262  const stdair::DispatchingCurve_T& lDispatchingCurve = itBCDC->second;
263  stdair::DispatchingCurve_T::const_iterator itDispatchingFactor =
264  lDispatchingCurve.find (iCurrentDCP);
265  assert (itDispatchingFactor != lDispatchingCurve.end());
266  const double& lDF = itDispatchingFactor->second;
267 
268  const stdair::MeanValue_T& lCurrentMean = lBC_ptr->getPriceDemMean();
269  const stdair::StdDevValue_T& lCurrentStdDev = lBC_ptr->getPriceDemStdDev();
270 
271  const stdair::MeanValue_T lAdditionalMean = iMean * lDF;
272  const stdair::StdDevValue_T lAdditionalStdDev = iStdDev * std::sqrt (lDF);
273 
274  const stdair::MeanValue_T lNewMean = lCurrentMean + lAdditionalMean;
275  const stdair::StdDevValue_T lNewStdDev =
276  std::sqrt (lCurrentStdDev * lCurrentStdDev
277  + lAdditionalStdDev * lAdditionalStdDev);
278 
279  lBC_ptr->setPriceDemMean (lNewMean);
280  lBC_ptr->setPriceDemStdDev (lNewStdDev);
281  }
282  }
283 
284  // ////////////////////////////////////////////////////////////////////
286  (const stdair::BookingClassSellUpCurveMap_T& iBCSellUpCurveMap,
287  const stdair::MeanValue_T& iMean,
288  const stdair::StdDevValue_T& iStdDev,
289  const stdair::DTD_T& iCurrentDCP) {
290  for (stdair::BookingClassSellUpCurveMap_T::const_iterator itBCSU =
291  iBCSellUpCurveMap.begin();
292  itBCSU != iBCSellUpCurveMap.end(); ++itBCSU) {
293  stdair::BookingClass* lBC_ptr = itBCSU->first;
294  assert (lBC_ptr != NULL);
295  const stdair::SellUpCurve_T& lSellUpCurve = itBCSU->second;
296  stdair::SellUpCurve_T::const_iterator itSellUpFactor =
297  lSellUpCurve.find (iCurrentDCP);
298  assert (itSellUpFactor != lSellUpCurve.end());
299  const stdair::SellupProbability_T& lSU = itSellUpFactor->second;
300 
301  const stdair::MeanValue_T& lCurrentMean = lBC_ptr->getCumuPriceDemMean();
302  const stdair::StdDevValue_T& lCurrentStdDev =
303  lBC_ptr->getCumuPriceDemStdDev();
304 
305  const stdair::MeanValue_T lAdditionalMean = iMean * lSU;
306  const stdair::StdDevValue_T lAdditionalStdDev = iStdDev * std::sqrt (lSU);
307 
308  const stdair::MeanValue_T lNewMean = lCurrentMean + lAdditionalMean;
309  const stdair::StdDevValue_T lNewStdDev =
310  std::sqrt (lCurrentStdDev * lCurrentStdDev
311  + lAdditionalStdDev * lAdditionalStdDev);
312 
313  lBC_ptr->setCumuPriceDemMean (lNewMean);
314  lBC_ptr->setCumuPriceDemStdDev (lNewStdDev);
315  }
316  }
317 }