models.hpp 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387
  1. /**
  2. * @file tests/multithreading/simple/models.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-2019 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 TESTS_MULTITHREADING_SIMPLE_MODELS_HPP
  26. #define TESTS_MULTITHREADING_SIMPLE_MODELS_HPP
  27. #include <artis-star/common/time/DoubleTime.hpp>
  28. #include <artis-star/kernel/pdevs/Dynamics.hpp>
  29. #include <random>
  30. #include <iostream>
  31. namespace artis {
  32. namespace tests {
  33. namespace multithreading {
  34. namespace simple {
  35. void delay() {
  36. for (unsigned int i = 0; i < 1000; ++i) {
  37. std::vector<int> v;
  38. for (unsigned int j = 1000; j > 0; --j) {
  39. v.push_back(j);
  40. }
  41. std::sort(v.begin(), v.end());
  42. }
  43. }
  44. struct State {
  45. enum values {
  46. STOP, UP, MAX, DOWN
  47. };
  48. };
  49. struct Vehicle {
  50. unsigned int index;
  51. double v_max;
  52. double acceleration;
  53. State::values state;
  54. artis::common::DoubleTime::type next_time;
  55. };
  56. struct GeneratorParameters {
  57. double v_max;
  58. double mean;
  59. double stddev;
  60. unsigned long seed;
  61. };
  62. class Generator
  63. : public artis::pdevs::Dynamics<artis::common::DoubleTime, Generator, GeneratorParameters> {
  64. public:
  65. struct outputs {
  66. enum values {
  67. OUT
  68. };
  69. };
  70. Generator(const std::string &name,
  71. const artis::pdevs::Context<artis::common::DoubleTime,
  72. Generator,
  73. GeneratorParameters> &context)
  74. :
  75. artis::pdevs::Dynamics<artis::common::DoubleTime, Generator, GeneratorParameters>(
  76. name, context),
  77. _v_max(context.parameters().v_max),
  78. _distribution(context.parameters().mean, context.parameters().stddev),
  79. _v_max_distribution(0.5, 1.),
  80. _port_distribution(0, 7) {
  81. _generator.seed(context.parameters().seed);
  82. output_ports({{outputs::OUT, "out_1"}});
  83. output_ports({{outputs::OUT + 1, "out_2"}});
  84. output_ports({{outputs::OUT + 2, "out_3"}});
  85. output_ports({{outputs::OUT + 3, "out_4"}});
  86. output_ports({{outputs::OUT + 4, "out_5"}});
  87. output_ports({{outputs::OUT + 5, "out_6"}});
  88. output_ports({{outputs::OUT + 6, "out_7"}});
  89. output_ports({{outputs::OUT + 7, "out_8"}});
  90. }
  91. ~Generator() override = default;
  92. void dint(const artis::common::DoubleTime::type &t) override {
  93. _last_time = t;
  94. _sigma = _distribution(_generator);
  95. _sigma = _sigma <= 0 ? 0.1 : _sigma;
  96. _next_v_max = _v_max * _v_max_distribution(_generator);
  97. _next_port = _port_distribution(_generator);
  98. ++_index;
  99. }
  100. void start(const artis::common::DoubleTime::type &t) override {
  101. _last_time = t;
  102. _sigma = _distribution(_generator);
  103. _sigma = _sigma <= 0 ? 0.1 : _sigma;
  104. _next_v_max = _v_max * _v_max_distribution(_generator);
  105. _next_port = _port_distribution(_generator);
  106. _index = 1;
  107. }
  108. artis::common::DoubleTime::type
  109. ta(const artis::common::DoubleTime::type & /* t */) const override { return _sigma; }
  110. artis::common::Bag<artis::common::DoubleTime>
  111. lambda(const artis::common::DoubleTime::type &t) const override {
  112. artis::common::Bag<artis::common::DoubleTime> bag;
  113. if (t > 0) {
  114. Vehicle vehicle = {_index, _next_v_max, 0.5, State::STOP, t};
  115. bag.push_back(
  116. artis::common::ExternalEvent<artis::common::DoubleTime>(
  117. outputs::OUT + _next_port, vehicle));
  118. }
  119. return bag;
  120. }
  121. common::DoubleTime::type
  122. lookahead(const common::DoubleTime::type & /* t */) const override {
  123. return _last_time + _sigma;
  124. }
  125. private:
  126. // parameters
  127. double _v_max;
  128. // state
  129. artis::common::DoubleTime::type _sigma;
  130. artis::common::DoubleTime::type _last_time;
  131. std::default_random_engine _generator;
  132. std::normal_distribution<double> _distribution;
  133. std::uniform_real_distribution<double> _v_max_distribution;
  134. std::uniform_int_distribution<int> _port_distribution;
  135. double _next_v_max;
  136. int _next_port;
  137. unsigned int _index;
  138. };
  139. class Counter
  140. : public artis::pdevs::Dynamics<artis::common::DoubleTime, Counter> {
  141. public:
  142. struct inputs {
  143. enum values {
  144. IN
  145. };
  146. };
  147. struct vars {
  148. enum values {
  149. COUNTER
  150. };
  151. };
  152. Counter(const std::string &name,
  153. const artis::pdevs::Context<artis::common::DoubleTime, Counter> &context)
  154. :
  155. artis::pdevs::Dynamics<artis::common::DoubleTime, Counter>(name,
  156. context) {
  157. input_port({inputs::IN, "in"});
  158. observable({vars::COUNTER, "counter"});
  159. }
  160. ~Counter() override = default;
  161. void
  162. dext(const artis::common::DoubleTime::type & /* t */,
  163. const artis::common::DoubleTime::type & /* e */,
  164. const artis::common::Bag<artis::common::DoubleTime> &bag) override {
  165. // std::cout << t << ": " << _counter << std::endl;
  166. _counter += bag.size();
  167. }
  168. void start(const artis::common::DoubleTime::type & /* t */) override {
  169. _counter = 0;
  170. }
  171. artis::common::DoubleTime::type
  172. ta(const artis::common::DoubleTime::type & /* t */) const override {
  173. return artis::common::DoubleTime::infinity;
  174. }
  175. artis::common::Value
  176. observe(const artis::common::DoubleTime::type & /* t */,
  177. unsigned int index) const override {
  178. if (index == vars::COUNTER) {
  179. return _counter;
  180. } else {
  181. return artis::common::Value();
  182. }
  183. }
  184. common::DoubleTime::type
  185. lookahead(const common::DoubleTime::type & /* t */) const override {
  186. return common::DoubleTime::infinity;
  187. }
  188. private:
  189. unsigned int _counter;
  190. };
  191. class Link :
  192. public artis::pdevs::Dynamics<common::DoubleTime, Link> {
  193. public :
  194. struct inputs {
  195. enum values {
  196. IN
  197. };
  198. };
  199. struct outputs {
  200. enum values {
  201. OUT
  202. };
  203. };
  204. Link(const std::string &name,
  205. const artis::pdevs::Context<common::DoubleTime, Link> &context)
  206. : artis::pdevs::Dynamics<common::DoubleTime, Link>(name, context) {
  207. input_port({inputs::IN, "in"});
  208. output_port({outputs::OUT, "out"});
  209. }
  210. ~ Link() override = default;
  211. void dint(const artis::common::DoubleTime::type &t) override {
  212. delay();
  213. auto it = _vehicles.begin();
  214. while (it != _vehicles.end()) {
  215. if (it->next_time == t and it->state == State::STOP) {
  216. _vehicles.erase(it);
  217. it = _vehicles.begin();
  218. } else {
  219. ++it;
  220. }
  221. }
  222. for (auto &vehicle: _vehicles) {
  223. if (vehicle.next_time == t) {
  224. switch (vehicle.state) {
  225. case State::UP: {
  226. double duration = vehicle.v_max / vehicle.acceleration;
  227. double acceleration_distance =
  228. 0.5 * vehicle.acceleration * duration * duration;
  229. vehicle.state = State::MAX;
  230. vehicle.next_time = t +
  231. (_length - 2 * acceleration_distance) / vehicle.v_max;
  232. break;
  233. }
  234. case State::MAX: {
  235. vehicle.state = State::DOWN;
  236. vehicle.next_time = t + vehicle.v_max / vehicle.acceleration;
  237. break;
  238. }
  239. case State::DOWN: {
  240. vehicle.state = State::STOP;
  241. vehicle.next_time = t;
  242. break;
  243. }
  244. case State::STOP: {
  245. assert(false);
  246. break;
  247. }
  248. }
  249. }
  250. }
  251. update_sigma(t);
  252. }
  253. void dext(const artis::common::DoubleTime::type &t,
  254. const artis::common::DoubleTime::type & /* e */,
  255. const artis::common::Bag<artis::common::DoubleTime> &bag) override {
  256. std::for_each(bag.begin(), bag.end(),
  257. [this, t](const common::ExternalEvent<common::DoubleTime> &event) {
  258. if (event.on_port(inputs::IN)) {
  259. Vehicle vehicle;
  260. event.data()(vehicle);
  261. vehicle.next_time =
  262. t + vehicle.v_max / vehicle.acceleration;
  263. vehicle.state = State::UP;
  264. _vehicles.push_back(vehicle);
  265. }
  266. });
  267. update_sigma(t);
  268. }
  269. artis::common::DoubleTime::type
  270. ta(const artis::common::DoubleTime::type & /* t */) const override { return _sigma; }
  271. artis::common::Bag<artis::common::DoubleTime>
  272. lambda(const artis::common::DoubleTime::type &t) const override {
  273. artis::common::Bag<artis::common::DoubleTime> bag;
  274. for (auto vehicle: _vehicles) {
  275. if (vehicle.next_time == t and vehicle.state == State::STOP) {
  276. bag.push_back(
  277. artis::common::ExternalEvent<artis::common::DoubleTime>(
  278. outputs::OUT, vehicle));
  279. }
  280. }
  281. return bag;
  282. }
  283. void
  284. start(const artis::common::DoubleTime::type & /* t */) override {}
  285. common::DoubleTime::type
  286. lookahead(const common::DoubleTime::type &t) const override {
  287. double eot = artis::common::DoubleTime::infinity;
  288. for (auto vehicle: _vehicles) {
  289. double eot_i = artis::common::DoubleTime::infinity;
  290. if (vehicle.next_time == t and vehicle.state == State::STOP) {
  291. eot_i = t;
  292. } else if (vehicle.state == State::DOWN) {
  293. eot_i = vehicle.next_time;
  294. } else if (vehicle.state == State::MAX) {
  295. eot_i = vehicle.next_time + vehicle.v_max / vehicle.acceleration;
  296. } else if (vehicle.state == State::UP) {
  297. double duration = vehicle.v_max / vehicle.acceleration;
  298. double acceleration_distance =
  299. 0.5 * vehicle.acceleration * duration * duration;
  300. eot_i = vehicle.next_time
  301. + (_length - 2 * acceleration_distance) / vehicle.v_max
  302. + vehicle.v_max / vehicle.acceleration;
  303. }
  304. if (eot_i < eot) {
  305. eot = eot_i;
  306. }
  307. }
  308. return eot;
  309. }
  310. private:
  311. void update_sigma(const artis::common::DoubleTime::type &t) {
  312. if (_vehicles.empty()) {
  313. _sigma = artis::common::DoubleTime::infinity;
  314. } else {
  315. _sigma = std::min_element(_vehicles.begin(), _vehicles.end(),
  316. [](const Vehicle &e1, const Vehicle &e2) {
  317. return e1.next_time < e2.next_time;
  318. })->next_time - t;
  319. }
  320. }
  321. const double _length = 500;
  322. std::deque<Vehicle> _vehicles;
  323. artis::common::DoubleTime::type _sigma;
  324. };
  325. }
  326. }
  327. }
  328. } // namespace artis tests multithreading simple
  329. #endif