source: NonGTP/Boost/boost/graph/graphviz.hpp @ 857

Revision 857, 24.4 KB checked in by igarcia, 19 years ago (diff)
Line 
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
27namespace 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/////////////////////////////////////////////////////////////////////////////
588struct graph_exception : public std::exception {
589  virtual ~graph_exception() throw() {}
590  virtual const char* what() const throw() = 0;
591};
592
593struct 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
611struct 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
620struct 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
629namespace detail { namespace graph {
630
631typedef std::string id_t;
632typedef id_t node_t;
633
634// edges are not uniquely determined by adjacent nodes
635class edge_t {
636  int idx_;
637  explicit edge_t(int i) : idx_(i) {}
638public:
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
652class 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
670template<typename MutableGraph>
671class 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
737bool 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.
742template <typename MutableGraph>
743bool 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
Note: See TracBrowser for help on using the repository browser.