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/Default_simulator.h $ 00016 // $Id: Default_simulator.h 45855 2008-09-29 16:59:08Z drussel $ 00017 // 00018 // 00019 // Author(s) : Daniel Russel <drussel@alumni.princeton.edu> 00020 00021 #ifndef CGAL_KINETIC_SIMULATOR_BASE_H_ 00022 #define CGAL_KINETIC_SIMULATOR_BASE_H_ 00023 #include <CGAL/Kinetic/basic.h> 00024 #include <CGAL/Kinetic/Heap_pointer_event_queue.h> 00025 #include <vector> 00026 #include <CGAL/Interval_arithmetic.h> 00027 #include <CGAL/Kinetic/Ref_counted.h> 00028 #include <CGAL/Kinetic/Multi_listener.h> 00029 00030 CGAL_KINETIC_BEGIN_NAMESPACE; 00031 00032 #ifdef CGAL_KINETIC_CHECK_EXPENSIVE 00033 #ifndef CGAL_KINETIC_DISABLE_AUDITING 00034 #define CGAL_KINETIC_ENABLE_AUDITING 00035 #endif 00036 //#warning Kinetic data structures will be audited at run time. 00037 #endif 00038 00039 00041 00080 template <class Polynomial_kernel_t, 00081 class Queue= CGAL::Kinetic::Heap_pointer_event_queue<Polynomial_kernel_t> > 00082 class Default_simulator: public Ref_counted<Default_simulator<Polynomial_kernel_t, Queue> > 00083 { 00084 protected: 00085 typedef Default_simulator<Polynomial_kernel_t, Queue> This; 00086 //typedef typename Polynomial_kernel_t::Function Poly; 00087 00088 00089 00090 typedef typename Queue::Priority Queue_time; 00091 00092 public: 00093 //typedef Kinetic_kernel_t Kinetic_kernel; 00095 00099 typedef Polynomial_kernel_t Function_kernel; 00100 00102 //typedef typename Function_kernel::Root_stack Root_stack; 00103 00105 00109 typedef typename Function_kernel::Root Time; 00110 00112 00116 //#ifdef NDEBUG 00117 typedef typename Queue::Key Event_key; 00118 /*#else 00119 typedef typename Queue::Key Queue_key; 00120 struct Event_key: public Queue_key { 00121 Event_key(){} 00122 Event_key(Queue_key k): Queue_key(k){} 00123 }; 00124 #endif*/ 00125 00127 typedef typename Function_kernel::FT NT; 00128 00130 Default_simulator(const Time &start_time, 00131 const Time &end_time, 00132 Function_kernel fk=Function_kernel()):queue_(start_time, end_time, fk, 100), 00133 cur_time_(start_time), 00134 //last_event_time_(start_time), 00135 mp_(fk.rational_between_roots_object()), 00136 //ir_(fk.is_rational_object()), 00137 //tr_(fk.to_rational_object()), 00138 is_forward_(true) { 00139 number_of_events_=0; 00140 #ifdef CGAL_KINETIC_ENABLE_AUDITING 00141 // make it less than the current time. 00142 //std::pair<double, double> ival= to_interval(cur_time_); 00143 //audit_time_=NT(ival.first-10.0); 00144 audit_time_= CGAL::to_interval(start_time).second; 00145 #endif 00146 }; 00147 00148 Default_simulator(const Time &start_time, 00149 Function_kernel fk=Function_kernel()):queue_(start_time, fk, 100), 00150 cur_time_(start_time), 00151 //last_event_time_(start_time), 00152 mp_(fk.rational_between_roots_object()), 00153 //ir_(fk.is_rational_object()), 00154 //tr_(fk.to_rational_object()), 00155 is_forward_(true) { 00156 number_of_events_=0; 00157 #ifdef CGAL_KINETIC_ENABLE_AUDITING 00158 // make it less than the current time. 00159 //std::pair<double, double> ival= to_interval(cur_time_); 00160 //audit_time_=NT(ival.first-10.0); 00161 audit_time_= CGAL::to_interval(start_time).second; 00162 #endif 00163 }; 00164 00166 00170 CGAL_GET(Time, current_time, return cur_time_); 00171 00173 00178 void set_current_time(const Time &t) { 00179 CGAL_precondition_code(CGAL::Comparison_result debug_cr 00180 =CGAL::compare(t, cur_time_)); 00181 CGAL_precondition(debug_cr != CGAL::SMALLER); 00182 /*#ifdef CGAL_KINETIC_CHECK_EXPENSIVE 00183 if (current_time() < audit_time_ && t >= audit_time_) { 00184 audit_all_kdss(); 00185 } 00186 #endif*/ 00187 while (CGAL::compare(next_event_time(), t) == CGAL::SMALLER 00188 && !queue_.empty()) { 00189 //Time net= next_event_time(); 00190 //CGAL::Comparison_result cr= CGAL::compare(next_event_time(), t); 00191 process_next_event(); 00192 /*#ifdef CGAL_KINETIC_CHECK_EXPENSIVE 00193 if (current_time() < audit_time_ && t >= audit_time_) { 00194 audit_all_kdss(); 00195 } 00196 cur_time_=audit_time_; 00197 #endif*/ 00198 } 00199 if (queue_.is_after_end(t)) { 00200 cur_time_= queue_.end_priority(); 00201 } else { 00202 cur_time_=t; 00203 } 00204 00205 } 00206 00208 void set_interval(const Time &ts, const Time &te) { 00209 //CGAL_precondition(t <=cur_time_); 00210 if (!queue_.empty()) { 00211 std::cerr << queue_ << std::endl; 00212 } 00213 CGAL_precondition(queue_.empty()); 00214 cur_time_=ts; 00215 //last_event_time_=ts; 00216 queue_.set_interval(ts, te); 00217 } 00218 00220 00224 NT next_time_representable_as_nt() const 00225 { 00226 // why did I have this? "&& cur_time_ != end_time()" 00227 double ub= to_interval(current_time()).second; 00228 if (CGAL::compare(current_time(), next_event_time()) == CGAL::EQUAL 00229 || CGAL::compare(Time(ub), next_event_time()) == CGAL::SMALLER) { 00230 return NT(ub); 00231 } else { 00232 //typename Function_kernel::Rational_between_roots bet= kernel_.rational_between_roots_object(); 00233 if (current_time() == end_time()) { 00234 // really, I do want last_event, but I removed it :-( 00235 std::pair<double,double> ti= CGAL::to_interval(end_time()); 00236 if (ti.first == ti.second) { 00237 return NT(ti.first); 00238 } else { 00239 std::cerr << "You cannot currently call this function at the end of time if the end time is not" 00240 "exactly representable as a double. Sorry. This is fixable, so complain to me--Daniel" << std::endl; 00241 CGAL_error(); 00242 return NT(ti.first); 00243 } 00244 } else { 00245 return mp_(current_time(), next_event_time()); 00246 } 00247 } 00248 } 00249 00250 00252 00255 bool has_audit_time() const 00256 { 00257 #ifdef CGAL_KINETIC_ENABLE_AUDITING 00258 return CGAL::compare(Time(audit_time_), current_time()) != CGAL::SMALLER; 00259 #else 00260 return false; 00261 #endif 00262 } 00263 00264 const NT& audit_time() const 00265 { 00266 CGAL_precondition(has_audit_time()); 00267 #ifdef CGAL_KINETIC_ENABLE_AUDITING 00268 CGAL_precondition(queue_.empty() || Time(audit_time_) < next_event_time()); 00269 return audit_time_; 00270 #else 00271 CGAL_precondition(0); 00272 static NT z(0); 00273 return z; 00274 #endif 00275 } 00276 00278 00281 CGAL_GETNR(Time, next_event_time, return queue_.empty()? 00282 end_time(): Time(queue_.front_priority())); 00283 00284 CGAL_GETNR(Event_key, next_event, return queue_.empty()? 00285 Event_key(): queue_.front()); 00286 00288 00291 CGAL_GETNR(Time, end_time, return is_forward_? 00292 queue_.end_priority(): 00293 std::numeric_limits<Time>::infinity() 00294 ); 00295 00297 00301 /*void set_end_time(const Time &t) { 00302 CGAL_precondition(cur_time_==end_time()); 00303 //end_time_= t; 00304 queue_.set_end_priority(t); 00305 }*/ 00306 00308 00314 template <class E> 00315 Event_key new_event(const Time &t, const E& cert) { 00316 //CGAL_precondition(t != Time()); 00317 //CGAL_exactness_precondition(!(t < current_time())); 00318 //if (cert.time() == Time::infinity()) return final_event(); 00319 //CGAL_assertion(cert.time() < end_time()); 00320 //if (0) cert.process(); 00321 //std::cout << "Requested to schedule "; cert->write(std::cout); 00322 //std::cout<< " at time " << t << std::endl; 00323 CGAL_exactness_precondition(CGAL::compare(t, current_time()) != CGAL::SMALLER); 00324 CGAL_precondition(!std::numeric_limits<Time>::has_infinity 00325 || CGAL::compare(t, std::numeric_limits<Time>::infinity()) 00326 == CGAL::SMALLER); 00327 Event_key key= queue_.insert(t, cert); 00328 //write_eventqueue(log().stream(Log::DEBUG)); 00329 //log()->stream(Log::SOME) << key; 00330 //log()->stream(Log::SOME) 00331 00332 CGAL_LOG(Log::SOME, "Created event " << key << std::endl); 00333 //CGAL_LOG(Log::SOME, *this << std::endl); 00334 //if (log()->is_output(Log::LOTS)) write(log()->stream(Log::LOTS)); 00335 00336 #ifdef CGAL_KINETIC_ENABLE_AUDITING 00337 if (CGAL::compare(Time(audit_time_), t) != CGAL::SMALLER && has_audit_time() ) { 00338 compute_audit_time(current_time()); 00339 } 00340 //if (key != null_event()) audit_event(key); 00341 #endif 00342 00343 return key; 00344 //} 00345 } 00346 00347 00349 00352 CGAL_GETNR(Event_key, null_event, return queue_.end_key()); 00353 00354 /*const Event_key& final_event() const { 00355 return queue_.final_event(); 00356 }*/ 00357 00359 00361 template <class E> 00362 Event_key new_final_event(const E &cert) { 00363 // this should be in the simulator anyway, 00364 return queue_.insert(end_time(), cert); 00365 } 00366 00368 00371 void delete_event(const Event_key &k) { 00372 audit_event(k); 00373 //if (k== final_event()) return; 00374 //#ifdef NDEBUG 00375 if (k== null_event() || k== Event_key()) { 00376 return; 00377 } 00378 //#endif 00379 CGAL_LOG(Log::SOME, "Deleting event " << k << std::endl); 00380 queue_.erase(k); 00381 //CGAL_LOG(Log::LOTS , *this); 00382 } 00383 00385 /*template <class E> 00386 struct Event_handle: public Queue::template Event_info<E>::Handle { 00387 Event_handle(typename Queue::template Event_info<E>::Pointer p): Queue::template Event_info<E>::Handle(p) { 00388 } 00389 Event_handle(){} 00390 };*/ 00391 00393 00410 /*template <class Ev> 00411 typename Queue::template Event_pointer<Ev>::Pointer event(const Event_key &k, const Ev& e) const { 00412 CGAL_LOG(Log::LOTS, "Accessing event for key " << k << std::endl); 00413 return queue_.event(k,e); 00414 }*/ 00415 00416 template <class Event_type> 00417 const Event_type& event(const Event_key &k) const 00418 { 00419 CGAL_precondition(k != Event_key()); 00420 CGAL_precondition(k != null_event()); 00421 //CGAL_LOG(Log::LOTS, "Accessing event for key " << k << std::endl); 00422 return queue_.template get<Event_type>(k); 00423 } 00424 00425 00426 template <class Event_type> 00427 Event_type& event(const Event_key &k){ 00428 CGAL_precondition(k != Event_key()); 00429 CGAL_precondition(k != null_event()); 00430 //CGAL_LOG(Log::LOTS, "Accessing event for key " << k << std::endl); 00431 return queue_.template get<Event_type>(k); 00432 } 00433 00434 /*template <class Event_type> 00435 const Event_type& event(const Event_key &k, const Event_type&) const { 00436 CGAL_LOG(Log::LOTS, "Accessing event for key " << k << std::endl); 00437 return queue_.template get<Event_type>(k); 00438 }*/ 00439 00441 const Time &event_time(const Event_key &k) const 00442 { 00443 CGAL_precondition(k != Event_key()); 00444 return queue_.priority(k); 00445 } 00446 00448 00450 template <class Ev> 00451 Event_key set_event(const Event_key &k, const Ev& ev) { 00452 CGAL_LOG(Log::SOME, "Changed event " << k << std::flush); 00453 Event_key rk= queue_.set(k, ev); 00454 CGAL_LOG(Log::SOME, " to event " << rk << std::endl); 00455 CGAL_LOG(Log::LOTS, *this); 00456 return rk; 00457 } 00458 00460 00463 void set_direction_of_time(Sign sn); 00464 00466 CGAL_GETNR(CGAL::Sign, direction_of_time, return is_forward_? 00467 CGAL::POSITIVE: CGAL::NEGATIVE); 00468 00470 CGAL_GETNR(unsigned int, current_event_number, return number_of_events_); 00471 00472 00473 bool empty() const { 00474 return queue_.empty(); 00475 } 00476 00478 00481 CGAL_SET(unsigned int, current_event_number, 00482 while (!queue_.empty() && number_of_events_ < k) { 00483 /*#ifdef CGAL_KINETIC_CHECK_EXPENSIVE 00484 if (current_time() < audit_time_ && next_event_time() >= audit_time_) { 00485 audit_all_kdss(); 00486 } 00487 #endif*/ 00488 process_next_event(); 00489 } 00490 ); 00491 00492 std::ostream& write(std::ostream &out) const 00493 { 00494 out << "Simulator: (" << to_double(current_time()) 00495 << "..." << to_double(end_time()) << ")\n"; 00496 out << queue_ << std::endl; 00497 return out; 00498 } 00499 00500 void print() const 00501 { 00502 write(std::cout); 00503 } 00504 00505 void clear() { 00506 queue_.clear(); 00507 } 00508 00509 void audit_events() const { 00510 queue_.audit_events(); 00511 } 00512 00513 void audit_event(Event_key k) const { 00514 if (k!= null_event()) { 00515 CGAL_assertion(k != Event_key()); 00516 #ifndef NDEBUG 00517 if (!queue_.contains(k)) { 00518 CGAL_ERROR("Event " << k << " is not in queue."); 00519 } 00520 #endif 00521 CGAL_assertion(queue_.contains(k)); 00522 queue_.audit_event(k); 00523 } 00524 } 00525 00526 Event_key current_event() const { 00527 return cur_event_; 00528 } 00529 00530 protected: 00531 00532 template <class Root> 00533 bool compute_audit_time(const Root &) { 00534 #ifdef CGAL_KINETIC_ENABLE_AUDITING 00535 00536 if (current_time() == end_time() 00537 && end_time() == std::numeric_limits<Time>::infinity()) { 00538 return false; 00539 } 00540 if (queue_.empty()) { 00541 if (cur_time_ != end_time()) { 00542 std::pair<double,double> ei= CGAL::to_interval(end_time()); 00543 if (cur_time_ > Time(ei.first)) { 00544 return false; 00545 } 00546 else { 00547 audit_time_=ei.first; 00548 return true; 00549 } 00550 00551 } else { 00552 // bad form to just return like that 00553 audit_time_= NT(CGAL::to_interval(current_time()).first-10.0); 00554 return false; 00555 } 00556 } else { 00557 audit_time_= CGAL::to_interval(current_time()).second; 00558 if (CGAL::compare(Time(audit_time_), next_event_time()) != CGAL::SMALLER) { 00559 if(CGAL::compare(next_event_time(), current_time()) != CGAL::EQUAL) { 00560 audit_time_= mp_(current_time(), next_event_time()); 00561 return true; 00562 } else { 00563 audit_time_= CGAL::to_interval(current_time()).first -10; 00564 return false; 00565 } 00566 } else { 00567 return true; 00568 } 00569 } 00570 #else 00571 return false; 00572 #endif 00573 } 00574 00575 00576 00577 bool compute_audit_time(double) { 00578 #ifdef CGAL_KINETIC_ENABLE_AUDITING 00579 //bool audit_on_doubles; 00580 if (next_event_time()-current_time() < .1) return false; 00581 else { 00582 audit_time_= (current_time()+ next_event_time())/2.0; 00583 return audit_time_ > current_time() && audit_time_ < next_event_time(); 00584 } 00585 #else 00586 return false; 00587 #endif 00588 } 00589 00591 00594 //NT compute_free_time() const; 00595 00597 void process_next_event() { 00598 CGAL_LOG(Log::LOTS, *this); 00599 /*#ifndef NDEBUG 00600 if (cur_time_ < audit_time_){ 00601 audit_all_kdss(); 00602 } 00603 #endif*/ 00604 /*#ifdef CGAL_KINETIC_ENABLE_AUDITING 00605 if (CGAL::compare(next_event_time(), current_time()) != CGAL::EQUAL) { 00606 //typename Function_kernel::Rational_between_roots bet= kernel_.rational_between_roots_object(); 00607 CGAL_LOG(Log::SOME, "Audit is at time " << audit_time_ << std::endl); 00608 //if (current_time() < audit_time_ && t >= audit_time_) { 00609 audit_all_kdss(); 00610 //} 00611 } else { 00612 CGAL_LOG(Log::SOME, "Can't audit between events.\n"); 00613 } 00614 #endif*/ 00615 00616 CGAL_precondition(!queue_.empty()); 00617 CGAL_exactness_precondition(CGAL::compare(next_event_time(),current_time()) 00618 != CGAL::SMALLER); 00619 //if (CGAL::compare(next_event_time(),cur_time_) == CGAL::LARGER) { 00620 cur_time_= next_event_time(); 00621 cur_event_= queue_.front(); 00622 CGAL_LOG(Log::LOTS, "Processing event at time " << cur_time_ << std::endl); 00623 queue_.process_front(); 00624 ++number_of_events_; 00625 cur_event_= Event_key(); 00626 00627 CGAL_LOG(Log::LOTS, *this); 00628 00629 #ifdef CGAL_KINETIC_ENABLE_AUDITING 00630 if (compute_audit_time(Time())) { 00631 CGAL_LOG(Log::SOME, "Audit is at time " << audit_time_ << std::endl); 00632 //if (current_time() < audit_time_ && t >= audit_time_) { 00633 audit_all_kdss(); 00634 } 00635 #endif 00636 } 00637 00638 void audit_all_kdss() ; 00639 00640 00641 00642 /*struct Listener_core 00643 { 00644 typedef typename This::Handle Notifier_handle; 00645 typedef enum {} 00646 Notification_type; 00647 };*/ 00648 CGAL_KINETIC_MULTILISTENER2(HAS_AUDIT_TIME, DIRECTION_OF_TIME); 00649 00650 protected: 00651 Queue queue_; 00652 Time cur_time_; //, last_event_time_; 00653 unsigned int number_of_events_; 00654 typename Function_kernel::Rational_between_roots mp_; 00655 // typename Function_kernel::Is_rational ir_; 00656 // typename Function_kernel::To_rational tr_; 00657 bool is_forward_; 00658 Event_key cur_event_; 00659 #ifdef CGAL_KINETIC_ENABLE_AUDITING 00660 NT audit_time_; 00661 #endif 00662 }; 00663 00664 /*template <class S, bool E, class PQ> 00665 typename Default_simulator<S, E, PQ>::NT Default_simulator<S, E, PQ>::compute_free_time() const { 00666 if (!(last_time_ < next_event_time())) { 00667 std::cerr << "No time between " << current_time() << " and " << next_event_time() << std::endl; 00668 return current_time_nt()- CGAL::abs(current_time_nt()); 00669 } else { 00670 if (current_time() != last_time_){ 00671 double dt= CGAL::to_double(current_time()); 00672 NT ntdt(dt); 00673 Time tdt(ntdt); 00674 if (tdt > last_time_ && tdt < next_event_time()) return NT(dt); 00675 } 00676 00677 return mp_(current_time(), next_event_time()); 00678 } 00679 }*/ 00680 00681 template <class S, class PQ> 00682 void Default_simulator<S, PQ>::set_direction_of_time(CGAL::Sign dir) 00683 { 00684 if (dir != direction_of_time()) { 00685 while (next_event_time() == current_time()) { 00686 std::cerr << "Processing event in order to reverse time.\n"; 00687 process_next_event(); 00688 } 00689 00690 Time oct= cur_time_; 00691 NT tnt= NT(to_interval(cur_time_).second);// was CGAL:: 00692 00693 Time tdt(tnt); 00694 if (tdt == cur_time_) { 00695 tnt= tnt+ NT(.000001); 00696 tdt= Time(tnt); 00697 } 00698 00699 if (CGAL::compare(tdt, next_event_time()) != CGAL::SMALLER) { 00700 //typename Function_kernel::Rational_between_roots rbr= kernel_.rational_between_roots_object(); 00701 tnt= mp_(cur_time_, next_event_time()); 00702 tdt= Time(tnt); 00703 } 00704 00705 cur_time_= Time(-tnt); 00706 00707 is_forward_= !is_forward_; 00708 //end_time_=-end_time_; 00709 //last_event_time_= -std::numeric_limits<Time>::infinity(); 00710 CGAL_LOG(Log::SOME, "Current time is " << cur_time_ << " and was " << oct 00711 << ", end_time() is " << end_time() << std::endl); 00712 CGAL_KINETIC_MULTINOTIFY(DIRECTION_OF_TIME); 00713 } 00714 else { 00715 CGAL_LOG(Log::SOME, dir << " " << end_time() << " " << cur_time_ << std::endl); 00716 } 00717 } 00718 00719 00720 template <class S, class PQ> 00721 void Default_simulator<S, PQ>::audit_all_kdss() 00722 { 00723 #ifdef CGAL_KINETIC_ENABLE_AUDITING 00724 cur_time_= Time(audit_time_); 00725 CGAL_LOG(Log::SOME, "Auditing KDSs at time " << audit_time() << std::endl); 00726 CGAL_KINETIC_MULTINOTIFY(HAS_AUDIT_TIME); 00727 queue_.audit_events(); 00728 #endif 00729 } 00730 00731 00732 00733 CGAL_OUTPUT2(Default_simulator); 00734 00735 00736 CGAL_KINETIC_END_NAMESPACE; 00737 #endif