RMOL Logo  1.00.0
C++ library of Revenue Management and Optimisation classes and functions
 All Classes Namespaces Files Functions Variables Typedefs Friends Pages
Optimiser.cpp
Go to the documentation of this file.
1 // //////////////////////////////////////////////////////////////////////
2 // Import section
3 // //////////////////////////////////////////////////////////////////////
4 // STL
5 #include <cassert>
6 #include <sstream>
7 // StdAir
8 #include <stdair/basic/BasConst_General.hpp>
9 #include <stdair/basic/RandomGeneration.hpp>
10 #include <stdair/bom/BomManager.hpp>
11 #include <stdair/bom/FlightDate.hpp>
12 #include <stdair/bom/LegDate.hpp>
13 #include <stdair/bom/SegmentDate.hpp>
14 #include <stdair/bom/LegCabin.hpp>
15 #include <stdair/bom/SegmentCabin.hpp>
16 #include <stdair/bom/FareFamily.hpp>
17 #include <stdair/bom/BookingClass.hpp>
18 #include <stdair/service/Logger.hpp>
19 // RMOL
21 #include <rmol/bom/MCOptimiser.hpp>
22 #include <rmol/bom/Emsr.hpp>
23 #include <rmol/bom/DPOptimiser.hpp>
25 
26 namespace RMOL {
27 
28  // ////////////////////////////////////////////////////////////////////
29  void Optimiser::
30  optimalOptimisationByMCIntegration (const stdair::NbOfSamples_T& K,
31  stdair::LegCabin& ioLegCabin) {
32  // Retrieve the segment-cabin
33  const stdair::SegmentCabinList_T lSegmentCabinList =
34  stdair::BomManager::getList<stdair::SegmentCabin> (ioLegCabin);
35  stdair::SegmentCabinList_T::const_iterator itSC = lSegmentCabinList.begin();
36  assert (itSC != lSegmentCabinList.end());
37  const stdair::SegmentCabin* lSegmentCabin_ptr = *itSC;
38  assert (lSegmentCabin_ptr != NULL);
39 
40  // Retrieve the class list.
41  const stdair::BookingClassList_T lBookingClassList =
42  stdair::BomManager::getList<stdair::BookingClass> (*lSegmentCabin_ptr);
43  stdair::RandomGeneration lSeedGenerator (stdair::DEFAULT_RANDOM_SEED);
44 
45  // Generate the demand samples for the booking classes.
46  for (stdair::BookingClassList_T::const_iterator itBC =
47  lBookingClassList.begin(); itBC != lBookingClassList.end(); ++itBC) {
48  stdair::RandomSeed_T lRandomSeed =
49  lSeedGenerator.generateUniform01 () * 1e9;
50  stdair::BookingClass* lBookingClass_ptr = *itBC;
51  assert (lBookingClass_ptr != NULL);
52  lBookingClass_ptr->generateDemandSamples (K, lRandomSeed);
53 
54  // DEBUG
55  //STDAIR_LOG_DEBUG ("Generating " << K << " demand samples for the class "
56  // << lBookingClass_ptr->describeKey());
57  }
58 
59  // Call the class performing the actual algorithm
61  }
62 
63  // ////////////////////////////////////////////////////////////////////
64  void Optimiser::optimalOptimisationByDP (stdair::LegCabin& ioLegCabin) {
66  }
67 
68  // ////////////////////////////////////////////////////////////////////
69  void Optimiser::heuristicOptimisationByEmsr (stdair::LegCabin& ioLegCabin) {
71  }
72 
73  // ////////////////////////////////////////////////////////////////////
74  void Optimiser::heuristicOptimisationByEmsrA (stdair::LegCabin& ioLegCabin) {
76  }
77 
78  // ////////////////////////////////////////////////////////////////////
79  void Optimiser::heuristicOptimisationByEmsrB (stdair::LegCabin& ioLegCabin) {
81  }
82 
83  // ////////////////////////////////////////////////////////////////////
84  bool Optimiser::optimise (stdair::FlightDate& ioFlightDate,
85  const stdair::OptimisationMethod& iOptimisationMethod) {
86  bool optimiseSucceeded = false;
87  // Browse the leg-cabin list and build the virtual class list for
88  // each cabin.
89  const stdair::LegDateList_T& lLDList =
90  stdair::BomManager::getList<stdair::LegDate> (ioFlightDate);
91  for (stdair::LegDateList_T::const_iterator itLD = lLDList.begin();
92  itLD != lLDList.end(); ++itLD) {
93  stdair::LegDate* lLD_ptr = *itLD;
94  assert (lLD_ptr != NULL);
95  const bool isSucceeded = optimise(*lLD_ptr, iOptimisationMethod);
96  // If at least one leg date is optimised, the optimisation is succeeded.
97  if (isSucceeded == true) {
98  optimiseSucceeded = true;
99  // Do not return now because all leg dates need to be optimised.
100  }
101  }
102  return optimiseSucceeded;
103  }
104 
105  // ////////////////////////////////////////////////////////////////////
106  bool Optimiser::
107  optimise (stdair::LegDate& ioLegDate,
108  const stdair::OptimisationMethod& iOptimisationMethod) {
109  bool optimiseSucceeded = false;
110  // Browse the leg-cabin list
111  const stdair::LegCabinList_T& lLCList =
112  stdair::BomManager::getList<stdair::LegCabin> (ioLegDate);
113  for (stdair::LegCabinList_T::const_iterator itLC = lLCList.begin();
114  itLC != lLCList.end(); ++itLC) {
115  stdair::LegCabin* lLC_ptr = *itLC;
116  assert (lLC_ptr != NULL);
117  const bool isSucceeded = optimise(*lLC_ptr, iOptimisationMethod);
118  // If at least one leg cabin is optimised, the optimisation is succeeded.
119  if (isSucceeded == true) {
120  optimiseSucceeded = true;
121  // Do not return now because all leg cabins need to be optimised.
122  }
123  }
124  return optimiseSucceeded;
125  }
126 
127  // ////////////////////////////////////////////////////////////////////
128  bool Optimiser::
129  optimise (stdair::LegCabin& ioLegCabin,
130  const stdair::OptimisationMethod& iOptimisationMethod) {
131  bool optimiseSucceeded = false;
132  //
133  // Build the virtual class list.
134  bool hasVirtualClass =
136  if (hasVirtualClass == true) {
137  switch (iOptimisationMethod.getMethod()) {
138  case stdair::OptimisationMethod::LEG_BASED_MC: {
139  // Number of samples generated for the Monte Carlo integration.
140  // It is important that number is greater than 100 (=10000 here).
141  const stdair::NbOfSamples_T lNbOfSamples =
143  optimalOptimisationByMCIntegration (lNbOfSamples, ioLegCabin);
144  optimiseSucceeded = true;
145  break;
146  }
147  case stdair::OptimisationMethod::LEG_BASED_EMSR_B: {
148  heuristicOptimisationByEmsrB (ioLegCabin);
149  optimiseSucceeded = true;
150  break;
151  }
152  default: {
153  assert (false);
154  break;
155  }
156  }
157  }
158 
159  return optimiseSucceeded;
160  }
161 
162  // ////////////////////////////////////////////////////////////////////
163  bool Optimiser::
164  buildVirtualClassListForLegBasedOptimisation (stdair::LegCabin& ioLegCabin) {
165  // The map holding all virtual classes to be created.
166  stdair::VirtualClassMap_T lVirtualClassMap;
167  bool isNotEmpty = false;
168 
169  // Retrieve the segment-cabin
170  const stdair::SegmentCabinList_T& lSegmentCabinList =
171  stdair::BomManager::getList<stdair::SegmentCabin> (ioLegCabin);
172  stdair::SegmentCabinList_T::const_iterator itSC = lSegmentCabinList.begin();
173  assert (itSC != lSegmentCabinList.end());
174  const stdair::SegmentCabin* lSegmentCabin_ptr = *itSC;
175  assert (lSegmentCabin_ptr != NULL);
176 
177  // Retrieve the class list.
178  const stdair::BookingClassList_T lBookingClassList =
179  stdair::BomManager::getList<stdair::BookingClass> (*lSegmentCabin_ptr);
180 
181  // Generate the demand samples for the booking classes.
182  for (stdair::BookingClassList_T::const_iterator itBC =
183  lBookingClassList.begin(); itBC != lBookingClassList.end(); ++itBC) {
184  stdair::BookingClass* lBookingClass_ptr = *itBC;
185  assert (lBookingClass_ptr != NULL);
186 
187  // If the demand forecast of the class is zero, there no need to create
188  // a virtual class.
189  // TODO: use float utils
190  const stdair::NbOfRequests_T& lMean = lBookingClass_ptr->getMean();
191  const stdair::StdDevValue_T& lStdDev = lBookingClass_ptr->getStdDev();
192  if (lMean > 0.0) {
193  const stdair::Yield_T& lYield = lBookingClass_ptr->getAdjustedYield();
194  // TODO: use float utils
195  assert (lYield >= 0.0);
196  const stdair::Yield_T lRoundedYieldDouble = std::floor(lYield +0.5);
197  const stdair::YieldLevel_T lRoundedYieldLevel =
198  static_cast<stdair::YieldLevel_T>(lRoundedYieldDouble);
199  if (lRoundedYieldLevel > 0) {
200  // If there is already a virtual class with this yield, add the current
201  // booking class to its list and sum the two demand distributions.
202  // Otherwise, create a new virtual class.
203  stdair::VirtualClassMap_T::iterator itVCMap =
204  lVirtualClassMap.find(lRoundedYieldLevel);
205  if (itVCMap == lVirtualClassMap.end()) {
206  stdair::BookingClassList_T lBookingClassList;
207  lBookingClassList.push_back(lBookingClass_ptr);
208  stdair::VirtualClassStruct lVirtualClass (lBookingClassList);
209  lVirtualClass.setYield (lRoundedYieldLevel);
210  lVirtualClass.setMean (lMean);
211  lVirtualClass.setStdDev (lStdDev);
212 
213  lVirtualClassMap.insert (stdair::VirtualClassMap_T::
214  value_type (lRoundedYieldLevel, lVirtualClass));
215  } else {
216  stdair::VirtualClassStruct& lVirtualClass = itVCMap->second;
217  const stdair::MeanValue_T& lVCMean = lVirtualClass.getMean();
218  const stdair::StdDevValue_T& lVCStdDev = lVirtualClass.getStdDev();
219  const stdair::MeanValue_T lNewMean = lVCMean + lMean;
220  const stdair::StdDevValue_T lNewStdDev =
221  std::sqrt(lVCStdDev * lVCStdDev + lStdDev * lStdDev);
222  lVirtualClass.setMean (lNewMean);
223  lVirtualClass.setStdDev (lNewStdDev);
224 
225  lVirtualClass.addBookingClass(*lBookingClass_ptr);
226  }
227  }
228  }
229  }
230 
231  // Browse the virtual class map from high to low yield.
232  ioLegCabin.emptyVirtualClassList();
233  for (stdair::VirtualClassMap_T::reverse_iterator itVC =
234  lVirtualClassMap.rbegin(); itVC != lVirtualClassMap.rend(); ++itVC) {
235  stdair::VirtualClassStruct& lVC = itVC->second;
236 
237  ioLegCabin.addVirtualClass (lVC);
238  if (isNotEmpty == false) {
239  isNotEmpty = true;
240  }
241  }
242  return isNotEmpty;
243  }
244 
245  // ////////////////////////////////////////////////////////////////////
246  double Optimiser::
247  optimiseUsingOnDForecast (stdair::FlightDate& ioFlightDate,
248  const bool& iReduceFluctuations) {
249  double lMaxBPVariation = 0.0;
250  // Check if the flight date holds a list of leg dates.
251  // If so, retieve it and optimise the cabins.
252  const bool hasLegDateList =
253  stdair::BomManager::hasList<stdair::LegDate> (ioFlightDate);
254  if (hasLegDateList == true) {
255  STDAIR_LOG_DEBUG ("Optimisation for the flight date: "
256  << ioFlightDate.toString());
257  const stdair::LegDateList_T& lLDList =
258  stdair::BomManager::getList<stdair::LegDate> (ioFlightDate);
259  for (stdair::LegDateList_T::const_iterator itLD = lLDList.begin();
260  itLD != lLDList.end(); ++itLD) {
261  stdair::LegDate* lLD_ptr = *itLD;
262  assert (lLD_ptr != NULL);
263 
264  //
265  const stdair::LegCabinList_T& lLCList =
266  stdair::BomManager::getList<stdair::LegCabin> (*lLD_ptr);
267  for (stdair::LegCabinList_T::const_iterator itLC = lLCList.begin();
268  itLC != lLCList.end(); ++itLC) {
269  stdair::LegCabin* lLC_ptr = *itLC;
270  assert (lLC_ptr != NULL);
272  const stdair::BidPrice_T& lCurrentBidPrice =
273  lLC_ptr->getCurrentBidPrice();
274  const stdair::BidPrice_T& lPreviousBidPrice =
275  lLC_ptr->getPreviousBidPrice();
276  assert (lPreviousBidPrice != 0);
277  const double lBPVariation =
278  std::abs((lCurrentBidPrice - lPreviousBidPrice)/lPreviousBidPrice);
279  lMaxBPVariation = std::max(lMaxBPVariation, lBPVariation);
280  }
281  }
282  }
283  return lMaxBPVariation;
284  }
285 
286 }