Parcourir la source

Add new formalism: dsde

Eric Ramat il y a 4 ans
Parent
commit
088948cec9

+ 7 - 0
src/artis-star/common/Coordinator.hpp

@@ -119,6 +119,11 @@ namespace artis {
                 }
             }
 
+            virtual void remove_model(const typename Time::type& t, common::Model<Time>* model)
+            {
+                model->finish(t);
+            }
+
             void restore(const common::context::State<Time>& state)
             {
                 Model<Time>::restore(state);
@@ -140,6 +145,8 @@ namespace artis {
             }
 
 // DEVS methods
+            virtual void finish(const typename Time::type& t) = 0;
+
             virtual common::Value
             observe(const typename Time::type& t, unsigned int index) const = 0;
 

+ 12 - 1
src/artis-star/common/GraphManager.hpp

@@ -68,9 +68,20 @@ namespace artis {
 
             const common::ModelMap<Time>& child_map() const { return _child_map; }
 
+            common::Model<Time>* child_map(size_t index) const { return _child_map.at(index); }
+
             const common::ModelsMap<Time>& children_map() const { return _children_map; }
 
-            common::Coordinator<Time>* get_coordinator() const { return _coordinator; }
+            common::Coordinator<Time>* coordinator() const { return _coordinator; }
+
+            virtual void remove_child(unsigned int index)
+            {
+                common::Model<Time>* child = _child_map[index];
+
+                _children.erase(std::find(_children.begin(), _children.end(), child));
+                _child_map[index] = nullptr;
+                _child_map.erase(index);
+            }
 
             void restore(const common::context::State<Time>& state)
             {

+ 53 - 24
src/artis-star/common/Links.hpp

@@ -40,10 +40,10 @@ namespace artis {
         class Node;
 
         template<class Time>
-        class Links : public std::multimap<Node<Time>,
-                Node<Time> > {
-        public:
+        class Links : public std::multimap<Node<Time>, Node<Time> > {
+            typedef std::multimap<Node<Time>, Node<Time> > type;
 
+        public:
             typedef std::pair<
                     typename Links<Time>::const_iterator,
                     typename Links<Time>::const_iterator
@@ -53,19 +53,12 @@ namespace artis {
 
             virtual ~Links() { }
 
-            void add(Model<Time>* out_model,
-                    unsigned int out_port_index,
-                    Model<Time>* in_model,
-                    unsigned int in_port_index)
+            void add(Model<Time>* out_model, unsigned int out_port_index,
+                    Model<Time>* in_model, unsigned int in_port_index)
             {
-                std::multimap<Node<Time>,
-                        Node<Time> >::insert(
-                        std::pair<Node<Time>,
-                                Node<Time> >(
-                                Node<Time>(
-                                        out_model, out_port_index),
-                                Node<Time>(
-                                        in_model, in_port_index)));
+                type::insert(std::pair<Node<Time>, Node<Time> >(
+                        Node<Time>(out_model, out_port_index),
+                        Node<Time>(in_model, in_port_index)));
             }
 
             bool exist(Model<Time>* out_model,
@@ -75,9 +68,7 @@ namespace artis {
             {
                 std::pair<typename Links<Time>::const_iterator,
                         typename Links<Time>::const_iterator> it =
-                        std::multimap<Node<Time>,
-                                Node<Time> >::equal_range(
-                                Node<Time>(out_model, out_port_index));
+                        type::equal_range(Node<Time>(out_model, out_port_index));
                 typename Links<Time>::const_iterator it2 = it.first;
                 bool found = false;
 
@@ -89,13 +80,51 @@ namespace artis {
                 return found;
             }
 
-            Links::Result find(Model<Time>* out_model,
-                    unsigned int out_port_index) const
+            typename Links<Time>::const_iterator
+            find(Model<Time>* out_model, unsigned int out_port_index,
+                    Model<Time>* in_model, unsigned int in_port_index) const
+            {
+                std::pair<typename Links<Time>::const_iterator,
+                        typename Links<Time>::const_iterator> it =
+                        type::equal_range(Node<Time>(out_model, out_port_index));
+                typename Links<Time>::const_iterator it2 = it.first;
+                bool found = false;
+
+                while (not found and it2 != it.second) {
+                    found = it2->second == Node<Time>(
+                            in_model, in_port_index);
+                    if (not found) {
+                        ++it2;
+                    }
+                }
+                return it2;
+            }
+
+            Links::Result find(Model<Time>* out_model, unsigned int out_port_index) const
+            {
+                return type::equal_range(common::Node<Time>(out_model, out_port_index));
+            }
+
+            void remove(common::Model<Time>* src_model, unsigned int src_port_index,
+                    common::Model<Time>* dst_model, unsigned int dst_port_index)
+            {
+                typename Links<Time>::const_iterator result = find(src_model, src_port_index, dst_model, dst_port_index);
+
+                this->erase(result);
+            }
+
+            void remove_links(common::Model<Time>* model)
             {
-                return std::multimap<Node<Time>,
-                        Node<Time> >::equal_range(
-                        common::Node<Time>(
-                                out_model, out_port_index));
+                typename Links<Time>::iterator it = this->begin();
+
+                while (it != this->end()) {
+                    if (it->first.get_model() == model or it->second.get_model() == model) {
+                        this->erase(it);
+                        it = this->begin();
+                    } else {
+                        ++it;
+                    }
+                }
             }
 
             std::string to_string(int level = 0) const

+ 2 - 0
src/artis-star/common/Model.hpp

@@ -247,6 +247,8 @@ namespace artis {
             typename Time::type get_tn() const { return _tn; }
 
             // devs methods
+            virtual void finish(const typename Time::type& t) = 0;
+
             virtual common::Value observe(const typename Time::type& t,
                     unsigned int index) const = 0;
 

+ 2 - 0
src/artis-star/common/Simulator.hpp

@@ -53,6 +53,8 @@ namespace artis {
             }
 
 // DEVS methods
+            virtual void finish(const typename Time::type& t) = 0;
+
             virtual common::Value observe(const typename Time::type& t,
                     unsigned int index) const = 0;
 

+ 5 - 1
src/artis-star/common/scheduler/HeapScheduler.hpp

@@ -25,7 +25,7 @@
  */
 
 #ifndef COMMON_SCHEDULER_HEAP_SCHEDULER_HPP
-#define COMMON_SCHEDULER_HEAP_SCHEDULER_HPP 1
+#define COMMON_SCHEDULER_HEAP_SCHEDULER_HPP
 
 #include <artis-star/common/InternalEvent.hpp>
 
@@ -110,6 +110,10 @@ namespace artis {
                     }
                 }
 
+                void remove_model(model_type* model) {
+                    type::erase(model->handle()._handle);
+                }
+
                 std::string to_string() const
                 {
                     std::stringstream ss;

+ 1 - 1
src/artis-star/common/scheduler/SchedulerHandle.hpp

@@ -25,7 +25,7 @@
  */
 
 #ifndef COMMON_SCHEDULER_SCHEDULER_HANDLE_HPP
-#define COMMON_SCHEDULER_SCHEDULER_HANDLE_HPP 1
+#define COMMON_SCHEDULER_SCHEDULER_HANDLE_HPP
 
 namespace artis {
     namespace common {

+ 1 - 1
src/artis-star/common/scheduler/VectorScheduler.hpp

@@ -25,7 +25,7 @@
  */
 
 #ifndef COMMON_SCHEDULER_VECTOR_SCHEDULER_HPP
-#define COMMON_SCHEDULER_VECTOR_SCHEDULER_HPP 1
+#define COMMON_SCHEDULER_VECTOR_SCHEDULER_HPP
 
 #include <artis-star/common/InternalEvent.hpp>
 #include <artis-star/common/scheduler/SchedulerHandle.hpp>

+ 3 - 1
src/artis-star/common/utils/FunctionType.hpp

@@ -35,7 +35,7 @@ namespace artis {
         class FunctionType {
         public:
             enum Values {
-                NONE = 0, CONSTRUCTOR, I_MESSAGE, POST_EVENT, S_MESSAGE, Y_MESSAGE,
+                NONE = 0, CONSTRUCTOR, FINISH, I_MESSAGE, POST_EVENT, S_MESSAGE, Y_MESSAGE,
                 DELTA_INT, DELTA_EXT, DELTA_CONF, TA, LAMBDA, START, OUTPUT, TRANSITION
             };
 
@@ -46,6 +46,8 @@ namespace artis {
                     return "none";
                 case CONSTRUCTOR:
                     return "constructor";
+                case FINISH:
+                    return "finish";
                 case I_MESSAGE:
                     return "i_message";
                 case POST_EVENT:

+ 1 - 0
src/artis-star/kernel/CMakeLists.txt

@@ -1,3 +1,4 @@
+ADD_SUBDIRECTORY(dsde)
 ADD_SUBDIRECTORY(dtss)
 ADD_SUBDIRECTORY(pdevs)
 ADD_SUBDIRECTORY(sss)

+ 11 - 0
src/artis-star/kernel/dsde/CMakeLists.txt

@@ -0,0 +1,11 @@
+INCLUDE_DIRECTORIES(
+        ${ARTIS_BINARY_DIR}/src
+        ${ARTIS_SOURCE_DIR}/src
+        ${Boost_INCLUDE_DIRS})
+
+LINK_DIRECTORIES(
+        ${Boost_LIBRARY_DIRS})
+
+SET(DSDE_HPP Coordinator.hpp Executive.hpp GraphManager.hpp)
+
+INSTALL(FILES ${DSDE_HPP} DESTINATION ${ARTIS_INCLUDE_DIRS}/kernel/dsde)

+ 392 - 0
src/artis-star/kernel/dsde/Coordinator.hpp

@@ -0,0 +1,392 @@
+/**
+ * @file kernel/dsde/Coordinator.hpp
+ * @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/>.
+ */
+
+#ifndef DSDE_COORDINATOR
+#define DSDE_COORDINATOR 1
+
+#include <artis-star/common/Coordinator.hpp>
+#include <artis-star/common/Parameters.hpp>
+#include <artis-star/common/Scheduler.hpp>
+#include <artis-star/common/utils/String.hpp>
+#include <artis-star/common/utils/Trace.hpp>
+#include <artis-star/kernel/pdevs/Simulator.hpp>
+#include <artis-star/kernel/dsde/Executive.hpp>
+#include <artis-star/kernel/dsde/GraphManager.hpp>
+
+#include <cassert>
+
+namespace artis {
+    namespace dsde {
+
+        template<class Time,
+                class GraphManager,
+                class Executive,
+                class Parameters = common::NoParameters,
+                class GraphParameters = common::NoParameters>
+        class Coordinator : public common::Coordinator<Time> {
+            typedef Coordinator<Time, GraphManager, Executive, Parameters, GraphParameters> type;
+
+        public:
+            typedef Parameters parameters_type;
+            typedef GraphParameters graph_parameters_type;
+
+            Coordinator(const std::string& name, const Parameters& parameters,
+                    const GraphParameters& graph_parameters)
+                    :
+                    common::Model<Time>(name),
+                    common::Coordinator<Time>(name),
+                    _graph_manager(this, parameters, graph_parameters),
+                    _executive(parameters, graph_parameters, _graph_manager)
+            {
+                _graph_manager.add_child(0, &_executive);
+            }
+
+            virtual ~Coordinator() { }
+
+            common::GraphManager<Time>& get_graph_manager() { return _graph_manager; }
+
+            const common::GraphManager<Time>& get_graph_manager() const { return _graph_manager; }
+
+            virtual std::string to_string(int level) const
+            {
+                std::ostringstream ss;
+
+                ss << common::String::make_spaces(level * 2) << "dsde coordinator \""
+                   << type::get_name() << "\":" << std::endl;
+                ss << _graph_manager.to_string(level + 1);
+                return ss.str();
+            }
+
+            void restore(const common::context::State<Time>& state)
+            {
+                common::Coordinator<Time>::restore(state);
+                for (auto& child : _graph_manager.children()) {
+                    _event_table.init(child->get_tn(), child);
+                }
+            }
+
+            virtual void finish(const typename Time::type& t)
+            {
+#ifndef WITH_TRACE
+                (void) t;
+#endif
+
+#ifdef WITH_TRACE
+                common::Trace<Time>::trace()
+                        << common::TraceElement<Time>(type::get_name(), t,
+                                common::FormalismType::DSDE,
+                                common::FunctionType::FINISH,
+                                common::LevelType::FORMALISM);
+                common::Trace<Time>::trace().flush();
+#endif
+            }
+
+            typename Time::type start(const typename Time::type& t)
+            {
+//             Network Simulator Start Message
+//                When receive (START,t)
+//                  send (START,t) to {I | I ∈ C}
+//                  tl ← t
+//                  tn ← min{tn,I | I ∈ C}
+//                End
+
+#ifdef WITH_TRACE
+                common::Trace<Time>::trace()
+                        << common::TraceElement<Time>(type::get_name(), t,
+                                common::FormalismType::DSDE,
+                                common::FunctionType::I_MESSAGE,
+                                common::LevelType::FORMALISM)
+                        << ": BEFORE => " << "tl = " << type::_tl << " ; tn = "
+                        << type::_tn;
+                common::Trace<Time>::trace().flush();
+#endif
+
+                assert(_graph_manager.children().size() > 0);
+
+                for (auto& child : _graph_manager.children()) {
+                    _event_table.init(child->start(t), child);
+                }
+                type::_tl = t;
+                type::_tn = _event_table.get_current_time();
+
+#ifdef WITH_TRACE
+                common::Trace<Time>::trace()
+                        << common::TraceElement<Time>(type::get_name(), t,
+                                common::FormalismType::DSDE,
+                                common::FunctionType::I_MESSAGE,
+                                common::LevelType::FORMALISM)
+                        << ": AFTER => " << "tl = " << type::_tl
+                        << " ; tn = " << type::_tn;
+                common::Trace<Time>::trace().flush();
+#endif
+
+                return type::_tn;
+            }
+
+            void output(const typename Time::type& t)
+            {
+//             Network Simulator Output Function
+//                When receive (OUTPUT,t)
+//                  if t = tn then
+//                    send (OUTPUT,t) to {I | I ∈ C}
+//                    y ← Zn (× I ∈ In (y_t))
+//                  else
+//                    y ← φ
+//                  endIf
+//                End
+
+#ifdef WITH_TRACE
+                common::Trace<Time>::trace()
+                        << common::TraceElement<Time>(type::get_name(), t,
+                                common::FormalismType::PDEVS,
+                                common::FunctionType::S_MESSAGE,
+                                common::LevelType::FORMALISM)
+                        << ": BEFORE => " << "tl = " << type::_tl << " ; tn = "
+                        << type::_tn << " ; scheduler = " << _event_table.to_string();
+                common::Trace<Time>::trace().flush();
+#endif
+
+                assert(t == type::_tn);
+
+                common::Models<Time> I_N = _event_table.get_current_models(t);
+
+#ifdef WITH_TRACE
+                common::Trace<Time>::trace()
+                        << common::TraceElement<Time>(type::get_name(), t,
+                                common::FormalismType::PDEVS,
+                                common::FunctionType::S_MESSAGE,
+                                common::LevelType::FORMALISM)
+                        << ": I_N = " << I_N.to_string();
+                common::Trace<Time>::trace().flush();
+#endif
+
+                for (auto& model : I_N) {
+                    model->output(t);
+                }
+
+#ifdef WITH_TRACE
+                common::Trace<Time>::trace()
+                        << common::TraceElement<Time>(type::get_name(), t,
+                                common::FormalismType::PDEVS,
+                                common::FunctionType::S_MESSAGE,
+                                common::LevelType::FORMALISM)
+                        << ": AFTER => " << "tl = " << type::_tl << " ; tn = "
+                        << type::_tn << " ; scheduler = " << _event_table.to_string();
+                common::Trace<Time>::trace().flush();
+#endif
+
+            }
+
+            typename Time::type transition(const typename Time::type& t)
+            {
+//             Network Simulator Transition
+//                When receive (TRANSITION,t,x)
+//                  if t ∉ [tl ,tn ] then ERROR endIf
+//                  if t < tn and x = φ then RETURN endIf
+//                  D' ← D
+//                  send (TRANSITION,t,Z_I ( × j ∈ I_I(v_j))) to {I | I ∈ D}
+//                  send (TRANSITION,t,Z_χ ( × j ∈ I_χ(v_j))) to χ
+//                  send (START,t) to {I | I ∈ D − D' }
+//                  tl ← t
+//                  tn ← min{tn,I | I ∈ C}
+//                End
+
+#ifdef WITH_TRACE
+                common::Trace<Time>::trace()
+                        << common::TraceElement<Time>(type::get_name(), t,
+                                common::FormalismType::PDEVS,
+                                common::FunctionType::S_MESSAGE,
+                                common::LevelType::FORMALISM)
+                        << ": BEFORE => " << "tl = " << type::_tl << " ; tn = "
+                        << type::_tn << " ; scheduler = " << _event_table.to_string();
+                common::Trace<Time>::trace().flush();
+#endif
+
+                assert(t >= type::_tl and t <= type::_tn);
+
+                common::Models<Time> receivers = _event_table.get_current_models(t);
+
+                add_models_with_inputs(receivers);
+
+#ifdef WITH_TRACE
+                common::Trace<Time>::trace()
+                        << common::TraceElement<Time>(type::get_name(), t,
+                                common::FormalismType::PDEVS,
+                                common::FunctionType::S_MESSAGE,
+                                common::LevelType::FORMALISM)
+                        << ": receivers = " << receivers.to_string();
+                common::Trace<Time>::trace().flush();
+#endif
+
+                bool found = false;
+
+                for (auto& model : receivers) {
+                    if (model != &_executive) {
+                        _event_table.put(model->transition(t), model);
+                    } else {
+                        found = true;
+                    }
+                }
+                if (found) {
+                    _event_table.put(_executive.transition(t), &_executive);
+
+                    if (not _graph_manager.new_models().empty()) {
+                        for (auto& child : _graph_manager.new_models()) {
+                            _event_table.init(child->start(t), child);
+                        }
+                        _graph_manager.clear_new_models();
+                    }
+                }
+
+                update_event_table(t);
+                type::_tl = t;
+                type::_tn = _event_table.get_current_time();
+                type::clear_bag();
+
+#ifdef WITH_TRACE
+                common::Trace<Time>::trace()
+                        << common::TraceElement<Time>(type::get_name(), t,
+                                common::FormalismType::PDEVS,
+                                common::FunctionType::S_MESSAGE,
+                                common::LevelType::FORMALISM)
+                        << ": AFTER => " << "tl = " << type::_tl << " ; tn = "
+                        << type::_tn << " ; scheduler = " << _event_table.to_string();
+                common::Trace<Time>::trace().flush();
+#endif
+
+                return type::_tn;
+            }
+
+            void post_event(const typename Time::type& t,
+                    const common::ExternalEvent<Time>& event)
+            {
+
+#ifdef WITH_TRACE
+                common::Trace<Time>::trace()
+                        << common::TraceElement<Time>(type::get_name(), t,
+                                common::FormalismType::PDEVS,
+                                common::FunctionType::POST_EVENT,
+                                common::LevelType::FORMALISM)
+                        << ": BEFORE => " << event.to_string();
+                common::Trace<Time>::trace().flush();
+#endif
+
+                type::add_event(event);
+                _graph_manager.post_event(t, event);
+                update_event_table(t);
+                type::_tn = _event_table.get_current_time();
+
+#ifdef WITH_TRACE
+                common::Trace<Time>::trace()
+                        << common::TraceElement<Time>(type::get_name(), t,
+                                common::FormalismType::PDEVS,
+                                common::FunctionType::POST_EVENT,
+                                common::LevelType::FORMALISM)
+                        << ": AFTER => " << event.to_string();
+                common::Trace<Time>::trace().flush();
+#endif
+
+            }
+
+            typename Time::type dispatch_events(
+                    const common::Bag<Time>& bag,
+                    const typename Time::type& t)
+            {
+
+#ifdef WITH_TRACE
+                common::Trace<Time>::trace()
+                        << common::TraceElement<Time>(type::get_name(), t,
+                                common::FormalismType::PDEVS,
+                                common::FunctionType::Y_MESSAGE,
+                                common::LevelType::FORMALISM)
+                        << ": BEFORE => " << "tl = " << type::_tl << " ; tn = "
+                        << type::_tn << " ; bag = " << bag.to_string()
+                        << " ; " << _event_table.to_string();
+                common::Trace<Time>::trace().flush();
+#endif
+
+                _graph_manager.dispatch_events(bag, t);
+                update_event_table(t);
+                type::_tn = _event_table.get_current_time();
+
+#ifdef WITH_TRACE
+                common::Trace<Time>::trace()
+                        << common::TraceElement<Time>(type::get_name(), t,
+                                common::FormalismType::PDEVS,
+                                common::FunctionType::Y_MESSAGE,
+                                common::LevelType::FORMALISM)
+                        << ": AFTER => " << "tl = " << type::_tl << " ; tn = " << type::_tn
+                        << " ; " << _event_table.to_string();
+                common::Trace<Time>::trace().flush();
+#endif
+
+                return type::_tn;
+            }
+
+            common::Value observe(const typename Time::type& /* t */,
+                    unsigned int /* index */) const
+            {
+                assert(false);
+                return common::Value();
+            }
+
+            void add_models_with_inputs(common::Models<Time>& receivers)
+            {
+                for (auto& model : _graph_manager.children()) {
+                    if (model->event_number() > 0) {
+                        if (std::find(receivers.begin(), receivers.end(), model)
+                                == receivers.end()) {
+                            receivers.push_back(model);
+                        }
+                    }
+                }
+            }
+
+            void remove_model(const typename Time::type& t, common::Model<Time>* model) override
+            {
+                common::Coordinator<Time>::remove_model(t, model);
+                _event_table.remove_model(model);
+            }
+
+            void update_event_table(typename Time::type t)
+            {
+                for (auto& model : _graph_manager.children()) {
+                    if (model->event_number() > 0) {
+                        _event_table.put(t, model);
+                    }
+                }
+            }
+
+        protected:
+            GraphManager _graph_manager;
+            dsde::ExecutiveSimulator<Time, Executive, Parameters, GraphParameters> _executive;
+            common::SchedulerType _event_table;
+        };
+
+    }
+} // namespace artis dsde
+
+#endif

+ 363 - 0
src/artis-star/kernel/dsde/Executive.hpp

@@ -0,0 +1,363 @@
+/**
+ * @file kernel/dsde/Executive.hpp
+ * @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/>.
+ */
+
+#ifndef DSDE_EXECUTIVE
+#define DSDE_EXECUTIVE
+
+#include <artis-star/kernel/dsde/GraphManager.hpp>
+#include <artis-star/kernel/pdevs/Dynamics.hpp>
+
+namespace artis {
+    namespace dsde {
+
+        template<class Time, class Dynamics, class Parameters, class GraphParameters>
+        class ExecutiveSimulator;
+
+        template<class Time, class Dynamics,
+                class Parameters = common::NoParameters,
+                class GraphParameters = common::NoParameters>
+        class ExecutiveContext {
+            typedef ExecutiveSimulator<Time, Dynamics, Parameters, GraphParameters> Simulator;
+
+        public:
+            ExecutiveContext(const Parameters& parameters, const GraphParameters& graph_parameters,
+                    Simulator* simulator)
+                    :
+                    _parameters(parameters), _graph_parameters(graph_parameters),
+                    _simulator(simulator) { }
+
+            virtual ~ExecutiveContext() { }
+
+            const GraphParameters& graph_parameters() const { return _graph_parameters; }
+
+            const Parameters& parameters() const { return _parameters; }
+
+            Simulator* simulator() const { return _simulator; }
+
+        private:
+            const Parameters& _parameters;
+            const GraphParameters& _graph_parameters;
+            Simulator* _simulator;
+        };
+
+        template<class Time, class Dynamics,
+                class Parameters = common::NoParameters,
+                class GraphParameters = common::NoParameters>
+        class ExecutiveSimulator : public common::Simulator<Time> {
+            typedef ExecutiveSimulator<Time, Dynamics, Parameters, GraphParameters> type;
+
+        public :
+            ExecutiveSimulator(const Parameters& parameters,
+                    const GraphParameters& graph_parameters,
+                    GraphManager<Time, Parameters, GraphParameters>& graph_manager)
+                    :
+                    common::Model<Time>("executive"),
+                    common::Simulator<Time>("executive"),
+                    _dynamics(ExecutiveContext<Time, Dynamics, Parameters, GraphParameters>(
+                            parameters, graph_parameters, this), graph_manager) { }
+
+            ~ExecutiveSimulator() { }
+
+            const Dynamics& dynamics() const { return _dynamics; }
+
+            virtual void restore(const common::context::State<Time>& state)
+            {
+                common::Simulator<Time>::restore(state);
+                _dynamics.restore(state);
+            }
+
+            virtual void save(common::context::State<Time>& state) const
+            {
+                common::Simulator<Time>::save(state);
+                _dynamics.save(state);
+            }
+
+            virtual std::string to_string(int level) const
+            {
+                std::ostringstream ss;
+
+                ss << common::String::make_spaces(level * 2) << "executive simulator \""
+                   << type::get_name() << "\"" << std::endl;
+                return ss.str();
+            }
+
+            virtual void finish(const typename Time::type& t)
+            {
+#ifndef WITH_TRACE
+                (void) t;
+#endif
+
+#ifdef WITH_TRACE
+                common::Trace<Time>::trace()
+                        << common::TraceElement<Time>(type::get_name(), t,
+                                common::FormalismType::DSDE,
+                                common::FunctionType::FINISH,
+                                common::LevelType::FORMALISM);
+                common::Trace<Time>::trace().flush();
+#endif
+            }
+
+            typename Time::type start(const typename Time::type& t)
+            {
+//                When i-message(t)
+//                  tl = t - e
+//                  tn = tl + ta(s)
+//                End
+
+#ifdef WITH_TRACE
+                common::Trace<Time>::trace()
+                        << common::TraceElement<Time>(type::get_name(), t,
+                                common::FormalismType::DSDE,
+                                common::FunctionType::I_MESSAGE,
+                                common::LevelType::FORMALISM)
+                        << ": BEFORE => " << "tl = " << type::_tl << " ; tn = "
+                        << type::_tn;
+                common::Trace<Time>::trace().flush();
+#endif
+
+                type::_tl = t;
+                type::_tn = type::_tl + _dynamics.start(t);
+
+#ifdef WITH_TRACE
+                common::Trace<Time>::trace()
+                        << common::TraceElement<Time>(type::get_name(), t,
+                                common::FormalismType::DSDE,
+                                common::FunctionType::I_MESSAGE,
+                                common::LevelType::FORMALISM)
+                        << ": AFTER => " << "tl = " << type::_tl << " ; tn = "
+                        << type::_tn;
+                common::Trace<Time>::trace().flush();
+#endif
+
+                return type::_tn;
+            }
+
+            common::Value observe(const typename Time::type& t,
+                    unsigned int index) const { return _dynamics.observe(t, index); }
+
+            void output(const typename Time::type& t)
+            {
+//                When *-message(t)
+//                  if (t = tn) then
+//                    y = lambda(s)
+//                    send y-message(y,t) to parent
+//                End
+
+#ifdef WITH_TRACE
+                common::Trace<Time>::trace()
+                        << common::TraceElement<Time>(type::get_name(), t,
+                                common::FormalismType::DSDE,
+                                common::FunctionType::OUTPUT,
+                                common::LevelType::FORMALISM)
+                                << ": BEFORE";
+                common::Trace<Time>::trace().flush();
+#endif
+
+                if (t == type::_tn) {
+                    common::Bag<Time> bag = _dynamics.lambda(t);
+
+                    if (not bag.empty()) {
+                        for (auto& event : bag) {
+                            event.set_model(this);
+                        }
+                        dynamic_cast < common::Coordinator<Time>* >(
+                                type::get_parent())->dispatch_events(bag, t);
+                    }
+                }
+
+#ifdef WITH_TRACE
+                common::Trace<Time>::trace()
+                        << common::TraceElement<Time>(type::get_name(), t,
+                                common::FormalismType::DSDE,
+                                common::FunctionType::OUTPUT,
+                                common::LevelType::FORMALISM)
+                                << ": AFTER";
+                common::Trace<Time>::trace().flush();
+#endif
+
+            }
+
+            void post_event(const typename Time::type& t,
+                    const common::ExternalEvent<Time>& event)
+            {
+
+#ifndef WITH_TRACE
+                (void) t;
+#endif
+
+#ifdef WITH_TRACE
+                common::Trace<Time>::trace()
+                        << common::TraceElement<Time>(type::get_name(), t,
+                                common::FormalismType::DSDE,
+                                common::FunctionType::POST_EVENT,
+                                common::LevelType::FORMALISM)
+                        << ": BEFORE => " << event.to_string();
+                common::Trace<Time>::trace().flush();
+#endif
+
+                type::add_event(event);
+
+#ifdef WITH_TRACE
+                common::Trace<Time>::trace()
+                        << common::TraceElement<Time>(type::get_name(), t,
+                                common::FormalismType::DSDE,
+                                common::FunctionType::POST_EVENT,
+                                common::LevelType::FORMALISM)
+                        << ": AFTER => " << event.to_string();
+                common::Trace<Time>::trace().flush();
+#endif
+
+            }
+
+            typename Time::type transition(const typename Time::type& t)
+            {
+//                When x-message(t)
+//                  if (x is empty and t = tn) then
+//                    s = delta_int(s)
+//                  else if (x isn't empty and t = tn)
+//                    s = delta_conf(s,x)
+//                  else if (x isn't empty and t < tn)
+//                    e = t - tl
+//                    s = delta_ext(s,e,x)
+//                  tn = t + ta(s)
+//                  tl = t
+//                End
+
+#ifdef WITH_TRACE
+                common::Trace<Time>::trace()
+                        << common::TraceElement<Time>(type::get_name(), t,
+                                common::FormalismType::DSDE,
+                                common::FunctionType::S_MESSAGE,
+                                common::LevelType::FORMALISM)
+                        << ": BEFORE => " << "tl = " << type::_tl << " ; tn = "
+                        << type::_tn;
+                common::Trace<Time>::trace().flush();
+#endif
+
+                assert(type::_tl <= t and t <= type::_tn);
+
+                if (t == type::_tn) {
+                    if (type::event_number() == 0) {
+                        _dynamics.dint(t);
+                    } else {
+                        _dynamics.dconf(t, t - type::_tl, type::get_bag());
+                    }
+                } else {
+                    _dynamics.dext(t, t - type::_tl, type::get_bag());
+                }
+                type::_tn = t + _dynamics.ta(t);
+                type::_tl = t;
+                type::clear_bag();
+
+#ifdef WITH_TRACE
+                common::Trace<Time>::trace()
+                        << common::TraceElement<Time>(type::get_name(), t,
+                                common::FormalismType::DSDE,
+                                common::FunctionType::S_MESSAGE,
+                                common::LevelType::FORMALISM)
+                        << ": AFTER => " << "tl = " << type::_tl << " ; tn = " << type::_tn;
+                common::Trace<Time>::trace().flush();
+#endif
+
+                return type::_tn;
+            }
+
+        private :
+            Dynamics _dynamics;
+        };
+
+        template<class Time, class Dyn, class Parameters = common::NoParameters, class GraphParameters = common::NoParameters>
+        class ExecutiveDynamics : public common::States<Time, Dyn> {
+            typedef dsde::ExecutiveSimulator<Time, Dyn, Parameters, GraphParameters> Simulator;
+
+        public:
+            ExecutiveDynamics(
+                    const ExecutiveContext<Time, Dyn, Parameters, GraphParameters>& context)
+                    :
+                    _simulator(context.simulator()), _name("executive") { }
+
+            virtual ~ExecutiveDynamics() { }
+
+            virtual void dconf(typename Time::type /* t */, typename Time::type /* e */,
+                    const common::Bag<Time>& /* bag */) { }
+
+            virtual void dint(typename Time::type /* t */) { }
+
+            virtual void dext(typename Time::type /* t */, typename Time::type /* e */,
+                    const common::Bag<Time>& /* bag */) { }
+
+            virtual typename Time::type
+            start(typename Time::type /* time */) { return Time::infinity; }
+
+            virtual typename Time::type
+            ta(typename Time::type /* time */) const { return Time::infinity; }
+
+            virtual common::Bag<Time>
+            lambda(typename Time::type /* time */) const { return common::Bag<Time>(); }
+
+            virtual common::Value observe(const typename Time::type& /* t */,
+                    unsigned int /* index */) const { return common::Value(); }
+
+            const std::string& get_name() const { return _name; }
+
+            void restore(const common::context::State<Time>& state)
+            {
+                common::States<Time, Dyn>::restore(static_cast<Dyn*>(this), state);
+            }
+
+            void save(common::context::State<Time>& state) const
+            {
+                common::States<Time, Dyn>::save(static_cast<const Dyn*>(this), state);
+            }
+
+        private:
+            Simulator* _simulator;
+            std::string _name;
+        };
+
+        template<class Time, class Dyn, class Parameters = common::NoParameters, class GraphParameters = common::NoParameters>
+        class Executive : public dsde::ExecutiveDynamics<Time, Dyn, Parameters, GraphParameters> {
+        public:
+            Executive(const ExecutiveContext<Time, Dyn, Parameters, GraphParameters>& context,
+                    dsde::GraphManager<Time, Parameters, GraphParameters>& graph_manager)
+                    :
+                    dsde::ExecutiveDynamics<Time, Dyn, Parameters, GraphParameters>(context),
+                    _graph_manager(graph_manager) { }
+
+            ~Executive() override = default;
+
+        protected:
+            dsde::GraphManager<Time, Parameters, GraphParameters>& graph_manager()
+            { return _graph_manager; }
+
+        private:
+            dsde::GraphManager<Time, Parameters, GraphParameters>& _graph_manager;
+        };
+
+    }
+}
+
+#endif

+ 124 - 0
src/artis-star/kernel/dsde/GraphManager.hpp

@@ -0,0 +1,124 @@
+/**
+ * @file kernel/dsde/GraphManager.hpp
+ * @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/>.
+ */
+
+#ifndef DSDE_GRAPH_MANAGER
+#define DSDE_GRAPH_MANAGER
+
+#include <artis-star/kernel/pdevs/GraphManager.hpp>
+
+#include <vector>
+
+namespace artis {
+    namespace dsde {
+
+        template<class Time,
+                class Parameters = common::NoParameters,
+                class GraphParameters = common::NoParameters>
+        class GraphManager : public pdevs::GraphManager<Time, Parameters, GraphParameters> {
+        public:
+            typedef pdevs::GraphManager<Time, Parameters, GraphParameters> super;
+            typedef GraphManager<Time, Parameters, GraphParameters> type;
+
+            GraphManager(common::Coordinator<Time>* coordinator,
+                    const Parameters& parameters,
+                    const GraphParameters& graph_parameters)
+                    :
+                    pdevs::GraphManager<Time, Parameters, GraphParameters>(coordinator, parameters,
+                            graph_parameters) { }
+
+            ~GraphManager() override
+            {
+                for (auto m: _models) {
+                    delete m;
+                }
+            }
+
+            virtual void add_dynamic_child(unsigned int index, common::Model<Time>* child)
+            {
+                super::add_child(index, child);
+                _models.push_back(child);
+                _new_models.push_back(child);
+            }
+
+            virtual void add_dynamic_children(unsigned int index, common::Model<Time>* child)
+            {
+                super::add_children(index, child);
+                _models.push_back(child);
+                _new_models.push_back(child);
+            }
+
+            void add_link(unsigned int source_model_index, unsigned int source_port_index,
+                    unsigned int destination_model_index, unsigned int destination_port_index)
+            {
+                common::Model<Time>* source_model = super::child_map(source_model_index);
+                common::Model<Time>* destination_model = super::child_map(destination_model_index);
+
+                assert(source_model and destination_model);
+
+                this->out({source_model, source_port_index})
+                        >> this->in({destination_model, destination_port_index});
+            }
+
+            void clear_new_models() { _new_models.clear(); }
+
+            std::vector<common::Model<Time>*>& new_models() { return _new_models; }
+
+            void remove_dynamic_child(const typename Time::type& t, unsigned int index)
+            {
+                size_t new_index = index
+                        - (pdevs::GraphManager<Time, Parameters, GraphParameters>::_children.size()
+                                - _models.size());
+
+                new_index -= std::count_if(_models.begin(), _models.end(),
+                        [](common::Model<Time>* model) { return model == nullptr; });
+                type::coordinator()->remove_model(t, _models[new_index]);
+                super::remove_child(index);
+                this->remove_links(_models[new_index]);
+                delete _models[new_index];
+                _models[new_index] = nullptr;
+            }
+
+            void remove_link(unsigned int source_model_index, unsigned int source_port_index,
+                    unsigned int destination_model_index, unsigned int destination_port_index)
+            {
+                common::Model<Time>* source_model = super::child_map(source_model_index);
+                common::Model<Time>* destination_model = super::child_map(destination_model_index);
+
+                assert(source_model and destination_model);
+
+                super::remove_link(source_model, source_port_index, destination_model,
+                        destination_port_index);
+            }
+
+        private:
+            std::vector<common::Model<Time>*> _models;
+            std::vector<common::Model<Time>*> _new_models;
+        };
+
+    }
+}
+
+#endif

+ 2 - 1
src/artis-star/kernel/dtss/Coordinator.hpp

@@ -55,7 +55,8 @@ namespace artis {
             typedef Parameters parameters_type;
             typedef GraphParameters graph_parameters_type;
 
-            Coordinator(const std::string& name, const Parameters& parameters, const GraphParameters& graph_parameters)
+            Coordinator(const std::string& name, const Parameters& parameters,
+                    const GraphParameters& graph_parameters)
                     :
                     common::Model<Time>(name),
                     common::Coordinator<Time>(name),

+ 27 - 23
src/artis-star/kernel/dtss/GraphManager.hpp

@@ -59,12 +59,13 @@ namespace artis {
                 }
             };
 
-            GraphManager(common::Coordinator<Time>* coordinator, const Parameters& /* parameters */,
+            GraphManager(common::Coordinator<Time>* coordinator,
+                    const Parameters& /* parameters */,
                     const GraphParameters& /* graph_parameters */)
                     :
                     common::GraphManager<Time>(coordinator) { }
 
-            virtual ~GraphManager() { }
+            ~GraphManager() override = default;
 
             ModelPort in(ModelPort p)
             {
@@ -78,37 +79,40 @@ namespace artis {
                 return p;
             }
 
-            void dispatch_events(common::Bag<Time> bag,
-                    typename Time::type t)
+            void dispatch_events(common::Bag<Time> bag, typename Time::type t)
             {
                 for (auto& ymsg : bag) {
-                    typename common::Links<Time>::Result result_model =
-                            _link_list.find(ymsg.get_model(),
-                                    ymsg.port_index());
+                    typename common::Links<Time>::Result result_model = _link_list.find(
+                            ymsg.get_model(),
+                            ymsg.port_index());
 
-                    for (typename common::Links<Time>::const_iterator it =
-                            result_model.first; it != result_model.second; ++it) {
-                        // event on output port of coupled model
+                    for (typename common::Links<Time>::const_iterator it = result_model.first;
+                         it != result_model.second; ++it) {
+                        // event on output port of coupled Model
                         if (it->second.get_model() == common::GraphManager<Time>::_coordinator) {
-                            common::Bag<Time> ymessages;
-
-                            ymessages.push_back(
-                                    common::ExternalEvent<Time>(
-                                            it->second, ymsg.data()));
-                            if (common::GraphManager<Time>::_coordinator->get_parent()) {
-                                dynamic_cast < common::Coordinator<Time>* >(
-                                        common::GraphManager<Time>::_coordinator->get_parent())
-                                        ->dispatch_events(ymessages, t);
-                            }
+                            dispatch_events_to_parent(it->second, ymsg.data(), t);
                         } else { // event on input port of internal model
-                            it->second.get_model()->post_event(
-                                    t, common::ExternalEvent<Time>(
-                                            it->second, ymsg.data()));
+                            it->second.get_model()->post_event(t,
+                                    common::ExternalEvent<Time>(it->second, ymsg.data()));
                         }
                     }
                 }
             }
 
+            virtual void
+            dispatch_events_to_parent(common::Node<Time> node, const common::Value& content,
+                    typename Time::type t)
+            {
+                common::Bag<Time> ymessages;
+
+                ymessages.push_back(common::ExternalEvent<Time>(node, content));
+
+                if (common::GraphManager<Time>::_coordinator->get_parent()) {
+                    dynamic_cast < common::Coordinator<Time>* >(common::GraphManager<Time>::_coordinator->get_parent())
+                            ->dispatch_events(ymessages, t);
+                }
+            }
+
             void post_event(typename Time::type t, const common::ExternalEvent<Time>& event)
             {
                 typename common::Links<Time>::Result result =

+ 17 - 1
src/artis-star/kernel/dtss/Simulator.hpp

@@ -86,6 +86,22 @@ namespace artis {
                 _dynamics.save(state);
             }
 
+            virtual void finish(const typename Time::type& t)
+            {
+#ifndef WITH_TRACE
+                (void) t;
+#endif
+
+#ifdef WITH_TRACE
+                common::Trace<Time>::trace()
+                        << common::TraceElement<Time>(type::get_name(), t,
+                                common::FormalismType::DTSS,
+                                common::FunctionType::FINISH,
+                                common::LevelType::FORMALISM);
+                common::Trace<Time>::trace().flush();
+#endif
+            }
+
             typename Time::type start(const typename Time::type& t)
             {
 
@@ -163,7 +179,7 @@ namespace artis {
             {
 
 #ifndef WITH_TRACE
-                (void)t;
+                (void) t;
 #endif
 
 #ifdef WITH_TRACE

+ 1 - 2
src/artis-star/kernel/pdevs/CMakeLists.txt

@@ -6,8 +6,7 @@ INCLUDE_DIRECTORIES(
 LINK_DIRECTORIES(
         ${Boost_LIBRARY_DIRS})
 
-SET(PDEVS_HPP Coordinator.hpp Dynamics.hpp GraphManager.hpp
-        Simulator.hpp)
+SET(PDEVS_HPP Coordinator.hpp Dynamics.hpp GraphManager.hpp Simulator.hpp)
 
 INSTALL(FILES ${PDEVS_HPP} DESTINATION ${ARTIS_INCLUDE_DIRS}/kernel/pdevs)
 

+ 22 - 27
src/artis-star/kernel/pdevs/Coordinator.hpp

@@ -82,10 +82,12 @@ namespace artis {
 
             typename Time::type start(const typename Time::type& t)
             {
-//                When receive (START,t)
-//                  send (START,t) to {I | I ∈ C}
+//                When i-message (i, t) at time t
+//                  for-each d ∈ D do
+//                    send i-message to child d
+//                  sort event-list according to tn,d
 //                  tl ← t
-//                  tn ← min{t N,I | I ∈ C}
+//                  tn ← min{tn,d | d ∈ D}
 //                End
 
 #ifdef WITH_TRACE
@@ -123,20 +125,18 @@ namespace artis {
 
             void output(const typename Time::type& t)
             {
-//                When *-message(t)
-//                  calculate IMM (models with tn = t in scheduler
-//                  calculate INF from IMM
-//                  for each e in IMM U INF
-//                    calculate influencer
-//                    ...
-//                  send done to parent
+//                When *-message (*, t)
+//                  if t != tn then Error
+//                  IMM = {d | (d, th,d) ∈ (event-list & tn,d = tn) }
+//                  for-each r ∈ IMM
+//                    send *-message (*, t) to r
 //                End
 
 #ifdef WITH_TRACE
                 common::Trace<Time>::trace()
                         << common::TraceElement<Time>(type::get_name(), t,
                                 common::FormalismType::PDEVS,
-                                common::FunctionType::OUTPUT,
+                                common::FunctionType::S_MESSAGE,
                                 common::LevelType::FORMALISM)
                         << ": BEFORE => " << "tl = " << type::_tl << " ; tn = "
                         << type::_tn << " ; scheduler = " << _event_table.to_string();
@@ -145,14 +145,13 @@ namespace artis {
 
                 assert(t == type::_tn);
 
-                common::Models<Time> IMM =
-                        _event_table.get_current_models(t);
+                common::Models<Time> IMM = _event_table.get_current_models(t);
 
 #ifdef WITH_TRACE
                 common::Trace<Time>::trace()
                         << common::TraceElement<Time>(type::get_name(), t,
                                 common::FormalismType::PDEVS,
-                                common::FunctionType::OUTPUT,
+                                common::FunctionType::S_MESSAGE,
                                 common::LevelType::FORMALISM)
                         << ": IMM = " << IMM.to_string();
                 common::Trace<Time>::trace().flush();
@@ -166,7 +165,7 @@ namespace artis {
                 common::Trace<Time>::trace()
                         << common::TraceElement<Time>(type::get_name(), t,
                                 common::FormalismType::PDEVS,
-                                common::FunctionType::OUTPUT,
+                                common::FunctionType::S_MESSAGE,
                                 common::LevelType::FORMALISM)
                         << ": AFTER => " << "tl = " << type::_tl << " ; tn = "
                         << type::_tn << " ; scheduler = " << _event_table.to_string();
@@ -177,15 +176,16 @@ namespace artis {
 
             typename Time::type transition(const typename Time::type& t)
             {
-//                When x-message(t)
-//                  receivers = { r | r in children, N in Ir, Z(N,r)(x) isn't empty }
-//                  for each r in receivers
+//                When x-message (x, t)
+//                  if not (tl <= t <= tn) then Error
+//                  receivers = { r | r ∈ children, N ∈ Ir, Z(N,r)(x) isn't empty }
+//                  for each r ∈ receivers
 //                    send x-message(Z(N,r)(x), t) with input value Z(N,r)(x) to r
-//                  for each r in IMM and not in receivers
+//                  for each r  IMM and not in receivers
 //                    send x-message(empty, t) to r
 //                  sort event list according to tn
 //                  tl = t
-//                  tn = min(tn_d | d in D)
+//                  tn = min(tn,d | d ∈ D)
 //                End
 
 #ifdef WITH_TRACE
@@ -201,8 +201,7 @@ namespace artis {
 
                 assert(t >= type::_tl and t <= type::_tn);
 
-                common::Models<Time> receivers =
-                        _event_table.get_current_models(t);
+                common::Models<Time> receivers = _event_table.get_current_models(t);
 
                 add_models_with_inputs(receivers);
 
@@ -270,11 +269,7 @@ namespace artis {
 
             }
 
-/*******************************************************************
- * when y-message(y_d, t) with output y_d from d
- *******************************************************************/
-            typename Time::type dispatch_events(
-                    const common::Bag<Time>& bag,
+            typename Time::type dispatch_events(const common::Bag<Time>& bag,
                     const typename Time::type& t)
             {
 

+ 29 - 9
src/artis-star/kernel/pdevs/GraphManager.hpp

@@ -58,8 +58,7 @@ namespace artis {
 
                 void operator>>(const ModelPort& dst)
                 {
-                    graph_manager->add_link(model, port_index,
-                            dst.model, dst.port_index);
+                    graph_manager->add_link(model, port_index, dst.model, dst.port_index);
                 }
             };
 
@@ -86,7 +85,8 @@ namespace artis {
             void dispatch_events(common::Bag<Time> bag, typename Time::type t)
             {
                 for (auto& ymsg : bag) {
-                    typename common::Links<Time>::Result result_model = _link_list.find(ymsg.get_model(),
+                    typename common::Links<Time>::Result result_model = _link_list.find(
+                            ymsg.get_model(),
                             ymsg.port_index());
 
                     for (typename common::Links<Time>::const_iterator it = result_model.first;
@@ -95,13 +95,15 @@ namespace artis {
                         if (it->second.get_model() == common::GraphManager<Time>::_coordinator) {
                             dispatch_events_to_parent(it->second, ymsg.data(), t);
                         } else { // event on input port of internal model
-                            it->second.get_model()->post_event(t, common::ExternalEvent<Time>(it->second, ymsg.data()));
+                            it->second.get_model()->post_event(t,
+                                    common::ExternalEvent<Time>(it->second, ymsg.data()));
                         }
                     }
                 }
             }
 
-            virtual void dispatch_events_to_parent(common::Node<Time> node, const common::Value& content,
+            virtual void
+            dispatch_events_to_parent(common::Node<Time> node, const common::Value& content,
                     typename Time::type t)
             {
                 common::Bag<Time> ymessages;
@@ -123,10 +125,14 @@ namespace artis {
             void post_event(typename Time::type t, const common::ExternalEvent<Time>& event)
             {
                 typename common::Links<Time>::Result result =
-                        _link_list.find(common::GraphManager<Time>::_coordinator, event.port_index());
-
-                for (typename common::Links<Time>::const_iterator it_r = result.first; it_r != result.second; ++it_r) {
-                    it_r->second.get_model()->post_event(t, common::ExternalEvent<Time>(it_r->second, event.data()));
+                        _link_list.find(common::GraphManager<Time>::_coordinator,
+                                event.port_index());
+
+                for (typename common::Links<Time>::const_iterator it_r = result.first;
+                     it_r != result.second;
+                     ++it_r) {
+                    it_r->second.get_model()->post_event(t,
+                            common::ExternalEvent<Time>(it_r->second, event.data()));
                 }
             }
 
@@ -142,6 +148,20 @@ namespace artis {
                 return ss.str();
             }
 
+        protected:
+            void remove_link(common::Model<Time>* src_model, unsigned int src_port_index,
+                    common::Model<Time>* dst_model, unsigned int dst_port_index)
+            {
+                assert(exist_link(src_model, src_port_index, dst_model, dst_port_index));
+
+                _link_list.remove(src_model, src_port_index, dst_model, dst_port_index);
+            }
+
+            void remove_links(common::Model<Time>* model)
+            {
+                _link_list.remove_links(model);
+            }
+
         private:
             void add_link(common::Model<Time>* src_model, unsigned int src_port_index,
                     common::Model<Time>* dst_model, unsigned int dst_port_index)

+ 16 - 0
src/artis-star/kernel/pdevs/Simulator.hpp

@@ -99,6 +99,22 @@ namespace artis {
                 return ss.str();
             }
 
+            virtual void finish(const typename Time::type& t)
+            {
+#ifndef WITH_TRACE
+                (void) t;
+#endif
+
+#ifdef WITH_TRACE
+                common::Trace<Time>::trace()
+                        << common::TraceElement<Time>(type::get_name(), t,
+                                common::FormalismType::PDEVS,
+                                common::FunctionType::FINISH,
+                                common::LevelType::FORMALISM);
+                common::Trace<Time>::trace().flush();
+#endif
+            }
+
             typename Time::type start(const typename Time::type& t)
             {
 //                When i-message(t)

+ 16 - 0
src/artis-star/kernel/sss/Simulator.hpp

@@ -73,6 +73,22 @@ namespace artis {
 
             virtual std::string to_string(int level) const { return common::Simulator<Time>::to_string(level); }
 
+            virtual void finish(const typename Time::type& t)
+            {
+#ifndef WITH_TRACE
+                (void) t;
+#endif
+
+#ifdef WITH_TRACE
+                common::Trace<Time>::trace()
+                        << common::TraceElement<Time>(type::get_name(), t,
+                                common::FormalismType::SSS,
+                                common::FunctionType::FINISH,
+                                common::LevelType::FORMALISM);
+                common::Trace<Time>::trace().flush();
+#endif
+            }
+
             typename Time::type start(const typename Time::type& t)
             {