Browse Source

Add new graph manager

Eric Ramat 10 years ago
parent
commit
6a82a56a25
1 changed files with 973 additions and 0 deletions
  1. 973 0
      src/tests/boost_graph/hierarchical_graph_manager.hpp

+ 973 - 0
src/tests/boost_graph/hierarchical_graph_manager.hpp

@@ -0,0 +1,973 @@
+/**
+ * @file tests/boost_graph/hierarchical_graph_manager.hpp
+ * @author The PARADEVS Development Team
+ * See the AUTHORS or Authors.txt file
+ */
+
+/*
+ * PARADEVS - the multimodeling and simulation environment
+ * This file is a part of the PARADEVS environment
+ *
+ * Copyright (C) 2013-2015 ULCO http://www.univ-litoral.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 __TESTS_BOOST_GRAPH_HIERARCHICAL_GRAPH_MANAGER_HPP
+#define __TESTS_BOOST_GRAPH_HIERARCHICAL_GRAPH_MANAGER_HPP 1
+
+#include <paradevs/common/scheduler/HeapScheduler.hpp>
+
+#include <paradevs/kernel/pdevs/Coordinator.hpp>
+#include <paradevs/kernel/pdevs/GraphManager.hpp>
+#include <paradevs/kernel/pdevs/Simulator.hpp>
+
+#include <tests/boost_graph/models.hpp>
+#include <tests/boost_graph/graph_manager.hpp>
+
+namespace paradevs { namespace tests { namespace boost_graph {
+
+struct RootHierarchicalParameters
+{
+    int level_number;
+    GraphGenerator& generator;
+
+    RootHierarchicalParameters(int level, GraphGenerator& generator) :
+        level_number(level), generator(generator)
+    { }
+};
+
+struct HierarchicalParameters
+{
+    int index;
+    int level_number;
+    std::map < int, int >& cluster;
+    OrientedGraph& graph;
+
+    HierarchicalParameters(int index,
+                           int level,
+                           std::map < int, int >& cluster,
+                           OrientedGraph& graph) :
+        index(index), level_number(level), cluster(cluster), graph(graph)
+    { }
+};
+
+template < class SchedulerHandle >
+class LeafGraphManager :
+        public paradevs::pdevs::GraphManager < common::DoubleTime,
+                                               SchedulerHandle,
+                                               HierarchicalParameters >
+{
+public:
+    LeafGraphManager(
+        common::Coordinator < common::DoubleTime,
+                              SchedulerHandle >* coordinator,
+        const HierarchicalParameters& parameters) :
+        paradevs::pdevs::GraphManager < common::DoubleTime, SchedulerHandle,
+                                        HierarchicalParameters >(
+            coordinator, parameters)
+    {
+        build_flat_graph(parameters.index, parameters.graph,
+                         parameters.cluster);
+
+        // input
+        {
+            OrientedGraph::vertex_iterator vertexIt, vertexEnd;
+
+            boost::tie(vertexIt, vertexEnd) = boost::vertices(parameters.graph);
+            for (; vertexIt != vertexEnd; ++vertexIt) {
+                if (parameters.cluster.at(parameters.graph[*vertexIt]._index) !=
+                    parameters.index) {
+                    OrientedGraph::adjacency_iterator neighbourIt, neighbourEnd;
+
+                    boost::tie(neighbourIt, neighbourEnd) =
+                        boost::adjacent_vertices(*vertexIt, parameters.graph);
+                    for (; neighbourIt != neighbourEnd; ++neighbourIt) {
+                        std::map < int, int >::const_iterator it =
+                            parameters.cluster.find(
+                                parameters.graph[*neighbourIt]._index);
+
+                        if (it != parameters.cluster.end() and
+                            it->second == parameters.index) {
+                            std::ostringstream ss_in;
+
+                            ss_in << "in_"
+                                  << parameters.graph[*vertexIt]._index;
+                            if (not coordinator->exist_in_port(ss_in.str())) {
+                                coordinator->add_in_port(ss_in.str());
+                            }
+                            if (not LeafGraphManager <
+                                    SchedulerHandle >::exist_link(
+                                        coordinator, ss_in.str(),
+                                        _normal_simulators[it->second], "in")) {
+                                LeafGraphManager < SchedulerHandle>::add_link(
+                                    coordinator, ss_in.str(),
+                                    _normal_simulators[it->second], "in");
+                            }
+
+                            std::cout << "DEBUG: "
+                                      << parameters.graph[*neighbourIt]._index
+                                      << " input -> "
+                                      << parameters.graph[*vertexIt]._index
+                                      << " "
+                                      << parameters.index << ":" << ss_in.str()
+                                      << " -> "
+                                      << parameters.graph[*neighbourIt]._index
+                                      << ":in"
+                                      << std::endl;
+                        }
+                    }
+                }
+            }
+        }
+
+        // output
+        {
+            OrientedGraph::vertex_iterator vertexIt, vertexEnd;
+
+            boost::tie(vertexIt, vertexEnd) = boost::vertices(parameters.graph);
+            for (; vertexIt != vertexEnd; ++vertexIt) {
+                if (parameters.cluster.at(parameters.graph[*vertexIt]._index) ==
+                    parameters.index) {
+                    OrientedGraph::adjacency_iterator neighbourIt, neighbourEnd;
+
+                    boost::tie(neighbourIt, neighbourEnd) =
+                        boost::adjacent_vertices(*vertexIt, parameters.graph);
+                    for (; neighbourIt != neighbourEnd; ++neighbourIt) {
+                        std::map < int, int >::const_iterator it =
+                            parameters.cluster.find(
+                                parameters.graph[*neighbourIt]._index);
+
+                        if (it != parameters.cluster.end() and
+                            it->second != parameters.index) {
+                            std::ostringstream ss_out;
+
+                            ss_out << "out_"
+                                   << parameters.graph[*vertexIt]._index;
+                            if (not coordinator->exist_out_port(ss_out.str())) {
+                                coordinator->add_out_port(ss_out.str());
+                            }
+                            if (_normal_simulators.find(it->first) !=
+                                _normal_simulators.end()) {
+                                if (not LeafGraphManager <
+                                        SchedulerHandle >::exist_link(
+                                            _normal_simulators[it->first],
+                                            "out", coordinator, ss_out.str())) {
+                                    LeafGraphManager <
+                                        SchedulerHandle >::add_link(
+                                            _normal_simulators[it->first],
+                                            "out", coordinator, ss_out.str());
+                                }
+
+                                std::cout << "DEBUG: "
+                                          << parameters.graph[*vertexIt]._index
+                                          << " output -> "
+                                          << parameters.graph[*neighbourIt]._index
+                                          << " "
+                                          << parameters.graph[*vertexIt]._index
+                                          << ":out -> "
+                                          << parameters.index << ":"
+                                          << ss_out.str()
+                                          << std::endl;
+
+                            } else {
+                                if (not LeafGraphManager <
+                                        SchedulerHandle >::exist_link(
+                                            _top_simulators[it->first],
+                                            "out", coordinator, ss_out.str())) {
+                                    LeafGraphManager <
+                                        SchedulerHandle>::add_link(
+                                            _top_simulators[it->first],
+                                            "out", coordinator, ss_out.str());
+                                }
+
+                                std::cout << "DEBUG: "
+                                          << parameters.graph[*vertexIt]._index
+                                          << " output -> "
+                                          << parameters.graph[*neighbourIt]._index
+                                          << " "
+                                          << parameters.graph[*vertexIt]._index
+                                          << ":out -> "
+                                          << parameters.index << ":"
+                                          << ss_out.str()
+                                          << std::endl;
+
+                            }
+                        }
+                    }
+                }
+            }
+        }
+    }
+
+    virtual ~LeafGraphManager()
+    {
+        for (typename TopSimulators::const_iterator it =
+                 _top_simulators.begin(); it != _top_simulators.end();
+             ++it) {
+            delete it->second;
+        }
+        for (typename NormalSimulators::const_iterator it =
+                 _normal_simulators.begin(); it != _normal_simulators.end();
+             ++it) {
+            delete it->second;
+        }
+    }
+
+private:
+    void build_flat_graph(int index, const OrientedGraph& g,
+                          const std::map < int, int >& cluster)
+    {
+        OrientedGraph::vertex_iterator vertexIt, vertexEnd;
+
+        boost::tie(vertexIt, vertexEnd) = boost::vertices(g);
+        for (; vertexIt != vertexEnd; ++vertexIt) {
+            std::ostringstream ss;
+
+            if (cluster.at(g[*vertexIt]._index) == index) {
+                ss << "a" << g[*vertexIt]._index;
+
+                std::cout << "DEBUG: " << g[*vertexIt]._index << " => "
+                          << index << std::endl;
+
+                switch (g[*vertexIt]._type) {
+                case TOP_PIXEL:
+                    _top_simulators[g[*vertexIt]._index] =
+                        new pdevs::Simulator <
+                            common::DoubleTime, TopPixel < SchedulerHandle >,
+                            SchedulerHandle,
+                            TopPixelParameters >(ss.str(),
+                                                 TopPixelParameters());
+                    _top_simulators[g[*vertexIt]._index]->add_out_port("out");
+                    LeafGraphManager < SchedulerHandle >::add_child(
+                        _top_simulators[g[*vertexIt]._index]);
+                    break;
+                case NORMAL_PIXEL:
+                    unsigned int n = 0;
+                    OrientedGraph::vertex_iterator vertexIt2, vertexEnd2;
+
+                    std::cout << "DEBUG: " << g[*vertexIt]._index << " = [ ";
+                    boost::tie(vertexIt2, vertexEnd2) = boost::vertices(g);
+                    for (; vertexIt2 != vertexEnd2; ++vertexIt2) {
+                        OrientedGraph::adjacency_iterator neighbourIt,
+                            neighbourEnd;
+
+                        boost::tie(neighbourIt, neighbourEnd) =
+                            boost::adjacent_vertices(*vertexIt2, g);
+                        for (; neighbourIt != neighbourEnd; ++neighbourIt) {
+                            if (g[*neighbourIt]._index == g[*vertexIt]._index) {
+                                ++n;
+                                std::cout << g[*vertexIt2]._index << " ";
+                            }
+                        }
+                    }
+                    std::cout << "]" << std::endl;
+
+                    std::cout << "DEBUG: " << g[*vertexIt]._index << " => N = "
+                              << n << std::endl;
+
+                    _normal_simulators[g[*vertexIt]._index] =
+                        new pdevs::Simulator <
+                            common::DoubleTime, NormalPixel < SchedulerHandle >,
+                            SchedulerHandle, NormalPixelParameters >(
+                                ss.str(), NormalPixelParameters(n));
+                    _normal_simulators[g[*vertexIt]._index]->add_in_port("in");
+                    _normal_simulators[g[*vertexIt]._index]->add_out_port("out");
+                    LeafGraphManager < SchedulerHandle >::add_child(
+                        _normal_simulators[g[*vertexIt]._index]);
+                    break;
+                };
+            }
+        }
+
+        boost::tie(vertexIt, vertexEnd) = boost::vertices(g);
+        for (; vertexIt != vertexEnd; ++vertexIt)
+        {
+            if (cluster.at(g[*vertexIt]._index) == index) {
+                OrientedGraph::adjacency_iterator neighbourIt, neighbourEnd;
+
+                std::cout << "DEBUG: " << g[*vertexIt]._index << " = [ ";
+                boost::tie(neighbourIt, neighbourEnd) =
+                    boost::adjacent_vertices(*vertexIt, g);
+                for (; neighbourIt != neighbourEnd; ++neighbourIt) {
+                    std::map < int, int >::const_iterator it =
+                        cluster.find(g[*neighbourIt]._index);
+                    std::cout << g[*neighbourIt]._index << "/"
+                              << it->second << " ";
+                }
+                std::cout << "]" << std::endl;
+
+                boost::tie(neighbourIt, neighbourEnd) =
+                    boost::adjacent_vertices(*vertexIt, g);
+                for (; neighbourIt != neighbourEnd; ++neighbourIt) {
+                    std::map < int, int >::const_iterator it =
+                        cluster.find(g[*neighbourIt]._index);
+
+                    if (it != cluster.end() and it->second == index) {
+                        paradevs::common::Model < common::DoubleTime,
+                                                  SchedulerHandle >* a = 0;
+                        paradevs::common::Model < common::DoubleTime,
+                                                  SchedulerHandle >* b = 0;
+
+                        if (g[*vertexIt]._type == TOP_PIXEL) {
+                            a = _top_simulators[g[*vertexIt]._index];
+                        } else {
+                            a = _normal_simulators[g[*vertexIt]._index];
+                        }
+                        if (g[*neighbourIt]._type == TOP_PIXEL) {
+                            b = _top_simulators[g[*neighbourIt]._index];
+                        } else {
+                            b = _normal_simulators[g[*neighbourIt]._index];
+                        }
+                        if (LeafGraphManager <
+                                SchedulerHandle >::exist_link(a, "out",
+                                                              b, "in")) {
+                            std::cout << "== BUG == : "
+                                      << g[*vertexIt]._index
+                                      << ":out -> "
+                                      << g[*neighbourIt]._index
+                                      << ":in"
+                                      << std::endl;
+                        }
+
+
+                            std::cout << "DEBUG: "
+                                      << g[*vertexIt]._index
+                                      << " internal -> "
+                                      << g[*neighbourIt]._index
+                                      << " "
+                                      << g[*vertexIt]._index
+                                      << ":out -> "
+                                      << g[*neighbourIt]._index
+                                      << ":in"
+                                      << std::endl;
+
+                            LeafGraphManager < SchedulerHandle >::add_link(
+                                a, "out", b, "in");
+                    }
+                }
+            }
+        }
+    }
+
+    typedef std::map < int, pdevs::Simulator <
+                                common::DoubleTime,
+                                TopPixel < SchedulerHandle >,
+                                SchedulerHandle,
+                                TopPixelParameters >* > TopSimulators;
+    typedef std::map < int, pdevs::Simulator <
+                                common::DoubleTime,
+                                NormalPixel < SchedulerHandle >,
+                                SchedulerHandle,
+                                NormalPixelParameters >* > NormalSimulators;
+
+    TopSimulators    _top_simulators;
+    NormalSimulators _normal_simulators;
+};
+
+template < class SchedulerHandle >
+class HierarchicalGraphManager :
+    public paradevs::pdevs::GraphManager < common::DoubleTime,
+                                           SchedulerHandle,
+                                           HierarchicalParameters >
+{
+public:
+    HierarchicalGraphManager(
+        common::Coordinator < common::DoubleTime,
+                              SchedulerHandle >* coordinator,
+        const HierarchicalParameters& parameters) :
+        paradevs::pdevs::GraphManager < common::DoubleTime, SchedulerHandle,
+                                        HierarchicalParameters >(
+                                            coordinator, parameters)
+    {
+        std::map < int, int > cluster = parameters.cluster;
+
+        int n1 = 1;
+        int n2 = 0;
+        for (int i = 1; i <= parameters.level_number; ++i) {
+            n2 += 1 << i;
+        }
+        n2 >>= 1;
+        n2++;
+
+        OrientedGraph::vertex_iterator vertexIt, vertexEnd;
+        boost::tie(vertexIt, vertexEnd) = boost::vertices(parameters.graph);
+        for (; vertexIt != vertexEnd; ++vertexIt) {
+            if (parameters.index ==
+                parameters.cluster[parameters.graph[*vertexIt]._index]) {
+                if (rand() % 2) {
+                    parameters.cluster[parameters.graph[*vertexIt]._index] += n1;
+                } else {
+                    parameters.cluster[parameters.graph[*vertexIt]._index] += n2;
+                }
+            }
+        }
+
+        std::map < int, int > copy_cluster = parameters.cluster;
+
+        // build coordinators
+        for (unsigned int i = 0; i < 2; ++i) {
+            unsigned index = parameters.index + ((i == 0) ? n1 : n2);
+
+            if (parameters.level_number > 1) {
+                Coordinator* coordinator = 0;
+                std::ostringstream ss;
+
+                ss << "S" << index;
+                coordinator =
+                    new Coordinator(ss.str(),
+                                    paradevs::common::NoParameters(),
+                                    HierarchicalParameters(
+                                        index,
+                                        parameters.level_number - 1,
+                                        parameters.cluster,
+                                        parameters.graph));
+                _coordinators.push_back(coordinator);
+                HierarchicalGraphManager < SchedulerHandle >::add_child(
+                    coordinator);
+            } else {
+                LeafCoordinator* coordinator = 0;
+                std::ostringstream ss;
+
+                ss << "S" << index;
+                coordinator =
+                    new LeafCoordinator(ss.str(),
+                                        paradevs::common::NoParameters(),
+                                        HierarchicalParameters(
+                                            index,
+                                            -1,
+                                            parameters.cluster,
+                                            parameters.graph));
+                _leaf_coordinators.push_back(coordinator);
+                HierarchicalGraphManager < SchedulerHandle >::add_child(
+                    coordinator);
+            }
+        }
+
+        // build ports and connections
+        // input
+        for (unsigned int i = 0; i < 2; ++i) {
+            unsigned index = (i == 0) ? n1 : n2;
+            OrientedGraph::vertex_iterator vertexIt, vertexEnd;
+
+            boost::tie(vertexIt, vertexEnd) = boost::vertices(parameters.graph);
+            for (; vertexIt != vertexEnd; ++vertexIt) {
+                if (cluster.at(parameters.graph[*vertexIt]._index) !=
+                    parameters.index) {
+                    OrientedGraph::adjacency_iterator neighbourIt, neighbourEnd;
+
+                    boost::tie(neighbourIt, neighbourEnd) =
+                        boost::adjacent_vertices(*vertexIt, parameters.graph);
+                    for (; neighbourIt != neighbourEnd; ++neighbourIt) {
+                        std::map < int, int >::const_iterator it =
+                            copy_cluster.find(
+                                parameters.graph[*neighbourIt]._index);
+
+                        if (it != copy_cluster.end() and
+                            it->second == parameters.index + index) {
+                            std::ostringstream ss_in_a;
+                            std::ostringstream ss_in_b;
+
+                            ss_in_a << "in_"
+                                    << parameters.graph[*vertexIt]._index;
+                            ss_in_b << "in_"
+                                    << parameters.graph[*vertexIt]._index;
+
+                            std::cout << "DEBUG: ="
+                                      << parameters.index
+                                      << " "
+                                      << (parameters.index + index)
+                                      << " "
+                                      << parameters.graph[*vertexIt]._index
+                                      << " "
+                                      << parameters.index << ":"
+                                      << ss_in_a.str() << " -> "
+                                      << (parameters.index + index) << ":"
+                                      << ss_in_b.str()
+                                      << std::endl;
+
+                            if (not coordinator->exist_in_port(
+                                    ss_in_a.str())) {
+                                coordinator->add_in_port(
+                                    ss_in_a.str());
+                            }
+                            if (parameters.level_number > 1) {
+                                if (not _coordinators[i]->exist_in_port(
+                                        ss_in_b.str())) {
+                                    _coordinators[i]->add_in_port(
+                                        ss_in_b.str());
+                                }
+                                if (not HierarchicalGraphManager <
+                                    SchedulerHandle >::exist_link(
+                                        coordinator, ss_in_a.str(),
+                                        _coordinators[i], ss_in_b.str())) {
+                                    HierarchicalGraphManager <
+                                        SchedulerHandle >::add_link(
+                                            coordinator, ss_in_a.str(),
+                                            _coordinators[i], ss_in_b.str());
+                                }
+                            } else {
+                                if (not _leaf_coordinators[i]->exist_in_port(
+                                        ss_in_b.str())) {
+                                    _leaf_coordinators[i]->add_in_port(
+                                        ss_in_b.str());
+                                }
+                                if (not HierarchicalGraphManager <
+                                        SchedulerHandle >::exist_link(
+                                            coordinator, ss_in_a.str(),
+                                            _leaf_coordinators[i], ss_in_b.str())) {
+                                    HierarchicalGraphManager <
+                                        SchedulerHandle >::add_link(
+                                            coordinator, ss_in_a.str(),
+                                            _leaf_coordinators[i], ss_in_b.str());
+                                }
+                            }
+                        }
+                    }
+                }
+            }
+        }
+
+        // output
+        for (unsigned int i = 0; i < 2; ++i) {
+            unsigned index = (i == 0) ? n1 : n2;
+            OrientedGraph::vertex_iterator vertexIt, vertexEnd;
+
+            boost::tie(vertexIt, vertexEnd) = boost::vertices(parameters.graph);
+            for (; vertexIt != vertexEnd; ++vertexIt) {
+                if (copy_cluster.at(parameters.graph[*vertexIt]._index) ==
+                    parameters.index + index) {
+                    OrientedGraph::adjacency_iterator neighbourIt, neighbourEnd;
+
+                    boost::tie(neighbourIt, neighbourEnd) =
+                        boost::adjacent_vertices(*vertexIt, parameters.graph);
+                    for (; neighbourIt != neighbourEnd; ++neighbourIt) {
+                        std::map < int, int >::const_iterator it =
+                            cluster.find(
+                                parameters.graph[*neighbourIt]._index);
+
+                        if (it != cluster.end() and
+                            it->second != parameters.index) {
+                            std::ostringstream ss_out_a;
+                            std::ostringstream ss_out_b;
+
+                            ss_out_a << "out_"
+                                     << parameters.graph[*vertexIt]._index;
+                            ss_out_b << "out_"
+                                     << parameters.graph[*vertexIt]._index;
+                            if (not coordinator->exist_out_port(
+                                    ss_out_b.str())) {
+                                coordinator->add_out_port(
+                                    ss_out_b.str());
+                            }
+
+                            std::cout << "DEBUG: ="
+                                      << parameters.index
+                                      << " "
+                                      << (parameters.index + index)
+                                      << " "
+                                      << parameters.graph[*vertexIt]._index
+                                      << " "
+                                      << parameters.graph[*neighbourIt]._index
+                                      << " "
+                                      << (parameters.index + index) << ":"
+                                      << ss_out_a.str() << " -> "
+                                      << parameters.index << ":"
+                                      << ss_out_b.str()
+                                      << std::endl;
+
+                            if (parameters.level_number > 1) {
+                                if (not _coordinators[i]->exist_out_port(
+                                        ss_out_a.str())) {
+                                    _coordinators[i]->add_out_port(
+                                        ss_out_a.str());
+                                }
+                                if (not HierarchicalGraphManager <
+                                        SchedulerHandle >::exist_link(
+                                            _coordinators[i],
+                                            ss_out_a.str(),
+                                            coordinator,
+                                            ss_out_b.str())) {
+                                    HierarchicalGraphManager <
+                                        SchedulerHandle >::add_link(
+                                            _coordinators[i],
+                                            ss_out_a.str(),
+                                            coordinator,
+                                            ss_out_b.str());
+                                }
+                            } else {
+                                if (not _leaf_coordinators[i]->exist_out_port(
+                                        ss_out_a.str())) {
+                                    _leaf_coordinators[i]->add_out_port(
+                                        ss_out_a.str());
+                                }
+                                if (not HierarchicalGraphManager <
+                                        SchedulerHandle >::exist_link(
+                                            _leaf_coordinators[i],
+                                            ss_out_a.str(),
+                                            coordinator,
+                                            ss_out_b.str())) {
+                                    HierarchicalGraphManager <
+                                        SchedulerHandle >::add_link(
+                                            _leaf_coordinators[i],
+                                            ss_out_a.str(),
+                                            coordinator,
+                                            ss_out_b.str());
+                                }
+                            }
+                        }
+                    }
+                }
+            }
+        }
+
+        // internal
+        for (unsigned int i = 0; i < 2; ++i) {
+            unsigned index1 = (i == 0) ? n1 : n2;
+            unsigned index2 = (i == 0) ? n2 : n1;
+            OrientedGraph::vertex_iterator vertexIt, vertexEnd;
+
+            boost::tie(vertexIt, vertexEnd) = boost::vertices(parameters.graph);
+            for (; vertexIt != vertexEnd; ++vertexIt) {
+                if (copy_cluster.at(parameters.graph[*vertexIt]._index) ==
+                    parameters.index + index1) {
+                    OrientedGraph::adjacency_iterator neighbourIt, neighbourEnd;
+
+                    boost::tie(neighbourIt, neighbourEnd) =
+                        boost::adjacent_vertices(*vertexIt, parameters.graph);
+                    for (; neighbourIt != neighbourEnd; ++neighbourIt) {
+                        std::map < int, int >::const_iterator it =
+                            copy_cluster.find(
+                                parameters.graph[*neighbourIt]._index);
+
+                        if (it != copy_cluster.end() and
+                            it->second == parameters.index + index2) {
+                            std::ostringstream ss_out_a;
+                            std::ostringstream ss_out_b;
+
+                            ss_out_a << "out_"
+                                     << parameters.graph[*vertexIt]._index;
+                            ss_out_b << "in_"
+                                     << parameters.graph[*vertexIt]._index;
+
+                            std::cout << "DEBUG: ="
+                                      << parameters.index
+                                      << " "
+                                      << (parameters.index + index1)
+                                      << " "
+                                      << parameters.graph[*vertexIt]._index
+                                      << " "
+                                      << (parameters.index + index2)
+                                      << " "
+                                      << parameters.graph[*neighbourIt]._index
+                                      << " "
+                                      << (parameters.index + index1) << ":"
+                                      << ss_out_a.str()
+                                      << " -> "
+                                      << (parameters.index + index2) << ":"
+                                      << ss_out_b.str()
+                                      << std::endl;
+
+                            if (parameters.level_number > 1) {
+                                if (not _coordinators[i]->exist_out_port(
+                                        ss_out_a.str())) {
+                                    _coordinators[i]->add_out_port(
+                                        ss_out_a.str());
+                                }
+                                if (not _coordinators[(i==0)?1:0]->exist_in_port(
+                                            ss_out_b.str())) {
+                                    _coordinators[(i==0)?1:0]->add_in_port(
+                                        ss_out_b.str());
+                                }
+                                if (not HierarchicalGraphManager <
+                                        SchedulerHandle >::exist_link(
+                                            _coordinators[i],
+                                            ss_out_a.str(),
+                                            _coordinators[(i==0)?1:0],
+                                            ss_out_b.str())) {
+                                    HierarchicalGraphManager <
+                                        SchedulerHandle >::add_link(
+                                            _coordinators[i],
+                                            ss_out_a.str(),
+                                            _coordinators[(i==0)?1:0],
+                                            ss_out_b.str());
+                                }
+                            } else {
+                                if (not _leaf_coordinators[i]->exist_out_port(
+                                        ss_out_a.str())) {
+                                    _leaf_coordinators[i]->add_out_port(
+                                        ss_out_a.str());
+                                }
+                                if (not _leaf_coordinators[(i==0)?1:0]->exist_in_port(
+                                        ss_out_b.str())) {
+                                    _leaf_coordinators[(i==0)?1:0]->add_in_port(
+                                        ss_out_b.str());
+                                }
+                                if (not HierarchicalGraphManager <
+                                        SchedulerHandle >::exist_link(
+                                            _leaf_coordinators[i],
+                                            ss_out_a.str(),
+                                            _leaf_coordinators[(i==0)?1:0],
+                                            ss_out_b.str())) {
+                                    HierarchicalGraphManager <
+                                        SchedulerHandle >::add_link(
+                                            _leaf_coordinators[i],
+                                            ss_out_a.str(),
+                                            _leaf_coordinators[(i==0)?1:0],
+                                            ss_out_b.str());
+                                }
+                            }
+                        }
+                    }
+                }
+            }
+        }
+
+    }
+
+    virtual ~HierarchicalGraphManager()
+    {
+        for (typename Coordinators::const_iterator it = _coordinators.begin();
+             it != _coordinators.end(); ++it) {
+            delete *it;
+        }
+    }
+
+private:
+    // INTERNODE
+    typedef paradevs::pdevs::Coordinator <
+        common::DoubleTime,
+        SchedulerType,
+        SchedulerHandle,
+        HierarchicalGraphManager < SchedulerHandle >,
+        common::NoParameters,
+        HierarchicalParameters > Coordinator;
+    typedef std::vector < Coordinator* > Coordinators;
+
+    Coordinators _coordinators;
+
+    // LEAF
+    typedef paradevs::pdevs::Coordinator <
+        common::DoubleTime,
+        SchedulerType,
+        SchedulerHandle,
+        LeafGraphManager < SchedulerHandle >,
+        common::NoParameters,
+        HierarchicalParameters > LeafCoordinator;
+    typedef std::vector < LeafCoordinator* > LeafCoordinators;
+
+    LeafCoordinators _leaf_coordinators;
+};
+
+template < class SchedulerHandle, class GraphBuilder >
+class RootHierarchicalGraphManager :
+    public paradevs::pdevs::GraphManager < common::DoubleTime,
+                                           SchedulerHandle,
+                                           RootHierarchicalParameters >
+{
+public:
+    RootHierarchicalGraphManager(
+        common::Coordinator < common::DoubleTime,
+                              SchedulerHandle >* coordinator,
+        const RootHierarchicalParameters& parameters) :
+        paradevs::pdevs::GraphManager < common::DoubleTime, SchedulerHandle,
+                                        RootHierarchicalParameters >(
+                                            coordinator, parameters)
+    {
+        GraphBuilder graph_builder(parameters.generator);
+        OrientedGraph graph;
+
+        graph_builder.build(graph);
+
+        if (parameters.level_number == 1) {
+            std::map < int, int > cluster;
+
+            OrientedGraph::vertex_iterator vertexIt, vertexEnd;
+            boost::tie(vertexIt, vertexEnd) = boost::vertices(graph);
+            for (; vertexIt != vertexEnd; ++vertexIt) {
+                cluster[graph[*vertexIt]._index] = 1;
+            }
+            {
+                LeafCoordinator* coordinator = 0;
+
+                coordinator =
+                    new LeafCoordinator("S1", paradevs::common::NoParameters(),
+                                        HierarchicalParameters(
+                                            1,
+                                            -1,
+                                            cluster,
+                                            graph));
+                RootHierarchicalGraphManager < SchedulerHandle,
+                                               GraphBuilder >::add_child(
+                                                   coordinator);
+            }
+        } else {
+            int n1 = 1;
+            int n2 = 0;
+            for (int i = 1; i <= parameters.level_number; ++i) {
+                n2 += 1 << i;
+            }
+            n2 >>= 1;
+            n2++;
+
+            std::map < int, int > cluster;
+            std::map < int, int > copy_cluster;
+
+            OrientedGraph::vertex_iterator vertexIt, vertexEnd;
+            boost::tie(vertexIt, vertexEnd) = boost::vertices(graph);
+            for (; vertexIt != vertexEnd; ++vertexIt) {
+                if (rand() % 2) {
+                    cluster[graph[*vertexIt]._index] = n1;
+                } else {
+                    cluster[graph[*vertexIt]._index] = n2;
+                }
+            }
+            copy_cluster = cluster;
+
+            // build coordinators (graphs)
+            for (unsigned int i = 0; i < 2; ++i) {
+                Coordinator* coordinator = 0;
+                std::ostringstream ss;
+                unsigned index = (i == 0) ? n1 : n2;
+
+                ss << "S" << index;
+                coordinator =
+                    new Coordinator(ss.str(), paradevs::common::NoParameters(),
+                                    HierarchicalParameters(
+                                        index,
+                                        parameters.level_number - 1,
+                                        cluster,
+                                        graph));
+                _coordinators.push_back(coordinator);
+                RootHierarchicalGraphManager < SchedulerHandle,
+                                               GraphBuilder >::add_child(
+                                                   coordinator);
+
+            }
+
+            // build ports and connections
+            // internal
+            for (unsigned int i = 0; i < 2; ++i) {
+                unsigned index = (i == 0) ? n1 : n2;
+                OrientedGraph::vertex_iterator vertexIt, vertexEnd;
+
+                boost::tie(vertexIt, vertexEnd) = boost::vertices(graph);
+                for (; vertexIt != vertexEnd; ++vertexIt) {
+                    if (copy_cluster.at(graph[*vertexIt]._index) != index) {
+                        OrientedGraph::adjacency_iterator neighbourIt, neighbourEnd;
+
+                        boost::tie(neighbourIt, neighbourEnd) =
+                            boost::adjacent_vertices(*vertexIt, graph);
+                        for (; neighbourIt != neighbourEnd; ++neighbourIt) {
+                            std::map < int, int >::const_iterator it =
+                                copy_cluster.find(graph[*neighbourIt]._index);
+
+                            if (it != copy_cluster.end() and it->second == index) {
+
+                                std::ostringstream ss_in_a;
+                                std::ostringstream ss_in_b;
+
+                                ss_in_a << "out_" << graph[*vertexIt]._index;
+                                ss_in_b << "in_" << graph[*vertexIt]._index;
+
+                                std::cout << "DEBUG: =>"
+                                          << index
+                                          << " "
+                                          << graph[*vertexIt]._index
+                                          << " "
+                                          << ((i == 0) ? n2 : n1)
+                                          << " "
+                                          << ((i == 0) ? n2 : n1) << ":"
+                                          << ss_in_a.str()
+                                          << " -> " << index << ":"
+                                          << ss_in_b.str()
+                                          << std::endl;
+
+                                if (not _coordinators[i]->exist_in_port(
+                                        ss_in_b.str())) {
+                                    _coordinators[i]->add_in_port(
+                                        ss_in_b.str());
+                                }
+                                if (not _coordinators[(i==0)?1:0]->exist_out_port(
+                                        ss_in_a.str())) {
+                                    _coordinators[(i==0)?1:0]->add_out_port(
+                                        ss_in_a.str());
+                                }
+                                if (not RootHierarchicalGraphManager <
+                                        SchedulerHandle, GraphBuilder >::exist_link(
+                                            _coordinators[(i==0)?1:0],
+                                            ss_in_a.str(),
+                                            _coordinators[i],
+                                            ss_in_b.str())) {
+                                    RootHierarchicalGraphManager <
+                                        SchedulerHandle, GraphBuilder >::add_link(
+                                            _coordinators[(i==0)?1:0],
+                                            ss_in_a.str(),
+                                            _coordinators[i],
+                                            ss_in_b.str());
+                                }
+                            }
+                        }
+                    }
+                }
+            }
+        }
+    }
+
+    virtual ~RootHierarchicalGraphManager()
+    {
+        for (typename Coordinators::const_iterator it = _coordinators.begin();
+             it != _coordinators.end(); ++it) {
+            delete *it;
+        }
+    }
+
+private:
+    typedef paradevs::pdevs::Coordinator <
+        common::DoubleTime,
+        SchedulerType,
+        SchedulerHandle,
+        HierarchicalGraphManager < SchedulerHandle >,
+        common::NoParameters,
+        HierarchicalParameters > Coordinator;
+    typedef std::vector < Coordinator* > Coordinators;
+
+    // LEAF
+    typedef paradevs::pdevs::Coordinator <
+        common::DoubleTime,
+        SchedulerType,
+        SchedulerHandle,
+        LeafGraphManager < SchedulerHandle >,
+        common::NoParameters,
+        HierarchicalParameters > LeafCoordinator;
+
+    Coordinators _coordinators;
+};
+
+class RootHierarchicalGraphBuilder
+{
+public:
+    RootHierarchicalGraphBuilder(GraphGenerator& g) : generator(g)
+    { }
+
+    void build(OrientedGraph& graph)
+    { generator.generate(graph); }
+
+private:
+    GraphGenerator& generator;
+};
+
+} } } // namespace paradevs tests boost_graph
+
+#endif