graph_manager.hpp 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403
  1. /**
  2. * @file tests/multithreading/lifegame/graph_manager.cpp
  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_LIFEGAME_GRAPH_MANAGER_HPP
  26. #define TESTS_MULTITHREADING_LIFEGAME_GRAPH_MANAGER_HPP
  27. #include <tests/multithreading/lifegame/models.hpp>
  28. #include <artis-star/kernel/pdevs/multithreading/Coordinator.hpp>
  29. #include <artis-star/kernel/pdevs/GraphManager.hpp>
  30. #include <artis-star/kernel/pdevs/Simulator.hpp>
  31. namespace artis {
  32. namespace tests {
  33. namespace multithreading {
  34. namespace lifegame {
  35. struct GridGraphManagerParameters {
  36. unsigned int begin_column;
  37. unsigned int end_column;
  38. unsigned int begin_line;
  39. unsigned int end_line;
  40. unsigned int min_column;
  41. unsigned int max_column;
  42. unsigned int min_line;
  43. unsigned int max_line;
  44. };
  45. class FlatGraphManager
  46. : public artis::pdevs::GraphManager<common::DoubleTime,
  47. CellParameters,
  48. GridGraphManagerParameters> {
  49. public:
  50. enum submodels {
  51. CELL
  52. };
  53. FlatGraphManager(common::Coordinator<common::DoubleTime> *coordinator,
  54. const CellParameters &parameters,
  55. const GridGraphManagerParameters &graph_parameters)
  56. :
  57. artis::pdevs::GraphManager<common::DoubleTime, CellParameters, GridGraphManagerParameters>(
  58. coordinator, parameters, graph_parameters) {
  59. unsigned int column_number =
  60. graph_parameters.end_column - graph_parameters.begin_column + 1;
  61. unsigned int line_number =
  62. graph_parameters.end_line - graph_parameters.begin_line + 1;
  63. for (unsigned int i = graph_parameters.begin_column;
  64. i <= graph_parameters.end_column; ++i) {
  65. for (unsigned int j = graph_parameters.begin_line;
  66. j <= graph_parameters.end_line; ++j) {
  67. std::ostringstream ss;
  68. ss << "C_" << i << "_" << j;
  69. auto cell = new Simulator(ss.str(), parameters);
  70. _cells.push_back(cell);
  71. add_children(CELL, cell);
  72. }
  73. }
  74. for (int i = 0; i < (int) column_number; ++i) {
  75. for (int j = 0; j < (int) line_number; ++j) {
  76. int index = i * (int) line_number + j;
  77. // north
  78. if (j - 1 >= 0) {
  79. out({_cells[index], Cell::OUT})
  80. >> in({_cells[i * line_number + j - 1],
  81. Cell::IN});
  82. }
  83. // south
  84. if (j + 1 < (int) line_number) {
  85. out({_cells[index], Cell::OUT})
  86. >> in({_cells[i * line_number + j + 1],
  87. Cell::IN});
  88. }
  89. // west
  90. if (i - 1 >= 0) {
  91. out({_cells[index], Cell::OUT})
  92. >> in({_cells[(i - 1) * line_number
  93. + j], Cell::IN});
  94. }
  95. // east
  96. if (i + 1 < (int) column_number) {
  97. out({_cells[index], Cell::OUT})
  98. >> in({_cells[(i + 1) * line_number
  99. + j], Cell::IN});
  100. }
  101. // north west
  102. if (j - 1 >= 0 and i - 1 >= 0) {
  103. out({_cells[index], Cell::OUT})
  104. >> in({_cells[(i - 1) * line_number + j
  105. - 1], Cell::IN});
  106. }
  107. // south west
  108. if (j + 1 < (int) line_number and i - 1 >= 0) {
  109. out({_cells[index], Cell::OUT})
  110. >> in({_cells[(i - 1) * line_number + j
  111. + 1], Cell::IN});
  112. }
  113. // north east
  114. if (j - 1 >= 0 and i + 1 < (int) column_number) {
  115. out({_cells[index], Cell::OUT})
  116. >> in({_cells[(i + 1) * line_number + j
  117. - 1], Cell::IN});
  118. }
  119. // south east
  120. if (j + 1 < (int) line_number and i + 1 < (int) column_number) {
  121. out({_cells[index], Cell::OUT})
  122. >> in({_cells[(i + 1) * line_number + j
  123. + 1], Cell::IN});
  124. }
  125. }
  126. }
  127. }
  128. ~FlatGraphManager() override {
  129. std::for_each(_cells.begin(), _cells.end(),
  130. std::default_delete<Simulator>());
  131. }
  132. private:
  133. typedef pdevs::Simulator<common::DoubleTime, Cell, CellParameters> Simulator;
  134. typedef std::vector<Simulator *> Simulators;
  135. Simulators _cells;
  136. };
  137. class ParallelBuiltFlatGraphManager : public FlatGraphManager {
  138. public:
  139. ParallelBuiltFlatGraphManager(
  140. common::Coordinator<common::DoubleTime> *coordinator,
  141. const CellParameters &parameters,
  142. const GridGraphManagerParameters &graph_parameters)
  143. :
  144. FlatGraphManager(coordinator, parameters, graph_parameters) {
  145. // inputs
  146. unsigned int k = 0;
  147. // top / bottom
  148. {
  149. int j_top = (int) graph_parameters.begin_line - 1;
  150. int j_bottom = (int) graph_parameters.end_line + 1;
  151. for (int i = (int) graph_parameters.begin_column - 1;
  152. i <= (int) graph_parameters.end_column + 1; ++i) {
  153. std::ostringstream ss_out;
  154. ++k;
  155. if (i >= (int) graph_parameters.min_column
  156. and i <= (int) graph_parameters.max_column
  157. and j_top >= (int) graph_parameters.min_line) {
  158. ss_out << "in_" << i << "_" << j_top;
  159. coordinator->add_in_port({k, ss_out.str()});
  160. }
  161. ++k;
  162. if (i >= (int) graph_parameters.min_column
  163. and i <= (int) graph_parameters.max_column
  164. and j_bottom <= (int) graph_parameters.max_line) {
  165. ss_out << "in_" << i << "_" << j_bottom;
  166. coordinator->add_in_port({k, ss_out.str()});
  167. }
  168. }
  169. }
  170. // left / right
  171. {
  172. int i_left = (int) graph_parameters.begin_column - 1;
  173. int i_right = (int) graph_parameters.end_column + 1;
  174. for (int j = (int) graph_parameters.begin_line;
  175. j <= (int) graph_parameters.end_line; ++j) {
  176. std::ostringstream ss_out;
  177. ++k;
  178. if (j >= (int) graph_parameters.min_line
  179. and j <= (int) graph_parameters.max_line
  180. and i_left >= (int) graph_parameters.min_column) {
  181. ss_out << "out_" << i_left << "_" << j;
  182. coordinator->add_in_port({k, ss_out.str()});
  183. }
  184. ++k;
  185. if (j >= (int) graph_parameters.min_line
  186. and j <= (int) graph_parameters.max_line
  187. and i_right >= (int) graph_parameters.max_column) {
  188. ss_out << "out_" << i_right << "_" << j;
  189. coordinator->add_in_port({k, ss_out.str()});
  190. }
  191. }
  192. }
  193. // outputs
  194. k = 0;
  195. // top / bottom
  196. {
  197. int j_top = (int) graph_parameters.begin_line;
  198. int j_bottom = (int) graph_parameters.end_line;
  199. for (int i = (int) graph_parameters.begin_column;
  200. i <= (int) graph_parameters.end_column; ++i) {
  201. std::ostringstream ss_out;
  202. ++k;
  203. ss_out << "out_" << i << "_" << j_top;
  204. coordinator->add_out_port({k, ss_out.str()});
  205. ++k;
  206. ss_out << "out_" << i << "_" << j_bottom;
  207. coordinator->add_out_port({k, ss_out.str()});
  208. }
  209. }
  210. // left / right
  211. {
  212. int i_left = (int) graph_parameters.begin_column;
  213. int i_right = (int) graph_parameters.end_column;
  214. for (int j = (int) graph_parameters.begin_line + 1;
  215. j <= (int) graph_parameters.end_line - 1; ++j) {
  216. std::ostringstream ss_out;
  217. ++k;
  218. ss_out << "out_" << i_left << "_" << j;
  219. coordinator->add_out_port({k, ss_out.str()});
  220. ++k;
  221. ss_out << "out_" << i_right << "_" << j;
  222. coordinator->add_out_port({k, ss_out.str()});
  223. }
  224. }
  225. // for (Edges::const_iterator it = parameters._output_edges.begin();
  226. // it != parameters._output_edges.end(); ++it) {
  227. // std::ostringstream ss_out;
  228. //
  229. // ss_out << "out_" << it->first;
  230. // if (not coordinator->exist_out_port(ss_out.str())) {
  231. // coordinator->add_out_port(ss_out.str());
  232. // }
  233. // if (not ParallelBuiltFlatGraphManager::exist_link(
  234. // ParallelBuiltFlatGraphManager::_simulators[it->first],
  235. // "out", coordinator, ss_out.str())) {
  236. // ParallelBuiltFlatGraphManager::add_link(
  237. // ParallelBuiltFlatGraphManager::_simulators[it->first],
  238. // "out", coordinator, ss_out.str());
  239. // }
  240. // }
  241. }
  242. void init() {}
  243. void start(common::DoubleTime::type /* t */) {}
  244. void transition(
  245. const common::Models<common::DoubleTime> & /* receivers */,
  246. common::DoubleTime::type /* t */) {}
  247. ~ParallelBuiltFlatGraphManager() override = default;
  248. };
  249. class ParallelHierarchicalGraphManager :
  250. public artis::pdevs::GraphManager<common::DoubleTime,
  251. CellParameters,
  252. GridGraphManagerParameters> {
  253. public:
  254. enum submodels {
  255. S1_1 = 0, S1_2, S2_1, S2_2
  256. };
  257. ParallelHierarchicalGraphManager(
  258. common::Coordinator<common::DoubleTime> *coordinator,
  259. const CellParameters &parameters,
  260. const GridGraphManagerParameters &graph_parameters)
  261. :
  262. artis::pdevs::GraphManager<common::DoubleTime, CellParameters,
  263. GridGraphManagerParameters>(
  264. coordinator, parameters, graph_parameters) {
  265. // build coordinators (graphs)
  266. for (unsigned int i = 0; i < 2; ++i) {
  267. for (unsigned int j = 0; j < 2; ++j) {
  268. ParallelCoordinator *sub_coordinator = nullptr;
  269. std::ostringstream ss;
  270. ss << "S_" << (i + 1) << "_" << (j + 1);
  271. sub_coordinator = new ParallelCoordinator(ss.str(),
  272. parameters,
  273. {i * 5 + 1, (i + 1) * 5, j * 5 + 1, (j + 1) * 5,
  274. 1, 10, 1, 10});
  275. _coordinators.push_back(sub_coordinator);
  276. add_child(i, sub_coordinator);
  277. }
  278. }
  279. // builds internal connections (edges)
  280. // for (Connections::const_iterator it = parent_connections.begin();
  281. // it != parent_connections.end(); ++it) {
  282. // const Connection& connection = *it;
  283. // std::ostringstream ss_out;
  284. // std::ostringstream ss_in;
  285. //
  286. // ss_out << "out_" << connection.first.second;
  287. // ss_in << "in_" << connection.first.second;
  288. //
  289. // if (not exist_link(
  290. // _coordinators[connection.first.first - 1],
  291. // ss_out.str(),
  292. // _coordinators[connection.second.first - 1],
  293. // ss_in.str())) {
  294. // add_link(
  295. // _coordinators[connection.first.first - 1],
  296. // ss_out.str(),
  297. // _coordinators[connection.second.first - 1],
  298. // ss_in.str());
  299. // }
  300. // }
  301. }
  302. ~ParallelHierarchicalGraphManager() override {
  303. for (typename Coordinators::const_iterator it = _coordinators.begin();
  304. it != _coordinators.end(); ++it) {
  305. delete *it;
  306. }
  307. }
  308. void init() {
  309. std::for_each(_coordinators.begin(), _coordinators.end(),
  310. [this](ParallelCoordinator *coordinator) {
  311. coordinator->set_sender(
  312. (dynamic_cast< artis::pdevs::multithreading::Coordinator<
  313. artis::common::DoubleTime,
  314. ParallelHierarchicalGraphManager,
  315. CellParameters,
  316. GridGraphManagerParameters> *>(this->coordinator()))->get_sender());
  317. });
  318. }
  319. void start(common::DoubleTime::type t) {
  320. std::for_each(_coordinators.begin(), _coordinators.end(),
  321. [t](ParallelCoordinator *coordinator) {
  322. coordinator->get_sender().send(
  323. artis::pdevs::multithreading::start_message<
  324. artis::common::DoubleTime>(t));
  325. });
  326. }
  327. void transition(const common::Models<common::DoubleTime> &receivers,
  328. artis::common::DoubleTime::type t) {
  329. std::for_each(receivers.begin(), receivers.end(),
  330. [this, t](const common::Model<common::DoubleTime> *model) {
  331. if (not model->is_atomic()) {
  332. typename Coordinators::const_iterator itc =
  333. std::find(_coordinators.begin(),
  334. _coordinators.end(), model);
  335. (*itc)->get_sender().send(
  336. artis::pdevs::multithreading::transition_message<
  337. artis::common::DoubleTime>(t));
  338. }
  339. });
  340. }
  341. private:
  342. typedef artis::pdevs::multithreading::Coordinator<
  343. common::DoubleTime,
  344. ParallelBuiltFlatGraphManager,
  345. CellParameters,
  346. GridGraphManagerParameters
  347. > ParallelCoordinator;
  348. typedef std::vector<ParallelCoordinator *> Coordinators;
  349. Coordinators _coordinators;
  350. };
  351. }
  352. }
  353. }
  354. } // namespace artis tests multithreading lifegame
  355. #endif