BWAPI
|
00001 // Copyright (c) 2005 Stanford University (USA). 00002 // All rights reserved. 00003 // 00004 // This file is part of CGAL (www.cgal.org); you can redistribute it and/or 00005 // modify it under the terms of the GNU Lesser General Public License as 00006 // published by the Free Software Foundation; version 2.1 of the License. 00007 // See the file LICENSE.LGPL distributed with CGAL. 00008 // 00009 // Licensees holding a valid commercial license may use this file in 00010 // accordance with the commercial license agreement provided with the software. 00011 // 00012 // This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE 00013 // WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. 00014 // 00015 // $URL: svn+ssh://scm.gforge.inria.fr/svn/cgal/branches/CGAL-3.5-branch/Kinetic_data_structures/include/CGAL/Kinetic/Heap_pointer_event_queue.h $ 00016 // $Id: Heap_pointer_event_queue.h 40832 2007-11-08 00:27:20Z ameyer $ 00017 // 00018 // 00019 // Author(s) : Daniel Russel <drussel@alumni.princeton.edu> 00020 00021 #ifndef CGAL_KINETIC_HEAP_POINTER_EVENT_QUEUE_H 00022 #define CGAL_KINETIC_HEAP_POINTER_EVENT_QUEUE_H 00023 #include <CGAL/Kinetic/basic.h> 00024 #include <iostream> 00025 #include <vector> 00026 #include <utility> 00027 #include <functional> 00028 #include <CGAL/assertions.h> 00029 #include <iostream> 00030 #include <CGAL/Kinetic/Ref_counted.h> 00031 #include <CGAL/Kinetic/internal/infinity_or_max.h> 00032 #include <algorithm> 00033 00034 CGAL_KINETIC_BEGIN_INTERNAL_NAMESPACE 00035 00036 template <class Priority> 00037 class Heap_pointer_event_queue_item_handle; 00038 00039 // The interface for an item stored in the ::Heap_pointer_event_queue 00040 template <class Priority> 00041 class Heap_pointer_event_queue_item: public Ref_counted<Heap_pointer_event_queue_item<Priority> > 00042 { 00043 typedef Ref_counted<Heap_pointer_event_queue_item<Priority> > P; 00044 public: 00045 00046 /* struct Key: public typename P::Handle { 00047 Key(){} 00048 Key(Item_handle h): P::Handle(h){} 00049 bool is_valid() const { 00050 return this->get() != NULL; 00051 } 00052 };*/ 00053 typedef Heap_pointer_event_queue_item_handle<Priority> Key; 00054 00055 Heap_pointer_event_queue_item():bin_(-1), time_(infinity_or_max<Priority>(Priority(0))){} 00056 Heap_pointer_event_queue_item(int bin, const Priority &t): bin_(bin), time_(t){} 00057 00058 virtual std::ostream& write(std::ostream &out) const =0; 00059 const Priority& time() const {return time_;}; 00060 virtual void process() =0; 00061 virtual void audit(Key) const=0; 00062 virtual void *kds() const =0; 00063 virtual CGAL::Comparison_result compare_concurrent(Key a, Key b) const =0; 00064 void set_bin(int bin) const { bin_=bin;} 00065 int bin() const {return bin_;}; 00066 virtual ~Heap_pointer_event_queue_item(){} 00067 //virtual const void *event() const=0; 00068 private: 00069 mutable int bin_; 00070 Priority time_; 00071 }; 00072 00073 CGAL_OUTPUT1(Heap_pointer_event_queue_item); 00074 00075 00076 template <class Priority> 00077 class Heap_pointer_event_queue_item_handle: public Ref_counted<Heap_pointer_event_queue_item<Priority> >::Handle 00078 { 00079 typedef typename Ref_counted<Heap_pointer_event_queue_item<Priority> >::Handle P; 00080 public: 00081 std::ostream &write(std::ostream &out) const { 00082 return P::operator*().write(out); 00083 } 00084 template <class T> 00085 Heap_pointer_event_queue_item_handle(T* t): P(t){} 00086 Heap_pointer_event_queue_item_handle(){} 00087 Heap_pointer_event_queue_item_handle(const P&p): P(p){} 00088 }; 00089 00090 CGAL_OUTPUT1(Heap_pointer_event_queue_item_handle); 00091 00092 // The how a dummy item is stored in the ::Heap_pointer_event_queue 00093 /* 00094 One dummy item is used to represent events which will never happen. 00095 */ 00096 template <class Priority> 00097 class Heap_pointer_event_queue_dummy_item: public Heap_pointer_event_queue_item<Priority> 00098 { 00099 typedef Heap_pointer_event_queue_item<Priority> P; 00100 public: 00101 Heap_pointer_event_queue_dummy_item(): P(-2, internal::infinity_or_max(Priority())){} 00102 virtual void process() { 00103 } 00104 virtual void *kds() const {return NULL;} 00105 virtual CGAL::Comparison_result compare_concurrent(typename P::Key a, 00106 typename P::Key b) const { 00107 if (a < b) return CGAL::SMALLER; 00108 else if (b < a) return CGAL::LARGER; 00109 else return CGAL::EQUAL; 00110 //return CGAL::compare(a,b); 00111 } 00112 virtual std::ostream& write(std::ostream &out) const 00113 { 00114 out << "Never."; 00115 return out; 00116 } 00117 virtual void audit(typename P::Key) const { 00118 std::cout << "Auditing a dummy event" << std::endl; 00119 } 00120 virtual ~Heap_pointer_event_queue_dummy_item(){} 00121 }; 00122 00123 // The how a real item is stored in the ::Heap_pointer_event_queue 00124 /* 00125 This just stores an object of type Event and passes the virtual calls on to it. 00126 00127 The object is reference counted so you don't have to worry about the 00128 queue deleting it or not. 00129 */ 00130 template <class Priority, class Event> 00131 class Heap_pointer_event_queue_item_rep: public internal::Heap_pointer_event_queue_item<Priority> 00132 { 00133 typedef internal::Heap_pointer_event_queue_item<Priority> P; 00134 public: 00135 //typedef CGAL::Ref_counted_pointer<Heap_pointer_event_queue_item_rep<Priority, Event> > Pointer; 00136 //typedef CGAL::Ref_counted_pointer<const Heap_pointer_event_queue_item_rep<Priority, Event> > Const_pointer; 00137 Heap_pointer_event_queue_item_rep(): internal::Heap_pointer_event_queue_item<Priority>(){} 00138 Heap_pointer_event_queue_item_rep(const Priority &t, const Event &e, 00139 unsigned int bin): internal::Heap_pointer_event_queue_item<Priority>(bin, t), 00140 event_(e){} 00141 virtual void process() { 00142 event_.process(); 00143 } 00144 virtual void *kds() const {return event_.kds();} 00145 virtual CGAL::Comparison_result compare_concurrent(typename P::Key a, 00146 typename P::Key b) const { 00147 return event_.compare_concurrent(a,b); 00148 } 00149 virtual void audit(typename P::Key k) const { 00150 event_.audit(k); 00151 } 00152 virtual std::ostream& write(std::ostream &out) const 00153 { 00154 out << "("; 00155 event_.write(out); 00156 out << ")"; 00157 return out; 00158 } 00159 // Access the actual event 00160 /* 00161 There is no non-const access so you can't change the time. 00162 */ 00163 const Event &event() const 00164 { 00165 return event_; 00166 } 00167 Event &event() 00168 { 00169 return event_; 00170 } 00171 void set_event(const Event &e) { 00172 event_=e; 00173 } 00174 virtual ~Heap_pointer_event_queue_item_rep(){} 00175 00176 protected: 00177 Event event_; 00178 }; 00179 00180 CGAL_KINETIC_END_INTERNAL_NAMESPACE 00181 00182 CGAL_KINETIC_BEGIN_NAMESPACE 00183 00184 template <class Priority> class Bin_pointer_event_queue; 00185 00187 00198 template <class FK, bool INF=false> 00199 class Heap_pointer_event_queue 00200 { 00201 public: 00202 typedef typename FK::Root Priority; 00203 friend class Bin_pointer_event_queue<Priority>; 00204 typedef Heap_pointer_event_queue<Priority> This; 00205 typedef internal::Heap_pointer_event_queue_item<Priority> Item; 00206 typedef typename Item::Handle Item_handle; 00207 typedef enum Child {FIRST=0, SECOND=1} 00208 Child; 00209 00210 class Compare 00211 { 00212 public: 00213 Compare(){} 00214 bool operator()(Item_handle i0, Item_handle i1) const 00215 { 00216 CGAL::Comparison_result cr= CGAL::compare(i0->time(), i1->time()); 00217 if (cr == CGAL::SMALLER) return true; 00218 else if (cr == CGAL::LARGER) return false; 00219 else { 00220 if (i0->kds() < i1->kds()) return true; 00221 else if (i0->kds() > i1->kds()) return false; 00222 else { 00223 cr= i0->compare_concurrent(Key(i0), Key(i1)); 00224 if (cr == CGAL::SMALLER) return true; 00225 else if (cr == CGAL::LARGER) return false; 00226 else { 00227 //CGAL_error(); 00228 return false; 00229 } 00230 } 00231 00232 } 00233 } 00234 }; 00235 00236 00237 //typedef Priority_t Priority; 00238 00240 00243 typedef typename Item::Key Key; 00244 /*struct Key: public Item_handle { 00245 Key(){}; 00246 Key(Item*i): Item_handle(i){} 00247 Key(Item_handle ih): Item_handle(ih){} 00248 static Key null() { 00249 return Key(); 00250 } 00251 };*/ 00252 //typedef Item_handle Key; 00253 00255 Heap_pointer_event_queue(const Priority&, const Priority &end, FK, int sz=1000): end_(end) { 00256 queue_.reserve(sz); 00257 null_event_= Key(new internal::Heap_pointer_event_queue_dummy_item<Priority>()); 00258 } 00259 00260 Heap_pointer_event_queue(const Priority&, FK, int sz=1000) { 00261 queue_.reserve(sz); 00262 null_event_= Key(new internal::Heap_pointer_event_queue_dummy_item<Priority>()); 00263 } 00264 00265 const Priority& end_priority() const 00266 { 00267 return end_; 00268 } 00269 00270 void set_interval(const Priority &, const Priority &e) 00271 { 00272 end_=e; 00273 } 00274 00275 bool is_after_end(const Priority &t) const { 00276 if (INF) return false; 00277 else return CGAL::compare(t,end_priority()) == CGAL::LARGER; 00278 } 00279 void audit_events() const { 00280 for (typename std::vector<Item_handle>::const_iterator it= queue_.begin(); 00281 it != queue_.end(); ++it) { 00282 (* it)->audit(Key(*it)); 00283 } 00284 } 00285 00286 void audit_event(Key k) const { 00287 k->audit(k); 00288 } 00289 00291 00294 template <class E> 00295 Key insert(const Priority &t, const E & e) { 00296 if (!is_after_end(t)) { 00297 Item_handle k= new internal::Heap_pointer_event_queue_item_rep<Priority, E>(t, e, queue_.size()); 00298 queue_.push_back(k); 00299 bubble_up(queue_.size()-1); 00300 //std::push_heap(queue_.begin(), queue_.end()); 00301 CGAL_expensive_postcondition(is_valid()); 00302 CGAL_postcondition(k->bin() != -1); 00303 return Key(k); 00304 } else { 00305 return null_event_; 00306 } 00307 } 00308 00310 void erase(const Key &item) { 00311 if (item == end_key()) return; 00312 CGAL_expensive_precondition(item != Key()); 00313 CGAL_expensive_precondition(is_in_heap(item)); 00314 int bin= item->bin(); 00315 //if (bin ==-1) return; 00316 CGAL_precondition(static_cast<unsigned int> (bin) < queue_.size() && bin >= 0); 00317 00318 // this is a bit more work than strictly necessary 00319 swap(queue_.size()-1, bin); 00320 queue_.pop_back(); 00321 if (static_cast<unsigned int>(bin) < queue_.size()) { 00322 bubble(bin); 00323 } 00324 item->set_bin(-1); 00325 CGAL_expensive_postcondition(is_valid()); 00326 } 00327 00329 00330 /* 00331 template <class E> 00332 struct Event_pointer { 00333 typedef const Heap_pointer_event_queue_item_rep<Priority, E>* Pointer; 00334 struct Handle: public Heap_pointer_event_queue_item_rep<Priority, E>::Const_pointer { 00335 Handle(Pointer p): 00336 Heap_pointer_event_queue_item_rep<Priority, E> 00337 ::Const_pointer(reinterpret_cast<const Heap_pointer_event_queue_item_rep<Priority, E>*>(p)){ 00338 } 00339 Handle(){} 00340 00341 }; 00342 };*/ 00343 00345 00351 /*template <class E> 00352 typename Event_pointer<E>::Pointer event(const Key &item, const E &) const { 00353 return reinterpret_cast<typename Event_pointer<E>::Pointer >( item.get()); 00354 }*/ 00355 00356 template <class E> 00357 const E& get(const Key &item) const 00358 { 00359 CGAL_precondition(item && item != null_event_); 00360 return reinterpret_cast<internal::Heap_pointer_event_queue_item_rep<Priority, E>*>( item.get())->event(); 00361 } 00362 00363 00364 template <class E> 00365 E& get(Key item) 00366 { 00367 CGAL_precondition(item && item != null_event_); 00368 typename internal::Heap_pointer_event_queue_item<Priority> *ptr= item.get(); 00369 typename internal::Heap_pointer_event_queue_item_rep<Priority, E>* nptr 00370 = reinterpret_cast<internal::Heap_pointer_event_queue_item_rep<Priority, E>*>(ptr); 00371 return nptr->event(); 00372 } 00373 00375 00378 template <class NE> 00379 Key set(const Key &item, const NE &ne) { 00380 CGAL_expensive_precondition(is_in_heap(item)); 00381 CGAL_precondition(item && item != null_event_); 00382 //CGAL_expensive_precondition(item.get()->time() == ne.time()); 00383 CGAL_expensive_precondition(item); 00384 int bin = item.get()->bin(); 00385 CGAL_expensive_precondition(Key(queue_[bin])==item); 00386 queue_[bin]= new internal::Heap_pointer_event_queue_item_rep<Priority, NE>(item.get()->time(), ne, bin); 00387 CGAL_expensive_postcondition(is_valid()); 00388 return queue_[bin]; 00389 } 00390 00392 00395 Priority front_priority() const 00396 { 00397 CGAL_precondition(!queue_.empty()); 00398 return queue_.front()->time(); 00399 } 00400 00402 const Priority& priority(const Key &item) const 00403 { 00404 CGAL_precondition(item); 00405 return item->time(); 00406 } 00407 00409 bool empty() const 00410 { 00411 return queue_.empty(); 00412 } 00413 00415 void clear() { 00416 // ref counted pointers are nice. 00417 queue_.clear(); 00418 } 00419 00420 00421 00423 00426 void process_front() { 00427 CGAL_precondition(!empty()); 00428 //if (queue_.front()->time() < end_priority()) { 00429 //CGAL_precondition_code(Item_handle k= queue_.front()); 00430 CGAL_LOG(Log::SOME, "Processing " << queue_.front() << std::endl); 00431 Item_handle ih= queue_.front(); 00432 pop_front(); 00433 //std::pop_heap(queue_.begin(), queue_.end()); 00434 ih->process(); 00435 //CGAL_expensive_postcondition(is_valid()); 00436 /*} 00437 else { 00438 clear(); 00439 }*/ 00440 } 00441 00443 bool print() const 00444 { 00445 write(std::cout); 00446 return true; 00447 } 00448 /* 00449 void process_final_events() { 00450 bool do_i_use_this; 00451 std::vector<Item_handle> c; 00452 c.swap(final_events_); 00453 for (unsigned int i=0; i< c.size(); ++i){ 00454 c[i]->set_processed(true); 00455 } 00456 }*/ 00458 00461 bool write(std::ostream &out) const 00462 { 00463 //std::cout << "Not writing queue.\n"; 00464 //return true; 00465 #if 0 00466 std::vector<Item_handle> bins; 00467 00468 for (unsigned int i=0; i< queue_.size(); ++i) { 00469 bins.push_back(queue_[i]); 00470 } 00471 00472 std::sort(bins.begin(), bins.end(), compare_); 00473 00474 typename std::vector<Item_handle>::const_iterator curi= bins.begin(), endi= bins.end(); 00475 #else 00476 typename std::vector<Item_handle>::const_iterator curi= queue_.begin(), endi= queue_.end(); 00477 #endif 00478 for (; curi != endi; ++curi) { 00479 Priority t=(*curi)->time(); 00480 // HACK HACK because CGAL::to_double(t) won't compile with gcc 3.4 00481 std::pair<double,double> d= CGAL::to_interval(t); 00482 //CGAL::to_double(t); 00483 out << "<" << d.first << "..." << d.second << ": "; 00484 (*curi)->write(out); 00485 out << ">\n"; 00486 } 00487 out << std::endl; 00488 #if 0 00489 for (unsigned int i=1; i< bins.size(); ++i) { 00490 if (bins[i-1]->time()== bins[i]->time()) { 00491 out << "Warning, two concurrent events: " << bins[i] << " and " 00492 << bins[i-1] << " at time " << bins[i]->time() << std::endl; 00493 } 00494 } 00495 #endif 00496 00497 /*if (!final_events.empty()) { 00498 out << "Finally: \n"; 00499 for (unsigned int i=0; i< final_events_.size(); ++i){ 00500 final_events_[i]->write(out) << std::endl; 00501 } 00502 }*/ 00503 00504 00505 //out << std::endl; 00506 return false; 00507 } 00508 00509 Key end_key() const 00510 { 00511 return null_event_; 00512 } 00513 00514 bool contains(Key k) const { 00515 return is_in_heap(k); 00516 } 00517 00518 00519 Key front() const { 00520 return Key(queue_.front()); 00521 } 00522 00523 00524 protected: 00526 std::vector<Item_handle> queue_; 00527 Compare compare_; 00528 //std::vector<Item_handle> final_events_; 00529 Key null_event_; 00530 Priority end_; 00531 00532 bool is_in_heap(Key k) const 00533 { 00534 for (unsigned int i=0; i< queue_.size(); ++i) { 00535 if (queue_[i]==k) return true; 00536 } 00537 return false; 00538 } 00539 00541 void swap(unsigned int i, unsigned int j) { 00542 std::swap(queue_[i], queue_[j]); 00543 int bin= queue_[i]->bin(); 00544 queue_[i]->set_bin(queue_[j]->bin()); 00545 queue_[j]->set_bin(bin); 00546 } 00547 00549 int parent(unsigned int i) const 00550 { 00551 return (static_cast<int>(i)-1)/2; 00552 }; 00553 00555 unsigned int child(unsigned int i, Child which) const 00556 { 00557 return 2*i+1+which; 00558 } 00559 00561 bool less_items(unsigned int i, unsigned int j) const 00562 { 00563 if (static_cast<unsigned int>(j) >= queue_.size()) return true; 00564 else if (static_cast<unsigned int>(i) >= queue_.size()) return false; 00565 else { 00566 return compare_(queue_[i], queue_[j]); 00567 } 00568 } 00570 bool less_than_child(unsigned int i, unsigned int c) const 00571 { 00572 int ch= child(i,c); 00573 return less_items(i, ch); 00574 } 00576 bool less_than_parent(unsigned int i) const 00577 { 00578 if (i==0) return false; 00579 else return less_items(i, parent(i)); 00580 } 00581 00583 void pop_front() { 00584 CGAL_expensive_precondition(!empty()); 00585 Item_handle item= queue_.front(); 00586 swap(0, queue_.size()-1); 00587 queue_.back()->set_bin(-1); 00588 queue_.pop_back(); 00589 if (!queue_.empty()) bubble_down(0); 00590 } 00591 00593 void bubble_down(unsigned int i) { 00594 CGAL_expensive_precondition(i<queue_.size()); 00595 while (i < queue_.size()) { 00596 unsigned int lc= child(i,FIRST), rc= child(i,SECOND); 00597 if (!less_items(rc, lc)) { // make the sorting stable 00598 if (less_items(lc, i)) { 00599 swap(i, lc); 00600 i=lc; 00601 } else break; 00602 } 00603 else { 00604 if (less_items(rc, i)) { 00605 swap(i, rc); 00606 i=rc; 00607 } else break; 00608 } 00609 } 00610 } 00612 void bubble_up(unsigned int i) { 00613 CGAL_expensive_precondition(i< queue_.size()); 00614 while (less_than_parent(i)) { 00615 swap(i, parent(i)); 00616 i=parent(i); 00617 } 00618 } 00620 void bubble(unsigned int i) { 00621 bubble_up(i); 00622 bubble_down(i); 00623 } 00624 00626 bool is_valid() const 00627 { 00628 for (unsigned int i=0; i< queue_.size(); ++i) { 00629 //int bin= i; 00630 int back= queue_[i]->bin(); 00631 CGAL_assertion(static_cast<unsigned int>(back)==i || write(std::cerr)); 00632 CGAL_assertion(!less_than_parent(i) || write(std::cerr)); 00633 //CGAL_assertion(less_than_child(i, FIRST)); 00634 //CGAL_assertion(less_than_child(i, SECOND)); 00635 } 00636 return true; 00637 } 00638 00639 }; 00640 00641 template <class D, bool INF> 00642 std::ostream &operator<<(std::ostream &out, const Heap_pointer_event_queue<D, INF> &q) 00643 { 00644 q.write(out); 00645 return out; 00646 } 00647 00648 00649 CGAL_KINETIC_END_NAMESPACE 00650 #endif