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