| [12] | 1 | //======================================================================= | 
|---|
 | 2 | // Copyright 2001 University of Notre Dame. | 
|---|
 | 3 | // Copyright 2003 Jeremy Siek | 
|---|
 | 4 | // Authors: Lie-Quan Lee and Jeremy Siek | 
|---|
 | 5 | // | 
|---|
 | 6 | // Distributed under the Boost Software License, Version 1.0. (See | 
|---|
 | 7 | // accompanying file LICENSE_1_0.txt or copy at | 
|---|
 | 8 | // http://www.boost.org/LICENSE_1_0.txt) | 
|---|
 | 9 | //======================================================================= | 
|---|
 | 10 | #ifndef BOOST_GRAPHVIZ_HPP | 
|---|
 | 11 | #define BOOST_GRAPHVIZ_HPP | 
|---|
 | 12 |  | 
|---|
 | 13 | #include <boost/config.hpp> | 
|---|
 | 14 | #include <string> | 
|---|
 | 15 | #include <map> | 
|---|
 | 16 | #include <iostream> | 
|---|
 | 17 | #include <fstream> | 
|---|
 | 18 | #include <stdio.h> // for FILE | 
|---|
 | 19 | #include <boost/property_map.hpp> | 
|---|
 | 20 | #include <boost/tuple/tuple.hpp> | 
|---|
 | 21 | #include <boost/graph/graph_traits.hpp> | 
|---|
 | 22 | #include <boost/graph/properties.hpp> | 
|---|
 | 23 | #include <boost/graph/subgraph.hpp> | 
|---|
 | 24 | #include <boost/graph/adjacency_list.hpp> | 
|---|
 | 25 | #include <boost/dynamic_property_map.hpp> | 
|---|
 | 26 |  | 
|---|
 | 27 | namespace boost { | 
|---|
 | 28 |  | 
|---|
 | 29 |   template <typename directed_category> | 
|---|
 | 30 |   struct graphviz_io_traits { | 
|---|
 | 31 |     static std::string name() { | 
|---|
 | 32 |       return "digraph"; | 
|---|
 | 33 |     } | 
|---|
 | 34 |     static std::string delimiter() { | 
|---|
 | 35 |       return "->"; | 
|---|
 | 36 |     }  }; | 
|---|
 | 37 |  | 
|---|
 | 38 |   template <> | 
|---|
 | 39 |   struct graphviz_io_traits <undirected_tag> { | 
|---|
 | 40 |     static std::string name() { | 
|---|
 | 41 |       return "graph"; | 
|---|
 | 42 |     } | 
|---|
 | 43 |     static std::string delimiter() { | 
|---|
 | 44 |       return "--"; | 
|---|
 | 45 |     } | 
|---|
 | 46 |   }; | 
|---|
 | 47 |  | 
|---|
 | 48 |   struct default_writer { | 
|---|
 | 49 |     void operator()(std::ostream&) const { | 
|---|
 | 50 |     } | 
|---|
 | 51 |     template <class VorE> | 
|---|
 | 52 |     void operator()(std::ostream&, const VorE&) const { | 
|---|
 | 53 |     } | 
|---|
 | 54 |   }; | 
|---|
 | 55 |  | 
|---|
 | 56 |   template <class Name> | 
|---|
 | 57 |   class label_writer { | 
|---|
 | 58 |   public: | 
|---|
 | 59 |     label_writer(Name _name) : name(_name) {} | 
|---|
 | 60 |     template <class VertexOrEdge> | 
|---|
 | 61 |     void operator()(std::ostream& out, const VertexOrEdge& v) const { | 
|---|
 | 62 |       out << "[label=\"" << get(name, v) << "\"]"; | 
|---|
 | 63 |     } | 
|---|
 | 64 |   private: | 
|---|
 | 65 |     Name name; | 
|---|
 | 66 |   }; | 
|---|
 | 67 |   template <class Name> | 
|---|
 | 68 |   inline label_writer<Name> | 
|---|
 | 69 |   make_label_writer(Name n) { | 
|---|
 | 70 |     return label_writer<Name>(n); | 
|---|
 | 71 |   } | 
|---|
 | 72 |  | 
|---|
 | 73 |   enum edge_attribute_t        { edge_attribute        = 1111 }; | 
|---|
 | 74 |   enum vertex_attribute_t      { vertex_attribute      = 2222 }; | 
|---|
 | 75 |   enum graph_graph_attribute_t { graph_graph_attribute = 3333 }; | 
|---|
 | 76 |   enum graph_vertex_attribute_t  { graph_vertex_attribute  = 4444 }; | 
|---|
 | 77 |   enum graph_edge_attribute_t  { graph_edge_attribute  = 5555 }; | 
|---|
 | 78 |  | 
|---|
 | 79 |   BOOST_INSTALL_PROPERTY(edge, attribute); | 
|---|
 | 80 |   BOOST_INSTALL_PROPERTY(vertex, attribute); | 
|---|
 | 81 |   BOOST_INSTALL_PROPERTY(graph, graph_attribute); | 
|---|
 | 82 |   BOOST_INSTALL_PROPERTY(graph, vertex_attribute); | 
|---|
 | 83 |   BOOST_INSTALL_PROPERTY(graph, edge_attribute); | 
|---|
 | 84 |  | 
|---|
 | 85 |  | 
|---|
 | 86 |   template <class Attribute> | 
|---|
 | 87 |   inline void write_attributes(const Attribute& attr, std::ostream& out) { | 
|---|
 | 88 |     typename Attribute::const_iterator i, iend; | 
|---|
 | 89 |     i    = attr.begin(); | 
|---|
 | 90 |     iend = attr.end(); | 
|---|
 | 91 |  | 
|---|
 | 92 |     while ( i != iend ) { | 
|---|
 | 93 |       out << i->first << "=\"" << i->second << "\""; | 
|---|
 | 94 |       ++i; | 
|---|
 | 95 |       if ( i != iend ) | 
|---|
 | 96 |         out << ", "; | 
|---|
 | 97 |     } | 
|---|
 | 98 |   } | 
|---|
 | 99 |  | 
|---|
 | 100 |   template<typename Attributes> | 
|---|
 | 101 |   inline void write_all_attributes(Attributes attributes, | 
|---|
 | 102 |                                    const std::string& name, | 
|---|
 | 103 |                                    std::ostream& out) | 
|---|
 | 104 |   { | 
|---|
 | 105 |     typename Attributes::const_iterator i = attributes.begin(), | 
|---|
 | 106 |                                         end = attributes.end(); | 
|---|
 | 107 |     if (i != end) { | 
|---|
 | 108 |       out << name << " [\n"; | 
|---|
 | 109 |       write_attributes(attributes, out); | 
|---|
 | 110 |       out << "];\n"; | 
|---|
 | 111 |     } | 
|---|
 | 112 |   } | 
|---|
 | 113 |  | 
|---|
 | 114 |   inline void write_all_attributes(detail::error_property_not_found, | 
|---|
 | 115 |                                    const std::string&, | 
|---|
 | 116 |                                    std::ostream&) | 
|---|
 | 117 |   { | 
|---|
 | 118 |     // Do nothing - no attributes exist | 
|---|
 | 119 |   } | 
|---|
 | 120 |  | 
|---|
 | 121 |  | 
|---|
 | 122 |  | 
|---|
 | 123 |  | 
|---|
 | 124 |   template <typename GraphGraphAttributes, | 
|---|
 | 125 |             typename GraphNodeAttributes, | 
|---|
 | 126 |             typename GraphEdgeAttributes> | 
|---|
 | 127 |   struct graph_attributes_writer | 
|---|
 | 128 |   { | 
|---|
 | 129 |     graph_attributes_writer(GraphGraphAttributes gg, | 
|---|
 | 130 |                             GraphNodeAttributes gn, | 
|---|
 | 131 |                             GraphEdgeAttributes ge) | 
|---|
 | 132 |       : g_attributes(gg), n_attributes(gn), e_attributes(ge) { } | 
|---|
 | 133 |  | 
|---|
 | 134 |     void operator()(std::ostream& out) const { | 
|---|
 | 135 |       write_all_attributes(g_attributes, "graph", out); | 
|---|
 | 136 |       write_all_attributes(n_attributes, "node", out); | 
|---|
 | 137 |       write_all_attributes(e_attributes, "edge", out); | 
|---|
 | 138 |     } | 
|---|
 | 139 |     GraphGraphAttributes g_attributes; | 
|---|
 | 140 |     GraphNodeAttributes n_attributes; | 
|---|
 | 141 |     GraphEdgeAttributes e_attributes; | 
|---|
 | 142 |   }; | 
|---|
 | 143 |  | 
|---|
 | 144 |   template <typename GAttrMap, typename NAttrMap, typename EAttrMap> | 
|---|
 | 145 |   graph_attributes_writer<GAttrMap, NAttrMap, EAttrMap> | 
|---|
 | 146 |   make_graph_attributes_writer(const GAttrMap& g_attr, const NAttrMap& n_attr, | 
|---|
 | 147 |                               const EAttrMap& e_attr) { | 
|---|
 | 148 |     return graph_attributes_writer<GAttrMap, NAttrMap, EAttrMap> | 
|---|
 | 149 |       (g_attr, n_attr, e_attr); | 
|---|
 | 150 |   } | 
|---|
 | 151 |  | 
|---|
 | 152 |  | 
|---|
 | 153 |   template <typename Graph> | 
|---|
 | 154 |   graph_attributes_writer | 
|---|
 | 155 |     <typename graph_property<Graph, graph_graph_attribute_t>::type, | 
|---|
 | 156 |      typename graph_property<Graph, graph_vertex_attribute_t>::type, | 
|---|
 | 157 |      typename graph_property<Graph, graph_edge_attribute_t>::type> | 
|---|
 | 158 |   make_graph_attributes_writer(const Graph& g) | 
|---|
 | 159 |   { | 
|---|
 | 160 |     typedef typename graph_property<Graph, graph_graph_attribute_t>::type | 
|---|
 | 161 |       GAttrMap; | 
|---|
 | 162 |     typedef typename graph_property<Graph, graph_vertex_attribute_t>::type | 
|---|
 | 163 |       NAttrMap; | 
|---|
 | 164 |     typedef typename graph_property<Graph, graph_edge_attribute_t>::type | 
|---|
 | 165 |       EAttrMap; | 
|---|
 | 166 |     GAttrMap gam = get_property(g, graph_graph_attribute); | 
|---|
 | 167 |     NAttrMap nam = get_property(g, graph_vertex_attribute); | 
|---|
 | 168 |     EAttrMap eam = get_property(g, graph_edge_attribute); | 
|---|
 | 169 |     graph_attributes_writer<GAttrMap, NAttrMap, EAttrMap> writer(gam, nam, eam); | 
|---|
 | 170 |     return writer; | 
|---|
 | 171 |   } | 
|---|
 | 172 |  | 
|---|
 | 173 |   template <typename AttributeMap> | 
|---|
 | 174 |   struct attributes_writer { | 
|---|
 | 175 |     attributes_writer(AttributeMap attr) | 
|---|
 | 176 |       : attributes(attr) { } | 
|---|
 | 177 |  | 
|---|
 | 178 |     template <class VorE> | 
|---|
 | 179 |     void operator()(std::ostream& out, const VorE& e) const { | 
|---|
 | 180 |       this->write_attribute(out, attributes[e]); | 
|---|
 | 181 |     } | 
|---|
 | 182 |  | 
|---|
 | 183 |     private: | 
|---|
 | 184 |       template<typename AttributeSequence> | 
|---|
 | 185 |       void write_attribute(std::ostream& out, | 
|---|
 | 186 |                            const AttributeSequence& seq) const | 
|---|
 | 187 |       { | 
|---|
 | 188 |         if (!seq.empty()) { | 
|---|
 | 189 |           out << "["; | 
|---|
 | 190 |           write_attributes(seq, out); | 
|---|
 | 191 |           out << "]"; | 
|---|
 | 192 |         } | 
|---|
 | 193 |       } | 
|---|
 | 194 |  | 
|---|
 | 195 |       void write_attribute(std::ostream&, | 
|---|
 | 196 |                            detail::error_property_not_found) const | 
|---|
 | 197 |       { | 
|---|
 | 198 |       } | 
|---|
 | 199 |     AttributeMap attributes; | 
|---|
 | 200 |   }; | 
|---|
 | 201 |  | 
|---|
 | 202 |   template <typename Graph> | 
|---|
 | 203 |   attributes_writer | 
|---|
 | 204 |     <typename property_map<Graph, edge_attribute_t>::const_type> | 
|---|
 | 205 |   make_edge_attributes_writer(const Graph& g) | 
|---|
 | 206 |   { | 
|---|
 | 207 |     typedef typename property_map<Graph, edge_attribute_t>::const_type | 
|---|
 | 208 |       EdgeAttributeMap; | 
|---|
 | 209 |     return attributes_writer<EdgeAttributeMap>(get(edge_attribute, g)); | 
|---|
 | 210 |   } | 
|---|
 | 211 |  | 
|---|
 | 212 |   template <typename Graph> | 
|---|
 | 213 |   attributes_writer | 
|---|
 | 214 |     <typename property_map<Graph, vertex_attribute_t>::const_type> | 
|---|
 | 215 |   make_vertex_attributes_writer(const Graph& g) | 
|---|
 | 216 |   { | 
|---|
 | 217 |     typedef typename property_map<Graph, vertex_attribute_t>::const_type | 
|---|
 | 218 |       VertexAttributeMap; | 
|---|
 | 219 |     return attributes_writer<VertexAttributeMap>(get(vertex_attribute, g)); | 
|---|
 | 220 |   } | 
|---|
 | 221 |  | 
|---|
 | 222 |   template <typename Graph, typename VertexPropertiesWriter, | 
|---|
 | 223 |             typename EdgePropertiesWriter, typename GraphPropertiesWriter, | 
|---|
 | 224 |             typename VertexID> | 
|---|
 | 225 |   inline void write_graphviz(std::ostream& out, const Graph& g, | 
|---|
 | 226 |                              VertexPropertiesWriter vpw, | 
|---|
 | 227 |                              EdgePropertiesWriter epw, | 
|---|
 | 228 |                              GraphPropertiesWriter gpw, | 
|---|
 | 229 |                              VertexID vertex_id) | 
|---|
 | 230 |   { | 
|---|
 | 231 |     typedef typename graph_traits<Graph>::directed_category cat_type; | 
|---|
 | 232 |     typedef graphviz_io_traits<cat_type> Traits; | 
|---|
 | 233 |     std::string name = "G"; | 
|---|
 | 234 |     out << Traits::name() << " " << name << " {" << std::endl; | 
|---|
 | 235 |  | 
|---|
 | 236 |     gpw(out); //print graph properties | 
|---|
 | 237 |  | 
|---|
 | 238 |     typename graph_traits<Graph>::vertex_iterator i, end; | 
|---|
 | 239 |  | 
|---|
 | 240 |     for(tie(i,end) = vertices(g); i != end; ++i) { | 
|---|
 | 241 |       out << get(vertex_id, *i); | 
|---|
 | 242 |       vpw(out, *i); //print vertex attributes | 
|---|
 | 243 |       out << ";" << std::endl; | 
|---|
 | 244 |     } | 
|---|
 | 245 |     typename graph_traits<Graph>::edge_iterator ei, edge_end; | 
|---|
 | 246 |     for(tie(ei, edge_end) = edges(g); ei != edge_end; ++ei) { | 
|---|
 | 247 |       out << get(vertex_id, source(*ei, g)) << Traits::delimiter() << get(vertex_id, target(*ei, g)) << " "; | 
|---|
 | 248 |       epw(out, *ei); //print edge attributes | 
|---|
 | 249 |       out << ";" << std::endl; | 
|---|
 | 250 |     } | 
|---|
 | 251 |     out << "}" << std::endl; | 
|---|
 | 252 |   } | 
|---|
 | 253 |  | 
|---|
 | 254 |   template <typename Graph, typename VertexPropertiesWriter, | 
|---|
 | 255 |             typename EdgePropertiesWriter, typename GraphPropertiesWriter> | 
|---|
 | 256 |   inline void write_graphviz(std::ostream& out, const Graph& g, | 
|---|
 | 257 |                              VertexPropertiesWriter vpw, | 
|---|
 | 258 |                              EdgePropertiesWriter epw, | 
|---|
 | 259 |                              GraphPropertiesWriter gpw) | 
|---|
 | 260 |   { write_graphviz(out, g, vpw, epw, gpw, get(vertex_index, g)); } | 
|---|
 | 261 |  | 
|---|
 | 262 | #if !defined(BOOST_MSVC) || BOOST_MSVC > 1300 | 
|---|
 | 263 |   // ambiguous overload problem with VC++ | 
|---|
 | 264 |   template <typename Graph> | 
|---|
 | 265 |   inline void | 
|---|
 | 266 |   write_graphviz(std::ostream& out, const Graph& g) { | 
|---|
 | 267 |     default_writer dw; | 
|---|
 | 268 |     default_writer gw; | 
|---|
 | 269 |     write_graphviz(out, g, dw, dw, gw); | 
|---|
 | 270 |   } | 
|---|
 | 271 | #endif | 
|---|
 | 272 |  | 
|---|
 | 273 |   template <typename Graph, typename VertexWriter> | 
|---|
 | 274 |   inline void | 
|---|
 | 275 |   write_graphviz(std::ostream& out, const Graph& g, VertexWriter vw) { | 
|---|
 | 276 |     default_writer dw; | 
|---|
 | 277 |     default_writer gw; | 
|---|
 | 278 |     write_graphviz(out, g, vw, dw, gw); | 
|---|
 | 279 |   } | 
|---|
 | 280 |  | 
|---|
 | 281 |   template <typename Graph, typename VertexWriter, typename EdgeWriter> | 
|---|
 | 282 |   inline void | 
|---|
 | 283 |   write_graphviz(std::ostream& out, const Graph& g, | 
|---|
 | 284 |                  VertexWriter vw, EdgeWriter ew) { | 
|---|
 | 285 |     default_writer gw; | 
|---|
 | 286 |     write_graphviz(out, g, vw, ew, gw); | 
|---|
 | 287 |   } | 
|---|
 | 288 |  | 
|---|
 | 289 |   namespace detail { | 
|---|
 | 290 |  | 
|---|
 | 291 |     template <class Graph_, class RandomAccessIterator, class VertexID> | 
|---|
 | 292 |     void write_graphviz_subgraph (std::ostream& out, | 
|---|
 | 293 |                                   const subgraph<Graph_>& g, | 
|---|
 | 294 |                                   RandomAccessIterator vertex_marker, | 
|---|
 | 295 |                                   RandomAccessIterator edge_marker, | 
|---|
 | 296 |                                   VertexID vertex_id) | 
|---|
 | 297 |     { | 
|---|
 | 298 |       typedef subgraph<Graph_> Graph; | 
|---|
 | 299 |       typedef typename graph_traits<Graph>::vertex_descriptor Vertex; | 
|---|
 | 300 |       typedef typename graph_traits<Graph>::directed_category cat_type; | 
|---|
 | 301 |       typedef graphviz_io_traits<cat_type> Traits; | 
|---|
 | 302 |  | 
|---|
 | 303 |       typedef typename graph_property<Graph, graph_name_t>::type NameType; | 
|---|
 | 304 |       const NameType& g_name = get_property(g, graph_name); | 
|---|
 | 305 |  | 
|---|
 | 306 |       if ( g.is_root() ) | 
|---|
 | 307 |         out << Traits::name() ; | 
|---|
 | 308 |       else | 
|---|
 | 309 |         out << "subgraph"; | 
|---|
 | 310 |  | 
|---|
 | 311 |       out << " " << g_name << " {" << std::endl; | 
|---|
 | 312 |  | 
|---|
 | 313 |       typename Graph::const_children_iterator i_child, j_child; | 
|---|
 | 314 |  | 
|---|
 | 315 |       //print graph/node/edge attributes | 
|---|
 | 316 | #if defined(BOOST_MSVC) && BOOST_MSVC <= 1300 | 
|---|
 | 317 |       typedef typename graph_property<Graph, graph_graph_attribute_t>::type | 
|---|
 | 318 |         GAttrMap; | 
|---|
 | 319 |       typedef typename graph_property<Graph, graph_vertex_attribute_t>::type | 
|---|
 | 320 |         NAttrMap; | 
|---|
 | 321 |       typedef typename graph_property<Graph, graph_edge_attribute_t>::type | 
|---|
 | 322 |         EAttrMap; | 
|---|
 | 323 |       GAttrMap gam = get_property(g, graph_graph_attribute); | 
|---|
 | 324 |       NAttrMap nam = get_property(g, graph_vertex_attribute); | 
|---|
 | 325 |       EAttrMap eam = get_property(g, graph_edge_attribute); | 
|---|
 | 326 |       graph_attributes_writer<GAttrMap, NAttrMap, EAttrMap> writer(gam, nam, eam); | 
|---|
 | 327 |       writer(out); | 
|---|
 | 328 | #else | 
|---|
 | 329 |       make_graph_attributes_writer(g)(out); | 
|---|
 | 330 | #endif | 
|---|
 | 331 |  | 
|---|
 | 332 |       //print subgraph | 
|---|
 | 333 |       for ( tie(i_child,j_child) = g.children(); | 
|---|
 | 334 |             i_child != j_child; ++i_child ) | 
|---|
 | 335 |         write_graphviz_subgraph(out, *i_child, vertex_marker, edge_marker, | 
|---|
 | 336 |                                 vertex_id); | 
|---|
 | 337 |  | 
|---|
 | 338 |       // Print out vertices and edges not in the subgraphs. | 
|---|
 | 339 |  | 
|---|
 | 340 |       typename graph_traits<Graph>::vertex_iterator i, end; | 
|---|
 | 341 |       typename graph_traits<Graph>::edge_iterator ei, edge_end; | 
|---|
 | 342 |  | 
|---|
 | 343 |       for(tie(i,end) = vertices(g); i != end; ++i) { | 
|---|
 | 344 |         Vertex v = g.local_to_global(*i); | 
|---|
 | 345 |         int pos = get(vertex_id, v); | 
|---|
 | 346 |         if ( vertex_marker[pos] ) { | 
|---|
 | 347 |           vertex_marker[pos] = false; | 
|---|
 | 348 |           out << pos; | 
|---|
 | 349 | #if defined(BOOST_MSVC) && BOOST_MSVC <= 1300 | 
|---|
 | 350 |           typedef typename property_map<Graph, vertex_attribute_t>::const_type | 
|---|
 | 351 |             VertexAttributeMap; | 
|---|
 | 352 |           attributes_writer<VertexAttributeMap> vawriter(get(vertex_attribute, | 
|---|
 | 353 |                                                              g.root())); | 
|---|
 | 354 |           vawriter(out, v); | 
|---|
 | 355 | #else | 
|---|
 | 356 |           make_vertex_attributes_writer(g.root())(out, v); | 
|---|
 | 357 | #endif | 
|---|
 | 358 |           out << ";" << std::endl; | 
|---|
 | 359 |         } | 
|---|
 | 360 |       } | 
|---|
 | 361 |  | 
|---|
 | 362 |       for (tie(ei, edge_end) = edges(g); ei != edge_end; ++ei) { | 
|---|
 | 363 |         Vertex u = g.local_to_global(source(*ei,g)), | 
|---|
 | 364 |           v = g.local_to_global(target(*ei, g)); | 
|---|
 | 365 |         int pos = get(get(edge_index, g.root()), g.local_to_global(*ei)); | 
|---|
 | 366 |         if ( edge_marker[pos] ) { | 
|---|
 | 367 |           edge_marker[pos] = false; | 
|---|
 | 368 |           out << get(vertex_id, u) << " " << Traits::delimiter() | 
|---|
 | 369 |               << " " << get(vertex_id, v); | 
|---|
 | 370 | #if defined(BOOST_MSVC) && BOOST_MSVC <= 1300 | 
|---|
 | 371 |           typedef typename property_map<Graph, edge_attribute_t>::const_type | 
|---|
 | 372 |             EdgeAttributeMap; | 
|---|
 | 373 |           attributes_writer<EdgeAttributeMap> eawriter(get(edge_attribute, g)); | 
|---|
 | 374 |           eawriter(out, *ei); | 
|---|
 | 375 | #else | 
|---|
 | 376 |           make_edge_attributes_writer(g)(out, *ei); //print edge properties | 
|---|
 | 377 | #endif | 
|---|
 | 378 |           out << ";" << std::endl; | 
|---|
 | 379 |         } | 
|---|
 | 380 |       } | 
|---|
 | 381 |       out << "}" << std::endl; | 
|---|
 | 382 |     } | 
|---|
 | 383 |   } // namespace detail | 
|---|
 | 384 |  | 
|---|
 | 385 |   // requires graph_name graph property | 
|---|
 | 386 |   template <typename Graph> | 
|---|
 | 387 |   void write_graphviz(std::ostream& out, const subgraph<Graph>& g) { | 
|---|
 | 388 |     std::vector<bool> edge_marker(num_edges(g), true); | 
|---|
 | 389 |     std::vector<bool> vertex_marker(num_vertices(g), true); | 
|---|
 | 390 |  | 
|---|
 | 391 |     detail::write_graphviz_subgraph(out, g, | 
|---|
 | 392 |                                     vertex_marker.begin(), | 
|---|
 | 393 |                                     edge_marker.begin(),  | 
|---|
 | 394 |                                     get(vertex_index, g)); | 
|---|
 | 395 |   } | 
|---|
 | 396 |  | 
|---|
 | 397 |   template <typename Graph> | 
|---|
 | 398 |   void write_graphviz(const std::string& filename, const subgraph<Graph>& g) { | 
|---|
 | 399 |     std::ofstream out(filename.c_str()); | 
|---|
 | 400 |     std::vector<bool> edge_marker(num_edges(g), true); | 
|---|
 | 401 |     std::vector<bool> vertex_marker(num_vertices(g), true); | 
|---|
 | 402 |  | 
|---|
 | 403 |     detail::write_graphviz_subgraph(out, g, | 
|---|
 | 404 |                                     vertex_marker.begin(), | 
|---|
 | 405 |                                     edge_marker.begin(), | 
|---|
 | 406 |                                     get(vertex_index, g)); | 
|---|
 | 407 |   } | 
|---|
 | 408 |  | 
|---|
 | 409 |   template <typename Graph, typename VertexID> | 
|---|
 | 410 |   void write_graphviz(std::ostream& out, const subgraph<Graph>& g, | 
|---|
 | 411 |                       VertexID vertex_id)  | 
|---|
 | 412 |   { | 
|---|
 | 413 |     std::vector<bool> edge_marker(num_edges(g), true); | 
|---|
 | 414 |     std::vector<bool> vertex_marker(num_vertices(g), true); | 
|---|
 | 415 |  | 
|---|
 | 416 |     detail::write_graphviz_subgraph(out, g, | 
|---|
 | 417 |                                     vertex_marker.begin(), | 
|---|
 | 418 |                                     edge_marker.begin(),  | 
|---|
 | 419 |                                     vertex_id); | 
|---|
 | 420 |   } | 
|---|
 | 421 |  | 
|---|
 | 422 |   template <typename Graph, typename VertexID> | 
|---|
 | 423 |   void write_graphviz(const std::string& filename, const subgraph<Graph>& g, | 
|---|
 | 424 |                       VertexID vertex_id)  | 
|---|
 | 425 |   { | 
|---|
 | 426 |     std::ofstream out(filename.c_str()); | 
|---|
 | 427 |     std::vector<bool> edge_marker(num_edges(g), true); | 
|---|
 | 428 |     std::vector<bool> vertex_marker(num_vertices(g), true); | 
|---|
 | 429 |  | 
|---|
 | 430 |     detail::write_graphviz_subgraph(out, g, | 
|---|
 | 431 |                                     vertex_marker.begin(), | 
|---|
 | 432 |                                     edge_marker.begin(), | 
|---|
 | 433 |                                     vertex_id); | 
|---|
 | 434 |   } | 
|---|
 | 435 |  | 
|---|
 | 436 |   typedef std::map<std::string, std::string> GraphvizAttrList; | 
|---|
 | 437 |  | 
|---|
 | 438 |   typedef property<vertex_attribute_t, GraphvizAttrList> | 
|---|
 | 439 |           GraphvizVertexProperty; | 
|---|
 | 440 |  | 
|---|
 | 441 |   typedef property<edge_attribute_t, GraphvizAttrList, | 
|---|
 | 442 |                    property<edge_index_t, int> > | 
|---|
 | 443 |           GraphvizEdgeProperty; | 
|---|
 | 444 |  | 
|---|
 | 445 |   typedef property<graph_graph_attribute_t, GraphvizAttrList, | 
|---|
 | 446 |                    property<graph_vertex_attribute_t, GraphvizAttrList, | 
|---|
 | 447 |                    property<graph_edge_attribute_t, GraphvizAttrList, | 
|---|
 | 448 |                    property<graph_name_t, std::string> > > > | 
|---|
 | 449 |           GraphvizGraphProperty; | 
|---|
 | 450 |  | 
|---|
 | 451 |   typedef subgraph<adjacency_list<vecS, | 
|---|
 | 452 |                    vecS, directedS, | 
|---|
 | 453 |                    GraphvizVertexProperty, | 
|---|
 | 454 |                    GraphvizEdgeProperty, | 
|---|
 | 455 |                    GraphvizGraphProperty> > | 
|---|
 | 456 |           GraphvizDigraph; | 
|---|
 | 457 |  | 
|---|
 | 458 |   typedef subgraph<adjacency_list<vecS, | 
|---|
 | 459 |                    vecS, undirectedS, | 
|---|
 | 460 |                    GraphvizVertexProperty, | 
|---|
 | 461 |                    GraphvizEdgeProperty, | 
|---|
 | 462 |                    GraphvizGraphProperty> > | 
|---|
 | 463 |           GraphvizGraph; | 
|---|
 | 464 |  | 
|---|
 | 465 |  | 
|---|
 | 466 |   // These four require linking the BGL-Graphviz library: libbgl-viz.a | 
|---|
 | 467 |   // from the /src directory. | 
|---|
 | 468 |   extern void read_graphviz(const std::string& file, GraphvizDigraph& g); | 
|---|
 | 469 |   extern void read_graphviz(FILE* file, GraphvizDigraph& g); | 
|---|
 | 470 |  | 
|---|
 | 471 |   extern void read_graphviz(const std::string& file, GraphvizGraph& g); | 
|---|
 | 472 |   extern void read_graphviz(FILE* file, GraphvizGraph& g); | 
|---|
 | 473 |  | 
|---|
 | 474 |   class dynamic_properties_writer | 
|---|
 | 475 |   { | 
|---|
 | 476 |   public: | 
|---|
 | 477 |     dynamic_properties_writer(const dynamic_properties& dp) : dp(&dp) { } | 
|---|
 | 478 |  | 
|---|
 | 479 |     template<typename Descriptor> | 
|---|
 | 480 |     void operator()(std::ostream& out, Descriptor key) const | 
|---|
 | 481 |     { | 
|---|
 | 482 |       bool first = true; | 
|---|
 | 483 |       for (dynamic_properties::const_iterator i = dp->begin();  | 
|---|
 | 484 |            i != dp->end(); ++i) { | 
|---|
 | 485 |         if (typeid(key) == i->second->key()) { | 
|---|
 | 486 |           if (first) out << " ["; | 
|---|
 | 487 |           else out << ", "; | 
|---|
 | 488 |           first = false; | 
|---|
 | 489 |  | 
|---|
 | 490 |           out << i->first << "=\"" << i->second->get_string(key) << "\""; | 
|---|
 | 491 |         } | 
|---|
 | 492 |       } | 
|---|
 | 493 |  | 
|---|
 | 494 |       if (!first) out << "]"; | 
|---|
 | 495 |     } | 
|---|
 | 496 |  | 
|---|
 | 497 |   private: | 
|---|
 | 498 |     const dynamic_properties* dp; | 
|---|
 | 499 |   }; | 
|---|
 | 500 |  | 
|---|
 | 501 |   class dynamic_vertex_properties_writer | 
|---|
 | 502 |   { | 
|---|
 | 503 |   public: | 
|---|
 | 504 |     dynamic_vertex_properties_writer(const dynamic_properties& dp, | 
|---|
 | 505 |                                      const std::string& node_id)  | 
|---|
 | 506 |       : dp(&dp), node_id(&node_id) { } | 
|---|
 | 507 |  | 
|---|
 | 508 |     template<typename Descriptor> | 
|---|
 | 509 |     void operator()(std::ostream& out, Descriptor key) const | 
|---|
 | 510 |     { | 
|---|
 | 511 |       bool first = true; | 
|---|
 | 512 |       for (dynamic_properties::const_iterator i = dp->begin();  | 
|---|
 | 513 |            i != dp->end(); ++i) { | 
|---|
 | 514 |         if (typeid(key) == i->second->key() | 
|---|
 | 515 |             && i->first != *node_id) { | 
|---|
 | 516 |           if (first) out << " ["; | 
|---|
 | 517 |           else out << ", "; | 
|---|
 | 518 |           first = false; | 
|---|
 | 519 |  | 
|---|
 | 520 |           out << i->first << "=\"" << i->second->get_string(key) << "\""; | 
|---|
 | 521 |         } | 
|---|
 | 522 |       } | 
|---|
 | 523 |  | 
|---|
 | 524 |       if (!first) out << "]"; | 
|---|
 | 525 |     } | 
|---|
 | 526 |  | 
|---|
 | 527 |   private: | 
|---|
 | 528 |     const dynamic_properties* dp; | 
|---|
 | 529 |     const std::string* node_id; | 
|---|
 | 530 |   }; | 
|---|
 | 531 |  | 
|---|
 | 532 |   namespace graph { namespace detail { | 
|---|
 | 533 |  | 
|---|
 | 534 |     template<typename Vertex> | 
|---|
 | 535 |     struct node_id_property_map | 
|---|
 | 536 |     { | 
|---|
 | 537 |       typedef std::string value_type; | 
|---|
 | 538 |       typedef value_type reference; | 
|---|
 | 539 |       typedef Vertex key_type; | 
|---|
 | 540 |       typedef readable_property_map_tag category; | 
|---|
 | 541 |  | 
|---|
 | 542 |       node_id_property_map() {} | 
|---|
 | 543 |  | 
|---|
 | 544 |       node_id_property_map(const dynamic_properties& dp, | 
|---|
 | 545 |                            const std::string& node_id) | 
|---|
 | 546 |         : dp(&dp), node_id(&node_id) { } | 
|---|
 | 547 |  | 
|---|
 | 548 |       const dynamic_properties* dp; | 
|---|
 | 549 |       const std::string* node_id; | 
|---|
 | 550 |     }; | 
|---|
 | 551 |  | 
|---|
 | 552 |     template<typename Vertex> | 
|---|
 | 553 |     inline std::string  | 
|---|
 | 554 |     get(node_id_property_map<Vertex> pm,  | 
|---|
 | 555 |         typename node_id_property_map<Vertex>::key_type v) | 
|---|
 | 556 |     { return get(*pm.node_id, *pm.dp, v); } | 
|---|
 | 557 |  | 
|---|
 | 558 |   } } // end namespace graph::detail | 
|---|
 | 559 |  | 
|---|
 | 560 |   template<typename Graph> | 
|---|
 | 561 |   inline void | 
|---|
 | 562 |   write_graphviz(std::ostream& out, const Graph& g, | 
|---|
 | 563 |                  const dynamic_properties& dp,  | 
|---|
 | 564 |                  const std::string& node_id = "node_id") | 
|---|
 | 565 |   { | 
|---|
 | 566 |     typedef typename graph_traits<Graph>::vertex_descriptor Vertex; | 
|---|
 | 567 |     write_graphviz(out, g, dp, node_id, | 
|---|
 | 568 |                    graph::detail::node_id_property_map<Vertex>(dp, node_id)); | 
|---|
 | 569 |   } | 
|---|
 | 570 |  | 
|---|
 | 571 |   template<typename Graph, typename VertexID> | 
|---|
 | 572 |   void | 
|---|
 | 573 |   write_graphviz(std::ostream& out, const Graph& g, | 
|---|
 | 574 |                  const dynamic_properties& dp, const std::string& node_id, | 
|---|
 | 575 |                  VertexID id) | 
|---|
 | 576 |   { | 
|---|
 | 577 |     write_graphviz | 
|---|
 | 578 |       (out, g, | 
|---|
 | 579 |        /*vertex_writer=*/dynamic_vertex_properties_writer(dp, node_id), | 
|---|
 | 580 |        /*edge_writer=*/dynamic_properties_writer(dp), | 
|---|
 | 581 |        /*graph_writer=*/default_writer(), | 
|---|
 | 582 |        id); | 
|---|
 | 583 |   } | 
|---|
 | 584 |  | 
|---|
 | 585 | ///////////////////////////////////////////////////////////////////////////// | 
|---|
 | 586 | // Graph reader exceptions | 
|---|
 | 587 | ///////////////////////////////////////////////////////////////////////////// | 
|---|
 | 588 | struct graph_exception : public std::exception { | 
|---|
 | 589 |   virtual ~graph_exception() throw() {} | 
|---|
 | 590 |   virtual const char* what() const throw() = 0; | 
|---|
 | 591 | }; | 
|---|
 | 592 |  | 
|---|
 | 593 | struct bad_parallel_edge : public graph_exception { | 
|---|
 | 594 |   std::string from; | 
|---|
 | 595 |   std::string to; | 
|---|
 | 596 |   mutable std::string statement; | 
|---|
 | 597 |   bad_parallel_edge(const std::string& i, const std::string& j) : | 
|---|
 | 598 |     from(i), to(j) {} | 
|---|
 | 599 |  | 
|---|
 | 600 |   virtual ~bad_parallel_edge() throw() {} | 
|---|
 | 601 |   const char* what() const throw() { | 
|---|
 | 602 |     if(statement.empty()) | 
|---|
 | 603 |       statement = | 
|---|
 | 604 |         std::string("Failed to add parallel edge: (") | 
|---|
 | 605 |         + from +  "," + to + ")\n"; | 
|---|
 | 606 |  | 
|---|
 | 607 |     return statement.c_str(); | 
|---|
 | 608 |   } | 
|---|
 | 609 | }; | 
|---|
 | 610 |  | 
|---|
 | 611 | struct directed_graph_error : public graph_exception { | 
|---|
 | 612 |   virtual ~directed_graph_error() throw() {} | 
|---|
 | 613 |   virtual const char* what() const throw() { | 
|---|
 | 614 |     return | 
|---|
 | 615 |       "read_graphviz: " | 
|---|
 | 616 |       "Tried to read a directed graph into an undirected graph."; | 
|---|
 | 617 |   } | 
|---|
 | 618 | }; | 
|---|
 | 619 |  | 
|---|
 | 620 | struct undirected_graph_error : public graph_exception { | 
|---|
 | 621 |   virtual ~undirected_graph_error() throw() {} | 
|---|
 | 622 |   virtual const char* what() const throw() { | 
|---|
 | 623 |     return | 
|---|
 | 624 |       "read_graphviz: " | 
|---|
 | 625 |       "Tried to read an undirected graph into a directed graph."; | 
|---|
 | 626 |   } | 
|---|
 | 627 | }; | 
|---|
 | 628 |  | 
|---|
 | 629 | namespace detail { namespace graph { | 
|---|
 | 630 |  | 
|---|
 | 631 | typedef std::string id_t; | 
|---|
 | 632 | typedef id_t node_t; | 
|---|
 | 633 |  | 
|---|
 | 634 | // edges are not uniquely determined by adjacent nodes | 
|---|
 | 635 | class edge_t { | 
|---|
 | 636 |   int idx_; | 
|---|
 | 637 |   explicit edge_t(int i) : idx_(i) {} | 
|---|
 | 638 | public: | 
|---|
 | 639 |   static edge_t new_edge() { | 
|---|
 | 640 |     static int idx = 0; | 
|---|
 | 641 |     return edge_t(idx++); | 
|---|
 | 642 |   }; | 
|---|
 | 643 |    | 
|---|
 | 644 |   bool operator==(const edge_t& rhs) const { | 
|---|
 | 645 |     return idx_ == rhs.idx_; | 
|---|
 | 646 |   } | 
|---|
 | 647 |   bool operator<(const edge_t& rhs) const { | 
|---|
 | 648 |     return idx_ < rhs.idx_; | 
|---|
 | 649 |   } | 
|---|
 | 650 | }; | 
|---|
 | 651 |  | 
|---|
 | 652 | class mutate_graph | 
|---|
 | 653 | { | 
|---|
 | 654 |  public: | 
|---|
 | 655 |   virtual ~mutate_graph() {} | 
|---|
 | 656 |   virtual bool is_directed() const = 0; | 
|---|
 | 657 |   virtual void do_add_vertex(const node_t& node) = 0; | 
|---|
 | 658 |  | 
|---|
 | 659 |   virtual void  | 
|---|
 | 660 |   do_add_edge(const edge_t& edge, const node_t& source, const node_t& target) | 
|---|
 | 661 |     = 0; | 
|---|
 | 662 |  | 
|---|
 | 663 |   virtual void  | 
|---|
 | 664 |   set_node_property(const id_t& key, const node_t& node, const id_t& value) = 0; | 
|---|
 | 665 |  | 
|---|
 | 666 |   virtual void  | 
|---|
 | 667 |   set_edge_property(const id_t& key, const edge_t& edge, const id_t& value) = 0; | 
|---|
 | 668 | }; | 
|---|
 | 669 |  | 
|---|
 | 670 | template<typename MutableGraph> | 
|---|
 | 671 | class mutate_graph_impl : public mutate_graph | 
|---|
 | 672 | { | 
|---|
 | 673 |   typedef typename graph_traits<MutableGraph>::vertex_descriptor bgl_vertex_t; | 
|---|
 | 674 |   typedef typename graph_traits<MutableGraph>::edge_descriptor   bgl_edge_t; | 
|---|
 | 675 |  | 
|---|
 | 676 |  public: | 
|---|
 | 677 |   mutate_graph_impl(MutableGraph& graph, dynamic_properties& dp, | 
|---|
 | 678 |                     std::string node_id_prop) | 
|---|
 | 679 |     : graph_(graph), dp_(dp), node_id_prop_(node_id_prop) { } | 
|---|
 | 680 |  | 
|---|
 | 681 |   ~mutate_graph_impl() {} | 
|---|
 | 682 |  | 
|---|
 | 683 |   bool is_directed() const | 
|---|
 | 684 |   { | 
|---|
 | 685 |     return  | 
|---|
 | 686 |       boost::is_convertible< | 
|---|
 | 687 |         typename boost::graph_traits<MutableGraph>::directed_category, | 
|---|
 | 688 |         boost::directed_tag>::value; | 
|---|
 | 689 |   } | 
|---|
 | 690 |  | 
|---|
 | 691 |   virtual void do_add_vertex(const node_t& node) | 
|---|
 | 692 |   { | 
|---|
 | 693 |     // Add the node to the graph. | 
|---|
 | 694 |     bgl_vertex_t v = add_vertex(graph_); | 
|---|
 | 695 |  | 
|---|
 | 696 |     // Set up a mapping from name to BGL vertex. | 
|---|
 | 697 |     bgl_nodes.insert(std::make_pair(node, v)); | 
|---|
 | 698 |      | 
|---|
 | 699 |     // node_id_prop_ allows the caller to see the real id names for nodes. | 
|---|
 | 700 |     put(node_id_prop_, dp_, v, node); | 
|---|
 | 701 |   } | 
|---|
 | 702 |  | 
|---|
 | 703 |   void  | 
|---|
 | 704 |   do_add_edge(const edge_t& edge, const node_t& source, const node_t& target) | 
|---|
 | 705 |   { | 
|---|
 | 706 |     std::pair<bgl_edge_t, bool> result = | 
|---|
 | 707 |      add_edge(bgl_nodes[source], bgl_nodes[target], graph_); | 
|---|
 | 708 |      | 
|---|
 | 709 |     if(!result.second) { | 
|---|
 | 710 |       // In the case of no parallel edges allowed | 
|---|
 | 711 |       throw bad_parallel_edge(source, target); | 
|---|
 | 712 |     } else { | 
|---|
 | 713 |       bgl_edges.insert(std::make_pair(edge, result.first)); | 
|---|
 | 714 |     } | 
|---|
 | 715 |   } | 
|---|
 | 716 |  | 
|---|
 | 717 |   void | 
|---|
 | 718 |   set_node_property(const id_t& key, const node_t& node, const id_t& value) | 
|---|
 | 719 |   { | 
|---|
 | 720 |     put(key, dp_, bgl_nodes[node], value); | 
|---|
 | 721 |   } | 
|---|
 | 722 |  | 
|---|
 | 723 |   void | 
|---|
 | 724 |   set_edge_property(const id_t& key, const edge_t& edge, const id_t& value) | 
|---|
 | 725 |   { | 
|---|
 | 726 |     put(key, dp_, bgl_edges[edge], value); | 
|---|
 | 727 |   } | 
|---|
 | 728 |  | 
|---|
 | 729 |  protected: | 
|---|
 | 730 |   MutableGraph& graph_; | 
|---|
 | 731 |   dynamic_properties& dp_; | 
|---|
 | 732 |   std::string node_id_prop_; | 
|---|
 | 733 |   std::map<node_t, bgl_vertex_t> bgl_nodes; | 
|---|
 | 734 |   std::map<edge_t, bgl_edge_t> bgl_edges; | 
|---|
 | 735 | }; | 
|---|
 | 736 |  | 
|---|
 | 737 | bool read_graphviz(std::istream& in, mutate_graph& graph); | 
|---|
 | 738 |  | 
|---|
 | 739 | } } // end namespace detail::graph | 
|---|
 | 740 |  | 
|---|
 | 741 | // Parse the passed stream as a GraphViz dot file. | 
|---|
 | 742 | template <typename MutableGraph> | 
|---|
 | 743 | bool read_graphviz(std::istream& in, MutableGraph& graph, | 
|---|
 | 744 |                    dynamic_properties& dp, | 
|---|
 | 745 |                    std::string const& node_id = "node_id")  | 
|---|
 | 746 | { | 
|---|
 | 747 |   detail::graph::mutate_graph_impl<MutableGraph> m_graph(graph, dp, node_id); | 
|---|
 | 748 |   return detail::graph::read_graphviz(in, m_graph); | 
|---|
 | 749 | } | 
|---|
 | 750 |  | 
|---|
 | 751 | } // namespace boost | 
|---|
 | 752 |  | 
|---|
 | 753 | #ifdef BOOST_GRAPH_READ_GRAPHVIZ_ITERATORS | 
|---|
 | 754 | #  include <boost/graph/detail/read_graphviz_spirit.hpp> | 
|---|
 | 755 | #endif // BOOST_GRAPH_READ_GRAPHVIZ_ITERATORS | 
|---|
 | 756 |  | 
|---|
 | 757 | #endif // BOOST_GRAPHVIZ_HPP | 
|---|