Parcourir la source

Ass new example: prey/predator and samrt gardener

Eric Ramat il y a 4 ans
Parent
commit
b6d0d268fb

+ 1 - 1
src/tests/common/CMakeLists.txt

@@ -7,6 +7,6 @@ INCLUDE_DIRECTORIES(
 
 LINK_DIRECTORIES()
 
-ADD_EXECUTABLE(common-tests tests.cpp)
+ADD_EXECUTABLE(common-tests multithreading-tests.cpp time-tests.cpp)
 
 TARGET_LINK_LIBRARIES(common-tests)

+ 49 - 0
src/tests/common/multithreading-tests.cpp

@@ -0,0 +1,49 @@
+/**
+ * @file tests/common/tests.cpp
+ * @author The ARTIS Development Team
+ * See the AUTHORS or Authors.txt file
+ */
+
+/*
+ * ARTIS - the multimodeling and simulation environment
+ * This file is a part of the ARTIS environment
+ *
+ * Copyright (C) 2013-2019 ULCO http://www.univ-littoral.fr
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <artis-star/common/utils/Multithreading.hpp>
+
+#include <tests/catch.hpp>
+
+using namespace artis::common;
+
+TEST_CASE("message queue", "multithreading")
+{
+    MessageQueue queue;
+    int msg;
+
+    queue.push(msg);
+    REQUIRE(true);
+}
+
+TEST_CASE("sender", "multithreading")
+{
+    Sender sender;
+    int msg;
+
+    sender.send(msg);
+    REQUIRE(true);
+}

+ 1 - 1
src/tests/common/tests.cpp

@@ -1,5 +1,5 @@
 /**
- * @file tests/common/tests.cpp
+ * @file tests/common/time-tests.cpp
  * @author The ARTIS Development Team
  * See the AUTHORS or Authors.txt file
  */

+ 2 - 4
src/tests/dtss/models.hpp

@@ -76,7 +76,7 @@ namespace artis {
 
                 }
 
-                artis::common::DoubleTime::type start(artis::common::DoubleTime::type t) override
+                void start(artis::common::DoubleTime::type t) override
                 {
 
 #ifndef WITH_TRACE
@@ -93,7 +93,6 @@ namespace artis {
                     artis::common::Trace<artis::common::DoubleTime>::trace().flush();
 #endif
 
-                    return 0;
                 }
 
                 artis::common::Bag<artis::common::DoubleTime> lambda(artis::common::DoubleTime::type t) const override
@@ -169,7 +168,7 @@ namespace artis {
 #endif
                 }
 
-                artis::common::DoubleTime::type start(artis::common::DoubleTime::type t) override
+                void start(artis::common::DoubleTime::type t) override
                 {
 
 #ifndef WITH_TRACE
@@ -186,7 +185,6 @@ namespace artis {
                     artis::common::Trace<artis::common::DoubleTime>::trace().flush();
 #endif
 
-                    return 0;
                 }
 
                 artis::common::Bag<artis::common::DoubleTime> lambda(

+ 293 - 23
src/tests/multithreading/lifegame/graph_manager.hpp

@@ -39,8 +39,14 @@ namespace artis {
             namespace lifegame {
 
                 struct GridGraphManagerParameters {
-                    unsigned int column_number;
-                    unsigned int line_number;
+                    unsigned int begin_column;
+                    unsigned int end_column;
+                    unsigned int begin_line;
+                    unsigned int end_line;
+                    unsigned int min_column;
+                    unsigned int max_column;
+                    unsigned int min_line;
+                    unsigned int max_line;
                 };
 
                 class FlatGraphManager
@@ -57,61 +63,76 @@ namespace artis {
                             artis::pdevs::GraphManager<common::DoubleTime, CellParameters, GridGraphManagerParameters>(
                                     coordinator, parameters, graph_parameters)
                     {
-                        for (unsigned int i = 0; i < graph_parameters.column_number; ++i) {
-                            for (unsigned int j = 0; j < graph_parameters.line_number; ++j) {
+                        unsigned int column_number =
+                                graph_parameters.end_column - graph_parameters.begin_column + 1;
+                        unsigned int line_number =
+                                graph_parameters.end_line - graph_parameters.begin_line + 1;
+
+                        for (unsigned int i = graph_parameters.begin_column;
+                             i <= graph_parameters.end_column; ++i) {
+                            for (unsigned int j = graph_parameters.begin_line;
+                                 j <= graph_parameters.end_line; ++j) {
                                 std::ostringstream ss;
 
-                                ss << "C_" << (i + 1) << "_" << (j + 1);
+                                ss << "C_" << i << "_" << j;
 
-                                Simulator* cell = new Simulator(ss.str(), parameters);
+                                auto cell = new Simulator(ss.str(), parameters);
 
                                 _cells.push_back(cell);
                                 add_children(CELL, cell);
                             }
                         }
-                        for (int i = 0; i < (int)graph_parameters.column_number; ++i) {
-                            for (int j = 0; j < (int)graph_parameters.line_number; ++j) {
-                                int index = i * graph_parameters.line_number + j;
+                        for (int i = 0; i < (int) column_number; ++i) {
+                            for (int j = 0; j < (int) line_number; ++j) {
+                                int index = i * (int) line_number + j;
 
                                 // north
                                 if (j - 1 >= 0) {
                                     out({_cells[index], Cell::OUT})
-                                            >> in({_cells[i * graph_parameters.line_number + j - 1], Cell::IN});
+                                            >> in({_cells[i * line_number + j - 1],
+                                                   Cell::IN});
                                 }
                                 // south
-                                if (j + 1 < (int)graph_parameters.line_number) {
+                                if (j + 1 < (int) line_number) {
                                     out({_cells[index], Cell::OUT})
-                                            >> in({_cells[i * graph_parameters.line_number + j + 1], Cell::IN});
+                                            >> in({_cells[i * line_number + j + 1],
+                                                   Cell::IN});
                                 }
                                 // west
                                 if (i - 1 >= 0) {
                                     out({_cells[index], Cell::OUT})
-                                            >> in({_cells[(i - 1) * graph_parameters.line_number + j], Cell::IN});
+                                            >> in({_cells[(i - 1) * line_number
+                                                    + j], Cell::IN});
                                 }
                                 // east
-                                if (i + 1 < (int)graph_parameters.column_number) {
+                                if (i + 1 < (int) column_number) {
                                     out({_cells[index], Cell::OUT})
-                                            >> in({_cells[(i + 1) * graph_parameters.line_number + j], Cell::IN});
+                                            >> in({_cells[(i + 1) * line_number
+                                                    + j], Cell::IN});
                                 }
                                 // north west
                                 if (j - 1 >= 0 and i - 1 >= 0) {
                                     out({_cells[index], Cell::OUT})
-                                            >> in({_cells[(i - 1) * graph_parameters.line_number + j - 1], Cell::IN});
+                                            >> in({_cells[(i - 1) * line_number + j
+                                                    - 1], Cell::IN});
                                 }
                                 // south west
-                                if (j + 1 < (int)graph_parameters.line_number and i - 1 >= 0) {
+                                if (j + 1 < (int) line_number and i - 1 >= 0) {
                                     out({_cells[index], Cell::OUT})
-                                            >> in({_cells[(i - 1) * graph_parameters.line_number + j + 1], Cell::IN});
+                                            >> in({_cells[(i - 1) * line_number + j
+                                                    + 1], Cell::IN});
                                 }
                                 // north east
-                                if (j - 1 >= 0 and i + 1 < (int)graph_parameters.column_number) {
+                                if (j - 1 >= 0 and i + 1 < (int) column_number) {
                                     out({_cells[index], Cell::OUT})
-                                            >> in({_cells[(i + 1) * graph_parameters.line_number + j - 1], Cell::IN});
+                                            >> in({_cells[(i + 1) * line_number + j
+                                                    - 1], Cell::IN});
                                 }
                                 // south east
-                                if (j + 1 < (int)graph_parameters.line_number and i + 1 < (int)graph_parameters.column_number) {
+                                if (j + 1 < (int) line_number and i + 1 < (int) column_number) {
                                     out({_cells[index], Cell::OUT})
-                                            >> in({_cells[(i + 1) * graph_parameters.line_number + j + 1], Cell::IN});
+                                            >> in({_cells[(i + 1) * line_number + j
+                                                    + 1], Cell::IN});
                                 }
                             }
                         }
@@ -119,7 +140,8 @@ namespace artis {
 
                     ~FlatGraphManager() override
                     {
-                        std::for_each(_cells.begin(), _cells.end(), std::default_delete<Simulator>());
+                        std::for_each(_cells.begin(), _cells.end(),
+                                std::default_delete<Simulator>());
                     }
 
                 private:
@@ -129,6 +151,254 @@ namespace artis {
                     Simulators _cells;
                 };
 
+                class ParallelBuiltFlatGraphManager : public FlatGraphManager {
+                public:
+                    ParallelBuiltFlatGraphManager(
+                            common::Coordinator<common::DoubleTime>* coordinator,
+                            const CellParameters& parameters,
+                            const GridGraphManagerParameters& graph_parameters)
+                            :
+                            FlatGraphManager(coordinator, parameters, graph_parameters)
+                    {
+                        // inputs
+                        unsigned int k = 0;
+
+                        // top / bottom
+                        {
+                            int j_top = (int) graph_parameters.begin_line - 1;
+                            int j_bottom = (int) graph_parameters.end_line + 1;
+
+                            for (int i = (int) graph_parameters.begin_column - 1;
+                                 i <= (int) graph_parameters.end_column + 1; ++i) {
+                                std::ostringstream ss_out;
+
+                                ++k;
+                                if (i >= (int) graph_parameters.min_column
+                                        and i <= (int) graph_parameters.max_column
+                                        and j_top >= (int) graph_parameters.min_line) {
+                                    ss_out << "in_" << i << "_" << j_top;
+                                    coordinator->add_in_port({k, ss_out.str()});
+                                }
+                                ++k;
+                                if (i >= (int) graph_parameters.min_column
+                                        and i <= (int) graph_parameters.max_column
+                                        and j_bottom <= (int) graph_parameters.max_line) {
+                                    ss_out << "in_" << i << "_" << j_bottom;
+                                    coordinator->add_in_port({k, ss_out.str()});
+                                }
+                            }
+                        }
+                        // left / right
+                        {
+                            int i_left = (int) graph_parameters.begin_column - 1;
+                            int i_right = (int) graph_parameters.end_column + 1;
+
+                            for (int j = (int) graph_parameters.begin_line;
+                                 j <= (int) graph_parameters.end_line; ++j) {
+                                std::ostringstream ss_out;
+
+                                ++k;
+                                if (j >= (int) graph_parameters.min_line
+                                        and j <= (int) graph_parameters.max_line
+                                        and i_left >= (int) graph_parameters.min_column) {
+                                    ss_out << "out_" << i_left << "_" << j;
+                                    coordinator->add_in_port({k, ss_out.str()});
+                                }
+                                ++k;
+                                if (j >= (int) graph_parameters.min_line
+                                        and j <= (int) graph_parameters.max_line
+                                        and i_right >= (int) graph_parameters.max_column) {
+                                    ss_out << "out_" << i_right << "_" << j;
+                                    coordinator->add_in_port({k, ss_out.str()});
+                                }
+                            }
+                        }
+
+                        // outputs
+                        k = 0;
+
+                        // top / bottom
+                        {
+                            int j_top = (int) graph_parameters.begin_line;
+                            int j_bottom = (int) graph_parameters.end_line;
+
+                            for (int i = (int) graph_parameters.begin_column;
+                                 i <= (int) graph_parameters.end_column; ++i) {
+                                std::ostringstream ss_out;
+
+                                ++k;
+                                ss_out << "out_" << i << "_" << j_top;
+                                coordinator->add_out_port({k, ss_out.str()});
+                                ++k;
+                                ss_out << "out_" << i << "_" << j_bottom;
+                                coordinator->add_out_port({k, ss_out.str()});
+                            }
+                        }
+                        // left / right
+                        {
+                            int i_left = (int) graph_parameters.begin_column;
+                            int i_right = (int) graph_parameters.end_column;
+
+                            for (int j = (int) graph_parameters.begin_line + 1;
+                                 j <= (int) graph_parameters.end_line - 1; ++j) {
+                                std::ostringstream ss_out;
+
+                                ++k;
+                                ss_out << "out_" << i_left << "_" << j;
+                                coordinator->add_out_port({k, ss_out.str()});
+                                ++k;
+                                ss_out << "out_" << i_right << "_" << j;
+                                coordinator->add_out_port({k, ss_out.str()});
+                            }
+                        }
+
+
+                        //                        for (Edges::const_iterator it = parameters._output_edges.begin();
+//                             it != parameters._output_edges.end(); ++it) {
+//                            std::ostringstream ss_out;
+//
+//                            ss_out << "out_" << it->first;
+//                            if (not coordinator->exist_out_port(ss_out.str())) {
+//                                coordinator->add_out_port(ss_out.str());
+//                            }
+//                            if (not ParallelBuiltFlatGraphManager::exist_link(
+//                                    ParallelBuiltFlatGraphManager::_simulators[it->first],
+//                                    "out", coordinator, ss_out.str())) {
+//                                ParallelBuiltFlatGraphManager::add_link(
+//                                        ParallelBuiltFlatGraphManager::_simulators[it->first],
+//                                        "out", coordinator, ss_out.str());
+//                            }
+//                        }
+                    }
+
+                    void init() { }
+
+                    void start(common::DoubleTime::type /* t */) { }
+
+                    void transition(
+                            const common::Models<common::DoubleTime>& /* receivers */,
+                            common::DoubleTime::type /* t */) { }
+
+                    ~ParallelBuiltFlatGraphManager() override = default;
+                };
+
+                class ParallelHierarchicalGraphManager :
+                        public artis::pdevs::GraphManager<common::DoubleTime, CellParameters, GridGraphManagerParameters> {
+                public:
+                    enum submodels {
+                        S1_1 = 0, S1_2, S2_1, S2_2
+                    };
+
+                    ParallelHierarchicalGraphManager(
+                            common::Coordinator<common::DoubleTime>* coordinator,
+                            const CellParameters& parameters,
+                            const GridGraphManagerParameters& graph_parameters)
+                            :
+                            artis::pdevs::GraphManager<common::DoubleTime, CellParameters,
+                                    GridGraphManagerParameters>(
+                                    coordinator, parameters, graph_parameters)
+                    {
+                        // build coordinators (graphs)
+                        for (unsigned int i = 0; i < 2; ++i) {
+                            for (unsigned int j = 0; j < 2; ++j) {
+                                ParallelCoordinator* sub_coordinator = nullptr;
+                                std::ostringstream ss;
+
+                                ss << "S_" << (i + 1) << "_" << (j + 1);
+                                sub_coordinator = new ParallelCoordinator(ss.str(),
+                                        parameters,
+                                        {i * 5 + 1, (i + 1) * 5, j * 5 + 1, (j + 1) * 5,
+                                         1, 10, 1, 10});
+                                _coordinators.push_back(sub_coordinator);
+                                add_child(i, sub_coordinator);
+                            }
+                        }
+
+                        // builds internal connections (edges)
+//                        for (Connections::const_iterator it = parent_connections.begin();
+//                             it != parent_connections.end(); ++it) {
+//                            const Connection& connection = *it;
+//                            std::ostringstream ss_out;
+//                            std::ostringstream ss_in;
+//
+//                            ss_out << "out_" << connection.first.second;
+//                            ss_in << "in_" << connection.first.second;
+//
+//                            if (not exist_link(
+//                                    _coordinators[connection.first.first - 1],
+//                                    ss_out.str(),
+//                                    _coordinators[connection.second.first - 1],
+//                                    ss_in.str())) {
+//                                add_link(
+//                                        _coordinators[connection.first.first - 1],
+//                                        ss_out.str(),
+//                                        _coordinators[connection.second.first - 1],
+//                                        ss_in.str());
+//                            }
+//                        }
+
+                    }
+
+                    ~ParallelHierarchicalGraphManager() override
+                    {
+                        for (typename Coordinators::const_iterator it = _coordinators.begin();
+                             it != _coordinators.end(); ++it) {
+                            delete *it;
+                        }
+                    }
+
+                    void init()
+                    {
+                        std::for_each(_coordinators.begin(), _coordinators.end(),
+                                [this](ParallelCoordinator* coordinator) {
+                                    coordinator->set_sender(
+                                            (dynamic_cast< artis::pdevs::multithreading::Coordinator<
+                                                    artis::common::DoubleTime,
+                                                    ParallelHierarchicalGraphManager,
+                                                    CellParameters,
+                                                    GridGraphManagerParameters>*>(this->coordinator()))->get_sender());
+                                });
+                    }
+
+                    void start(common::DoubleTime::type t)
+                    {
+                        std::for_each(_coordinators.begin(), _coordinators.end(),
+                                [t](ParallelCoordinator* coordinator) {
+                                    coordinator->get_sender().send(
+                                            artis::pdevs::multithreading::start_message<
+                                                    artis::common::DoubleTime>(t));
+                                });
+                    }
+
+                    void transition(const common::Models<common::DoubleTime>& receivers,
+                            artis::common::DoubleTime::type t)
+                    {
+                        std::for_each(receivers.begin(), receivers.end(),
+                                [this, t](const common::Model<common::DoubleTime>* model) {
+                                    if (not model->is_atomic()) {
+                                        typename Coordinators::const_iterator itc =
+                                                std::find(_coordinators.begin(),
+                                                        _coordinators.end(), model);
+
+                                        (*itc)->get_sender().send(
+                                                artis::pdevs::multithreading::transition_message<
+                                                        artis::common::DoubleTime>(t));
+                                    }
+                                });
+                    }
+
+                private:
+                    typedef artis::pdevs::multithreading::Coordinator<
+                            common::DoubleTime,
+                            ParallelBuiltFlatGraphManager,
+                            CellParameters,
+                            GridGraphManagerParameters
+                    > ParallelCoordinator;
+                    typedef std::vector<ParallelCoordinator*> Coordinators;
+
+                    Coordinators _coordinators;
+                };
+
             }
         }
     }

+ 229 - 227
src/tests/multithreading/lifegame/main.cpp

@@ -36,6 +36,214 @@ using namespace artis::common;
 using namespace std::chrono;
 using namespace artis::tests::multithreading::lifegame;
 
+CellParameters parameters({
+        {
+                {"C_1_1", 3},
+                {"C_1_2", 5},
+                {"C_1_3", 5},
+                {"C_1_4", 5},
+                {"C_1_5", 5},
+                {"C_1_6", 5},
+                {"C_1_7", 5},
+                {"C_1_8", 5},
+                {"C_1_9", 5},
+                {"C_1_10", 3},
+                {"C_2_1", 5},
+                {"C_2_2", 8},
+                {"C_2_3", 8},
+                {"C_2_4", 8},
+                {"C_2_5", 8},
+                {"C_2_6", 8},
+                {"C_2_7", 8},
+                {"C_2_8", 8},
+                {"C_2_9", 8},
+                {"C_2_10", 5},
+                {"C_3_1", 5},
+                {"C_3_2", 8},
+                {"C_3_3", 8},
+                {"C_3_4", 8},
+                {"C_3_5", 8},
+                {"C_3_6", 8},
+                {"C_3_7", 8},
+                {"C_3_8", 8},
+                {"C_3_9", 8},
+                {"C_3_10", 5},
+                {"C_4_1", 5},
+                {"C_4_2", 8},
+                {"C_4_3", 8},
+                {"C_4_4", 8},
+                {"C_4_5", 8},
+                {"C_4_6", 8},
+                {"C_4_7", 8},
+                {"C_4_8", 8},
+                {"C_4_9", 8},
+                {"C_4_10", 5},
+                {"C_5_1", 5},
+                {"C_5_2", 8},
+                {"C_5_3", 8},
+                {"C_5_4", 8},
+                {"C_5_5", 8},
+                {"C_5_6", 8},
+                {"C_5_7", 8},
+                {"C_5_8", 8},
+                {"C_5_9", 8},
+                {"C_5_10", 5},
+                {"C_6_1", 5},
+                {"C_6_2", 8},
+                {"C_6_3", 8},
+                {"C_6_4", 8},
+                {"C_6_5", 8},
+                {"C_6_6", 8},
+                {"C_6_7", 8},
+                {"C_6_8", 8},
+                {"C_6_9", 8},
+                {"C_6_10", 5},
+                {"C_7_1", 5},
+                {"C_7_2", 8},
+                {"C_7_3", 8},
+                {"C_7_4", 8},
+                {"C_7_5", 8},
+                {"C_7_6", 8},
+                {"C_7_7", 8},
+                {"C_7_8", 8},
+                {"C_7_9", 8},
+                {"C_7_10", 5},
+                {"C_8_1", 5},
+                {"C_8_2", 8},
+                {"C_8_3", 8},
+                {"C_8_4", 8},
+                {"C_8_5", 8},
+                {"C_8_6", 8},
+                {"C_8_7", 8},
+                {"C_8_8", 8},
+                {"C_8_9", 8},
+                {"C_8_10", 5},
+                {"C_9_1", 5},
+                {"C_9_2", 8},
+                {"C_9_3", 8},
+                {"C_9_4", 8},
+                {"C_9_5", 8},
+                {"C_9_6", 8},
+                {"C_9_7", 8},
+                {"C_9_8", 8},
+                {"C_9_9", 8},
+                {"C_9_10", 5},
+                {"C_10_1", 3},
+                {"C_10_2", 5},
+                {"C_10_3", 5},
+                {"C_10_4", 5},
+                {"C_10_5", 5},
+                {"C_10_6", 5},
+                {"C_10_7", 5},
+                {"C_10_8", 5},
+                {"C_10_9", 5},
+                {"C_10_10", 3}
+        },
+        {
+                {"C_1_1", false},
+                {"C_1_2", false},
+                {"C_1_3", false},
+                {"C_1_4", false},
+                {"C_1_5", false},
+                {"C_1_6", false},
+                {"C_1_7", false},
+                {"C_1_8", false},
+                {"C_1_9", false},
+                {"C_1_10", false},
+                {"C_2_1", false},
+                {"C_2_2", false},
+                {"C_2_3", false},
+                {"C_2_4", false},
+                {"C_2_5", true},
+                {"C_2_6", true},
+                {"C_2_7", false},
+                {"C_2_8", false},
+                {"C_2_9", false},
+                {"C_2_10", false},
+                {"C_3_1", false},
+                {"C_3_2", false},
+                {"C_3_3", false},
+                {"C_3_4", true},
+                {"C_3_5", false},
+                {"C_3_6", false},
+                {"C_3_7", true},
+                {"C_3_8", false},
+                {"C_3_9", false},
+                {"C_3_10", false},
+                {"C_4_1", false},
+                {"C_4_2", false},
+                {"C_4_3", true},
+                {"C_4_4", false},
+                {"C_4_5", false},
+                {"C_4_6", false},
+                {"C_4_7", false},
+                {"C_4_8", true},
+                {"C_4_9", false},
+                {"C_4_10", false},
+                {"C_5_1", false},
+                {"C_5_2", true},
+                {"C_5_3", false},
+                {"C_5_4", false},
+                {"C_5_5", false},
+                {"C_5_6", false},
+                {"C_5_7", false},
+                {"C_5_8", false},
+                {"C_5_9", true},
+                {"C_5_10", false},
+                {"C_6_1", false},
+                {"C_6_2", true},
+                {"C_6_3", false},
+                {"C_6_4", false},
+                {"C_6_5", false},
+                {"C_6_6", false},
+                {"C_6_7", false},
+                {"C_6_8", false},
+                {"C_6_9", true},
+                {"C_6_10", false},
+                {"C_7_1", false},
+                {"C_7_2", false},
+                {"C_7_3", true},
+                {"C_7_4", false},
+                {"C_7_5", false},
+                {"C_7_6", false},
+                {"C_7_7", false},
+                {"C_7_8", true},
+                {"C_7_9", false},
+                {"C_7_10", false},
+                {"C_8_1", false},
+                {"C_8_2", false},
+                {"C_8_3", false},
+                {"C_8_4", true},
+                {"C_8_5", false},
+                {"C_8_6", false},
+                {"C_8_7", true},
+                {"C_8_8", false},
+                {"C_8_9", false},
+                {"C_8_10", false},
+                {"C_9_1", false},
+                {"C_9_2", false},
+                {"C_9_3", false},
+                {"C_9_4", false},
+                {"C_9_5", true},
+                {"C_9_6", true},
+                {"C_9_7", false},
+                {"C_9_8", false},
+                {"C_9_9", false},
+                {"C_9_10", false},
+                {"C_10_1",  false},
+                {"C_10_2",  false},
+                {"C_10_3",  false},
+                {"C_10_4",  false},
+                {"C_10_5",  false},
+                {"C_10_6",  false},
+                {"C_10_7",  false},
+                {"C_10_8",  false},
+                {"C_10_9",  false},
+                {"C_10_10",  false}
+        }
+});
+GridGraphManagerParameters graph_parameters({1, 10, 1, 10, 1, 10, 1, 10});
+
 class View : public artis::observer::View<artis::common::DoubleTime> {
 public:
     View()
@@ -44,22 +252,21 @@ public:
     }
 };
 
-void show_state(const GridGraphManagerParameters& graph_parameters,
-        const artis::observer::View<artis::common::DoubleTime>& view)
+void show_state(const artis::observer::View<artis::common::DoubleTime>& view)
 {
     std::vector<std::vector<std::vector<bool> > > states;
 
     for (unsigned int t = 0; t <= 11; ++t) {
         states.emplace_back(std::vector<std::vector<bool> >());
-        for (unsigned int i = 0; i < graph_parameters.column_number; ++i) {
+        for (unsigned int i = graph_parameters.begin_column - 1; i < graph_parameters.end_column; ++i) {
             states[t].emplace_back(std::vector<bool>());
-            for (unsigned int j = 0; j < graph_parameters.line_number; ++j) {
+            for (unsigned int j = graph_parameters.begin_line - 1; j < graph_parameters.end_line; ++j) {
                 states[t][i].emplace_back(false);
             }
         }
     }
-    for (unsigned int i = 0; i < graph_parameters.column_number; ++i) {
-        for (unsigned int j = 0; j < graph_parameters.line_number; ++j) {
+    for (unsigned int i = graph_parameters.begin_column - 1; i < graph_parameters.end_column; ++i) {
+        for (unsigned int j = graph_parameters.begin_line - 1; j < graph_parameters.end_line; ++j) {
             std::ostringstream ss;
 
             ss << ":root:C_" << (i + 1) << "_" << (j + 1) << ":state";
@@ -70,13 +277,15 @@ void show_state(const GridGraphManagerParameters& graph_parameters,
                 bool state;
 
                 value.second(state);
-                states[(int) value.first][i][j] = state;
+                if (value.first < 11) {
+                    states[(int) value.first][i][j] = state;
+                }
             }
         }
     }
     for (unsigned int t = 0; t <= 10; ++t) {
-        for (unsigned int i = 0; i < graph_parameters.column_number; ++i) {
-            for (unsigned int j = 0; j < graph_parameters.line_number; ++j) {
+        for (unsigned int i = graph_parameters.begin_column - 1; i < graph_parameters.end_column; ++i) {
+            for (unsigned int j = graph_parameters.begin_line - 1; j < graph_parameters.end_line; ++j) {
                 std::cout << states[t][i][j] << " ";
             }
             std::cout << std::endl;
@@ -87,214 +296,6 @@ void show_state(const GridGraphManagerParameters& graph_parameters,
 
 double lifegame_monothreading()
 {
-    CellParameters parameters({
-            {
-                    {"C_1_1", 3},
-                    {"C_1_2", 5},
-                    {"C_1_3", 5},
-                    {"C_1_4", 5},
-                    {"C_1_5", 5},
-                    {"C_1_6", 5},
-                    {"C_1_7", 5},
-                    {"C_1_8", 5},
-                    {"C_1_9", 5},
-                    {"C_1_10", 3},
-                    {"C_2_1", 5},
-                    {"C_2_2", 8},
-                    {"C_2_3", 8},
-                    {"C_2_4", 8},
-                    {"C_2_5", 8},
-                    {"C_2_6", 8},
-                    {"C_2_7", 8},
-                    {"C_2_8", 8},
-                    {"C_2_9", 8},
-                    {"C_2_10", 5},
-                    {"C_3_1", 5},
-                    {"C_3_2", 8},
-                    {"C_3_3", 8},
-                    {"C_3_4", 8},
-                    {"C_3_5", 8},
-                    {"C_3_6", 8},
-                    {"C_3_7", 8},
-                    {"C_3_8", 8},
-                    {"C_3_9", 8},
-                    {"C_3_10", 5},
-                    {"C_4_1", 5},
-                    {"C_4_2", 8},
-                    {"C_4_3", 8},
-                    {"C_4_4", 8},
-                    {"C_4_5", 8},
-                    {"C_4_6", 8},
-                    {"C_4_7", 8},
-                    {"C_4_8", 8},
-                    {"C_4_9", 8},
-                    {"C_4_10", 5},
-                    {"C_5_1", 5},
-                    {"C_5_2", 8},
-                    {"C_5_3", 8},
-                    {"C_5_4", 8},
-                    {"C_5_5", 8},
-                    {"C_5_6", 8},
-                    {"C_5_7", 8},
-                    {"C_5_8", 8},
-                    {"C_5_9", 8},
-                    {"C_5_10", 5},
-                    {"C_6_1", 5},
-                    {"C_6_2", 8},
-                    {"C_6_3", 8},
-                    {"C_6_4", 8},
-                    {"C_6_5", 8},
-                    {"C_6_6", 8},
-                    {"C_6_7", 8},
-                    {"C_6_8", 8},
-                    {"C_6_9", 8},
-                    {"C_6_10", 5},
-                    {"C_7_1", 5},
-                    {"C_7_2", 8},
-                    {"C_7_3", 8},
-                    {"C_7_4", 8},
-                    {"C_7_5", 8},
-                    {"C_7_6", 8},
-                    {"C_7_7", 8},
-                    {"C_7_8", 8},
-                    {"C_7_9", 8},
-                    {"C_7_10", 5},
-                    {"C_8_1", 5},
-                    {"C_8_2", 8},
-                    {"C_8_3", 8},
-                    {"C_8_4", 8},
-                    {"C_8_5", 8},
-                    {"C_8_6", 8},
-                    {"C_8_7", 8},
-                    {"C_8_8", 8},
-                    {"C_8_9", 8},
-                    {"C_8_10", 5},
-                    {"C_9_1", 5},
-                    {"C_9_2", 8},
-                    {"C_9_3", 8},
-                    {"C_9_4", 8},
-                    {"C_9_5", 8},
-                    {"C_9_6", 8},
-                    {"C_9_7", 8},
-                    {"C_9_8", 8},
-                    {"C_9_9", 8},
-                    {"C_9_10", 5},
-                    {"C_10_1", 3},
-                    {"C_10_2", 5},
-                    {"C_10_3", 5},
-                    {"C_10_4", 5},
-                    {"C_10_5", 5},
-                    {"C_10_6", 5},
-                    {"C_10_7", 5},
-                    {"C_10_8", 5},
-                    {"C_10_9", 5},
-                    {"C_10_10", 3}
-            },
-            {
-                    {"C_1_1", false},
-                    {"C_1_2", false},
-                    {"C_1_3", false},
-                    {"C_1_4", false},
-                    {"C_1_5", false},
-                    {"C_1_6", false},
-                    {"C_1_7", false},
-                    {"C_1_8", false},
-                    {"C_1_9", false},
-                    {"C_1_10", false},
-                    {"C_2_1", false},
-                    {"C_2_2", false},
-                    {"C_2_3", false},
-                    {"C_2_4", false},
-                    {"C_2_5", true},
-                    {"C_2_6", true},
-                    {"C_2_7", false},
-                    {"C_2_8", false},
-                    {"C_2_9", false},
-                    {"C_2_10", false},
-                    {"C_3_1", false},
-                    {"C_3_2", false},
-                    {"C_3_3", false},
-                    {"C_3_4", true},
-                    {"C_3_5", false},
-                    {"C_3_6", false},
-                    {"C_3_7", true},
-                    {"C_3_8", false},
-                    {"C_3_9", false},
-                    {"C_3_10", false},
-                    {"C_4_1", false},
-                    {"C_4_2", false},
-                    {"C_4_3", true},
-                    {"C_4_4", false},
-                    {"C_4_5", false},
-                    {"C_4_6", false},
-                    {"C_4_7", false},
-                    {"C_4_8", true},
-                    {"C_4_9", false},
-                    {"C_4_10", false},
-                    {"C_5_1", false},
-                    {"C_5_2", true},
-                    {"C_5_3", false},
-                    {"C_5_4", false},
-                    {"C_5_5", false},
-                    {"C_5_6", false},
-                    {"C_5_7", false},
-                    {"C_5_8", false},
-                    {"C_5_9", true},
-                    {"C_5_10", false},
-                    {"C_6_1", false},
-                    {"C_6_2", true},
-                    {"C_6_3", false},
-                    {"C_6_4", false},
-                    {"C_6_5", false},
-                    {"C_6_6", false},
-                    {"C_6_7", false},
-                    {"C_6_8", false},
-                    {"C_6_9", true},
-                    {"C_6_10", false},
-                    {"C_7_1", false},
-                    {"C_7_2", false},
-                    {"C_7_3", true},
-                    {"C_7_4", false},
-                    {"C_7_5", false},
-                    {"C_7_6", false},
-                    {"C_7_7", false},
-                    {"C_7_8", true},
-                    {"C_7_9", false},
-                    {"C_7_10", false},
-                    {"C_8_1", false},
-                    {"C_8_2", false},
-                    {"C_8_3", false},
-                    {"C_8_4", true},
-                    {"C_8_5", false},
-                    {"C_8_6", false},
-                    {"C_8_7", true},
-                    {"C_8_8", false},
-                    {"C_8_9", false},
-                    {"C_8_10", false},
-                    {"C_9_1", false},
-                    {"C_9_2", false},
-                    {"C_9_3", false},
-                    {"C_9_4", false},
-                    {"C_9_5", true},
-                    {"C_9_6", true},
-                    {"C_9_7", false},
-                    {"C_9_8", false},
-                    {"C_9_9", false},
-                    {"C_9_10", false},
-                    {"C_10_1",  false},
-                    {"C_10_2",  false},
-                    {"C_10_3",  false},
-                    {"C_10_4",  false},
-                    {"C_10_5",  false},
-                    {"C_10_6",  false},
-                    {"C_10_7",  false},
-                    {"C_10_8",  false},
-                    {"C_10_9",  false},
-                    {"C_10_10",  false}
-            }
-    });
-    GridGraphManagerParameters graph_parameters({10, 10});
-
     artis::common::context::Context<artis::common::DoubleTime> context(0, 10);
     artis::common::RootCoordinator<
             DoubleTime, artis::pdevs::Coordinator<
@@ -314,24 +315,25 @@ double lifegame_monothreading()
 
     duration<double> time_span = duration_cast<duration<double> >(t2 - t1);
 
-    show_state(graph_parameters, rc.observer().view("Matrix"));
+    show_state(rc.observer().view("Matrix"));
 
     return time_span.count();
 }
 
 double lifegame_multithreading()
 {
-//    artis::common::RootCoordinator<
-//            DoubleTime, artis::pdevs::multithreading::Coordinator<
-//                    DoubleTime,
-//                    ParallelHierarchicalGraphManager,
-//                    artis::common::NoParameters,
-//                    GraphManagerParameters>
-//    > rc(0, 10, "root", artis::common::NoParameters(), GraphManagerParameters(cluster_number));
+    artis::common::context::Context<artis::common::DoubleTime> context(0, 10);
+    artis::common::RootCoordinator<
+            DoubleTime, artis::pdevs::multithreading::Coordinator<
+                    DoubleTime,
+                    ParallelHierarchicalGraphManager,
+                    CellParameters,
+                    GridGraphManagerParameters>
+    > rc(context, "root", parameters, graph_parameters);
 
     steady_clock::time_point t1 = steady_clock::now();
 
-//    rc.run(context);
+    rc.run(context);
 
     steady_clock::time_point t2 = steady_clock::now();
 
@@ -342,7 +344,7 @@ double lifegame_multithreading()
 
 int main()
 {
-    std::cout << lifegame_monothreading() << std::endl;
+//    std::cout << lifegame_monothreading() << std::endl;
     std::cout << lifegame_multithreading() << std::endl;
     return 0;
 }

+ 69 - 2
src/tests/qss/graph_manager.hpp

@@ -114,7 +114,7 @@ namespace artis {
                     public artis::pdevs::qss::GraphManager<common::DoubleTime, Predator, PreyPredatorParameters> {
             public:
                 enum inputs {
-                    IN_X
+                    IN_X = artis::pdevs::qss::GraphManager<common::DoubleTime, Predator, PreyPredatorParameters>::RESET + 1
                 };
 
                 PredatorGraphManager(common::Coordinator<common::DoubleTime>* coordinator,
@@ -135,7 +135,7 @@ namespace artis {
                     public artis::pdevs::qss::GraphManager<common::DoubleTime, Prey, PreyPredatorParameters> {
             public:
                 enum inputs {
-                    IN_Y
+                    IN_Y = artis::pdevs::qss::GraphManager<common::DoubleTime, Prey, PreyPredatorParameters>::RESET + 1
                 };
 
                 PreyGraphManager(common::Coordinator<common::DoubleTime>* coordinator,
@@ -164,6 +164,14 @@ namespace artis {
                     PREDATOR, PREY
                 };
 
+                enum inputs {
+                    RESET_X, RESET_Y
+                };
+
+                enum outputs {
+                    OUT_X, OUT_Y
+                };
+
                 PreyPredatorGraphManager(common::Coordinator<common::DoubleTime>* coordinator,
                         const PreyPredatorGraphManagerParameters& parameters,
                         const artis::common::NoParameters& graph_parameters)
@@ -175,6 +183,21 @@ namespace artis {
                 {
                     add_child(PREDATOR, &_predator);
                     add_child(PREY, &_prey);
+
+                    coordinator->input_ports({{RESET_X, "reset_x"},
+                                              {RESET_Y, "reset_y"}});
+                    coordinator->output_ports({{OUT_X, "out_x"},
+                                               {OUT_Y, "out_y"}});
+
+                    in({coordinator, RESET_X}) >> in({&_prey, PreyGraphManager::RESET});
+                    in({coordinator, RESET_Y}) >> in({&_prey, PreyGraphManager::IN_Y});
+
+                    in({coordinator, RESET_X}) >> in({&_predator, PredatorGraphManager::IN_X});
+                    in({coordinator, RESET_Y}) >> in({&_predator, PredatorGraphManager::RESET});
+
+                    out({&_prey, PreyGraphManager::OUT}) >> out({coordinator, OUT_X});
+                    out({&_predator, PredatorGraphManager::OUT}) >> out({coordinator, OUT_Y});
+
                     out({&_predator, PredatorGraphManager::OUT})
                             >> in({&_prey, PreyGraphManager::IN_Y});
                     out({&_prey, PreyGraphManager::OUT})
@@ -188,6 +211,50 @@ namespace artis {
                 artis::pdevs::Coordinator<common::DoubleTime, PreyGraphManager, artis::pdevs::qss::QSSParameters<PreyPredatorParameters>> _prey;
             };
 
+            struct PreyPredatorSmartGardenerGraphManagerParameters {
+                PreyPredatorGraphManagerParameters _prey_predator;
+                SmartGardenerParameters _smart_gardener;
+            };
+
+            class PreyPredatorSmartGardenerGraphManager :
+                    public artis::pdevs::GraphManager<common::DoubleTime, PreyPredatorSmartGardenerGraphManagerParameters> {
+            public:
+                enum submodels {
+                    PREY_PREDATOR, SMART_GARDENER
+                };
+
+                PreyPredatorSmartGardenerGraphManager(
+                        common::Coordinator<common::DoubleTime>* coordinator,
+                        const PreyPredatorSmartGardenerGraphManagerParameters& parameters,
+                        const artis::common::NoParameters& graph_parameters)
+                        :
+                        artis::pdevs::GraphManager<common::DoubleTime, PreyPredatorSmartGardenerGraphManagerParameters>(
+                                coordinator, parameters, graph_parameters),
+                        _prey_predator("prey_predator", parameters._prey_predator,
+                                graph_parameters),
+                        _smart_gardener("smart_gardener", parameters._smart_gardener)
+                {
+                    add_child(PREY_PREDATOR, &_prey_predator);
+                    add_child(SMART_GARDENER, &_smart_gardener);
+
+                    out({&_prey_predator, PreyPredatorGraphManager::OUT_X})
+                            >> in({&_smart_gardener, SmartGardener::IN_X});
+                    out({&_prey_predator, PreyPredatorGraphManager::OUT_Y})
+                            >> in({&_smart_gardener, SmartGardener::IN_Y});
+
+                    out({&_smart_gardener, SmartGardener::OUT_X})
+                            >> in({&_prey_predator, PreyPredatorGraphManager::RESET_X});
+                    out({&_smart_gardener, SmartGardener::OUT_Y})
+                            >> in({&_prey_predator, PreyPredatorGraphManager::RESET_Y});
+                }
+
+                ~PreyPredatorSmartGardenerGraphManager() override = default;
+
+            private:
+                artis::pdevs::Coordinator<common::DoubleTime, PreyPredatorGraphManager, PreyPredatorGraphManagerParameters> _prey_predator;
+                artis::pdevs::Simulator<common::DoubleTime, SmartGardener, SmartGardenerParameters> _smart_gardener;
+            };
+
         }
     }
 } // namespace artis tests qss

+ 45 - 2
src/tests/qss/main.cpp

@@ -28,6 +28,7 @@
 
 #include <artis-star/common/RootCoordinator.hpp>
 #include <artis-star/common/observer/Iterator.hpp>
+#include <artis-star/common/observer/Output.hpp>
 
 #include <fstream>
 #include <iostream>
@@ -130,7 +131,6 @@ void run_predator_prey(artis::common::context::Context<artis::common::DoubleTime
             ++it;
         }
     }
-
 }
 
 void test_predator_prey()
@@ -152,8 +152,51 @@ void test_predator_prey()
     run_predator_prey(new_context, parameters);
 }
 
+class PredatorPreySmartGardenerView : public artis::observer::View<artis::common::DoubleTime> {
+public:
+    PredatorPreySmartGardenerView()
+    {
+        selector("PredatorView",
+                {PreyPredatorSmartGardenerGraphManager::PREY_PREDATOR,
+                 PreyPredatorGraphManager::PREDATOR, PredatorGraphManager::S_Integrator,
+                 artis::pdevs::qss::Integrator<artis::common::DoubleTime>::VALUE});
+        selector("PreyView",
+                {PreyPredatorSmartGardenerGraphManager::PREY_PREDATOR,
+                 PreyPredatorGraphManager::PREY, PreyGraphManager::S_Integrator,
+                 artis::pdevs::qss::Integrator<artis::common::DoubleTime>::VALUE});
+    }
+};
+
+void test_predator_prey_smart_gardener()
+{
+    PreyPredatorSmartGardenerGraphManagerParameters parameters = {{{{45.},
+                                                                           {true, true, 0.1, 3},
+                                                                           {0.5, 0.01, 0.01, 0.2}},
+                                                                          {{5000.},
+                                                                                  {true, true, 1, 3},
+                                                                                  {0.5, 0.01, 0.01, 0.2}}},
+                                                                  {2000,  0.25, 0.75, 5}};
+
+    artis::common::context::Context<artis::common::DoubleTime> context(0, 100);
+    artis::common::RootCoordinator<
+            artis::common::DoubleTime, artis::pdevs::Coordinator<
+                    artis::common::DoubleTime,
+                    PreyPredatorSmartGardenerGraphManager,
+                    PreyPredatorSmartGardenerGraphManagerParameters>
+    > rc(context, "root", parameters, artis::common::NoParameters());
+
+    rc.attachView("Value", new PredatorPreySmartGardenerView());
+
+    rc.run(context);
+
+    artis::observer::Output<artis::common::DoubleTime> output(rc.observer());
+
+    output(0, 100, 0.1);
+}
+
 int main()
 {
 //    test_parabola();
-    test_predator_prey();
+//    test_predator_prey();
+    test_predator_prey_smart_gardener();
 }

+ 124 - 0
src/tests/qss/models.hpp

@@ -145,6 +145,130 @@ namespace artis {
                 double _y;
             };
 
+            struct SmartGardenerParameters {
+                double threshold;
+                double prey_proportion;
+                double predator_proportion;
+                double delay;
+            };
+
+            class SmartGardener
+                    : public artis::pdevs::Dynamics<common::DoubleTime, SmartGardener, SmartGardenerParameters> {
+            public:
+                enum inputs {
+                    IN_X, IN_Y
+                };
+                enum outputs {
+                    OUT_X, OUT_Y
+                };
+
+                SmartGardener(const std::string& name,
+                        const artis::pdevs::Context<common::DoubleTime, SmartGardener, SmartGardenerParameters>& context)
+                        :
+                        artis::pdevs::Dynamics<common::DoubleTime, SmartGardener, SmartGardenerParameters>(
+                                name, context),
+                        _threshold(context.parameters().threshold),
+                        _prey_proportion(context.parameters().prey_proportion),
+                        _predator_proportion(context.parameters().predator_proportion),
+                        _delay(context.parameters().delay)
+                {
+                    input_ports({{IN_X, "in_x"},
+                                 {IN_Y, "in_y"}});
+                    output_ports({{OUT_X, "out_x"},
+                                  {OUT_Y, "out_y"}});
+                }
+
+                ~SmartGardener() override = default;
+
+                void dint(typename common::DoubleTime::type /* t */) override
+                {
+                    switch (_phase) {
+                    case INIT:
+                        _phase = IDLE;
+                        _sigma = _delay;
+                        break;
+                    case IDLE:
+                        if (_prey_amount > _threshold) {
+                            _phase = PEST;
+                        } else {
+                            _phase = IDLE;
+                            _sigma = _delay;
+                        }
+                        break;
+                    case PEST:
+                        _phase = IDLE;
+                        _sigma = _delay;
+                        break;
+                    }
+                }
+
+                void
+                dext(typename common::DoubleTime::type /* t */, typename common::DoubleTime::type e,
+                        const common::Bag<common::DoubleTime>& bag) override
+                {
+                    std::for_each(bag.begin(), bag.end(),
+                            [this](const common::ExternalEvent<common::DoubleTime>& event) {
+                                artis::pdevs::qss::IntegratorData data;
+
+                                event.data()(data);
+                                if (event.on_port(IN_X)) {
+                                    _prey_amount = data.value;
+                                } else if (event.on_port(IN_Y)) {
+                                    _predator_amount = data.value;
+                                }
+                            });
+                    _sigma -= e;
+                }
+
+                void start(typename common::DoubleTime::type /* t */) override { _phase = INIT; }
+
+                typename common::DoubleTime::type
+                ta(typename common::DoubleTime::type /* t */) const override
+                {
+                    switch (_phase) {
+                    case INIT:
+                        return 0.0;
+                    case IDLE:
+                        return _sigma;
+                    case PEST:
+                        return 0.0;
+                    }
+                    return common::DoubleTime::infinity;
+                }
+
+                common::Bag<common::DoubleTime>
+                lambda(typename common::DoubleTime::type /* t */) const override
+                {
+                    common::Bag<common::DoubleTime> bag;
+
+                    if (_phase == PEST) {
+                        artis::pdevs::qss::IntegratorData data = {_prey_amount * _prey_proportion};
+
+                        bag.push_back(common::ExternalEvent<common::DoubleTime>(OUT_X, data));
+                        data = {_predator_amount * _predator_proportion};
+                        bag.push_back(common::ExternalEvent<common::DoubleTime>(OUT_Y, data));
+                    }
+                    return bag;
+                }
+
+            private:
+                enum Phase {
+                    INIT, IDLE, PEST
+                };
+
+                // parameters
+                double _threshold;
+                double _prey_proportion;
+                double _predator_proportion;
+                double _delay;
+
+                // state
+                Phase _phase;
+                common::DoubleTime::type _sigma;
+                double _prey_amount;
+                double _predator_amount;
+            };
+
         }
     }
 } // namespace artis tests qss