BWAPI
SPAR/AIModule/BWTA/vendors/CGAL/CGAL/Kinetic/Default_simulator.h
Go to the documentation of this file.
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
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines