Chris@16: // Copyright (C) 2004-2006 The Trustees of Indiana University. Chris@16: Chris@16: // Use, modification and distribution is subject to the Boost Software Chris@16: // License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at Chris@16: // http://www.boost.org/LICENSE_1_0.txt) Chris@16: Chris@16: // Authors: Douglas Gregor Chris@16: // Andrew Lumsdaine Chris@16: #ifndef BOOST_GRAPH_PARALLEL_GRAPHVIZ_HPP Chris@16: #define BOOST_GRAPH_PARALLEL_GRAPHVIZ_HPP Chris@16: Chris@16: #ifndef BOOST_GRAPH_USE_MPI Chris@16: #error "Parallel BGL files should not be included unless has been included" Chris@16: #endif Chris@16: Chris@16: #include Chris@16: #include Chris@16: #include Chris@16: #include Chris@16: #include Chris@16: #include Chris@16: #include Chris@16: #include Chris@16: #include Chris@16: #include Chris@16: #include Chris@16: #include Chris@16: #include Chris@16: Chris@16: namespace boost { Chris@16: Chris@16: template Chris@16: struct graph_id_writer Chris@16: { Chris@16: explicit graph_id_writer(const Graph& g) : g(g) { } Chris@16: Chris@16: void operator()(std::ostream& out) Chris@16: { Chris@16: out << " label=\"p" << process_id(g.process_group()) << "\";\n"; Chris@16: } Chris@16: Chris@16: private: Chris@16: const Graph& g; Chris@16: }; Chris@16: Chris@16: template Chris@16: struct paint_by_number_writer Chris@16: { Chris@16: explicit paint_by_number_writer(NumberMap number) : number(number) { } Chris@16: Chris@16: template Chris@16: void operator()(std::ostream& out, Descriptor k) Chris@16: { Chris@16: static const char* color_names[] = { Chris@16: "blue", Chris@16: "brown", Chris@16: "cyan", Chris@16: "darkgreen", Chris@16: "darkorchid", Chris@16: "darksalmon", Chris@16: "darkviolet", Chris@16: "deeppink", Chris@16: "gold3", Chris@16: "green", Chris@16: "magenta", Chris@16: "navy", Chris@16: "red", Chris@16: "yellow", Chris@16: "palegreen", Chris@16: "gray65", Chris@16: "gray21", Chris@16: "bisque2", Chris@16: "greenyellow", Chris@16: "indianred4", Chris@16: "lightblue2", Chris@16: "mediumspringgreen", Chris@16: "orangered", Chris@16: "orange" Chris@16: }; Chris@16: const int colors = sizeof(color_names) / sizeof(color_names[0]); Chris@16: if (get(number, k) < colors) { Chris@16: out << " [ style=\"filled\", fillcolor=\"" << color_names[get(number, k)] Chris@16: << "\" ]"; Chris@16: } else { Chris@16: out << " [ label=\"(" << get(number, k) << ")\" ]"; Chris@16: } Chris@16: } Chris@16: Chris@16: private: Chris@16: NumberMap number; Chris@16: }; Chris@16: Chris@16: template Chris@16: inline paint_by_number_writer Chris@16: paint_by_number(NumberMap number) Chris@16: { return paint_by_number_writer(number); } Chris@16: Chris@16: template Chris@16: void Chris@16: write_graphviz(std::ostream& out, Chris@16: const Graph& g, Chris@16: VertexPropertiesWriter vpw, Chris@16: EdgePropertiesWriter epw, Chris@16: GraphPropertiesWriter gpw Chris@16: BOOST_GRAPH_ENABLE_IF_MODELS_PARM(Graph,distributed_graph_tag)) Chris@16: { Chris@16: typedef typename graph_traits::directed_category directed_category; Chris@16: typedef typename boost::graph::parallel::process_group_type::type Chris@16: process_group_type; Chris@16: typedef typename property_map::const_type Chris@16: VertexIndexMap; Chris@16: typedef typename property_map::const_type Chris@16: VertexGlobalMap; Chris@16: Chris@16: static const bool is_undirected Chris@16: = (is_base_and_derived::value Chris@16: || is_same::value); Chris@16: static const char* graph_kind = is_undirected? "graph" : "digraph"; Chris@16: static const char* edge_kind = is_undirected? "--" : "->"; Chris@16: Chris@16: using boost::graph::parallel::process_group; Chris@16: process_group_type pg = process_group(g); Chris@16: Chris@16: parallel::global_index_map Chris@16: global_index(pg, num_vertices(g), get(vertex_index, g), Chris@16: get(vertex_global, g)); Chris@16: Chris@16: std::ostringstream local_graph_out; Chris@16: Chris@16: local_graph_out << " subgraph cluster_" << process_id(pg) << " {\n"; Chris@16: gpw(local_graph_out); Chris@16: Chris@16: typename graph_traits::vertex_iterator vi, vi_end; Chris@16: for (boost::tie(vi, vi_end) = vertices(g); vi != vi_end; ++vi) { Chris@16: Chris@16: int global_idx = get(global_index, *vi); Chris@16: local_graph_out << " n" << global_idx; Chris@16: vpw(local_graph_out, *vi); Chris@16: local_graph_out << ";\n"; Chris@16: } Chris@16: local_graph_out << " }\n\n"; Chris@16: Chris@16: Chris@16: typename graph_traits::edge_iterator ei, ei_end; Chris@16: for (boost::tie(ei, ei_end) = edges(g); ei != ei_end; ++ei) { Chris@16: int source_idx = get(global_index, source(*ei, g)); Chris@16: int target_idx = get(global_index, target(*ei, g)); Chris@16: local_graph_out << " n" << source_idx << " " << edge_kind << " n" Chris@16: << target_idx; Chris@16: epw(local_graph_out, *ei); Chris@16: local_graph_out << ";\n"; Chris@16: } Chris@16: Chris@16: if (process_id(pg) == 0) { Chris@16: out << graph_kind << " g {\n"; Chris@16: out << local_graph_out.str(); Chris@16: Chris@16: synchronize(pg); Chris@16: for (int i = 1; i < num_processes(pg); ++i) { Chris@16: int len; Chris@16: receive(pg, i, 0, len); Chris@16: char* data = new char [len+1]; Chris@16: data[len] = 0; Chris@16: receive(pg, i, 1, data, len); Chris@16: out << std::endl << data; Chris@16: delete [] data; Chris@16: } Chris@16: out << "}\n"; Chris@16: } else { Chris@16: std::string result_str = local_graph_out.str(); Chris@16: const char* data = result_str.c_str(); Chris@16: Chris@16: int len = result_str.length(); Chris@16: send(pg, 0, 0, len); Chris@16: send(pg, 0, 1, data, len); Chris@16: synchronize(pg); Chris@16: } Chris@16: synchronize(pg); Chris@16: synchronize(pg); Chris@16: synchronize(pg); Chris@16: } Chris@16: Chris@16: template Chris@16: inline void Chris@16: write_graphviz(std::ostream& out, Chris@16: const Graph& g, Chris@16: VertexPropertiesWriter vpw, Chris@16: EdgePropertiesWriter epw Chris@16: BOOST_GRAPH_ENABLE_IF_MODELS_PARM(Graph,distributed_graph_tag)) Chris@16: { Chris@16: write_graphviz(out, g, vpw, epw, graph_id_writer(g)); Chris@16: } Chris@16: Chris@16: template Chris@16: inline void Chris@16: write_graphviz(std::ostream& out, Chris@16: const Graph& g, Chris@16: VertexPropertiesWriter vpw Chris@16: BOOST_GRAPH_ENABLE_IF_MODELS_PARM(Graph,distributed_graph_tag)) Chris@16: { Chris@16: write_graphviz(out, g, vpw, default_writer()); Chris@16: } Chris@16: Chris@16: template Chris@16: inline void Chris@16: write_graphviz(std::ostream& out, const Graph& g Chris@16: BOOST_GRAPH_ENABLE_IF_MODELS_PARM(Graph,distributed_graph_tag)) Chris@16: { Chris@16: write_graphviz(out, g, default_writer()); Chris@16: } Chris@16: Chris@16: template Chris@16: void Chris@16: write_graphviz(const std::string& filename, Chris@16: const Graph& g, Chris@16: VertexPropertiesWriter vpw, Chris@16: EdgePropertiesWriter epw, Chris@16: GraphPropertiesWriter gpw Chris@16: BOOST_GRAPH_ENABLE_IF_MODELS_PARM(Graph,distributed_graph_tag)) Chris@16: { Chris@16: if (process_id(g.process_group()) == 0) { Chris@16: std::ofstream out(filename.c_str()); Chris@16: write_graphviz(out, g, vpw, epw, gpw); Chris@16: } else { Chris@16: write_graphviz(std::cout, g, vpw, epw, gpw); Chris@16: } Chris@16: } Chris@16: Chris@16: template Chris@16: void Chris@16: write_graphviz(const std::string& filename, Chris@16: const Graph& g, Chris@16: VertexPropertiesWriter vpw, Chris@16: EdgePropertiesWriter epw Chris@16: BOOST_GRAPH_ENABLE_IF_MODELS_PARM(Graph,distributed_graph_tag)) Chris@16: { Chris@16: if (process_id(g.process_group()) == 0) { Chris@16: std::ofstream out(filename.c_str()); Chris@16: write_graphviz(out, g, vpw, epw); Chris@16: } else { Chris@16: write_graphviz(std::cout, g, vpw, epw); Chris@16: } Chris@16: } Chris@16: Chris@16: template Chris@16: void Chris@16: write_graphviz(const std::string& filename, Chris@16: const Graph& g, Chris@16: VertexPropertiesWriter vpw Chris@16: BOOST_GRAPH_ENABLE_IF_MODELS_PARM(Graph,distributed_graph_tag)) Chris@16: { Chris@16: if (process_id(g.process_group()) == 0) { Chris@16: std::ofstream out(filename.c_str()); Chris@16: write_graphviz(out, g, vpw); Chris@16: } else { Chris@16: write_graphviz(std::cout, g, vpw); Chris@16: } Chris@16: } Chris@16: Chris@16: template Chris@16: void Chris@16: write_graphviz(const std::string& filename, const Graph& g Chris@16: BOOST_GRAPH_ENABLE_IF_MODELS_PARM(Graph,distributed_graph_tag)) Chris@16: { Chris@16: if (process_id(g.process_group()) == 0) { Chris@16: std::ofstream out(filename.c_str()); Chris@16: write_graphviz(out, g); Chris@16: } else { Chris@16: write_graphviz(std::cout, g); Chris@16: } Chris@16: } Chris@16: Chris@16: template Chris@16: void Chris@16: write_graphviz(std::ostream& out, const Graph& g, Chris@16: const dynamic_properties& dp, Chris@16: const std::string& node_id = "node_id" Chris@16: BOOST_GRAPH_ENABLE_IF_MODELS_PARM(Graph,distributed_graph_tag)) Chris@16: { Chris@16: write_graphviz Chris@16: (out, g, Chris@16: /*vertex_writer=*/dynamic_vertex_properties_writer(dp, node_id), Chris@16: /*edge_writer=*/dynamic_properties_writer(dp)); Chris@16: } Chris@16: Chris@16: } // end namespace boost Chris@16: Chris@16: #endif // BOOST_GRAPH_PARALLEL_GRAPHVIZ_HPP