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 {
nameboost::graphviz_io_traits31 static std::string name() {
32 return "digraph";
33 }
delimiterboost::graphviz_io_traits34 static std::string delimiter() {
35 return "->";
36 } };
37
38 template <>
39 struct graphviz_io_traits <undirected_tag> {
nameboost::graphviz_io_traits40 static std::string name() {
41 return "graph";
42 }
delimiterboost::graphviz_io_traits43 static std::string delimiter() {
44 return "--";
45 }
46 };
47
48 struct default_writer {
operator ()boost::default_writer49 void operator()(std::ostream&) const {
50 }
51 template <class VorE>
operator ()boost::default_writer52 void operator()(std::ostream&, const VorE&) const {
53 }
54 };
55
56 template <class Name>
57 class label_writer {
58 public:
label_writer(Name _name)59 label_writer(Name _name) : name(_name) {}
60 template <class VertexOrEdge>
operator ()(std::ostream & out,const VertexOrEdge & v) const61 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>
make_label_writer(Name n)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>
write_attributes(const Attribute & attr,std::ostream & out)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>
write_all_attributes(Attributes attributes,const std::string & name,std::ostream & out)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
write_all_attributes(detail::error_property_not_found,const std::string &,std::ostream &)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 {
graph_attributes_writerboost::graph_attributes_writer129 graph_attributes_writer(GraphGraphAttributes gg,
130 GraphNodeAttributes gn,
131 GraphEdgeAttributes ge)
132 : g_attributes(gg), n_attributes(gn), e_attributes(ge) { }
133
operator ()boost::graph_attributes_writer134 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>
make_graph_attributes_writer(const GAttrMap & g_attr,const NAttrMap & n_attr,const EAttrMap & e_attr)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>
make_graph_attributes_writer(const Graph & g)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 {
attributes_writerboost::attributes_writer175 attributes_writer(AttributeMap attr)
176 : attributes(attr) { }
177
178 template <class VorE>
operator ()boost::attributes_writer179 void operator()(std::ostream& out, const VorE& e) const {
180 this->write_attribute(out, attributes[e]);
181 }
182
183 private:
184 template<typename AttributeSequence>
write_attributeboost::attributes_writer185 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
write_attributeboost::attributes_writer195 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>
make_edge_attributes_writer(const Graph & g)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>
make_vertex_attributes_writer(const Graph & g)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>
write_graphviz(std::ostream & out,const Graph & g,VertexPropertiesWriter vpw,EdgePropertiesWriter epw,GraphPropertiesWriter gpw,VertexID vertex_id)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>
write_graphviz(std::ostream & out,const Graph & g,VertexPropertiesWriter vpw,EdgePropertiesWriter epw,GraphPropertiesWriter gpw)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
write_graphviz(std::ostream & out,const Graph & g)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
write_graphviz(std::ostream & out,const Graph & g,VertexWriter vw)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
write_graphviz(std::ostream & out,const Graph & g,VertexWriter vw,EdgeWriter ew)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>
write_graphviz_subgraph(std::ostream & out,const subgraph<Graph_> & g,RandomAccessIterator vertex_marker,RandomAccessIterator edge_marker,VertexID vertex_id)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>
write_graphviz(std::ostream & out,const subgraph<Graph> & g)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>
write_graphviz(const std::string & filename,const subgraph<Graph> & g)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>
write_graphviz(std::ostream & out,const subgraph<Graph> & g,VertexID vertex_id)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>
write_graphviz(const std::string & filename,const subgraph<Graph> & g,VertexID vertex_id)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:
dynamic_properties_writer(const dynamic_properties & dp)477 dynamic_properties_writer(const dynamic_properties& dp) : dp(&dp) { }
478
479 template<typename Descriptor>
operator ()(std::ostream & out,Descriptor key) const480 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:
dynamic_vertex_properties_writer(const dynamic_properties & dp,const std::string & node_id)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>
operator ()(std::ostream & out,Descriptor key) const509 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
node_id_property_mapboost::graph::detail::node_id_property_map542 node_id_property_map() {}
543
node_id_property_mapboost::graph::detail::node_id_property_map544 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
get(node_id_property_map<Vertex> pm,typename node_id_property_map<Vertex>::key_type v)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
write_graphviz(std::ostream & out,const Graph & g,const dynamic_properties & dp,const std::string & node_id="node_id")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
write_graphviz(std::ostream & out,const Graph & g,const dynamic_properties & dp,const std::string & node_id,VertexID id)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 {
~graph_exceptionboost::graph_exception589 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;
bad_parallel_edgeboost::bad_parallel_edge597 bad_parallel_edge(const std::string& i, const std::string& j) :
598 from(i), to(j) {}
599
~bad_parallel_edgeboost::bad_parallel_edge600 virtual ~bad_parallel_edge() throw() {}
whatboost::bad_parallel_edge601 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 {
~directed_graph_errorboost::directed_graph_error612 virtual ~directed_graph_error() throw() {}
whatboost::directed_graph_error613 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 {
~undirected_graph_errorboost::undirected_graph_error621 virtual ~undirected_graph_error() throw() {}
whatboost::undirected_graph_error622 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_;
edge_t(int i)637 explicit edge_t(int i) : idx_(i) {}
638 public:
new_edge()639 static edge_t new_edge() {
640 static int idx = 0;
641 return edge_t(idx++);
642 };
643
operator ==(const edge_t & rhs) const644 bool operator==(const edge_t& rhs) const {
645 return idx_ == rhs.idx_;
646 }
operator <(const edge_t & rhs) const647 bool operator<(const edge_t& rhs) const {
648 return idx_ < rhs.idx_;
649 }
650 };
651
652 class mutate_graph
653 {
654 public:
~mutate_graph()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:
mutate_graph_impl(MutableGraph & graph,dynamic_properties & dp,std::string node_id_prop)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
~mutate_graph_impl()681 ~mutate_graph_impl() {}
682
is_directed() const683 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
do_add_vertex(const node_t & node)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
do_add_edge(const edge_t & edge,const node_t & source,const node_t & target)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
set_node_property(const id_t & key,const node_t & node,const id_t & value)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
set_edge_property(const id_t & key,const edge_t & edge,const id_t & value)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>
read_graphviz(std::istream & in,MutableGraph & graph,dynamic_properties & dp,std::string const & node_id="node_id")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
758