00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027 #ifndef TIMELINE
00028 #define TIMELINE
00029
00030 #include "frepple/utils.h"
00031 #include <cmath>
00032
00033 namespace frepple
00034 {
00035 namespace utils
00036 {
00037
00038
00039
00040
00041
00042
00043
00044
00045
00046
00047
00048
00049
00050
00051
00052 template <class type> class TimeLine
00053 {
00054 friend class Event;
00055 public:
00056 class iterator;
00057 class const_iterator;
00058
00059 class Event : public NonCopyable
00060 {
00061 friend class TimeLine<type>;
00062 friend class const_iterator;
00063 friend class iterator;
00064 protected:
00065 Date dt;
00066 double oh;
00067 double cum_prod;
00068 Event* next;
00069 Event* prev;
00070 Event() : oh(0), cum_prod(0), next(NULL), prev(NULL) {};
00071
00072 public:
00073 virtual ~Event() {};
00074 virtual double getQuantity() const {return 0.0;}
00075
00076
00077 double getOnhand() const {return oh;}
00078
00079
00080 double getCumulativeProduced() const {return cum_prod;}
00081
00082
00083 double getCumulativeConsumed() const {return cum_prod - oh;}
00084
00085
00086 const Date& getDate() const {return dt;}
00087
00088
00089 virtual TimeLine<type>* getTimeLine() const {return NULL;}
00090
00091
00092
00093 virtual double getMin(bool inclusive = true) const
00094 {
00095 EventMinQuantity *m = this->getTimeLine()->lastMin;
00096 if (inclusive)
00097 while(m && getDate() < m->getDate()) m = m->prevMin;
00098 else
00099 while(m && getDate() <= m->getDate()) m = m->prevMin;
00100 return m ? m->newMin : 0.0;
00101 }
00102
00103
00104
00105 virtual double getMax(bool inclusive = true) const
00106 {
00107 EventMaxQuantity *m = this->getTimeLine()->lastMax;
00108 if (inclusive)
00109 while(m && getDate() < m->getDate()) m = m->prevMax;
00110 else
00111 while(m && getDate() <= m->getDate()) m = m->prevMax;
00112 return m ? m->newMax : 0.0;
00113 }
00114
00115 virtual unsigned short getType() const = 0;
00116
00117
00118
00119
00120
00121
00122
00123
00124
00125 bool operator < (Event const& fl2) const
00126 {
00127 assert (&fl2);
00128 if (getDate() != fl2.getDate())
00129 return getDate() < fl2.getDate();
00130 else if (fabs(getQuantity() - fl2.getQuantity()) > ROUNDING_ERROR)
00131 return getQuantity() > fl2.getQuantity();
00132 else
00133 return this < &fl2;
00134 }
00135 };
00136
00137
00138 class EventChangeOnhand : public Event
00139 {
00140 friend class TimeLine<type>;
00141 private:
00142 double quantity;
00143 public:
00144 double getQuantity() const {return quantity;}
00145 EventChangeOnhand(double qty = 0.0) : quantity(qty) {}
00146 virtual unsigned short getType() const {return 1;}
00147 };
00148
00149
00150 class EventMinQuantity : public Event
00151 {
00152 friend class TimeLine<type>;
00153 friend class Event;
00154 private:
00155 double newMin;
00156 protected:
00157 EventMinQuantity *prevMin;
00158 public:
00159 EventMinQuantity(Date d, double f=0.0) : newMin(f), prevMin(NULL)
00160 { this->dt = d; }
00161 void setMin(double f) {newMin = f;}
00162 virtual double getMin(bool inclusive = true) const
00163 {
00164 if (inclusive) return newMin;
00165 else return prevMin ? prevMin->newMin : 0.0;
00166 }
00167 virtual unsigned short getType() const {return 3;}
00168 };
00169
00170
00171 class EventMaxQuantity : public Event
00172 {
00173 friend class Event;
00174 friend class TimeLine<type>;
00175 private:
00176 double newMax;
00177 protected:
00178 EventMaxQuantity *prevMax;
00179 public:
00180 EventMaxQuantity(Date d, double f=0.0) : newMax(f), prevMax(NULL)
00181 {this->dt = d;}
00182 void setMax(double f) {newMax = f;}
00183 virtual double getMax(bool inclusive = true) const
00184 {
00185 if (inclusive) return newMax;
00186 else return prevMax ? prevMax->newMax : 0.0;
00187 }
00188 virtual unsigned short getType() const {return 4;}
00189 };
00190
00191
00192
00193
00194
00195
00196
00197
00198 class const_iterator
00199 {
00200 protected:
00201 const Event* cur;
00202 public:
00203 const_iterator() {}
00204 const_iterator(const Event* e) : cur(e) {};
00205 const_iterator(const iterator& c) : cur(c.cur) {}
00206 const Event& operator*() const {return *cur;}
00207 const Event* operator->() const {return cur;}
00208 const_iterator& operator++() {cur = cur->next; return *this;}
00209 const_iterator operator++(int)
00210 {const_iterator tmp = *this; ++*this; return tmp;}
00211 const_iterator& operator--() {cur = cur->prev; return *this; }
00212 const_iterator operator--(int)
00213 {const_iterator tmp = *this; --*this; return tmp;}
00214 bool operator==(const const_iterator& x) const {return cur == x.cur;}
00215 bool operator!=(const const_iterator& x) const {return cur != x.cur;}
00216 };
00217
00218
00219 class iterator : public const_iterator
00220 {
00221 public:
00222 iterator() {}
00223 iterator(Event* e) : const_iterator(e) {};
00224 Event& operator*() const {return *const_cast<Event*>(this->cur);}
00225 Event* operator->() const {return const_cast<Event*>(this->cur);}
00226 iterator& operator++() {this->cur = this->cur->next; return *this;}
00227 iterator operator++(int) {iterator tmp = *this; ++*this; return tmp;}
00228 iterator& operator--() {this->cur = this->cur->prev; return *this; }
00229 iterator operator--(int) {iterator tmp = *this; --*this; return tmp;}
00230 bool operator==(const iterator& x) const {return this->cur == x.cur;}
00231 bool operator!=(const iterator& x) const {return this->cur != x.cur;}
00232 };
00233
00234 TimeLine() : first(NULL), last(NULL), lastMax(NULL), lastMin(NULL) {}
00235 int size() const
00236 {
00237 int cnt(0);
00238 for (Event* p=first; p; p=p->next) ++cnt;
00239 return cnt;
00240 }
00241 iterator begin() {return iterator(first);}
00242 iterator begin(Event* e) {return iterator(e);}
00243 iterator rbegin() {return iterator(last);}
00244 iterator end() {return iterator(NULL);}
00245 const_iterator begin() const {return const_iterator(first);}
00246 const_iterator begin(const Event* e) const {return const_iterator(e);}
00247 const_iterator rbegin() const {return const_iterator(last);}
00248 const_iterator end() const {return const_iterator(NULL);}
00249 bool empty() const {return first==NULL;}
00250 void insert(Event*);
00251 void insert(EventChangeOnhand* e, double qty, const Date& d)
00252 {
00253 e->quantity = qty;
00254 e->dt = d;
00255 insert(static_cast<Event*>(e));
00256 };
00257 void erase(Event*);
00258 void update(EventChangeOnhand*, double, const Date&);
00259
00260
00261
00262
00263
00264 void inspect(string name) const
00265 {
00266 logger << "Inspecting " << this << ": \"" << name << "\":" << endl;
00267 for (const_iterator oo=begin(); oo!=end(); ++oo)
00268 logger << " " << oo->getDate() << " "
00269 << oo->getQuantity() << " " << oo->getOnhand()
00270 << " " << oo->getCumulativeProduced() << endl;
00271 }
00272
00273
00274 bool check() const;
00275
00276 private:
00277
00278 Event* first;
00279
00280
00281 Event* last;
00282
00283
00284 EventMaxQuantity *lastMax;
00285
00286
00287 EventMinQuantity *lastMin;
00288 };
00289
00290
00291 template <class type> void TimeLine<type>::insert (Event* e)
00292 {
00293
00294
00295
00296 iterator i = rbegin();
00297 double qty = e->getQuantity();
00298 if (qty > 0)
00299 for (; i!=end() && *e<*i; --i)
00300 {
00301 i->oh += qty;
00302 i->cum_prod += qty;
00303 }
00304 else
00305 for (; i!=end() && *e<*i; --i)
00306 i->oh += qty;
00307
00308
00309 if (i == end())
00310 {
00311
00312 if (first)
00313 first->prev = e;
00314 else
00315
00316 last = e;
00317 e->next = first;
00318 e->prev = NULL;
00319 first = e;
00320 e->oh = qty;
00321 if (qty>0) e->cum_prod = qty;
00322 }
00323 else
00324 {
00325
00326 e->prev = &*i;
00327 e->next = i->next;
00328 if (i->next)
00329 i->next->prev = e;
00330 else
00331
00332 last = e;
00333 i->next = e;
00334 e->oh = i->oh + qty;
00335 if (qty>0)
00336 e->cum_prod = i->cum_prod + qty;
00337 else
00338 e->cum_prod = i->cum_prod;
00339 }
00340
00341 if (e->getType() == 3)
00342 {
00343
00344 EventMinQuantity *m = static_cast<EventMinQuantity*>(e);
00345 if (!lastMin || m->getDate() >= lastMin->getDate())
00346 {
00347
00348 m->prevMin = lastMin;
00349 lastMin = m;
00350 }
00351 else
00352 {
00353 EventMinQuantity * o = lastMin;
00354 while (o->prevMin && m->getDate() >= o->prevMin->getDate())
00355 o = o->prevMin;
00356 m->prevMin = o->prevMin;
00357 o->prevMin = m;
00358 }
00359 }
00360 else if (e->getType() == 4)
00361 {
00362
00363 EventMaxQuantity* m = static_cast<EventMaxQuantity*>(e);
00364 if (!lastMax || m->getDate() >= lastMax->getDate())
00365 {
00366
00367 m->prevMax = lastMax;
00368 lastMax = m;
00369 }
00370 else
00371 {
00372 EventMaxQuantity *o = lastMax;
00373 while (o->prevMax && o->getDate() <= o->prevMax->getDate())
00374 o = o->prevMax;
00375 m->prevMax = o->prevMax;
00376 o->prevMax = m;
00377 }
00378 }
00379
00380
00381 assert(check());
00382 }
00383
00384
00385 template <class type> void TimeLine<type>::erase (Event* e)
00386 {
00387
00388 double qty = e->getQuantity();
00389 if (qty>0)
00390 for (iterator i = begin(e); i!=end(); ++i)
00391 {
00392 i->oh -= qty;
00393 i->cum_prod -= qty;
00394 }
00395 else
00396 for (iterator i = begin(e); i!=end(); ++i)
00397 i->oh -= qty;
00398
00399 if (e->prev)
00400 e->prev->next = e->next;
00401 else
00402
00403 first = e->next;
00404
00405 if (e->next)
00406 e->next->prev = e->prev;
00407 else
00408
00409 last = e->prev;
00410
00411
00412 assert(check());
00413 }
00414
00415
00416 template <class type> void TimeLine<type>::update(EventChangeOnhand* e, double newqty, const Date& d)
00417 {
00418
00419 double delta = e->quantity - newqty;
00420 double oldqty = e->quantity;
00421
00422
00423
00424 e->dt = d;
00425 e->quantity = newqty;
00426
00427
00428
00429
00430 while ( e->next && !(*e<*e->next) )
00431 {
00432
00433 Event *theNext = e->next, *theNextNext = theNext->next;
00434 if (e->prev) e->prev->next = theNext;
00435 theNext->prev = e->prev;
00436 theNext->next = e;
00437 e->prev = theNext;
00438 e->next = theNextNext;
00439 if (theNextNext)
00440 theNextNext->prev = e;
00441 else
00442 last = e;
00443 if (first == e) first = theNext;
00444 e->oh = theNext->oh;
00445 e->cum_prod = theNext->cum_prod;
00446 theNext->oh -= oldqty;
00447 if (oldqty > 0) theNext->cum_prod -= oldqty;
00448 }
00449 while ( e->prev && !(*e->prev<*e) )
00450 {
00451
00452 Event *thePrev = e->prev, *thePrevPrev = thePrev->prev;
00453 if (e->next) e->next->prev = thePrev;
00454 thePrev->next = e->next;
00455 thePrev->prev = e;
00456 e->next = thePrev;
00457 e->prev = thePrevPrev;
00458 if (thePrevPrev)
00459 thePrevPrev->next = e;
00460 else
00461 first = e;
00462 if (last == e) last = thePrev;
00463 thePrev->oh = e->oh;
00464 thePrev->cum_prod = e->cum_prod;
00465 e->oh -= thePrev->getQuantity();
00466 if (thePrev->getQuantity() > 0) e->cum_prod -= thePrev->getQuantity();
00467 }
00468
00469
00470 if (fabs(delta) > ROUNDING_ERROR)
00471 {
00472 double cumdelta = (oldqty>0? oldqty : 0) - (newqty>0 ? newqty : 0);
00473 if (fabs(cumdelta) > 0)
00474 for (iterator i=begin(e); i!=end(); ++i)
00475 {
00476 i->oh -= delta;
00477 i->cum_prod -= cumdelta;
00478 }
00479 else
00480 for (iterator i=begin(e); i!=end(); ++i)
00481 i->oh -= delta;
00482 }
00483
00484
00485
00486
00487
00488 }
00489
00490
00491 template <class type> bool TimeLine<type>::check() const
00492 {
00493 double expectedOH = 0.0;
00494 double expectedCumProd = 0.0;
00495 const Event *prev = NULL;
00496 for (const_iterator i = begin(); i!=end(); ++i)
00497 {
00498
00499 expectedOH += i->getQuantity();
00500 if (i->getQuantity() > 0) expectedCumProd += i->getQuantity();
00501 if (fabs(expectedOH - i->oh) > ROUNDING_ERROR)
00502 {
00503 inspect("Error: timeline onhand value corrupted on "
00504 + string(i->getDate()));
00505 return false;
00506 }
00507
00508 if (fabs(expectedCumProd - i->cum_prod) > ROUNDING_ERROR)
00509 {
00510 inspect("Error: timeline cumulative produced value corrupted on "
00511 + string(i->getDate()));
00512 return false;
00513 }
00514
00515 if (prev && !(*prev<*i)
00516 && fabs(prev->getQuantity() - i->getQuantity())>ROUNDING_ERROR)
00517 {
00518 inspect("Error: timeline sort corrupted on " + string(i->getDate()));
00519 return false;
00520 }
00521 prev = &*i;
00522 }
00523 return true;
00524 }
00525
00526 }
00527 }
00528 #endif
00529