/** * @file tests/boost_graph/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 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 . */ #ifndef __TESTS_BOOST_GRAPH_GRAPH_MANAGER_HPP #define __TESTS_BOOST_GRAPH_GRAPH_MANAGER_HPP 1 #include #include #include #include #include #include #include #include namespace paradevs { namespace tests { namespace boost_graph { struct SchedulerHandle; typedef typename paradevs::common::scheduler::HeapScheduler < common::DoubleTime, SchedulerHandle >::type SchedulerType; struct SchedulerHandle { SchedulerHandle() { } SchedulerHandle(const SchedulerType::handle_type& handle) : _handle(handle) { } const SchedulerHandle& handle() const { return *this; } void handle(const SchedulerHandle& handle) { _handle = handle._handle; } SchedulerType::handle_type _handle; }; struct GraphParameters { OrientedGraph _graph; InputEdges _input_edges; OutputEdges _output_edges; GraphParameters(const OrientedGraph& graph, const InputEdges& input_edges, const OutputEdges& output_edges) : _graph(graph), _input_edges(input_edges), _output_edges(output_edges) { } }; template < class SchedulerHandle, class Parameters > class FlatGraphManager : public paradevs::pdevs::GraphManager < common::DoubleTime, SchedulerHandle, Parameters > { public: FlatGraphManager(common::Coordinator < common::DoubleTime, SchedulerHandle >* coordinator, const Parameters& parameters) : paradevs::pdevs::GraphManager < common::DoubleTime, SchedulerHandle, Parameters >( coordinator, parameters) { } virtual ~FlatGraphManager() { 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; } } void build_flat_graph(const OrientedGraph& g, const InputEdges& inputs) { OrientedGraph::vertex_iterator vertexIt, vertexEnd; boost::tie(vertexIt, vertexEnd) = boost::vertices(g); for (; vertexIt != vertexEnd; ++vertexIt) { std::ostringstream ss; ss << "a" << g[*vertexIt]._index; 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"); FlatGraphManager < SchedulerHandle, Parameters >::add_child( _top_simulators[g[*vertexIt]._index]); break; case NORMAL_PIXEL: unsigned int n = 0; OrientedGraph::vertex_iterator vertexIt2, vertexEnd2; 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; } } } for (InputEdges::const_iterator it = inputs.begin(); it != inputs.end(); ++it) { if (g[*vertexIt]._index == it->second) { ++n; } } _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"); FlatGraphManager < SchedulerHandle, Parameters >::add_child( _normal_simulators[g[*vertexIt]._index]); break; }; } boost::tie(vertexIt, vertexEnd) = boost::vertices(g); for (; vertexIt != vertexEnd; ++vertexIt) { OrientedGraph::adjacency_iterator neighbourIt, neighbourEnd; boost::tie(neighbourIt, neighbourEnd) = boost::adjacent_vertices(*vertexIt, g); for (; neighbourIt != neighbourEnd; ++neighbourIt) { 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]; } FlatGraphManager < SchedulerHandle, Parameters >::add_link(a, "out", b, "in"); } } } protected: 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 BuiltFlatGraphManager : public FlatGraphManager < SchedulerHandle, GraphParameters > { public: BuiltFlatGraphManager( common::Coordinator < common::DoubleTime, SchedulerHandle >* coordinator, const GraphParameters& parameters) : FlatGraphManager < SchedulerHandle, GraphParameters >( coordinator, parameters) { BuiltFlatGraphManager < SchedulerHandle >::build_flat_graph( parameters._graph, parameters._input_edges); // input // std::cout << "Input edges:" << std::endl; for (Edges::const_iterator it = parameters._input_edges.begin(); it != parameters._input_edges.end(); ++it) { std::ostringstream ss_in; ss_in << "in_" << it->first; if (not coordinator->exist_in_port(ss_in.str())) { coordinator->add_in_port(ss_in.str()); } BuiltFlatGraphManager < SchedulerHandle>::add_link( coordinator, ss_in.str(), BuiltFlatGraphManager < SchedulerHandle >::_normal_simulators[it->second], "in"); // std::cout << "link = " << coordinator->get_name() // << "::" << ss_in.str() << " -> " // << BuiltFlatGraphManager < // SchedulerHandle >::_normal_simulators[it->second] // ->get_name() << "::" << "in" << std::endl; } // output // std::cout << "Output edges:" << std::endl; for (Edges::const_iterator it = parameters._output_edges.begin(); it != parameters._output_edges.end(); ++it) { std::ostringstream ss_out; ss_out << "out_" << it->first; if (not coordinator->exist_out_port(ss_out.str())) { coordinator->add_out_port(ss_out.str()); } if (BuiltFlatGraphManager < SchedulerHandle >::_normal_simulators.find(it->first) != BuiltFlatGraphManager < SchedulerHandle >::_normal_simulators.end()) { if (not BuiltFlatGraphManager < SchedulerHandle>::exist_link( BuiltFlatGraphManager < SchedulerHandle >::_normal_simulators[it->first], "out", coordinator, ss_out.str())) { BuiltFlatGraphManager < SchedulerHandle>::add_link( BuiltFlatGraphManager < SchedulerHandle >::_normal_simulators[it->first], "out", coordinator, ss_out.str()); // std::cout << "link = " << BuiltFlatGraphManager < // SchedulerHandle >::_normal_simulators[it->first] // ->get_name() << "::" << "out -> " // << coordinator->get_name() // << "::" << ss_out.str() // << std::endl; } } else { if (not BuiltFlatGraphManager < SchedulerHandle>::exist_link( BuiltFlatGraphManager < SchedulerHandle >::_top_simulators[it->first], "out", coordinator, ss_out.str())) { BuiltFlatGraphManager < SchedulerHandle>::add_link( BuiltFlatGraphManager < SchedulerHandle >::_top_simulators[it->first], "out", coordinator, ss_out.str()); // std::cout << "link = " << BuiltFlatGraphManager < // SchedulerHandle >::_top_simulators[it->first] // ->get_name() << "::" << "out -> " // << coordinator->get_name() // << "::" << ss_out.str() // << std::endl; } } } } virtual ~BuiltFlatGraphManager() { } }; template < class SchedulerHandle > class ParallelBuiltFlatGraphManager : public FlatGraphManager < SchedulerHandle, GraphParameters > { public: ParallelBuiltFlatGraphManager( common::Coordinator < common::DoubleTime, SchedulerHandle >* coordinator, const GraphParameters& parameters) : FlatGraphManager < SchedulerHandle, GraphParameters >( coordinator, parameters) { ParallelBuiltFlatGraphManager < SchedulerHandle >::build_flat_graph( parameters._graph, parameters._input_edges); // input for (Edges::const_iterator it = parameters._input_edges.begin(); it != parameters._input_edges.end(); ++it) { std::ostringstream ss_in; ss_in << "in_" << it->first; if (not coordinator->exist_in_port(ss_in.str())) { coordinator->add_in_port(ss_in.str()); } ParallelBuiltFlatGraphManager < SchedulerHandle>::add_link( coordinator, ss_in.str(), ParallelBuiltFlatGraphManager < SchedulerHandle >::_normal_simulators[it->second], "in"); } // output for (Edges::const_iterator it = parameters._output_edges.begin(); it != parameters._output_edges.end(); ++it) { std::ostringstream ss_out; ss_out << "out_" << it->first; if (not coordinator->exist_out_port(ss_out.str())) { coordinator->add_out_port(ss_out.str()); } if (not ParallelBuiltFlatGraphManager < SchedulerHandle >::exist_link( ParallelBuiltFlatGraphManager < SchedulerHandle >::_normal_simulators[it->first], "out", coordinator, ss_out.str())) { ParallelBuiltFlatGraphManager < SchedulerHandle>::add_link( ParallelBuiltFlatGraphManager < SchedulerHandle >::_normal_simulators[it->first], "out", coordinator, ss_out.str()); } } } void init() { } void start(common::DoubleTime::type /* t */) { } void transition( const common::Models < common::DoubleTime, SchedulerHandle >& /* receivers */, common::DoubleTime::type /* t */) { } virtual ~ParallelBuiltFlatGraphManager() { } }; template < class SchedulerHandle, class GraphBuilder > class InBuildFlatGraphManager : public FlatGraphManager < SchedulerHandle, paradevs::common::NoParameters > { public: InBuildFlatGraphManager( common::Coordinator < common::DoubleTime, SchedulerHandle >* coordinator, const paradevs::common::NoParameters& parameters) : FlatGraphManager < SchedulerHandle, paradevs::common::NoParameters >( coordinator, parameters) { GraphBuilder builder; OrientedGraphs graphs; InputEdgeList input_edges; OutputEdgeList output_edges; Connections parent_connections; builder.build(graphs, input_edges, output_edges, parent_connections); InBuildFlatGraphManager < SchedulerHandle, GraphBuilder >::build_flat_graph( graphs.front(), InputEdges()); } virtual ~InBuildFlatGraphManager() { } }; struct PartitioningParameters { int cluster_number; std::string partitioning_method_name; int contraction_coef; bool contraction_coef_flag; PartitioningParameters(int cn, const std::string& pmn, int cc, bool ccf) : cluster_number(cn), partitioning_method_name(pmn), contraction_coef(cc), contraction_coef_flag(ccf) { } }; template < class SchedulerHandle, class GraphBuilder > class HeapHierarchicalGraphManager : public paradevs::pdevs::GraphManager < common::DoubleTime, SchedulerHandle, PartitioningParameters > { public: HeapHierarchicalGraphManager( common::Coordinator < common::DoubleTime, SchedulerHandle >* coordinator, const PartitioningParameters& parameters) : paradevs::pdevs::GraphManager < common::DoubleTime, SchedulerHandle, PartitioningParameters >( coordinator, parameters) { GraphBuilder graph_builder(parameters.cluster_number, parameters.partitioning_method_name, parameters.contraction_coef, parameters.contraction_coef_flag); OrientedGraphs graphs; InputEdgeList input_edges; OutputEdgeList output_edges; Connections parent_connections; graph_builder.build(graphs, input_edges, output_edges, parent_connections); // build coordinators (graphs) for (unsigned int i = 0; i < graphs.size(); ++i) { Coordinator* coordinator = 0; std::ostringstream ss; ss << "S" << i; coordinator = new Coordinator(ss.str(), paradevs::common::NoParameters(), GraphParameters(graphs[i], input_edges[i], output_edges[i])); _coordinators.push_back(coordinator); HeapHierarchicalGraphManager < SchedulerHandle, GraphBuilder >::add_child( coordinator); } // std::cout << "Root:" << std::endl; // builds internal connections (edges) for (Connections::const_iterator it = parent_connections.begin(); it != parent_connections.end(); ++it) { const Connection& connection = *it; std::ostringstream ss_out; std::ostringstream ss_in; ss_out << "out_" << connection.first.second; ss_in << "in_" << connection.first.second; if (not HeapHierarchicalGraphManager < SchedulerHandle, GraphBuilder >::exist_link( _coordinators[connection.first.first - 1], ss_out.str(), _coordinators[connection.second.first - 1], ss_in.str())) { // std::cout << "link = " // << _coordinators[connection.first.first - 1] // ->get_name() // << "::" << ss_out.str() << " -> " // << _coordinators[connection.second.first - 1] // ->get_name() // << "::" << ss_in.str() << std::endl; HeapHierarchicalGraphManager < SchedulerHandle, GraphBuilder >::add_link( _coordinators[connection.first.first - 1], ss_out.str(), _coordinators[connection.second.first - 1], ss_in.str()); } } } virtual ~HeapHierarchicalGraphManager() { for (typename Coordinators::const_iterator it = _coordinators.begin(); it != _coordinators.end(); ++it) { delete *it; } } private: typedef paradevs::pdevs::Coordinator < common::DoubleTime, SchedulerType, SchedulerHandle, BuiltFlatGraphManager < SchedulerHandle >, common::NoParameters, GraphParameters > Coordinator; typedef std::vector < Coordinator* > Coordinators; Coordinators _coordinators; }; template < class SchedulerHandle, class GraphBuilder > class VectorHierarchicalGraphManager : public paradevs::pdevs::GraphManager < common::DoubleTime, SchedulerHandle, PartitioningParameters > { public: VectorHierarchicalGraphManager( common::Coordinator < common::DoubleTime, SchedulerHandle >* coordinator, const PartitioningParameters& parameters) : paradevs::pdevs::GraphManager < common::DoubleTime, SchedulerHandle, PartitioningParameters >( coordinator, parameters) { GraphBuilder graph_builder(parameters.cluster_number, parameters.partitioning_method_name, parameters.contraction_coef, parameters.contraction_coef_flag); OrientedGraphs graphs; InputEdgeList input_edges; OutputEdgeList output_edges; Connections parent_connections; graph_builder.build(graphs, input_edges, output_edges, parent_connections); // build coordinators (graphs) for (unsigned int i = 0; i < graphs.size(); ++i) { Coordinator* coordinator = 0; std::ostringstream ss; ss << "S" << i; coordinator = new Coordinator(ss.str(), paradevs::common::NoParameters(), GraphParameters(graphs[i], input_edges[i], output_edges[i])); _coordinators.push_back(coordinator); VectorHierarchicalGraphManager < SchedulerHandle, GraphBuilder >::add_child( coordinator); } // builds internal connections (edges) for (Connections::const_iterator it = parent_connections.begin(); it != parent_connections.end(); ++it) { const Connection& connection = *it; std::ostringstream ss_out; std::ostringstream ss_in; ss_out << "out_" << connection.first.second; ss_in << "in_" << connection.first.second; if (not VectorHierarchicalGraphManager < SchedulerHandle, GraphBuilder >::exist_link( _coordinators[connection.first.first - 1], ss_out.str(), _coordinators[connection.second.first - 1], ss_in.str())) { VectorHierarchicalGraphManager < SchedulerHandle, GraphBuilder >::add_link( _coordinators[connection.first.first - 1], ss_out.str(), _coordinators[connection.second.first - 1], ss_in.str()); } } } virtual ~VectorHierarchicalGraphManager() { for (typename Coordinators::const_iterator it = _coordinators.begin(); it != _coordinators.end(); ++it) { delete *it; } } private: typedef paradevs::pdevs::Coordinator < common::DoubleTime, paradevs::common::scheduler::VectorScheduler < paradevs::common::DoubleTime >, paradevs::common::scheduler::NoSchedulerHandle, BuiltFlatGraphManager < paradevs::common::scheduler::NoSchedulerHandle >, common::NoParameters, GraphParameters > Coordinator; typedef std::vector < Coordinator* > Coordinators; Coordinators _coordinators; }; template < class SchedulerHandle, class GraphBuilder > class ParallelHeapHierarchicalGraphManager : public paradevs::pdevs::GraphManager < common::DoubleTime, SchedulerHandle, PartitioningParameters > { public: ParallelHeapHierarchicalGraphManager( common::Coordinator < common::DoubleTime, SchedulerHandle >* coordinator, const PartitioningParameters& parameters) : paradevs::pdevs::GraphManager < common::DoubleTime, SchedulerHandle, PartitioningParameters >( coordinator, parameters) { GraphBuilder graph_builder(parameters.cluster_number, parameters.partitioning_method_name, parameters.contraction_coef, parameters.contraction_coef_flag); OrientedGraphs graphs; InputEdgeList input_edges; OutputEdgeList output_edges; Connections parent_connections; graph_builder.build(graphs, input_edges, output_edges, parent_connections); // build coordinators (graphs) for (unsigned int i = 0; i < graphs.size(); ++i) { ParallelCoordinator* coordinator = 0; std::ostringstream ss; ss << "S" << i; coordinator = new ParallelCoordinator(ss.str(), paradevs::common::NoParameters(), GraphParameters(graphs[i], input_edges[i], output_edges[i])); _coordinators.push_back(coordinator); ParallelHeapHierarchicalGraphManager < SchedulerHandle, GraphBuilder >::add_child( coordinator); } // builds internal connections (edges) for (Connections::const_iterator it = parent_connections.begin(); it != parent_connections.end(); ++it) { const Connection& connection = *it; std::ostringstream ss_out; std::ostringstream ss_in; ss_out << "out_" << connection.first.second; ss_in << "in_" << connection.first.second; if (not ParallelHeapHierarchicalGraphManager < SchedulerHandle, GraphBuilder >::exist_link( _coordinators[connection.first.first - 1], ss_out.str(), _coordinators[connection.second.first - 1], ss_in.str())) { ParallelHeapHierarchicalGraphManager < SchedulerHandle, GraphBuilder >::add_link( _coordinators[connection.first.first - 1], ss_out.str(), _coordinators[connection.second.first - 1], ss_in.str()); } } } virtual ~ParallelHeapHierarchicalGraphManager() { for (typename Coordinators::const_iterator it = _coordinators.begin(); it != _coordinators.end(); ++it) { delete *it; } } void init() { for (typename Coordinators::const_iterator it = _coordinators.begin(); it != _coordinators.end(); ++it) { (*it)->set_sender( dynamic_cast < paradevs::pdevs::multithreading::Coordinator < common::DoubleTime, SchedulerType, SchedulerHandle, ParallelHeapHierarchicalGraphManager < SchedulerHandle, PartitioningGraphBuilder >, paradevs::common::NoParameters, PartitioningParameters >* >(ParallelHeapHierarchicalGraphManager < SchedulerHandle, GraphBuilder >:: get_coordinator())->get_sender()); } } void start(common::DoubleTime::type t) { for (typename Coordinators::const_iterator it = _coordinators.begin(); it != _coordinators.end(); ++it) { (*it)->get_sender().send( paradevs::pdevs::multithreading::start_message < paradevs::common::DoubleTime >(t)); } } void transition(const common::Models < common::DoubleTime, SchedulerHandle >& receivers, paradevs::common::DoubleTime::type t) { typename Coordinators::const_iterator it = _coordinators.begin(); bool found = false; while (not found) { if (std::find(receivers.begin(), receivers.end(), *it) != receivers.end()) { (*it)->get_sender().send( paradevs::pdevs::multithreading::transition_message < paradevs::common::DoubleTime >(t)); found = true; } else { ++it; } } } private: typedef paradevs::pdevs::multithreading::Coordinator < common::DoubleTime, SchedulerType, SchedulerHandle, ParallelBuiltFlatGraphManager < SchedulerHandle >, common::NoParameters, GraphParameters > ParallelCoordinator; typedef std::vector < ParallelCoordinator* > Coordinators; Coordinators _coordinators; }; } } } // namespace paradevs tests boost_graph #endif