00001
00002
00003
00004
00005 #include <cassert>
00006 #include <sstream>
00007 #include <cmath>
00008 #include <iomanip>
00009
00010 #include <boost/make_shared.hpp>
00011
00012 #include <stdair/basic/BasConst_General.hpp>
00013 #include <stdair/basic/BasConst_Inventory.hpp>
00014 #include <stdair/basic/BasConst_Request.hpp>
00015 #include <stdair/bom/BookingRequestStruct.hpp>
00016 #include <stdair/service/Logger.hpp>
00017
00018 #include <trademgen/basic/BasConst_DemandGeneration.hpp>
00019 #include <trademgen/bom/DemandStream.hpp>
00020
00021 namespace TRADEMGEN {
00022
00023
00024 DemandStream::DemandStream()
00025 : _key (stdair::DEFAULT_ORIGIN, stdair::DEFAULT_DESTINATION,
00026 stdair::DEFAULT_DEPARTURE_DATE, stdair::DEFAULT_CABIN_CODE),
00027 _parent (NULL),
00028 _demandCharacteristics (ArrivalPatternCumulativeDistribution_T(),
00029 POSProbabilityMassFunction_T(),
00030 ChannelProbabilityMassFunction_T(),
00031 TripTypeProbabilityMassFunction_T(),
00032 StayDurationProbabilityMassFunction_T(),
00033 FrequentFlyerProbabilityMassFunction_T(),
00034 PreferredDepartureTimeContinuousDistribution_T(),
00035 0.0,
00036 ValueOfTimeContinuousDistribution_T()),
00037 _posProMass (DEFAULT_POS_PROBALILITY_MASS),
00038 _firstDateTimeRequest (true) {
00039 assert (false);
00040 }
00041
00042
00043 DemandStream::DemandStream (const DemandStream&)
00044 : _key (stdair::DEFAULT_ORIGIN, stdair::DEFAULT_DESTINATION,
00045 stdair::DEFAULT_DEPARTURE_DATE, stdair::DEFAULT_CABIN_CODE),
00046 _parent (NULL),
00047 _demandCharacteristics (ArrivalPatternCumulativeDistribution_T(),
00048 POSProbabilityMassFunction_T(),
00049 ChannelProbabilityMassFunction_T(),
00050 TripTypeProbabilityMassFunction_T(),
00051 StayDurationProbabilityMassFunction_T(),
00052 FrequentFlyerProbabilityMassFunction_T(),
00053 PreferredDepartureTimeContinuousDistribution_T(),
00054 0.0,
00055 ValueOfTimeContinuousDistribution_T()),
00056 _posProMass (DEFAULT_POS_PROBALILITY_MASS),
00057 _firstDateTimeRequest (true) {
00058 assert (false);
00059 }
00060
00061
00062 DemandStream::DemandStream (const Key_T& iKey) :
00063 _key (iKey) {
00064 }
00065
00066
00067 DemandStream::~DemandStream() {
00068 }
00069
00070
00071 std::string DemandStream::toString() const {
00072 std::ostringstream oStr;
00073 oStr << _key.toString();
00074 return oStr.str();
00075 }
00076
00077
00078 void DemandStream::
00079 setAll (const ArrivalPatternCumulativeDistribution_T& iArrivalPattern,
00080 const POSProbabilityMassFunction_T& iPOSProbMass,
00081 const ChannelProbabilityMassFunction_T& iChannelProbMass,
00082 const TripTypeProbabilityMassFunction_T& iTripTypeProbMass,
00083 const StayDurationProbabilityMassFunction_T& iStayDurationProbMass,
00084 const FrequentFlyerProbabilityMassFunction_T& iFrequentFlyerProbMass,
00085 const PreferredDepartureTimeContinuousDistribution_T& iPreferredDepartureTimeContinuousDistribution,
00086 const stdair::WTP_T& iMinWTP,
00087 const ValueOfTimeContinuousDistribution_T& iValueOfTimeContinuousDistribution,
00088 const DemandDistribution& iDemandDistribution,
00089 stdair::BaseGenerator_T& ioSharedGenerator,
00090 const stdair::RandomSeed_T& iRequestDateTimeSeed,
00091 const stdair::RandomSeed_T& iDemandCharacteristicsSeed,
00092 const POSProbabilityMass_T& iDefaultPOSProbablityMass) {
00093
00094 setDemandCharacteristics (iArrivalPattern, iPOSProbMass,
00095 iChannelProbMass, iTripTypeProbMass,
00096 iStayDurationProbMass, iFrequentFlyerProbMass,
00097 iPreferredDepartureTimeContinuousDistribution,
00098 iMinWTP, iValueOfTimeContinuousDistribution);
00099
00100 setDemandDistribution (iDemandDistribution);
00101 setTotalNumberOfRequestsToBeGenerated (0);
00102 setRequestDateTimeRandomGeneratorSeed (iRequestDateTimeSeed);
00103 setDemandCharacteristicsRandomGeneratorSeed (iDemandCharacteristicsSeed);
00104 setPOSProbabilityMass (iDefaultPOSProbablityMass);
00105
00106
00107 init (ioSharedGenerator);
00108 }
00109
00110
00111 std::string DemandStream::display() const {
00112 std::ostringstream oStr;
00113
00114 oStr << "Demand stream key: " << _key.toString() << std::endl;
00115
00116
00117 oStr << _demandCharacteristics.describe();
00118
00119
00120 oStr << _demandDistribution.describe() << " => "
00121 << _totalNumberOfRequestsToBeGenerated << " to be generated"
00122 << std::endl;
00123
00124
00125 oStr << "Random generation context: " << _randomGenerationContext
00126 << std::endl;
00127
00128
00129 oStr << "Random generator for date-time: "
00130 << _requestDateTimeRandomGenerator << std::endl;
00131 oStr << "Random generator for demand characteristics: "
00132 << _demandCharacteristicsRandomGenerator << std::endl;
00133
00134
00135 oStr << _posProMass.displayProbabilityMass() << std::endl;
00136
00137 return oStr.str();
00138 }
00139
00140
00141 void DemandStream::init (stdair::BaseGenerator_T& ioSharedGenerator) {
00142
00143
00144 const stdair::RealNumber_T lMu = _demandDistribution._meanNumberOfRequests;
00145 const stdair::RealNumber_T lSigma =
00146 _demandDistribution._stdDevNumberOfRequests;
00147
00148 stdair::NormalDistribution_T lDistrib (lMu, lSigma);
00149 stdair::NormalGenerator_T lNormalGen (ioSharedGenerator, lDistrib);
00150
00151 const stdair::RealNumber_T lRealNumberOfRequestsToBeGenerated =lNormalGen();
00152
00153 const stdair::NbOfRequests_T lIntegerNumberOfRequestsToBeGenerated =
00154 std::floor (lRealNumberOfRequestsToBeGenerated + 0.5);
00155
00156 _totalNumberOfRequestsToBeGenerated = lIntegerNumberOfRequestsToBeGenerated;
00157
00158 _stillHavingRequestsToBeGenerated = true;
00159 _firstDateTimeRequest = true;
00160 }
00161
00162
00163 const bool DemandStream::
00164 stillHavingRequestsToBeGenerated (const stdair::DemandGenerationMethod& iDemandGenerationMethod) const {
00165
00166 const stdair::DemandGenerationMethod::EN_DemandGenerationMethod& lENDemandGenerationMethod =
00167 iDemandGenerationMethod.getMethod();
00168 if (lENDemandGenerationMethod == stdair::DemandGenerationMethod::STA_ORD) {
00169 bool hasStillHavingRequestsToBeGenerated = true;
00170
00171
00172 const stdair::Count_T lNbOfRequestsGeneratedSoFar =
00173 _randomGenerationContext.getNumberOfRequestsGeneratedSoFar();
00174
00175 const stdair::Count_T lRemainingNumberOfRequestsToBeGenerated =
00176 _totalNumberOfRequestsToBeGenerated - lNbOfRequestsGeneratedSoFar;
00177
00178 if (lRemainingNumberOfRequestsToBeGenerated <= 0) {
00179 hasStillHavingRequestsToBeGenerated = false;
00180 }
00181
00182 return hasStillHavingRequestsToBeGenerated;
00183 } else {
00184 return _stillHavingRequestsToBeGenerated;
00185 }
00186 }
00187
00188
00189 const stdair::DateTime_T DemandStream::generateTimeOfRequestPoissonProcess() {
00190
00191
00192 const ContinuousFloatDuration_T& lArrivalPattern =
00193 _demandCharacteristics._arrivalPattern;
00194
00195 const stdair::Time_T lHardcodedReferenceDepartureTime =
00196 boost::posix_time::hours (8);
00197
00198
00199 const stdair::DateTime_T lDepartureDateTime =
00200 boost::posix_time::ptime (_key.getPreferredDepartureDate(),
00201 lHardcodedReferenceDepartureTime);
00202
00203
00204 if (_firstDateTimeRequest) {
00205 const stdair::Probability_T lProbabilityFirstRequest = 0;
00206
00207
00208
00209 _dateTimeLastRequest =
00210 lArrivalPattern.getValue (lProbabilityFirstRequest);
00211
00212 _firstDateTimeRequest = false;
00213 }
00214
00215
00216 assert (_firstDateTimeRequest == false);
00217
00218
00219
00220
00221
00222 if (_dateTimeLastRequest == DEFAULT_LAST_LOWER_BOUND_ARRIVAL_PATTERN) {
00223 _stillHavingRequestsToBeGenerated = false;
00224
00225
00226 const stdair::Duration_T lDifferenceBetweenDepartureAndThisLowerBound =
00227 convertFloatIntoDuration (-DEFAULT_LAST_LOWER_BOUND_ARRIVAL_PATTERN);
00228
00229
00230
00231 const stdair::DateTime_T oDateTimeThisRequest =
00232 lDepartureDateTime + lDifferenceBetweenDepartureAndThisLowerBound;
00233
00234 return oDateTimeThisRequest;
00235 }
00236
00237
00238 stdair::FloatDuration_T lUpperBound =
00239 lArrivalPattern.getUpperBound (_dateTimeLastRequest);
00240
00241
00242 double lDailyRate =lArrivalPattern.getDerivativeValue(_dateTimeLastRequest);
00243
00244 const double lDemandMean = _demandDistribution._meanNumberOfRequests;
00245
00246 lDailyRate *= lDemandMean;
00247
00248
00249 const stdair::FloatDuration_T lExponentialVariable =
00250 _requestDateTimeRandomGenerator.generateExponential (lDailyRate);
00251
00252
00253 const stdair::FloatDuration_T lDateTimeThisRequest =
00254 _dateTimeLastRequest + lExponentialVariable;
00255
00256 stdair::DateTime_T oDateTimeThisRequest;
00257
00258
00259 if (lDateTimeThisRequest < lUpperBound) {
00260
00261
00262 const stdair::Duration_T lDifferenceBetweenDepartureAndThisRequest =
00263 convertFloatIntoDuration (lDateTimeThisRequest);
00264
00265
00266 oDateTimeThisRequest = lDepartureDateTime
00267 + lDifferenceBetweenDepartureAndThisRequest;
00268
00269
00270 _dateTimeLastRequest = lDateTimeThisRequest;
00271
00272
00273 incrementGeneratedRequestsCounter();
00274
00275 const double lRefDateTimeThisRequest = lDateTimeThisRequest + double(28800.001/86400.0);
00276 STDAIR_LOG_NOTIFICATION (boost::gregorian::to_iso_string(_key.getPreferredDepartureDate()) << ";" << std::setprecision(10) << lRefDateTimeThisRequest);
00277 } else {
00278
00279
00280
00281 _dateTimeLastRequest = lUpperBound;
00282
00283
00284 oDateTimeThisRequest = generateTimeOfRequestPoissonProcess ();
00285 }
00286
00287 return oDateTimeThisRequest;
00288 }
00289
00290
00291 const stdair::DateTime_T DemandStream::generateTimeOfRequestStatisticsOrder() {
00292
00309
00310
00311
00312
00313
00314
00315 const stdair::Count_T& lNbOfRequestsGeneratedSoFar =
00316 _randomGenerationContext.getNumberOfRequestsGeneratedSoFar();
00317
00318
00319
00320 const stdair::Count_T lRemainingNumberOfRequestsToBeGenerated =
00321 _totalNumberOfRequestsToBeGenerated - lNbOfRequestsGeneratedSoFar;
00322
00323
00324 assert (lRemainingNumberOfRequestsToBeGenerated > 0);
00325
00326
00327
00328 const double lRemainingRate =
00329 1.0 / static_cast<double> (lRemainingNumberOfRequestsToBeGenerated);
00330
00331
00332
00333 const stdair::Probability_T& lCumulativeProbabilitySoFar =
00334 _randomGenerationContext.getCumulativeProbabilitySoFar();
00335 const stdair::Probability_T lComplementOfCumulativeProbabilitySoFar =
00336 1.0 - lCumulativeProbabilitySoFar;
00337
00338
00339
00340 const stdair::Probability_T& lVariate = _requestDateTimeRandomGenerator();
00341 double lFactor = std::pow (1.0 - lVariate, lRemainingRate);
00342 if (lFactor >= 1.0 - 1e-6){
00343 lFactor = 1.0 - 1e-6;
00344 }
00345
00346
00347
00348
00349 const stdair::Probability_T lCumulativeProbabilityThisRequest =
00350 1.0 - lComplementOfCumulativeProbabilitySoFar * lFactor;
00351
00352
00353
00354
00355 const stdair::FloatDuration_T lNumberOfDaysBetweenDepartureAndThisRequest =
00356 _demandCharacteristics._arrivalPattern.getValue (lCumulativeProbabilityThisRequest);
00357
00358 const stdair::Duration_T lDifferenceBetweenDepartureAndThisRequest =
00359 convertFloatIntoDuration (lNumberOfDaysBetweenDepartureAndThisRequest);
00360
00361 const stdair::Time_T lHardcodedReferenceDepartureTime =
00362 boost::posix_time::hours (8);
00363
00364 const stdair::DateTime_T lDepartureDateTime =
00365 boost::posix_time::ptime (_key.getPreferredDepartureDate(),
00366 lHardcodedReferenceDepartureTime);
00367
00368
00369 const stdair::DateTime_T oDateTimeThisRequest =
00370 lDepartureDateTime + lDifferenceBetweenDepartureAndThisRequest;
00371
00372
00373 _randomGenerationContext.setCumulativeProbabilitySoFar (lCumulativeProbabilityThisRequest);
00374
00375
00376 incrementGeneratedRequestsCounter();
00377
00378
00379
00380
00381
00382
00383 double lRefNumberOfDaysBetweenDepartureAndThisRequest =
00384 lNumberOfDaysBetweenDepartureAndThisRequest + double(1.0/3.0);
00385 STDAIR_LOG_NOTIFICATION (boost::gregorian::to_iso_string(_key.getPreferredDepartureDate()) << ";" << std::setprecision(10) << lRefNumberOfDaysBetweenDepartureAndThisRequest);
00386
00387 return oDateTimeThisRequest;
00388 }
00389
00390
00391
00392 const stdair::Duration_T DemandStream::
00393 convertFloatIntoDuration (const stdair::FloatDuration_T iNumberOfDays) {
00394
00395
00396 const stdair::FloatDuration_T lNumberOfSeconds =
00397 iNumberOfDays * stdair::SECONDS_IN_ONE_DAY;
00398
00399
00400 const stdair::IntDuration_T lIntNumberOfSeconds =
00401 std::floor (lNumberOfSeconds);
00402
00403
00404 const stdair::FloatDuration_T lNumberOfMilliseconds =
00405 (lNumberOfSeconds - lIntNumberOfSeconds)
00406 * stdair::MILLISECONDS_IN_ONE_SECOND;
00407
00408
00409
00410 const stdair::IntDuration_T lIntNumberOfMilliseconds =
00411 std::floor (lNumberOfMilliseconds) + 1;
00412
00413
00414 const stdair::Duration_T lDifferenceBetweenDepartureAndThisRequest =
00415 boost::posix_time::seconds (lIntNumberOfSeconds)
00416 + boost::posix_time::millisec (lIntNumberOfMilliseconds);
00417
00418 return lDifferenceBetweenDepartureAndThisRequest;
00419 }
00420
00421
00422 const stdair::AirportCode_T DemandStream::generatePOS() {
00423
00424
00425 const stdair::Probability_T& lVariate = _demandCharacteristicsRandomGenerator();
00426 const stdair::AirportCode_T& oPOS = _demandCharacteristics.getPOSValue (lVariate);
00427
00428 return oPOS;
00429 }
00430
00431
00432 const stdair::ChannelLabel_T DemandStream::generateChannel() {
00433
00434 const stdair::Probability_T lVariate =
00435 _demandCharacteristicsRandomGenerator();
00436
00437 return _demandCharacteristics._channelProbabilityMass.getValue (lVariate);
00438 }
00439
00440
00441 const stdair::TripType_T DemandStream::generateTripType() {
00442
00443 const stdair::Probability_T lVariate =
00444 _demandCharacteristicsRandomGenerator();
00445
00446 return _demandCharacteristics._tripTypeProbabilityMass.getValue (lVariate);
00447 }
00448
00449
00450 const stdair::DayDuration_T DemandStream::generateStayDuration() {
00451
00452 const stdair::Probability_T lVariate =
00453 _demandCharacteristicsRandomGenerator();
00454
00455 return _demandCharacteristics._stayDurationProbabilityMass.getValue (lVariate);
00456 }
00457
00458
00459 const stdair::FrequentFlyer_T DemandStream::generateFrequentFlyer() {
00460
00461 const stdair::Probability_T lVariate =
00462 _demandCharacteristicsRandomGenerator();
00463
00464 return _demandCharacteristics._frequentFlyerProbabilityMass.getValue (lVariate);
00465 }
00466
00467
00468 const stdair::Duration_T DemandStream::generatePreferredDepartureTime() {
00469
00470 const stdair::Probability_T lVariate =
00471 _demandCharacteristicsRandomGenerator();
00472 const stdair::IntDuration_T lNbOfSeconds = _demandCharacteristics.
00473 _preferredDepartureTimeCumulativeDistribution.getValue (lVariate);
00474
00475 const stdair::Duration_T oTime = boost::posix_time::seconds (lNbOfSeconds);
00476
00477 return oTime;
00478 }
00479
00480
00481 const stdair::WTP_T DemandStream::
00482 generateWTP (stdair::RandomGeneration& ioGenerator,
00483 const stdair::Date_T& iDepartureDate,
00484 const stdair::DateTime_T& iDateTimeThisRequest,
00485 const stdair::DayDuration_T& iDurationOfStay) {
00486 const stdair::Date_T lDateThisRequest = iDateTimeThisRequest.date();
00487 const stdair::DateOffset_T lAP = iDepartureDate - lDateThisRequest;
00488 const stdair::DayDuration_T lAPInDays = lAP.days();
00489
00490 stdair::RealNumber_T lProb = -lAPInDays;
00491
00492 if (lProb < 0.0) { lProb = 0.0; }
00493 stdair::RealNumber_T lFrat5Coef =
00494 _demandCharacteristics._frat5Pattern.getValue (lProb);
00495
00496 const stdair::WTP_T lWTP = _demandCharacteristics._minWTP
00497 * (1.0 + (lFrat5Coef - 1.0) * log(ioGenerator()) / log(0.5));
00498
00499 return lWTP;
00500 }
00501
00502
00503 const stdair::PriceValue_T DemandStream::generateValueOfTime() {
00504
00505 const stdair::Probability_T lVariate =
00506 _demandCharacteristicsRandomGenerator();
00507
00508 return _demandCharacteristics._valueOfTimeCumulativeDistribution.getValue (lVariate);
00509 }
00510
00511
00512 stdair::BookingRequestPtr_T DemandStream::
00513 generateNextRequest (stdair::RandomGeneration& ioGenerator,
00514 const stdair::DemandGenerationMethod& iDemandGenerationMethod) {
00515
00516
00517 const stdair::AirportCode_T& lOrigin = _key.getOrigin();
00518
00519 const stdair::AirportCode_T& lDestination = _key.getDestination();
00520
00521 const stdair::Date_T& lPreferredDepartureDate =
00522 _key.getPreferredDepartureDate();
00523
00524 const stdair::CabinCode_T& lPreferredCabin = _key.getPreferredCabin();
00525
00526 const stdair::NbOfSeats_T lPartySize = stdair::DEFAULT_PARTY_SIZE;
00527
00528 const stdair::AirportCode_T lPOS = generatePOS();
00529
00530
00531 stdair::DateTime_T lDateTimeThisRequest;
00532 const stdair::DemandGenerationMethod::EN_DemandGenerationMethod& lENDemandGenerationMethod =
00533 iDemandGenerationMethod.getMethod();
00534 switch(lENDemandGenerationMethod) {
00535 case stdair::DemandGenerationMethod::POI_PRO:
00536 lDateTimeThisRequest = generateTimeOfRequestPoissonProcess(); break;
00537 case stdair::DemandGenerationMethod::STA_ORD:
00538 lDateTimeThisRequest = generateTimeOfRequestStatisticsOrder(); break;
00539 default: assert (false); break;
00540 }
00541
00542
00543 const stdair::ChannelLabel_T lChannelLabel = generateChannel();
00544
00545 const stdair::TripType_T lTripType = generateTripType();
00546
00547 const stdair::DayDuration_T lStayDuration = generateStayDuration();
00548
00549 const stdair::FrequentFlyer_T lFrequentFlyer = generateFrequentFlyer();
00550
00551 const stdair::Duration_T lPreferredDepartureTime =
00552 generatePreferredDepartureTime();
00553
00554 const stdair::PriceValue_T lValueOfTime = generateValueOfTime();
00555
00556 const stdair::WTP_T lWTP = generateWTP (ioGenerator,lPreferredDepartureDate,
00557 lDateTimeThisRequest,lStayDuration);
00558
00559
00560
00561
00562
00563
00564
00565
00566
00567
00568
00569
00570 stdair::BookingRequestPtr_T oBookingRequest_ptr =
00571 stdair::BookingRequestPtr_T
00572 (new stdair::BookingRequestStruct (describeKey(), lOrigin,
00573 lDestination, lPOS,
00574 lPreferredDepartureDate,
00575 lDateTimeThisRequest,
00576 lPreferredCabin, lPartySize,
00577 lChannelLabel, lTripType,
00578 lStayDuration, lFrequentFlyer,
00579 lPreferredDepartureTime,
00580 lWTP, lValueOfTime));
00581
00582
00583
00584
00585 return oBookingRequest_ptr;
00586 }
00587
00588
00589 void DemandStream::reset (stdair::BaseGenerator_T& ioSharedGenerator) {
00590 _randomGenerationContext.reset();
00591 init (ioSharedGenerator);
00592 }
00593
00594 }