graph_manager.hpp 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407
  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, CellParameters, GridGraphManagerParameters> {
  47. public:
  48. enum submodels {
  49. CELL
  50. };
  51. FlatGraphManager(common::Coordinator<common::DoubleTime>* coordinator,
  52. const CellParameters& parameters,
  53. const GridGraphManagerParameters& graph_parameters)
  54. :
  55. artis::pdevs::GraphManager<common::DoubleTime, CellParameters, GridGraphManagerParameters>(
  56. coordinator, parameters, graph_parameters)
  57. {
  58. unsigned int column_number =
  59. graph_parameters.end_column - graph_parameters.begin_column + 1;
  60. unsigned int line_number =
  61. graph_parameters.end_line - graph_parameters.begin_line + 1;
  62. for (unsigned int i = graph_parameters.begin_column;
  63. i <= graph_parameters.end_column; ++i) {
  64. for (unsigned int j = graph_parameters.begin_line;
  65. j <= graph_parameters.end_line; ++j) {
  66. std::ostringstream ss;
  67. ss << "C_" << i << "_" << j;
  68. auto cell = new Simulator(ss.str(), parameters);
  69. _cells.push_back(cell);
  70. add_children(CELL, cell);
  71. }
  72. }
  73. for (int i = 0; i < (int) column_number; ++i) {
  74. for (int j = 0; j < (int) line_number; ++j) {
  75. int index = i * (int) line_number + j;
  76. // north
  77. if (j - 1 >= 0) {
  78. out({_cells[index], Cell::OUT})
  79. >> in({_cells[i * line_number + j - 1],
  80. Cell::IN});
  81. }
  82. // south
  83. if (j + 1 < (int) line_number) {
  84. out({_cells[index], Cell::OUT})
  85. >> in({_cells[i * line_number + j + 1],
  86. Cell::IN});
  87. }
  88. // west
  89. if (i - 1 >= 0) {
  90. out({_cells[index], Cell::OUT})
  91. >> in({_cells[(i - 1) * line_number
  92. + j], Cell::IN});
  93. }
  94. // east
  95. if (i + 1 < (int) column_number) {
  96. out({_cells[index], Cell::OUT})
  97. >> in({_cells[(i + 1) * line_number
  98. + j], Cell::IN});
  99. }
  100. // north west
  101. if (j - 1 >= 0 and i - 1 >= 0) {
  102. out({_cells[index], Cell::OUT})
  103. >> in({_cells[(i - 1) * line_number + j
  104. - 1], Cell::IN});
  105. }
  106. // south west
  107. if (j + 1 < (int) line_number and i - 1 >= 0) {
  108. out({_cells[index], Cell::OUT})
  109. >> in({_cells[(i - 1) * line_number + j
  110. + 1], Cell::IN});
  111. }
  112. // north east
  113. if (j - 1 >= 0 and i + 1 < (int) column_number) {
  114. out({_cells[index], Cell::OUT})
  115. >> in({_cells[(i + 1) * line_number + j
  116. - 1], Cell::IN});
  117. }
  118. // south east
  119. if (j + 1 < (int) line_number and i + 1 < (int) column_number) {
  120. out({_cells[index], Cell::OUT})
  121. >> in({_cells[(i + 1) * line_number + j
  122. + 1], Cell::IN});
  123. }
  124. }
  125. }
  126. }
  127. ~FlatGraphManager() override
  128. {
  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. {
  146. // inputs
  147. unsigned int k = 0;
  148. // top / bottom
  149. {
  150. int j_top = (int) graph_parameters.begin_line - 1;
  151. int j_bottom = (int) graph_parameters.end_line + 1;
  152. for (int i = (int) graph_parameters.begin_column - 1;
  153. i <= (int) graph_parameters.end_column + 1; ++i) {
  154. std::ostringstream ss_out;
  155. ++k;
  156. if (i >= (int) graph_parameters.min_column
  157. and i <= (int) graph_parameters.max_column
  158. and j_top >= (int) graph_parameters.min_line) {
  159. ss_out << "in_" << i << "_" << j_top;
  160. coordinator->add_in_port({k, ss_out.str()});
  161. }
  162. ++k;
  163. if (i >= (int) graph_parameters.min_column
  164. and i <= (int) graph_parameters.max_column
  165. and j_bottom <= (int) graph_parameters.max_line) {
  166. ss_out << "in_" << i << "_" << j_bottom;
  167. coordinator->add_in_port({k, ss_out.str()});
  168. }
  169. }
  170. }
  171. // left / right
  172. {
  173. int i_left = (int) graph_parameters.begin_column - 1;
  174. int i_right = (int) graph_parameters.end_column + 1;
  175. for (int j = (int) graph_parameters.begin_line;
  176. j <= (int) graph_parameters.end_line; ++j) {
  177. std::ostringstream ss_out;
  178. ++k;
  179. if (j >= (int) graph_parameters.min_line
  180. and j <= (int) graph_parameters.max_line
  181. and i_left >= (int) graph_parameters.min_column) {
  182. ss_out << "out_" << i_left << "_" << j;
  183. coordinator->add_in_port({k, ss_out.str()});
  184. }
  185. ++k;
  186. if (j >= (int) graph_parameters.min_line
  187. and j <= (int) graph_parameters.max_line
  188. and i_right >= (int) graph_parameters.max_column) {
  189. ss_out << "out_" << i_right << "_" << j;
  190. coordinator->add_in_port({k, ss_out.str()});
  191. }
  192. }
  193. }
  194. // outputs
  195. k = 0;
  196. // top / bottom
  197. {
  198. int j_top = (int) graph_parameters.begin_line;
  199. int j_bottom = (int) graph_parameters.end_line;
  200. for (int i = (int) graph_parameters.begin_column;
  201. i <= (int) graph_parameters.end_column; ++i) {
  202. std::ostringstream ss_out;
  203. ++k;
  204. ss_out << "out_" << i << "_" << j_top;
  205. coordinator->add_out_port({k, ss_out.str()});
  206. ++k;
  207. ss_out << "out_" << i << "_" << j_bottom;
  208. coordinator->add_out_port({k, ss_out.str()});
  209. }
  210. }
  211. // left / right
  212. {
  213. int i_left = (int) graph_parameters.begin_column;
  214. int i_right = (int) graph_parameters.end_column;
  215. for (int j = (int) graph_parameters.begin_line + 1;
  216. j <= (int) graph_parameters.end_line - 1; ++j) {
  217. std::ostringstream ss_out;
  218. ++k;
  219. ss_out << "out_" << i_left << "_" << j;
  220. coordinator->add_out_port({k, ss_out.str()});
  221. ++k;
  222. ss_out << "out_" << i_right << "_" << j;
  223. coordinator->add_out_port({k, ss_out.str()});
  224. }
  225. }
  226. // for (Edges::const_iterator it = parameters._output_edges.begin();
  227. // it != parameters._output_edges.end(); ++it) {
  228. // std::ostringstream ss_out;
  229. //
  230. // ss_out << "out_" << it->first;
  231. // if (not coordinator->exist_out_port(ss_out.str())) {
  232. // coordinator->add_out_port(ss_out.str());
  233. // }
  234. // if (not ParallelBuiltFlatGraphManager::exist_link(
  235. // ParallelBuiltFlatGraphManager::_simulators[it->first],
  236. // "out", coordinator, ss_out.str())) {
  237. // ParallelBuiltFlatGraphManager::add_link(
  238. // ParallelBuiltFlatGraphManager::_simulators[it->first],
  239. // "out", coordinator, ss_out.str());
  240. // }
  241. // }
  242. }
  243. void init() { }
  244. void start(common::DoubleTime::type /* t */) { }
  245. void transition(
  246. const common::Models<common::DoubleTime>& /* receivers */,
  247. common::DoubleTime::type /* t */) { }
  248. ~ParallelBuiltFlatGraphManager() override = default;
  249. };
  250. class ParallelHierarchicalGraphManager :
  251. public artis::pdevs::GraphManager<common::DoubleTime, CellParameters, GridGraphManagerParameters> {
  252. public:
  253. enum submodels {
  254. S1_1 = 0, S1_2, S2_1, S2_2
  255. };
  256. ParallelHierarchicalGraphManager(
  257. common::Coordinator<common::DoubleTime>* coordinator,
  258. const CellParameters& parameters,
  259. const GridGraphManagerParameters& graph_parameters)
  260. :
  261. artis::pdevs::GraphManager<common::DoubleTime, CellParameters,
  262. GridGraphManagerParameters>(
  263. coordinator, parameters, graph_parameters)
  264. {
  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. {
  304. for (typename Coordinators::const_iterator it = _coordinators.begin();
  305. it != _coordinators.end(); ++it) {
  306. delete *it;
  307. }
  308. }
  309. void init()
  310. {
  311. std::for_each(_coordinators.begin(), _coordinators.end(),
  312. [this](ParallelCoordinator* coordinator) {
  313. coordinator->set_sender(
  314. (dynamic_cast< artis::pdevs::multithreading::Coordinator<
  315. artis::common::DoubleTime,
  316. ParallelHierarchicalGraphManager,
  317. CellParameters,
  318. GridGraphManagerParameters>*>(this->coordinator()))->get_sender());
  319. });
  320. }
  321. void start(common::DoubleTime::type t)
  322. {
  323. std::for_each(_coordinators.begin(), _coordinators.end(),
  324. [t](ParallelCoordinator* coordinator) {
  325. coordinator->get_sender().send(
  326. artis::pdevs::multithreading::start_message<
  327. artis::common::DoubleTime>(t));
  328. });
  329. }
  330. void transition(const common::Models<common::DoubleTime>& receivers,
  331. artis::common::DoubleTime::type t)
  332. {
  333. std::for_each(receivers.begin(), receivers.end(),
  334. [this, t](const common::Model<common::DoubleTime>* model) {
  335. if (not model->is_atomic()) {
  336. typename Coordinators::const_iterator itc =
  337. std::find(_coordinators.begin(),
  338. _coordinators.end(), model);
  339. (*itc)->get_sender().send(
  340. artis::pdevs::multithreading::transition_message<
  341. artis::common::DoubleTime>(t));
  342. }
  343. });
  344. }
  345. private:
  346. typedef artis::pdevs::multithreading::Coordinator<
  347. common::DoubleTime,
  348. ParallelBuiltFlatGraphManager,
  349. CellParameters,
  350. GridGraphManagerParameters
  351. > ParallelCoordinator;
  352. typedef std::vector<ParallelCoordinator*> Coordinators;
  353. Coordinators _coordinators;
  354. };
  355. }
  356. }
  357. }
  358. } // namespace artis tests multithreading lifegame
  359. #endif