StateMachine.hpp 9.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319
  1. /**
  2. * @file utils/StateMachine.hpp
  3. * @author The ARTIS Development Team
  4. * See the AUTHORS or Authors.txt file
  5. */
  6. /*
  7. * ARTIS - the multimodeling and simulation environment
  8. * This file is a part of the ARTIS environment
  9. *
  10. * Copyright (C) 2013-2023 ULCO http://www.univ-littoral.fr
  11. *
  12. * This program is free software: you can redistribute it and/or modify
  13. * it under the terms of the GNU General Public License as published by
  14. * the Free Software Foundation, either version 3 of the License, or
  15. * (at your option) any later version.
  16. *
  17. * This program is distributed in the hope that it will be useful,
  18. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  19. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  20. * GNU General Public License for more details.
  21. *
  22. * You should have received a copy of the GNU General Public License
  23. * along with this program. If not, see <http://www.gnu.org/licenses/>.
  24. */
  25. #ifndef ARTIS_STAR_ADDONS_UTILS_STATE_MACHINE_HPP
  26. #define ARTIS_STAR_ADDONS_UTILS_STATE_MACHINE_HPP
  27. #include <artis-star/common/event/Value.hpp>
  28. #include <map>
  29. #include <memory>
  30. #include <vector>
  31. namespace artis::addons::utils {
  32. template<class Time, class Types, class Parameters, class StateMachineTypes>
  33. class RootStateMachine;
  34. template<class Time, class Types>
  35. class AbstractStateMachine {
  36. public:
  37. struct Event {
  38. int id;
  39. artis::common::event::Value data;
  40. };
  41. struct InternalEvent : Event {
  42. int machine_id;
  43. };
  44. struct ExternalEvent : Event {
  45. };
  46. struct Events {
  47. std::vector <InternalEvent> internals;
  48. std::vector <ExternalEvent> externals;
  49. };
  50. struct AbstractState {
  51. int _id;
  52. AbstractState(int id) : _id(id) {}
  53. virtual typename Time::type ta(const typename Time::type & /* t */) const = 0;
  54. virtual ~AbstractState() = default;
  55. };
  56. template<class Machine>
  57. struct State : AbstractState {
  58. std::shared_ptr <Machine> _machine;
  59. State(int id, const std::shared_ptr <Machine> &machine) :
  60. AbstractState(id), _machine(machine) {}
  61. typename Time::type ta(const typename Time::type & /* t */) const override { return Time::infinity; }
  62. };
  63. struct AbstractTransition {
  64. virtual void action(const typename Time::type & /* t */,
  65. const artis::common::event::Value & /* value */) = 0;
  66. virtual bool event(const typename Time::type & /* t */, int /* event */) = 0;
  67. virtual bool guard(const typename Time::type & /* t */) const = 0;
  68. virtual bool no_event() const = 0;
  69. virtual Events output(const typename Time::type & /* t */) const = 0;
  70. virtual ~AbstractTransition() = default;
  71. };
  72. template<class Machine>
  73. struct Transition : AbstractTransition {
  74. std::shared_ptr <Machine> _machine;
  75. Transition(const std::shared_ptr <Machine> &machine) : _machine(machine) {}
  76. void action(const typename Time::type & /* t */,
  77. const artis::common::event::Value & /* value */) override {}
  78. bool event(const typename Time::type & /* t */,
  79. int /* event */) override { return false; }
  80. bool guard(const typename Time::type & /* t */) const override { return true; }
  81. bool no_event() const override { return false; }
  82. Events output(const typename Time::type & /* t */) const override { return {}; }
  83. };
  84. AbstractStateMachine(const typename Types::root_state_machine_type &root) : _root(root) {}
  85. virtual ~AbstractStateMachine() = default;
  86. // virtual void build(const std::shared_ptr<StateMachine<Types>> &machine) = 0;
  87. const std::unique_ptr <AbstractState> &current_state() const {
  88. return _states.at(_current_state);
  89. }
  90. int current_state(int machine_id) const {
  91. return _root.current_state(machine_id);
  92. }
  93. void initial_state(int state) {
  94. _initial_state = state;
  95. }
  96. bool is_ready(const typename Time::type &t) const {
  97. return std::abs(_sigma - (t - _last_time)) < 1e-6;
  98. }
  99. const typename Types::root_state_machine_type &root() const { return _root; }
  100. void start(const typename Time::type &t) {
  101. _current_state = _initial_state;
  102. _last_time = t;
  103. compute_sigma(t);
  104. }
  105. void state(AbstractState *state) {
  106. _states.insert(std::make_pair(state->_id, std::unique_ptr<AbstractState>(state)));
  107. _transitions.insert(std::make_pair(state->_id, _transitions_type{}));
  108. }
  109. void switch_transition(int state, int next_state, size_t index, AbstractTransition *transition) {
  110. auto it = std::find_if(_transitions[state].begin(), _transitions[state].end(), [next_state](const auto &e) {
  111. return e.second == next_state;
  112. });
  113. assert(it != _transitions[state].end());
  114. while (it + 1 != _transitions[state].end() and index > 0) {
  115. it = std::find_if(it + 1, _transitions[state].end(), [next_state](const auto &e) {
  116. return e.second == next_state;
  117. });
  118. --index;
  119. }
  120. assert(it != _transitions[state].end());
  121. it->first.reset(transition);
  122. }
  123. typename Time::type ta(const typename Time::type & /* t */) const {
  124. return _sigma;
  125. }
  126. void transition(int state, int next_state, AbstractTransition *transition) {
  127. _transitions[state].push_back(std::make_pair(std::unique_ptr<AbstractTransition>(transition), next_state));
  128. }
  129. // without event
  130. Events transition(const typename Time::type &t) {
  131. typename std::map<int, _transitions_type>::const_iterator it = _transitions.find(_current_state);
  132. Events events{};
  133. uint unique = 0;
  134. if (it != _transitions.cend()) {
  135. AbstractTransition *select = nullptr;
  136. int stateID{};
  137. std::for_each(it->second.cbegin(), it->second.cend(),
  138. [t, &unique, &select, &stateID](
  139. const std::pair<std::unique_ptr<AbstractTransition>, int> &e) {
  140. if (e.first->no_event() and e.first->guard(t)) {
  141. select = e.first.get();
  142. stateID = e.second;
  143. ++unique;
  144. }
  145. });
  146. assert(unique <= 1);
  147. if (select != nullptr) {
  148. select->action(t, {});
  149. events = select->output(t);
  150. _current_state = stateID;
  151. compute_sigma(t);
  152. } else {
  153. update_sigma(t);
  154. }
  155. }
  156. return events;
  157. }
  158. // with external event
  159. Events transition(const typename Time::type &t, const ExternalEvent &event) {
  160. typename std::map<int, _transitions_type>::const_iterator it = _transitions.find(_current_state);
  161. Events events{};
  162. uint unique = 0;
  163. if (it != _transitions.cend()) {
  164. AbstractTransition *select = nullptr;
  165. int stateID{};
  166. std::for_each(it->second.cbegin(), it->second.cend(),
  167. [t, event, &unique, &select, &stateID](
  168. const std::pair<std::unique_ptr<AbstractTransition>, int> &e) {
  169. if (e.first->guard(t) and e.first->event(t, event.id)) {
  170. select = e.first.get();
  171. stateID = e.second;
  172. ++unique;
  173. }
  174. });
  175. assert(unique <= 1);
  176. if (select != nullptr) {
  177. select->action(t, event.data);
  178. events = select->output(t);
  179. _current_state = stateID;
  180. compute_sigma(t);
  181. } else {
  182. update_sigma(t);
  183. }
  184. }
  185. return events;
  186. }
  187. // with internal event
  188. Events transition(const typename Time::type &t, const InternalEvent &event) {
  189. typename std::map<int, _transitions_type>::const_iterator it = _transitions.find(_current_state);
  190. Events events{};
  191. uint unique = 0;
  192. if (it != _transitions.cend()) {
  193. AbstractTransition *select = nullptr;
  194. int stateID{};
  195. std::for_each(it->second.cbegin(), it->second.cend(),
  196. [t, event, &unique, &select, &stateID](
  197. const std::pair<std::unique_ptr<AbstractTransition>, int> &e) {
  198. if (e.first->guard(t) and e.first->event(t, event.id)) {
  199. select = e.first.get();
  200. stateID = e.second;
  201. ++unique;
  202. }
  203. });
  204. assert(unique <= 1);
  205. if (select != nullptr) {
  206. select->action(t, event.data);
  207. events = select->output(t);
  208. _current_state = stateID;
  209. compute_sigma(t);
  210. } else {
  211. update_sigma(t);
  212. }
  213. }
  214. return events;
  215. }
  216. void update_sigma(const typename Time::type &t) {
  217. _sigma -= t - _last_time;
  218. _last_time = t;
  219. }
  220. private:
  221. void compute_sigma(const typename Time::type &t) {
  222. _sigma = current_state()->ta(t);
  223. _last_time = t;
  224. }
  225. typedef std::vector<std::pair<std::unique_ptr < AbstractTransition>, int >> _transitions_type;
  226. std::map<int, std::unique_ptr<AbstractState>> _states;
  227. std::map<int, _transitions_type> _transitions;
  228. int _initial_state;
  229. const typename Types::root_state_machine_type &_root;
  230. int _current_state;
  231. typename Time::type _last_time{};
  232. typename Time::type _sigma{};
  233. };
  234. template<class Time, class Types, class StateType>
  235. class StateMachine : public AbstractStateMachine<Time, Types> {
  236. public:
  237. StateMachine(const typename Types::root_state_machine_type &root, StateType state)
  238. : AbstractStateMachine<Time, Types>(root), _state(state) {}
  239. virtual ~StateMachine() = default;
  240. const StateType &state_() const { return _state; }
  241. StateType &state_() { return _state; }
  242. protected:
  243. StateType _state;
  244. };
  245. }
  246. #endif //ARTIS_STAR_ADDONS_UTILS_STATE_MACHINE_HPP