adevs_wrapper.h 8.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208
  1. /**
  2. * Copyright (c) 2013, James Nutaro
  3. * All rights reserved.
  4. *
  5. * Redistribution and use in source and binary forms, with or without
  6. * modification, are permitted provided that the following conditions are met:
  7. *
  8. * 1. Redistributions of source code must retain the above copyright notice, this
  9. * list of conditions and the following disclaimer.
  10. * 2. Redistributions in binary form must reproduce the above copyright notice,
  11. * this list of conditions and the following disclaimer in the documentation
  12. * and/or other materials provided with the distribution.
  13. *
  14. * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
  15. * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
  16. * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
  17. * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
  18. * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
  19. * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
  20. * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
  21. * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
  22. * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
  23. * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  24. *
  25. * The views and conclusions contained in the software and documentation are those
  26. * of the authors and should not be interpreted as representing official policies,
  27. * either expressed or implied, of the FreeBSD Project.
  28. *
  29. * Bugs, comments, and questions can be sent to nutaro@gmail.com
  30. */
  31. #ifndef __adevs_wrapper_h_
  32. #define __adevs_wrapper_h_
  33. #include "adevs_models.h"
  34. namespace adevs
  35. {
  36. /**
  37. * <p>This class wraps a Network or Atomic model with interface type InternalType in an
  38. * Atomic model with interface type ExternalType. Input to the ModelWrapper is passed
  39. * through a user provided input translation method before being handed off
  40. * to the wrapped model for processing. Output from the wrapped model is
  41. * passed through a user provided output translation method before emerging
  42. * as output from the ModelWrapper. If the wrapped model is a Network, the input
  43. * translation method can create inputs for any of its components. Similarly
  44. * the output translation method is provided with every output produced by
  45. * every component in the Network. If the wrapped model is Atomic then there
  46. * is, of course, only one possible destination for incoming events and only
  47. * one source of outgoing events.
  48. * <p>You will need to implement the usual gc_output event for outputs
  49. * produced by the ModelWrapper. You will also need to implement
  50. * gcInputEvents method to clean up events that are created during
  51. * the input translation process.
  52. */
  53. template <typename ExternalType, typename InternalType, class T = double> class ModelWrapper:
  54. public Atomic<ExternalType,T>,
  55. public EventListener<InternalType,T>
  56. {
  57. public:
  58. /**
  59. * Create a wrapper for the specified model. The ModelWrapper takes
  60. * ownership of the supplied model and will delete it when the
  61. * ModelWrapper is deleted.
  62. */
  63. ModelWrapper(Devs<InternalType,T>* model);
  64. /**
  65. * This method is used to translate incoming input objects into
  66. * input objects that the wrapped model can process. The supplied
  67. * internal_input bag should be filled with Events that contain the targeted
  68. * internal models and the values to supply to them. The external_input
  69. * bag contains the input values supplied to the wrapper's external or
  70. * confluent transition function.
  71. */
  72. virtual void translateInput(const Bag<ExternalType>& external_input,
  73. Bag<Event<InternalType,T> >& internal_input) = 0;
  74. /**
  75. * This method is used to translate outgoing output objects
  76. * into objects that the ModelWrapper can produce. The
  77. * internal_output bag contains all of the output events that the
  78. * were produced by the wrapped model. The external_output bag
  79. * should be filled with objects of type ExternalType that
  80. * will be produced as output by the ModelWrapper.
  81. */
  82. virtual void translateOutput(const Bag<Event<InternalType,T> >& internal_output,
  83. Bag<ExternalType>& external_output) = 0;
  84. /**
  85. * This is the garbage collection method for internal input events.
  86. * It will be called when the wrapper is done with a set of events
  87. * that you created with the translateInput method. The supplied bag
  88. * is the same one that you filled out in the translateInput method.
  89. */
  90. virtual void gc_input(Bag<Event<InternalType,T> >& g) = 0;
  91. /// Get the model that is wrapped by this object
  92. Devs<InternalType,T>* getWrappedModel() { return model; }
  93. /// Atomic internal transition function
  94. void delta_int();
  95. /// Atomic external transition function
  96. void delta_ext(T e, const Bag<ExternalType>& xb);
  97. /// Atomic confluent transition function
  98. void delta_conf(const Bag<ExternalType>& xb);
  99. /// Atomic output function
  100. void output_func(Bag<ExternalType>& yb);
  101. /// Atomic time advance function
  102. T ta();
  103. /// EventListener outputEvent method
  104. void outputEvent(Event<InternalType,T> y, T t);
  105. /// Destructor. This destroys the wrapped model too.
  106. ~ModelWrapper();
  107. private:
  108. ModelWrapper(){}
  109. ModelWrapper(const ModelWrapper&){}
  110. void operator=(const ModelWrapper&){}
  111. // Bag of events created by the input translation method
  112. Bag<Event<InternalType,T> > input;
  113. // Output from the wrapped model
  114. Bag<Event<InternalType,T> > output;
  115. // The wrapped model
  116. Devs<InternalType,T>* model;
  117. // Simulator for driving the wrapped model
  118. Simulator<InternalType,T>* sim;
  119. // Last event time
  120. T tL;
  121. };
  122. template <typename ExternalType, typename InternalType, class T>
  123. ModelWrapper<ExternalType,InternalType,T>::ModelWrapper(Devs<InternalType,T>* model):
  124. Atomic<ExternalType,T>(),
  125. EventListener<InternalType,T>(),
  126. model(model),
  127. tL(adevs_zero<T>())
  128. {
  129. sim = new Simulator<InternalType,T>(model);
  130. sim->addEventListener(this);
  131. }
  132. template <typename ExternalType, typename InternalType, class T>
  133. void ModelWrapper<ExternalType,InternalType,T>::delta_int()
  134. {
  135. // Update the internal clock
  136. tL = sim->nextEventTime();
  137. // Execute the next autonomous event for the wrapped model
  138. sim->execNextEvent();
  139. }
  140. template <typename ExternalType, typename InternalType, class T>
  141. void ModelWrapper<ExternalType,InternalType,T>::delta_ext(T e, const Bag<ExternalType>& xb)
  142. {
  143. // Update the internal clock
  144. tL += e;
  145. // Convert the external inputs to internal inputs
  146. translateInput(xb,input);
  147. // Apply the input
  148. sim->computeNextState(input,tL);
  149. // Clean up
  150. gc_input(input);
  151. input.clear();
  152. }
  153. template <typename ExternalType, typename InternalType, class T>
  154. void ModelWrapper<ExternalType,InternalType,T>::delta_conf(const Bag<ExternalType>& xb)
  155. {
  156. // Update the internal clock
  157. tL = sim->nextEventTime();
  158. // Convert the external inputs to internal inputs
  159. translateInput(xb,input);
  160. // Apply the input
  161. sim->computeNextState(input,tL);
  162. // Clean up
  163. gc_input(input);
  164. input.clear();
  165. }
  166. template <typename ExternalType, typename InternalType, class T>
  167. T ModelWrapper<ExternalType,InternalType,T>::ta()
  168. {
  169. if (sim->nextEventTime() < adevs_inf<T>()) return sim->nextEventTime()-tL;
  170. else return adevs_inf<T>();
  171. }
  172. template <typename ExternalType, typename InternalType, class T>
  173. void ModelWrapper<ExternalType,InternalType,T>::output_func(Bag<ExternalType>& yb)
  174. {
  175. // Compute the model's output events; this causes the outputEvent method to be called
  176. sim->computeNextOutput();
  177. // Translate the output events to external output events
  178. translateOutput(output,yb);
  179. // Clean up; the contents of the output bag are deleted by the wrapped model's
  180. // gc_output method
  181. output.clear();
  182. }
  183. template <typename ExternalType, typename InternalType, class T>
  184. void ModelWrapper<ExternalType,InternalType,T>::outputEvent(Event<InternalType,T> y, T t)
  185. {
  186. // Just save the events for processing by the output_func
  187. output.insert(y);
  188. }
  189. template <typename ExternalType, typename InternalType, class T>
  190. ModelWrapper<ExternalType,InternalType,T>::~ModelWrapper()
  191. {
  192. delete sim;
  193. delete model;
  194. }
  195. } // end of namespace
  196. #endif