Main Page | Class Hierarchy | Class List | File List | Class Members

/home/nutarojj/Desktop/adevs/include/adevs_simulator.h

00001 /***************
00002 Copyright (C) 2000-2008 by James Nutaro
00003 
00004 This library is free software; you can redistribute it and/or
00005 modify it under the terms of the GNU Lesser General Public
00006 License as published by the Free Software Foundation; either
00007 version 2 of the License, or (at your option) any later version.
00008 
00009 This library is distributed in the hope that it will be useful,
00010 but WITHOUT ANY WARRANTY; without even the implied warranty of
00011 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00012 Lesser General Public License for more details.
00013 
00014 You should have received a copy of the GNU Lesser General Public
00015 License along with this library; if not, write to the Free Software
00016 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
00017 
00018 Bugs, comments, and questions can be sent to nutaro@gmail.com
00019 ***************/
00020 #ifndef __adevs_simulator_h_
00021 #define __adevs_simulator_h_
00022 #include "adevs_abstract_simulator.h"
00023 #include "adevs_models.h"
00024 #include "adevs_event_listener.h"
00025 #include "adevs_sched.h"
00026 #include "adevs_bag.h"
00027 #include "adevs_set.h"
00028 #include "object_pool.h"
00029 #include "adevs_lp.h"
00030 #include <cassert>
00031 #include <cstdlib>
00032 #include <iostream>
00033 #include <vector>
00034 
00035 namespace adevs
00036 {
00037 
00044 template <class X> class Simulator:
00045         public AbstractSimulator<X>
00046 {
00047         public:
00053                 Simulator(Devs<X>* model):
00054                         AbstractSimulator<X>(),lp(NULL)
00055                 {
00056                         schedule(model,0.0);
00057                 }
00059                 double nextEventTime()
00060                 {
00061                         return sched.minPriority();
00062                 }
00064                 void execNextEvent()
00065                 {
00066                         computeNextOutput();
00067                         computeNextState(bogus_input,sched.minPriority());
00068                 }
00070                 void execUntil(double tend)
00071                 {
00072                         while (nextEventTime() <= tend && nextEventTime() < DBL_MAX)
00073                                 execNextEvent();
00074                 }
00082                 void computeNextOutput();
00089                 void computeNextState(Bag<Event<X> >& input, double t);
00095                 ~Simulator();
00100                 void addModel(Atomic<X>* model) 
00101                 {
00102                         schedule(model,0.0);
00103                 }
00108                 Simulator(LogicalProcess<X>* lp):
00109                         AbstractSimulator<X>(),lp(lp)
00110                 {
00111                 }
00112         private:
00114                 LogicalProcess<X>* lp;
00116                 Bag<Event<X> > bogus_input;
00118                 Schedule<X> sched;
00120                 Bag<Atomic<X>*> imm;
00122                 Bag<Atomic<X>*> activated;
00124                 object_pool<Bag<X> > io_pool;
00125                 object_pool<Bag<Event<X> > > recv_pool;
00126                 // Sets for computing structure changes.
00127                 Set<Devs<X>*> added;
00128                 Set<Devs<X>*> removed;
00129                 Set<Devs<X>*> next;
00130                 Set<Devs<X>*> prev;
00131                 // Model transition functions are evaluated from the bottom up!
00132                 struct bottom_to_top_depth_compare
00133                 {
00134                         bool operator()(const Network<X>* m1, const Network<X>* m2) const
00135                         {
00136                                 unsigned long int d1 = 0, d2 = 0;
00137                                 // Compute depth of m1
00138                                 const Network<X>* m = m1->getParent();
00139                                 while (m != NULL) 
00140                                 {
00141                                         d1++;
00142                                         m = m->getParent();
00143                                 }
00144                                 // Compute depth of m2
00145                                 m = m2->getParent();
00146                                 while (m != NULL)
00147                                 {
00148                                         d2++;
00149                                         m = m->getParent();
00150                                 }
00151                                 // Models at the same depth are sorted by name
00152                                 if (d1 == d2) return m1 < m2;
00153                                 // Otherwise, sort by depth
00154                                 return d1 > d2;
00155                         }
00156                 };
00157                 struct top_to_bottom_depth_compare
00158                 {
00159                         bool operator()(const Devs<X>* m1, const Devs<X>* m2) const
00160                         {
00161                                 unsigned long int d1 = 0, d2 = 0;
00162                                 // Compute depth of m1
00163                                 const Network<X>* m = m1->getParent();
00164                                 while (m != NULL) 
00165                                 {
00166                                         d1++;
00167                                         m = m->getParent();
00168                                 }
00169                                 // Compute depth of m2
00170                                 m = m2->getParent();
00171                                 while (m != NULL)
00172                                 {
00173                                         d2++;
00174                                         m = m->getParent();
00175                                 }
00176                                 // Models at the same depth are sorted by name
00177                                 if (d1 == d2) return m1 < m2;
00178                                 // Otherwise, sort by depth
00179                                 return d1 < d2;
00180                         }
00181                 };
00182                 std::set<Network<X>*,bottom_to_top_depth_compare> model_func_eval_set;
00183                 std::set<Devs<X>*,top_to_bottom_depth_compare> sorted_removed;
00188                 void schedule(Devs<X>* model, double t);
00190                 void route(Network<X>* parent, Devs<X>* src, X& x);
00195                 void inject_event(Atomic<X>* model, X& value);
00200                 void unschedule_model(Devs<X>* model);
00206                 void clean_up(Devs<X>* model);
00212                 void exec_event(Atomic<X>* model, bool internal, double t);
00216                 void getAllChildren(Network<X>* model, Set<Devs<X>*>& s);
00217 };
00218 
00219 template <class X>
00220 void Simulator<X>::computeNextOutput()
00221 {
00222         // If the imminent set is up to date, then just return
00223         if (imm.empty() == false) return;
00224         // Get the imminent models from the schedule. This sets the active flags.
00225         sched.getImminent(imm);
00226         // Compute output functions and route the events. The bags of output
00227         // are held for garbage collection at a later time.
00228         for (typename Bag<Atomic<X>*>::iterator imm_iter = imm.begin(); 
00229                 imm_iter != imm.end(); imm_iter++)
00230         {
00231                 Atomic<X>* model = *imm_iter;
00232                 // If the output for this model has already been computed, then skip it
00233                 if (model->y == NULL)
00234                 {
00235                         model->y = io_pool.make_obj();
00236                         model->output_func(*(model->y));
00237                         // Route each event in y
00238                         for (typename Bag<X>::iterator y_iter = model->y->begin(); 
00239                         y_iter != model->y->end(); y_iter++)
00240                         {
00241                                 route(model->getParent(),model,*y_iter);
00242                         }
00243                 }
00244         }
00245 }
00246 
00247 template <class X>
00248 void Simulator<X>::computeNextState(Bag<Event<X> >& input, double t)
00249 {
00250         // Clean up if there was a previous IO calculation
00251         if (t < sched.minPriority())
00252         {
00253                 typename Bag<Atomic<X>*>::iterator iter;
00254                 for (iter = activated.begin(); iter != activated.end(); iter++)
00255                 {
00256                         clean_up(*iter);
00257                 }
00258                 activated.clear();
00259                 for (iter = imm.begin(); iter != imm.end(); iter++)
00260                 {
00261                         clean_up(*iter);
00262                 }
00263                 imm.clear();
00264         }
00265         // Otherwise, if the internal IO needs to be computed, do it
00266         else if (t == sched.minPriority() && imm.empty())
00267         {
00268                 computeNextOutput();
00269         }
00270         // Apply the injected inputs
00271         for (typename Bag<Event<X> >::iterator iter = input.begin(); 
00272         iter != input.end(); iter++)
00273         {
00274                 Atomic<X>* amodel = (*iter).model->typeIsAtomic();
00275                 if (amodel != NULL)
00276                 {
00277                         inject_event(amodel,(*iter).value);
00278                 }
00279                 else
00280                 {
00281                         route((*iter).model->typeIsNetwork(),(*iter).model,(*iter).value);
00282                 }
00283         }
00284         /*
00285         Compute the states of atomic models.  Store Network models that need to have
00286         their model transition function evaluated in a
00287         special container that will be used when the structure changes are
00288         computed (see exec_event(.)).
00289         */
00290         for (typename Bag<Atomic<X>*>::iterator iter = imm.begin(); 
00291         iter != imm.end(); iter++)
00292         {
00293                 exec_event(*iter,true,t); // Internal and confluent transitions
00294         }
00295         for (typename Bag<Atomic<X>*>::iterator iter = activated.begin(); 
00296         iter != activated.end(); iter++)
00297         {
00298                 exec_event(*iter,false,t); // External transitions
00299         }
00306         if (model_func_eval_set.empty() == false)
00307         {
00308                 while (!model_func_eval_set.empty())
00309                 {
00310                         Network<X>* network_model = *(model_func_eval_set.begin());
00311                         getAllChildren(network_model,prev);
00312                         if (network_model->model_transition() && network_model->getParent() != NULL)
00313                         {
00314                                 model_func_eval_set.insert(network_model->getParent());
00315                         }
00316                         getAllChildren(network_model,next);
00317                         model_func_eval_set.erase(network_model);
00318                 }
00319                 // Find the set of models that were added.
00320                 set_assign_union(added,set_difference(next,prev));
00321                 // Find the set of models that were removed
00322                 set_assign_union(removed,set_difference(prev,next));
00323                 next.clear();
00324                 prev.clear();
00325                 // Any models that moved from one network to another should be left alone.
00326                 Set<Devs<X>*> moved(set_intersect(removed,added));
00327                 for (typename Set<Devs<X>*>::iterator iter = moved.begin();
00328                 iter != moved.end(); iter++)
00329                 {
00330                         typename Set<Devs<X>*>::iterator iter_tmp = added.find(*iter);
00331                         if (iter_tmp != added.end()) added.erase(iter_tmp);
00332                         iter_tmp = removed.find(*iter);
00333                         if (iter_tmp != removed.end()) removed.erase(iter_tmp);
00334                 }
00341                 for (typename Set<Devs<X>*>::iterator iter = added.begin(); 
00342                         iter != added.end(); iter++)
00343                 {
00344                         schedule(*iter,t);
00345                 }
00346                 // Done with the additions
00347                 added.clear();
00348                 // Remove the models that are in the removed set.
00349                 for (typename Set<Devs<X>*>::iterator iter = removed.begin(); 
00350                         iter != removed.end(); iter++)
00351                 {
00352                         clean_up(*iter);
00353                         unschedule_model(*iter);
00354                         sorted_removed.insert(*iter); // Add to a sorted remove set for deletion
00355                 }
00356                 // Done with the unsorted remove set
00357                 removed.clear();
00358                 // Delete the sorted removed models
00359                 while (!sorted_removed.empty())
00360                 {
00361                         // Get the model to erase
00362                         Devs<X>* model_to_remove = *(sorted_removed.begin());
00367                         if (model_to_remove->typeIsNetwork() != NULL)
00368                         {
00369                                 getAllChildren(model_to_remove->typeIsNetwork(),removed);
00370                                 for (typename Set<Devs<X>*>::iterator iter = removed.begin(); 
00371                                         iter != removed.end(); iter++)
00372                                 {
00373                                         sorted_removed.erase(*iter);
00374                                 }
00375                                 removed.clear();
00376                         }
00377                         // Remove the model
00378                         sorted_removed.erase(sorted_removed.begin());
00379                         // Delete the model and its children
00380                         delete model_to_remove;
00381                 }
00382                 // Removed sets should be empty now
00383                 assert(removed.empty());
00384                 assert(sorted_removed.empty());
00385         } // End of the structure change
00386         // Cleanup and reschedule models that changed state in this iteration
00387         // and survived the structure change phase.
00388         for (typename Bag<Atomic<X>*>::iterator iter = imm.begin(); // Schedule the imminents
00389         iter != imm.end(); iter++)
00390         {
00391                 clean_up(*iter);
00392                 schedule(*iter,t);
00393         }
00394         for (typename Bag<Atomic<X>*>::iterator iter = activated.begin(); // Schedule the activated
00395         iter != activated.end(); iter++)
00396         {
00397                 clean_up(*iter);
00398                 schedule(*iter,t);
00399         }
00400         // Empty the bags
00401         imm.clear();
00402         activated.clear();
00403 }
00404 
00405 template <class X>
00406 void Simulator<X>::clean_up(Devs<X>* model)
00407 {
00408         Atomic<X>* amodel = model->typeIsAtomic();
00409         if (amodel != NULL)
00410         {
00411                 amodel->active = false;
00412                 if (amodel->x != NULL)
00413                 {
00414                         amodel->x->clear();
00415                         io_pool.destroy_obj(amodel->x);
00416                         amodel->x = NULL;
00417                 }
00418                 if (amodel->y != NULL)
00419                 {
00420                         amodel->gc_output(*(amodel->y));
00421                         amodel->y->clear();
00422                         io_pool.destroy_obj(amodel->y);
00423                         amodel->y = NULL;
00424                 }
00425         }
00426         else
00427         {
00428                 Set<Devs<X>*> components;
00429                 model->typeIsNetwork()->getComponents(components);
00430                 for (typename Set<Devs<X>*>::iterator iter = components.begin();
00431                 iter != components.end(); iter++)
00432                 {
00433                         clean_up(*iter);
00434                 }
00435         }
00436 }
00437 
00438 template <class X>
00439 void Simulator<X>::unschedule_model(Devs<X>* model)
00440 {
00441         if (model->typeIsAtomic() != NULL)
00442         {
00443                 sched.schedule(model->typeIsAtomic(),DBL_MAX);
00444                 imm.erase(model->typeIsAtomic());
00445                 activated.erase(model->typeIsAtomic());
00446         }
00447         else
00448         {
00449                 Set<Devs<X>*> components;
00450                 model->typeIsNetwork()->getComponents(components);
00451                 for (typename Set<Devs<X>*>::iterator iter = components.begin();
00452                 iter != components.end(); iter++)
00453                 {
00454                         unschedule_model(*iter);
00455                 }
00456         }
00457 }
00458 
00459 template <class X>
00460 void Simulator<X>::schedule(Devs<X>* model, double t)
00461 {
00462         Atomic<X>* a = model->typeIsAtomic();
00463         if (a != NULL)
00464         {
00465                 a->tL = t;
00466                 double dt = a->ta();
00467                 if (dt < 0.0)
00468                 {
00469                         exception err("Negative time advance",a);
00470                         throw err;
00471                 }
00472                 if (dt == DBL_MAX)
00473                         sched.schedule(a,DBL_MAX);
00474                 else
00475                         sched.schedule(a,t+dt);
00476         }
00477         else
00478         {
00479                 Set<Devs<X>*> components;
00480                 model->typeIsNetwork()->getComponents(components);
00481                 typename Set<Devs<X>*>::iterator iter = components.begin();
00482                 for (; iter != components.end(); iter++)
00483                 {
00484                         schedule(*iter,t);
00485                 }
00486         }
00487 }
00488 
00489 template <class X>
00490 void Simulator<X>::inject_event(Atomic<X>* model, X& value)
00491 {
00492         if (model->active == false)
00493         {
00494                 model->active = true;
00495                 activated.insert(model);
00496         }
00497         if (model->x == NULL)
00498         {
00499                 model->x = io_pool.make_obj();
00500         }
00501         model->x->insert(value);
00502 }
00503 
00504 template <class X>
00505 void Simulator<X>::route(Network<X>* parent, Devs<X>* src, X& x)
00506 {
00507         // Notify event listeners if this is an output event
00508         if (parent != src)
00509                 notify_output_listeners(src,x,sched.minPriority());
00510         // No one to do the routing, so return
00511         if (parent == NULL) return;
00512         // Compute the set of receivers for this value
00513         Bag<Event<X> >* recvs = recv_pool.make_obj();
00514         parent->route(x,src,*recvs);
00515         // Deliver the event to each of its targets
00516         Atomic<X>* amodel = NULL;
00517         typename Bag<Event<X> >::iterator recv_iter = recvs->begin();
00518         for (; recv_iter != recvs->end(); recv_iter++)
00519         {
00520                 // Check for self-influencing error condition
00521                 if (src == (*recv_iter).model)
00522                 {
00523                         exception err("Model tried to influence self",src);
00524                         throw err;
00525                 }
00530                 amodel = (*recv_iter).model->typeIsAtomic();
00531                 if (amodel != NULL)
00532                 {
00533                         // Inject it only if it is assigned to our processor
00534                         if (lp == NULL || amodel->getProc() == lp->getID())
00535                                 inject_event(amodel,(*recv_iter).value);
00536                         // Otherwise tell the lp about it
00537                         else lp->notifyInput(amodel,(*recv_iter).value);
00538                 }
00539                 // if this is an external output from the parent model
00540                 else if ((*recv_iter).model == parent)
00541                 {
00542                         route(parent->getParent(),parent,(*recv_iter).value);
00543                 }
00544                 // otherwise it is an input to a coupled model
00545                 else
00546                 {
00547                         route((*recv_iter).model->typeIsNetwork(),
00548                         (*recv_iter).model,(*recv_iter).value);
00549                 }
00550         }
00551         recvs->clear();
00552         recv_pool.destroy_obj(recvs);
00553 }
00554 
00555 template <class X>
00556 void Simulator<X>::exec_event(Atomic<X>* model, bool internal, double t)
00557 {
00558         // Compute the state change
00559         if (model->x == NULL)
00560         {
00561                 model->delta_int();
00562         }
00563         else if (internal)
00564         {
00565                 model->delta_conf(*(model->x));
00566         }
00567         else
00568         {
00569                 model->delta_ext(t-model->tL,*(model->x));
00570         }
00571         // Notify any listeners
00572         notify_state_listeners(model,t);
00573         // Check for a model transition
00574         if (model->model_transition() && model->getParent() != NULL)
00575         {
00576                 model_func_eval_set.insert(model->getParent());
00577         }
00578 }
00579 
00580 template <class X>
00581 void Simulator<X>::getAllChildren(Network<X>* model, Set<Devs<X>*>& s)
00582 {
00583         Set<Devs<X>*> tmp;
00584         // Get the component set
00585         model->getComponents(tmp);
00586         // Find the components of type network and update s recursively
00587         typename Set<Devs<X>*>::iterator iter;
00588         for (iter = tmp.begin(); iter != tmp.end(); iter++)
00589         {
00590                 if ((*iter)->typeIsNetwork() != NULL)
00591                 {
00592                         getAllChildren((*iter)->typeIsNetwork(),s);
00593                 }
00594         }
00595         // Add all of the local level elements to s
00596         for (iter = tmp.begin(); iter != tmp.end(); iter++)
00597         {
00598                 s.insert(*iter);
00599         }
00600 }
00601 
00602 template <class X>
00603 Simulator<X>::~Simulator()
00604 {
00605         // Clean up the models with stale IO
00606         typename Bag<Atomic<X>*>::iterator imm_iter;
00607         for (imm_iter = imm.begin(); imm_iter != imm.end(); imm_iter++)
00608         {
00609                 clean_up(*imm_iter);
00610         }
00611         for (imm_iter = activated.begin(); imm_iter != activated.end(); imm_iter++)
00612         {
00613                 clean_up(*imm_iter);
00614         }
00615 }
00616 
00617 } // End of namespace
00618 
00619 #endif

Generated on Mon Jun 1 09:53:42 2009 for adevs by  doxygen 1.3.9.1