StateMachine.hpp 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384
  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 */,
  68. const artis::common::event::Value & /* value */) const = 0;
  69. virtual bool no_event() const = 0;
  70. virtual Events output(const typename Time::type & /* t */) const = 0;
  71. virtual ~AbstractTransition() = default;
  72. };
  73. template<class Machine>
  74. struct Transition : AbstractTransition {
  75. std::shared_ptr <Machine> _machine;
  76. Transition(const std::shared_ptr <Machine> &machine) : _machine(machine) {}
  77. void action(const typename Time::type & /* t */,
  78. const artis::common::event::Value & /* value */) override {}
  79. bool event(const typename Time::type & /* t */,
  80. int /* event */) override { return false; }
  81. bool guard(const typename Time::type & /* t */,
  82. const artis::common::event::Value & /* value */) const override { return true; }
  83. bool no_event() const override { return false; }
  84. Events output(const typename Time::type & /* t */) const override { return {}; }
  85. };
  86. AbstractStateMachine(const typename Types::root_state_machine_type &root) : _root(root) {}
  87. virtual ~AbstractStateMachine() = default;
  88. // virtual void build(const std::shared_ptr<StateMachine<Types>> &machine) = 0;
  89. const std::unique_ptr <AbstractState> &current_state() const {
  90. return _states.at(_current_state);
  91. }
  92. int current_state(int machine_id) const {
  93. return _root.current_state(machine_id);
  94. }
  95. void initial_state(int state) {
  96. _initial_state = state;
  97. }
  98. bool is_ready(const typename Time::type &t) const {
  99. return std::abs(_sigma - (t - _last_time)) < 1e-6;
  100. }
  101. const typename Types::root_state_machine_type &root() const { return _root; }
  102. void start(const typename Time::type &t) {
  103. _current_state = _initial_state;
  104. _last_time = t;
  105. compute_sigma(t);
  106. }
  107. void state(AbstractState *state) {
  108. _states.insert(std::make_pair(state->_id, std::unique_ptr<AbstractState>(state)));
  109. _transitions.insert(std::make_pair(state->_id, _transitions_type{}));
  110. }
  111. void switch_transition(int state, int next_state, size_t index, AbstractTransition *transition) {
  112. auto it = std::find_if(_transitions[state].begin(), _transitions[state].end(), [next_state](const auto &e) {
  113. return e.second == next_state;
  114. });
  115. assert(it != _transitions[state].end());
  116. while (it + 1 != _transitions[state].end() and index > 0) {
  117. it = std::find_if(it + 1, _transitions[state].end(), [next_state](const auto &e) {
  118. return e.second == next_state;
  119. });
  120. --index;
  121. }
  122. assert(it != _transitions[state].end());
  123. it->first.reset(transition);
  124. }
  125. typename Time::type ta(const typename Time::type & /* t */) const {
  126. return _sigma;
  127. }
  128. void transition(int state, int next_state, AbstractTransition *transition) {
  129. _transitions[state].push_back(std::make_pair(std::unique_ptr<AbstractTransition>(transition), next_state));
  130. }
  131. // without event
  132. Events transition(const typename Time::type &t) {
  133. typename std::map<int, _transitions_type>::const_iterator it = _transitions.find(_current_state);
  134. Events events{};
  135. uint unique = 0;
  136. if (it != _transitions.cend()) {
  137. AbstractTransition *select = nullptr;
  138. int stateID{};
  139. std::for_each(it->second.cbegin(), it->second.cend(),
  140. [t, &unique, &select, &stateID](
  141. const std::pair<std::unique_ptr<AbstractTransition>, int> &e) {
  142. if (e.first->no_event() and e.first->guard(t, {})) {
  143. select = e.first.get();
  144. stateID = e.second;
  145. ++unique;
  146. }
  147. });
  148. assert(unique <= 1);
  149. if (select != nullptr) {
  150. select->action(t, {});
  151. events = select->output(t);
  152. _current_state = stateID;
  153. compute_sigma(t);
  154. } else {
  155. update_sigma(t);
  156. }
  157. }
  158. return events;
  159. }
  160. // with external event
  161. Events transition(const typename Time::type &t, const ExternalEvent &event) {
  162. typename std::map<int, _transitions_type>::const_iterator it = _transitions.find(_current_state);
  163. Events events{};
  164. uint unique = 0;
  165. if (it != _transitions.cend()) {
  166. AbstractTransition *select = nullptr;
  167. int stateID{};
  168. std::for_each(it->second.cbegin(), it->second.cend(),
  169. [t, event, &unique, &select, &stateID](
  170. const std::pair<std::unique_ptr<AbstractTransition>, int> &e) {
  171. if (e.first->guard(t, event.data) and e.first->event(t, event.id)) {
  172. select = e.first.get();
  173. stateID = e.second;
  174. ++unique;
  175. }
  176. });
  177. assert(unique <= 1);
  178. if (select != nullptr) {
  179. select->action(t, event.data);
  180. events = select->output(t);
  181. _current_state = stateID;
  182. compute_sigma(t);
  183. } else {
  184. update_sigma(t);
  185. }
  186. }
  187. return events;
  188. }
  189. // with internal event
  190. Events transition(const typename Time::type &t, const InternalEvent &event) {
  191. typename std::map<int, _transitions_type>::const_iterator it = _transitions.find(_current_state);
  192. Events events{};
  193. uint unique = 0;
  194. if (it != _transitions.cend()) {
  195. AbstractTransition *select = nullptr;
  196. int stateID{};
  197. std::for_each(it->second.cbegin(), it->second.cend(),
  198. [t, event, &unique, &select, &stateID](
  199. const std::pair<std::unique_ptr<AbstractTransition>, int> &e) {
  200. if (e.first->guard(t, event.data) and e.first->event(t, event.id)) {
  201. select = e.first.get();
  202. stateID = e.second;
  203. ++unique;
  204. }
  205. });
  206. assert(unique <= 1);
  207. if (select != nullptr) {
  208. select->action(t, event.data);
  209. events = select->output(t);
  210. _current_state = stateID;
  211. compute_sigma(t);
  212. } else {
  213. update_sigma(t);
  214. }
  215. }
  216. return events;
  217. }
  218. void update_sigma(const typename Time::type &t) {
  219. _sigma -= t - _last_time;
  220. _last_time = t;
  221. }
  222. private:
  223. void compute_sigma(const typename Time::type &t) {
  224. _sigma = current_state()->ta(t);
  225. _last_time = t;
  226. }
  227. typedef std::vector<std::pair<std::unique_ptr < AbstractTransition>, int >> _transitions_type;
  228. std::map<int, std::unique_ptr<AbstractState>> _states;
  229. std::map<int, _transitions_type> _transitions;
  230. int _initial_state;
  231. const typename Types::root_state_machine_type &_root;
  232. int _current_state;
  233. typename Time::type _last_time{};
  234. typename Time::type _sigma{};
  235. };
  236. template<class Time, class Types, class StateType>
  237. class StateMachine : public AbstractStateMachine<Time, Types> {
  238. public:
  239. StateMachine(const typename Types::root_state_machine_type &root, StateType state)
  240. : AbstractStateMachine<Time, Types>(root), _state(state) {}
  241. virtual ~StateMachine() = default;
  242. const StateType &state_() const { return _state; }
  243. StateType &state_() { return _state; }
  244. protected:
  245. StateType _state;
  246. };
  247. }
  248. #define DECLARE_STATE_TRANSITION_TYPES(StateMachineClassName) \
  249. typedef typename StateMachineClassName<Types, Parameters, StateType>::template State<StateMachineClassName<Types, Parameters, StateType>> State_t; \
  250. typedef typename StateMachineClassName<Types, Parameters, StateType>::template Transition<StateMachineClassName<Types, Parameters, StateType>> Transition_t;
  251. #define DEFINE_STATE_MACHINE_STATE(StateClassName, StateID, StateMachineClassName) \
  252. template<class Types, class Parameters, class StateType> \
  253. struct StateClassName : StateMachineClassName<Types, Parameters, StateType>::State_t { \
  254. StateClassName(const std::shared_ptr<StateMachineClassName<Types, Parameters, StateType>> &machine) : \
  255. StateMachineClassName<Types, Parameters, StateType>::State_t(StateID, machine) {} \
  256. };
  257. #define DEFINE_STATE_MACHINE_STATE_WITH_NULL_TA(StateClassName, StateID, StateMachineClassName) \
  258. template<class Types, class Parameters, class StateType> \
  259. struct StateClassName : StateMachineClassName<Types, Parameters, StateType>::State_t { \
  260. StateClassName(const std::shared_ptr<StateMachineClassName<Types, Parameters, StateType>> &machine) : \
  261. StateMachineClassName<Types, Parameters, StateType>::State_t(StateID, machine) {} \
  262. artis::traffic::core::Time ta(const artis::traffic::core::Time & /* t */) const override { return 0; }\
  263. };
  264. #define DEFINE_STATE_MACHINE_STATE_WITH_TA(StateClassName, StateID, StateMachineClassName) \
  265. template<class Types, class Parameters, class StateType> \
  266. struct StateClassName : StateMachineClassName<Types, Parameters, StateType>::State_t { \
  267. StateClassName(const std::shared_ptr<StateMachineClassName<Types, Parameters, StateType>> &machine) : \
  268. StateMachineClassName<Types, Parameters, StateType>::State_t(StateID, machine) {} \
  269. artis::traffic::core::Time ta(const artis::traffic::core::Time & /* t */) const override; \
  270. };
  271. #define DEFINE_STATE_MACHINE_TRANSITION_HEADER(TransitionClassName, StateMachineClassName) \
  272. template<class Types, class Parameters, class StateType> \
  273. struct TransitionClassName : StateMachineClassName<Types, Parameters, StateType>::Transition_t { \
  274. TransitionClassName( \
  275. const std::shared_ptr<StateMachineClassName<Types, Parameters, StateType>> &machine) : \
  276. StateMachineClassName<Types, Parameters, StateType>::Transition_t(machine) {}
  277. #define ATTRIBUTE(Type, Var) Type Var;
  278. #define NO_ATTRIBUTE
  279. #define DEFINE_STATE_MACHINE_TRANSITION_FOOTER(Attribute) \
  280. Attribute \
  281. };
  282. #define DEFINE_STATE_MACHINE_TRANSITION_ACTION_true void action(const artis::traffic::core::Time & /* t */, const artis::common::event::Value & /* value */) override;
  283. #define DEFINE_STATE_MACHINE_TRANSITION_ACTION_false
  284. #define DEFINE_STATE_MACHINE_TRANSITION_EVENT_true bool event(const artis::traffic::core::Time & /* t */, int event) override;
  285. #define DEFINE_STATE_MACHINE_TRANSITION_EVENT_false
  286. #define DEFINE_STATE_MACHINE_TRANSITION_GUARD_true bool guard(const artis::traffic::core::Time & /* t */, const artis::common::event::Value & /* value */) const override;
  287. #define DEFINE_STATE_MACHINE_TRANSITION_GUARD_false
  288. #define DEFINE_STATE_MACHINE_TRANSITION_NO_EVENT_true bool no_event() const override { return true; }
  289. #define DEFINE_STATE_MACHINE_TRANSITION_NO_EVENT_false
  290. #define DEFINE_STATE_MACHINE_TRANSITION_OUTPUT_true(StateMachineClassName) typename StateMachineClassName<Types, Parameters, StateType>::Events output(const artis::traffic::core::Time & /* t */) const override;
  291. #define DEFINE_STATE_MACHINE_TRANSITION_OUTPUT_false(StateMachineClassName)
  292. #define DEFINE_STATE_MACHINE_TRANSITION(TransitionClassName, StateMachineClassName, Attribute, ActionMethod, EventMethod, GuardMethod, NoEventMethod, OutputMethod) \
  293. DEFINE_STATE_MACHINE_TRANSITION_HEADER(TransitionClassName, StateMachineClassName) \
  294. DEFINE_STATE_MACHINE_TRANSITION_ACTION_##ActionMethod \
  295. DEFINE_STATE_MACHINE_TRANSITION_EVENT_##EventMethod \
  296. DEFINE_STATE_MACHINE_TRANSITION_GUARD_##GuardMethod \
  297. DEFINE_STATE_MACHINE_TRANSITION_NO_EVENT_##NoEventMethod \
  298. DEFINE_STATE_MACHINE_TRANSITION_OUTPUT_##OutputMethod(StateMachineClassName) \
  299. DEFINE_STATE_MACHINE_TRANSITION_FOOTER(Attribute)
  300. #endif //ARTIS_STAR_ADDONS_UTILS_STATE_MACHINE_HPP