annotate DEPENDENCIES/generic/include/boost/graph/graphviz.hpp @ 125:34e428693f5d vext

Vext -> Repoint
author Chris Cannam
date Thu, 14 Jun 2018 11:15:39 +0100
parents c530137014c0
children
rev   line source
Chris@16 1 //=======================================================================
Chris@16 2 // Copyright 2001 University of Notre Dame.
Chris@16 3 // Copyright 2003 Jeremy Siek
Chris@16 4 // Authors: Lie-Quan Lee, Jeremy Siek, and Douglas Gregor
Chris@16 5 //
Chris@16 6 // Distributed under the Boost Software License, Version 1.0. (See
Chris@16 7 // accompanying file LICENSE_1_0.txt or copy at
Chris@16 8 // http://www.boost.org/LICENSE_1_0.txt)
Chris@16 9 //=======================================================================
Chris@16 10 #ifndef BOOST_GRAPHVIZ_HPP
Chris@16 11 #define BOOST_GRAPHVIZ_HPP
Chris@16 12
Chris@16 13 #include <boost/config.hpp>
Chris@16 14 #include <string>
Chris@16 15 #include <map>
Chris@16 16 #include <iostream>
Chris@16 17 #include <fstream>
Chris@16 18 #include <stdio.h> // for FILE
Chris@16 19 #include <boost/property_map/property_map.hpp>
Chris@16 20 #include <boost/tuple/tuple.hpp>
Chris@16 21 #include <boost/graph/graph_traits.hpp>
Chris@16 22 #include <boost/graph/properties.hpp>
Chris@16 23 #include <boost/graph/subgraph.hpp>
Chris@16 24 #include <boost/graph/adjacency_list.hpp>
Chris@16 25 #include <boost/property_map/dynamic_property_map.hpp>
Chris@16 26 #include <boost/graph/overloading.hpp>
Chris@16 27 #include <boost/graph/dll_import_export.hpp>
Chris@16 28 #include <boost/graph/compressed_sparse_row_graph.hpp>
Chris@16 29 #include <boost/graph/iteration_macros.hpp>
Chris@16 30 #include <boost/spirit/include/classic_multi_pass.hpp>
Chris@16 31 #include <boost/lexical_cast.hpp>
Chris@16 32 #include <boost/static_assert.hpp>
Chris@16 33 #include <boost/algorithm/string/replace.hpp>
Chris@16 34 #include <boost/xpressive/xpressive_static.hpp>
Chris@16 35 #include <boost/foreach.hpp>
Chris@16 36
Chris@16 37 namespace boost {
Chris@16 38
Chris@16 39 template <typename directed_category>
Chris@16 40 struct graphviz_io_traits {
Chris@16 41 static std::string name() {
Chris@16 42 return "digraph";
Chris@16 43 }
Chris@16 44 static std::string delimiter() {
Chris@16 45 return "->";
Chris@16 46 } };
Chris@16 47
Chris@16 48 template <>
Chris@16 49 struct graphviz_io_traits <undirected_tag> {
Chris@16 50 static std::string name() {
Chris@16 51 return "graph";
Chris@16 52 }
Chris@16 53 static std::string delimiter() {
Chris@16 54 return "--";
Chris@16 55 }
Chris@16 56 };
Chris@16 57
Chris@16 58 struct default_writer {
Chris@16 59 void operator()(std::ostream&) const {
Chris@16 60 }
Chris@16 61 template <class VorE>
Chris@16 62 void operator()(std::ostream&, const VorE&) const {
Chris@16 63 }
Chris@16 64 };
Chris@16 65
Chris@16 66 template <typename T>
Chris@16 67 inline std::string escape_dot_string(const T& obj) {
Chris@16 68 using namespace boost::xpressive;
Chris@16 69 static sregex valid_unquoted_id = (((alpha | '_') >> *_w) | (!as_xpr('-') >> (('.' >> *_d) | (+_d >> !('.' >> *_d)))));
Chris@16 70 std::string s(boost::lexical_cast<std::string>(obj));
Chris@16 71 if (regex_match(s, valid_unquoted_id)) {
Chris@16 72 return s;
Chris@16 73 } else {
Chris@16 74 boost::algorithm::replace_all(s, "\"", "\\\"");
Chris@16 75 return "\"" + s + "\"";
Chris@16 76 }
Chris@16 77 }
Chris@16 78
Chris@16 79 template <class Name>
Chris@16 80 class label_writer {
Chris@16 81 public:
Chris@16 82 label_writer(Name _name) : name(_name) {}
Chris@16 83 template <class VertexOrEdge>
Chris@16 84 void operator()(std::ostream& out, const VertexOrEdge& v) const {
Chris@16 85 out << "[label=" << escape_dot_string(get(name, v)) << "]";
Chris@16 86 }
Chris@16 87 private:
Chris@16 88 Name name;
Chris@16 89 };
Chris@16 90 template <class Name>
Chris@16 91 inline label_writer<Name>
Chris@16 92 make_label_writer(Name n) {
Chris@16 93 return label_writer<Name>(n);
Chris@16 94 }
Chris@16 95
Chris@16 96 enum edge_attribute_t { edge_attribute = 1111 };
Chris@16 97 enum vertex_attribute_t { vertex_attribute = 2222 };
Chris@16 98 enum graph_graph_attribute_t { graph_graph_attribute = 3333 };
Chris@16 99 enum graph_vertex_attribute_t { graph_vertex_attribute = 4444 };
Chris@16 100 enum graph_edge_attribute_t { graph_edge_attribute = 5555 };
Chris@16 101
Chris@16 102 BOOST_INSTALL_PROPERTY(edge, attribute);
Chris@16 103 BOOST_INSTALL_PROPERTY(vertex, attribute);
Chris@16 104 BOOST_INSTALL_PROPERTY(graph, graph_attribute);
Chris@16 105 BOOST_INSTALL_PROPERTY(graph, vertex_attribute);
Chris@16 106 BOOST_INSTALL_PROPERTY(graph, edge_attribute);
Chris@16 107
Chris@16 108
Chris@16 109 template <class Attribute>
Chris@16 110 inline void write_attributes(const Attribute& attr, std::ostream& out) {
Chris@16 111 typename Attribute::const_iterator i, iend;
Chris@16 112 i = attr.begin();
Chris@16 113 iend = attr.end();
Chris@16 114
Chris@16 115 while ( i != iend ) {
Chris@16 116 out << i->first << "=" << escape_dot_string(i->second);
Chris@16 117 ++i;
Chris@16 118 if ( i != iend )
Chris@16 119 out << ", ";
Chris@16 120 }
Chris@16 121 }
Chris@16 122
Chris@16 123 template<typename Attributes>
Chris@16 124 inline void write_all_attributes(Attributes attributes,
Chris@16 125 const std::string& name,
Chris@16 126 std::ostream& out)
Chris@16 127 {
Chris@16 128 typename Attributes::const_iterator i = attributes.begin(),
Chris@16 129 end = attributes.end();
Chris@16 130 if (i != end) {
Chris@16 131 out << name << " [\n";
Chris@16 132 write_attributes(attributes, out);
Chris@16 133 out << "];\n";
Chris@16 134 }
Chris@16 135 }
Chris@16 136
Chris@16 137 inline void write_all_attributes(detail::error_property_not_found,
Chris@16 138 const std::string&,
Chris@16 139 std::ostream&)
Chris@16 140 {
Chris@16 141 // Do nothing - no attributes exist
Chris@16 142 }
Chris@16 143
Chris@16 144
Chris@16 145
Chris@16 146
Chris@16 147 template <typename GraphGraphAttributes,
Chris@16 148 typename GraphNodeAttributes,
Chris@16 149 typename GraphEdgeAttributes>
Chris@16 150 struct graph_attributes_writer
Chris@16 151 {
Chris@16 152 graph_attributes_writer(GraphGraphAttributes gg,
Chris@16 153 GraphNodeAttributes gn,
Chris@16 154 GraphEdgeAttributes ge)
Chris@16 155 : g_attributes(gg), n_attributes(gn), e_attributes(ge) { }
Chris@16 156
Chris@16 157 void operator()(std::ostream& out) const {
Chris@16 158 write_all_attributes(g_attributes, "graph", out);
Chris@16 159 write_all_attributes(n_attributes, "node", out);
Chris@16 160 write_all_attributes(e_attributes, "edge", out);
Chris@16 161 }
Chris@16 162 GraphGraphAttributes g_attributes;
Chris@16 163 GraphNodeAttributes n_attributes;
Chris@16 164 GraphEdgeAttributes e_attributes;
Chris@16 165 };
Chris@16 166
Chris@16 167 template <typename GAttrMap, typename NAttrMap, typename EAttrMap>
Chris@16 168 graph_attributes_writer<GAttrMap, NAttrMap, EAttrMap>
Chris@16 169 make_graph_attributes_writer(const GAttrMap& g_attr, const NAttrMap& n_attr,
Chris@16 170 const EAttrMap& e_attr) {
Chris@16 171 return graph_attributes_writer<GAttrMap, NAttrMap, EAttrMap>
Chris@16 172 (g_attr, n_attr, e_attr);
Chris@16 173 }
Chris@16 174
Chris@16 175
Chris@16 176 template <typename Graph>
Chris@16 177 graph_attributes_writer
Chris@16 178 <typename graph_property<Graph, graph_graph_attribute_t>::type,
Chris@16 179 typename graph_property<Graph, graph_vertex_attribute_t>::type,
Chris@16 180 typename graph_property<Graph, graph_edge_attribute_t>::type>
Chris@16 181 make_graph_attributes_writer(const Graph& g)
Chris@16 182 {
Chris@16 183 typedef typename graph_property<Graph, graph_graph_attribute_t>::type
Chris@16 184 GAttrMap;
Chris@16 185 typedef typename graph_property<Graph, graph_vertex_attribute_t>::type
Chris@16 186 NAttrMap;
Chris@16 187 typedef typename graph_property<Graph, graph_edge_attribute_t>::type
Chris@16 188 EAttrMap;
Chris@16 189 GAttrMap gam = get_property(g, graph_graph_attribute);
Chris@16 190 NAttrMap nam = get_property(g, graph_vertex_attribute);
Chris@16 191 EAttrMap eam = get_property(g, graph_edge_attribute);
Chris@16 192 graph_attributes_writer<GAttrMap, NAttrMap, EAttrMap> writer(gam, nam, eam);
Chris@16 193 return writer;
Chris@16 194 }
Chris@16 195
Chris@16 196 template <typename AttributeMap>
Chris@16 197 struct attributes_writer {
Chris@16 198 attributes_writer(AttributeMap attr)
Chris@16 199 : attributes(attr) { }
Chris@16 200
Chris@16 201 template <class VorE>
Chris@16 202 void operator()(std::ostream& out, const VorE& e) const {
Chris@16 203 this->write_attribute(out, attributes[e]);
Chris@16 204 }
Chris@16 205
Chris@16 206 private:
Chris@16 207 template<typename AttributeSequence>
Chris@16 208 void write_attribute(std::ostream& out,
Chris@16 209 const AttributeSequence& seq) const
Chris@16 210 {
Chris@16 211 if (!seq.empty()) {
Chris@16 212 out << "[";
Chris@16 213 write_attributes(seq, out);
Chris@16 214 out << "]";
Chris@16 215 }
Chris@16 216 }
Chris@16 217
Chris@16 218 void write_attribute(std::ostream&,
Chris@16 219 detail::error_property_not_found) const
Chris@16 220 {
Chris@16 221 }
Chris@16 222 AttributeMap attributes;
Chris@16 223 };
Chris@16 224
Chris@16 225 template <typename Graph>
Chris@16 226 attributes_writer
Chris@16 227 <typename property_map<Graph, edge_attribute_t>::const_type>
Chris@16 228 make_edge_attributes_writer(const Graph& g)
Chris@16 229 {
Chris@16 230 typedef typename property_map<Graph, edge_attribute_t>::const_type
Chris@16 231 EdgeAttributeMap;
Chris@16 232 return attributes_writer<EdgeAttributeMap>(get(edge_attribute, g));
Chris@16 233 }
Chris@16 234
Chris@16 235 template <typename Graph>
Chris@16 236 attributes_writer
Chris@16 237 <typename property_map<Graph, vertex_attribute_t>::const_type>
Chris@16 238 make_vertex_attributes_writer(const Graph& g)
Chris@16 239 {
Chris@16 240 typedef typename property_map<Graph, vertex_attribute_t>::const_type
Chris@16 241 VertexAttributeMap;
Chris@16 242 return attributes_writer<VertexAttributeMap>(get(vertex_attribute, g));
Chris@16 243 }
Chris@16 244
Chris@16 245 template <typename Graph, typename VertexPropertiesWriter,
Chris@16 246 typename EdgePropertiesWriter, typename GraphPropertiesWriter,
Chris@16 247 typename VertexID>
Chris@16 248 inline void
Chris@16 249 write_graphviz
Chris@16 250 (std::ostream& out, const Graph& g,
Chris@16 251 VertexPropertiesWriter vpw,
Chris@16 252 EdgePropertiesWriter epw,
Chris@16 253 GraphPropertiesWriter gpw,
Chris@16 254 VertexID vertex_id
Chris@16 255 BOOST_GRAPH_ENABLE_IF_MODELS_PARM(Graph,vertex_list_graph_tag))
Chris@16 256 {
Chris@16 257 BOOST_CONCEPT_ASSERT((EdgeListGraphConcept<Graph>));
Chris@16 258
Chris@16 259 typedef typename graph_traits<Graph>::directed_category cat_type;
Chris@16 260 typedef graphviz_io_traits<cat_type> Traits;
Chris@16 261 std::string name = "G";
Chris@16 262 out << Traits::name() << " " << escape_dot_string(name) << " {" << std::endl;
Chris@16 263
Chris@16 264 gpw(out); //print graph properties
Chris@16 265
Chris@16 266 typename graph_traits<Graph>::vertex_iterator i, end;
Chris@16 267
Chris@16 268 for(boost::tie(i,end) = vertices(g); i != end; ++i) {
Chris@16 269 out << escape_dot_string(get(vertex_id, *i));
Chris@16 270 vpw(out, *i); //print vertex attributes
Chris@16 271 out << ";" << std::endl;
Chris@16 272 }
Chris@16 273 typename graph_traits<Graph>::edge_iterator ei, edge_end;
Chris@16 274 for(boost::tie(ei, edge_end) = edges(g); ei != edge_end; ++ei) {
Chris@16 275 out << escape_dot_string(get(vertex_id, source(*ei, g))) << Traits::delimiter() << escape_dot_string(get(vertex_id, target(*ei, g))) << " ";
Chris@16 276 epw(out, *ei); //print edge attributes
Chris@16 277 out << ";" << std::endl;
Chris@16 278 }
Chris@16 279 out << "}" << std::endl;
Chris@16 280 }
Chris@16 281
Chris@16 282 template <typename Graph, typename VertexPropertiesWriter,
Chris@16 283 typename EdgePropertiesWriter, typename GraphPropertiesWriter>
Chris@16 284 inline void
Chris@16 285 write_graphviz(std::ostream& out, const Graph& g,
Chris@16 286 VertexPropertiesWriter vpw,
Chris@16 287 EdgePropertiesWriter epw,
Chris@16 288 GraphPropertiesWriter gpw
Chris@16 289 BOOST_GRAPH_ENABLE_IF_MODELS_PARM(Graph,vertex_list_graph_tag))
Chris@16 290 { write_graphviz(out, g, vpw, epw, gpw, get(vertex_index, g)); }
Chris@16 291
Chris@16 292 template <typename Graph>
Chris@16 293 inline void
Chris@16 294 write_graphviz(std::ostream& out, const Graph& g
Chris@16 295 BOOST_GRAPH_ENABLE_IF_MODELS_PARM(Graph,vertex_list_graph_tag))
Chris@16 296 {
Chris@16 297 default_writer dw;
Chris@16 298 default_writer gw;
Chris@16 299 write_graphviz(out, g, dw, dw, gw);
Chris@16 300 }
Chris@16 301
Chris@16 302 template <typename Graph, typename VertexWriter>
Chris@16 303 inline void
Chris@16 304 write_graphviz(std::ostream& out, const Graph& g, VertexWriter vw
Chris@16 305 BOOST_GRAPH_ENABLE_IF_MODELS_PARM(Graph,vertex_list_graph_tag))
Chris@16 306 {
Chris@16 307 default_writer dw;
Chris@16 308 default_writer gw;
Chris@16 309 write_graphviz(out, g, vw, dw, gw);
Chris@16 310 }
Chris@16 311
Chris@16 312 template <typename Graph, typename VertexWriter, typename EdgeWriter>
Chris@16 313 inline void
Chris@16 314 write_graphviz(std::ostream& out, const Graph& g,
Chris@16 315 VertexWriter vw, EdgeWriter ew
Chris@16 316 BOOST_GRAPH_ENABLE_IF_MODELS_PARM(Graph,vertex_list_graph_tag))
Chris@16 317 {
Chris@16 318 default_writer gw;
Chris@16 319 write_graphviz(out, g, vw, ew, gw);
Chris@16 320 }
Chris@16 321
Chris@16 322 namespace detail {
Chris@16 323
Chris@16 324 template <class Graph_, class RandomAccessIterator, class VertexID>
Chris@16 325 void write_graphviz_subgraph (std::ostream& out,
Chris@16 326 const subgraph<Graph_>& g,
Chris@16 327 RandomAccessIterator vertex_marker,
Chris@16 328 RandomAccessIterator edge_marker,
Chris@16 329 VertexID vertex_id)
Chris@16 330 {
Chris@16 331 typedef subgraph<Graph_> Graph;
Chris@16 332 typedef typename graph_traits<Graph>::vertex_descriptor Vertex;
Chris@16 333 typedef typename graph_traits<Graph>::directed_category cat_type;
Chris@16 334 typedef graphviz_io_traits<cat_type> Traits;
Chris@16 335
Chris@16 336 typedef typename graph_property<Graph, graph_name_t>::type NameType;
Chris@16 337 const NameType& g_name = get_property(g, graph_name);
Chris@16 338
Chris@16 339 if ( g.is_root() )
Chris@16 340 out << Traits::name() ;
Chris@16 341 else
Chris@16 342 out << "subgraph";
Chris@16 343
Chris@16 344 out << " " << escape_dot_string(g_name) << " {" << std::endl;
Chris@16 345
Chris@16 346 typename Graph::const_children_iterator i_child, j_child;
Chris@16 347
Chris@16 348 //print graph/node/edge attributes
Chris@16 349 make_graph_attributes_writer(g)(out);
Chris@16 350
Chris@16 351 //print subgraph
Chris@16 352 for ( boost::tie(i_child,j_child) = g.children();
Chris@16 353 i_child != j_child; ++i_child )
Chris@16 354 write_graphviz_subgraph(out, *i_child, vertex_marker, edge_marker,
Chris@16 355 vertex_id);
Chris@16 356
Chris@16 357 // Print out vertices and edges not in the subgraphs.
Chris@16 358
Chris@16 359 typename graph_traits<Graph>::vertex_iterator i, end;
Chris@16 360 typename graph_traits<Graph>::edge_iterator ei, edge_end;
Chris@16 361
Chris@16 362 for(boost::tie(i,end) = vertices(g); i != end; ++i) {
Chris@16 363 Vertex v = g.local_to_global(*i);
Chris@16 364 int pos = get(vertex_id, v);
Chris@16 365 if ( vertex_marker[pos] ) {
Chris@16 366 vertex_marker[pos] = false;
Chris@16 367 out << escape_dot_string(pos);
Chris@16 368 make_vertex_attributes_writer(g.root())(out, v);
Chris@16 369 out << ";" << std::endl;
Chris@16 370 }
Chris@16 371 }
Chris@16 372
Chris@16 373 for (boost::tie(ei, edge_end) = edges(g); ei != edge_end; ++ei) {
Chris@16 374 Vertex u = g.local_to_global(source(*ei,g)),
Chris@16 375 v = g.local_to_global(target(*ei, g));
Chris@16 376 int pos = get(get(edge_index, g.root()), g.local_to_global(*ei));
Chris@16 377 if ( edge_marker[pos] ) {
Chris@16 378 edge_marker[pos] = false;
Chris@16 379 out << escape_dot_string(get(vertex_id, u)) << " " << Traits::delimiter()
Chris@16 380 << " " << escape_dot_string(get(vertex_id, v));
Chris@16 381 make_edge_attributes_writer(g)(out, *ei); //print edge properties
Chris@16 382 out << ";" << std::endl;
Chris@16 383 }
Chris@16 384 }
Chris@16 385 out << "}" << std::endl;
Chris@16 386 }
Chris@16 387 } // namespace detail
Chris@16 388
Chris@16 389 // requires graph_name graph property
Chris@16 390 template <typename Graph>
Chris@16 391 void write_graphviz(std::ostream& out, const subgraph<Graph>& g) {
Chris@16 392 std::vector<bool> edge_marker(num_edges(g), true);
Chris@16 393 std::vector<bool> vertex_marker(num_vertices(g), true);
Chris@16 394
Chris@16 395 detail::write_graphviz_subgraph(out, g,
Chris@16 396 vertex_marker.begin(),
Chris@16 397 edge_marker.begin(),
Chris@16 398 get(vertex_index, g));
Chris@16 399 }
Chris@16 400
Chris@16 401 template <typename Graph>
Chris@16 402 void write_graphviz(const std::string& filename, const subgraph<Graph>& g) {
Chris@16 403 std::ofstream out(filename.c_str());
Chris@16 404 std::vector<bool> edge_marker(num_edges(g), true);
Chris@16 405 std::vector<bool> vertex_marker(num_vertices(g), true);
Chris@16 406
Chris@16 407 detail::write_graphviz_subgraph(out, g,
Chris@16 408 vertex_marker.begin(),
Chris@16 409 edge_marker.begin(),
Chris@16 410 get(vertex_index, g));
Chris@16 411 }
Chris@16 412
Chris@16 413 template <typename Graph, typename VertexID>
Chris@16 414 void write_graphviz(std::ostream& out, const subgraph<Graph>& g,
Chris@16 415 VertexID vertex_id)
Chris@16 416 {
Chris@16 417 std::vector<bool> edge_marker(num_edges(g), true);
Chris@16 418 std::vector<bool> vertex_marker(num_vertices(g), true);
Chris@16 419
Chris@16 420 detail::write_graphviz_subgraph(out, g,
Chris@16 421 vertex_marker.begin(),
Chris@16 422 edge_marker.begin(),
Chris@16 423 vertex_id);
Chris@16 424 }
Chris@16 425
Chris@16 426 template <typename Graph, typename VertexID>
Chris@16 427 void write_graphviz(const std::string& filename, const subgraph<Graph>& g,
Chris@16 428 VertexID vertex_id)
Chris@16 429 {
Chris@16 430 std::ofstream out(filename.c_str());
Chris@16 431 std::vector<bool> edge_marker(num_edges(g), true);
Chris@16 432 std::vector<bool> vertex_marker(num_vertices(g), true);
Chris@16 433
Chris@16 434 detail::write_graphviz_subgraph(out, g,
Chris@16 435 vertex_marker.begin(),
Chris@16 436 edge_marker.begin(),
Chris@16 437 vertex_id);
Chris@16 438 }
Chris@16 439
Chris@16 440 #if 0
Chris@16 441 // This interface has not worked for a long time
Chris@16 442 typedef std::map<std::string, std::string> GraphvizAttrList;
Chris@16 443
Chris@16 444 typedef property<vertex_attribute_t, GraphvizAttrList>
Chris@16 445 GraphvizVertexProperty;
Chris@16 446
Chris@16 447 typedef property<edge_attribute_t, GraphvizAttrList,
Chris@16 448 property<edge_index_t, int> >
Chris@16 449 GraphvizEdgeProperty;
Chris@16 450
Chris@16 451 typedef property<graph_graph_attribute_t, GraphvizAttrList,
Chris@16 452 property<graph_vertex_attribute_t, GraphvizAttrList,
Chris@16 453 property<graph_edge_attribute_t, GraphvizAttrList,
Chris@16 454 property<graph_name_t, std::string> > > >
Chris@16 455 GraphvizGraphProperty;
Chris@16 456
Chris@16 457 typedef subgraph<adjacency_list<vecS,
Chris@16 458 vecS, directedS,
Chris@16 459 GraphvizVertexProperty,
Chris@16 460 GraphvizEdgeProperty,
Chris@16 461 GraphvizGraphProperty> >
Chris@16 462 GraphvizDigraph;
Chris@16 463
Chris@16 464 typedef subgraph<adjacency_list<vecS,
Chris@16 465 vecS, undirectedS,
Chris@16 466 GraphvizVertexProperty,
Chris@16 467 GraphvizEdgeProperty,
Chris@16 468 GraphvizGraphProperty> >
Chris@16 469 GraphvizGraph;
Chris@16 470
Chris@16 471 // These four require linking the BGL-Graphviz library: libbgl-viz.a
Chris@16 472 // from the /src directory.
Chris@16 473 // Library has not existed for a while
Chris@16 474 extern void read_graphviz(const std::string& file, GraphvizDigraph& g);
Chris@16 475 extern void read_graphviz(FILE* file, GraphvizDigraph& g);
Chris@16 476
Chris@16 477 extern void read_graphviz(const std::string& file, GraphvizGraph& g);
Chris@16 478 extern void read_graphviz(FILE* file, GraphvizGraph& g);
Chris@16 479 #endif
Chris@16 480
Chris@16 481 class dynamic_properties_writer
Chris@16 482 {
Chris@16 483 public:
Chris@16 484 dynamic_properties_writer(const dynamic_properties& dp) : dp(&dp) { }
Chris@16 485
Chris@16 486 template<typename Descriptor>
Chris@16 487 void operator()(std::ostream& out, Descriptor key) const
Chris@16 488 {
Chris@16 489 bool first = true;
Chris@16 490 for (dynamic_properties::const_iterator i = dp->begin();
Chris@16 491 i != dp->end(); ++i) {
Chris@16 492 if (typeid(key) == i->second->key()) {
Chris@16 493 if (first) out << " [";
Chris@16 494 else out << ", ";
Chris@16 495 first = false;
Chris@16 496
Chris@16 497 out << i->first << "=" << escape_dot_string(i->second->get_string(key));
Chris@16 498 }
Chris@16 499 }
Chris@16 500
Chris@16 501 if (!first) out << "]";
Chris@16 502 }
Chris@16 503
Chris@16 504 private:
Chris@16 505 const dynamic_properties* dp;
Chris@16 506 };
Chris@16 507
Chris@16 508 class dynamic_vertex_properties_writer
Chris@16 509 {
Chris@16 510 public:
Chris@16 511 dynamic_vertex_properties_writer(const dynamic_properties& dp,
Chris@16 512 const std::string& node_id)
Chris@16 513 : dp(&dp), node_id(&node_id) { }
Chris@16 514
Chris@16 515 template<typename Descriptor>
Chris@16 516 void operator()(std::ostream& out, Descriptor key) const
Chris@16 517 {
Chris@16 518 bool first = true;
Chris@16 519 for (dynamic_properties::const_iterator i = dp->begin();
Chris@16 520 i != dp->end(); ++i) {
Chris@16 521 if (typeid(key) == i->second->key()
Chris@16 522 && i->first != *node_id) {
Chris@16 523 if (first) out << " [";
Chris@16 524 else out << ", ";
Chris@16 525 first = false;
Chris@16 526
Chris@16 527 out << i->first << "=" << escape_dot_string(i->second->get_string(key));
Chris@16 528 }
Chris@16 529 }
Chris@16 530
Chris@16 531 if (!first) out << "]";
Chris@16 532 }
Chris@16 533
Chris@16 534 private:
Chris@16 535 const dynamic_properties* dp;
Chris@16 536 const std::string* node_id;
Chris@16 537 };
Chris@16 538
Chris@101 539 template <typename Graph>
Chris@101 540 class dynamic_graph_properties_writer
Chris@101 541 {
Chris@101 542 public:
Chris@101 543 dynamic_graph_properties_writer(const dynamic_properties& dp, const Graph& g) : g(&g), dp(&dp) { }
Chris@101 544
Chris@101 545 void operator()(std::ostream& out) const
Chris@101 546 {
Chris@101 547 for (dynamic_properties::const_iterator i = dp->begin();
Chris@101 548 i != dp->end(); ++i) {
Chris@101 549 if (typeid(Graph*) == i->second->key()) {
Chris@101 550 // const_cast here is to match interface used in read_graphviz
Chris@101 551 out << i->first << "=" << escape_dot_string(i->second->get_string(const_cast<Graph*>(g))) << ";\n";
Chris@101 552 }
Chris@101 553 }
Chris@101 554 }
Chris@101 555
Chris@101 556 private:
Chris@101 557 const Graph* g;
Chris@101 558 const dynamic_properties* dp;
Chris@101 559 };
Chris@101 560
Chris@16 561 namespace graph { namespace detail {
Chris@16 562
Chris@16 563 template<typename Vertex>
Chris@16 564 struct node_id_property_map
Chris@16 565 {
Chris@16 566 typedef std::string value_type;
Chris@16 567 typedef value_type reference;
Chris@16 568 typedef Vertex key_type;
Chris@16 569 typedef readable_property_map_tag category;
Chris@16 570
Chris@16 571 node_id_property_map() {}
Chris@16 572
Chris@16 573 node_id_property_map(const dynamic_properties& dp,
Chris@16 574 const std::string& node_id)
Chris@16 575 : dp(&dp), node_id(&node_id) { }
Chris@16 576
Chris@16 577 const dynamic_properties* dp;
Chris@16 578 const std::string* node_id;
Chris@16 579 };
Chris@16 580
Chris@16 581 template<typename Vertex>
Chris@16 582 inline std::string
Chris@16 583 get(node_id_property_map<Vertex> pm,
Chris@16 584 typename node_id_property_map<Vertex>::key_type v)
Chris@16 585 { return get(*pm.node_id, *pm.dp, v); }
Chris@16 586
Chris@16 587 } } // end namespace graph::detail
Chris@16 588
Chris@16 589 template<typename Graph>
Chris@16 590 inline void
Chris@16 591 write_graphviz_dp(std::ostream& out, const Graph& g,
Chris@16 592 const dynamic_properties& dp,
Chris@16 593 const std::string& node_id = "node_id"
Chris@16 594 BOOST_GRAPH_ENABLE_IF_MODELS_PARM(Graph,vertex_list_graph_tag))
Chris@16 595 {
Chris@16 596 typedef typename graph_traits<Graph>::vertex_descriptor Vertex;
Chris@16 597 write_graphviz_dp(out, g, dp, node_id,
Chris@16 598 graph::detail::node_id_property_map<Vertex>(dp, node_id));
Chris@16 599 }
Chris@16 600
Chris@16 601 template<typename Graph, typename VertexID>
Chris@16 602 void
Chris@16 603 write_graphviz_dp(std::ostream& out, const Graph& g,
Chris@16 604 const dynamic_properties& dp, const std::string& node_id,
Chris@16 605 VertexID id
Chris@16 606 BOOST_GRAPH_ENABLE_IF_MODELS_PARM(Graph,vertex_list_graph_tag))
Chris@16 607 {
Chris@16 608 write_graphviz
Chris@16 609 (out, g,
Chris@16 610 /*vertex_writer=*/dynamic_vertex_properties_writer(dp, node_id),
Chris@16 611 /*edge_writer=*/dynamic_properties_writer(dp),
Chris@101 612 /*graph_writer=*/dynamic_graph_properties_writer<Graph>(dp, g),
Chris@16 613 id);
Chris@16 614 }
Chris@16 615
Chris@16 616 /////////////////////////////////////////////////////////////////////////////
Chris@16 617 // Graph reader exceptions
Chris@16 618 /////////////////////////////////////////////////////////////////////////////
Chris@16 619 struct graph_exception : public std::exception {
Chris@16 620 virtual ~graph_exception() throw() {}
Chris@16 621 virtual const char* what() const throw() = 0;
Chris@16 622 };
Chris@16 623
Chris@16 624 struct bad_parallel_edge : public graph_exception {
Chris@16 625 std::string from;
Chris@16 626 std::string to;
Chris@16 627 mutable std::string statement;
Chris@16 628 bad_parallel_edge(const std::string& i, const std::string& j) :
Chris@16 629 from(i), to(j) {}
Chris@16 630
Chris@16 631 virtual ~bad_parallel_edge() throw() {}
Chris@16 632 const char* what() const throw() {
Chris@16 633 if(statement.empty())
Chris@16 634 statement =
Chris@16 635 std::string("Failed to add parallel edge: (")
Chris@16 636 + from + "," + to + ")\n";
Chris@16 637
Chris@16 638 return statement.c_str();
Chris@16 639 }
Chris@16 640 };
Chris@16 641
Chris@16 642 struct directed_graph_error : public graph_exception {
Chris@16 643 virtual ~directed_graph_error() throw() {}
Chris@16 644 virtual const char* what() const throw() {
Chris@16 645 return
Chris@16 646 "read_graphviz: "
Chris@16 647 "Tried to read a directed graph into an undirected graph.";
Chris@16 648 }
Chris@16 649 };
Chris@16 650
Chris@16 651 struct undirected_graph_error : public graph_exception {
Chris@16 652 virtual ~undirected_graph_error() throw() {}
Chris@16 653 virtual const char* what() const throw() {
Chris@16 654 return
Chris@16 655 "read_graphviz: "
Chris@16 656 "Tried to read an undirected graph into a directed graph.";
Chris@16 657 }
Chris@16 658 };
Chris@16 659
Chris@16 660 struct bad_graphviz_syntax: public graph_exception {
Chris@16 661 std::string errmsg;
Chris@16 662 bad_graphviz_syntax(const std::string& errmsg)
Chris@16 663 : errmsg(errmsg) {}
Chris@16 664 const char* what() const throw () {return errmsg.c_str();}
Chris@16 665 ~bad_graphviz_syntax() throw () {};
Chris@16 666 };
Chris@16 667
Chris@16 668 namespace detail { namespace graph {
Chris@16 669
Chris@16 670 typedef std::string id_t;
Chris@16 671 typedef id_t node_t;
Chris@16 672
Chris@16 673 // edges are not uniquely determined by adjacent nodes
Chris@16 674 class edge_t {
Chris@16 675 int idx_;
Chris@16 676 explicit edge_t(int i) : idx_(i) {}
Chris@16 677 public:
Chris@16 678 static edge_t new_edge() {
Chris@16 679 static int idx = 0;
Chris@16 680 return edge_t(idx++);
Chris@16 681 };
Chris@16 682
Chris@16 683 bool operator==(const edge_t& rhs) const {
Chris@16 684 return idx_ == rhs.idx_;
Chris@16 685 }
Chris@16 686 bool operator<(const edge_t& rhs) const {
Chris@16 687 return idx_ < rhs.idx_;
Chris@16 688 }
Chris@16 689 };
Chris@16 690
Chris@16 691 class mutate_graph
Chris@16 692 {
Chris@16 693 public:
Chris@16 694 virtual ~mutate_graph() {}
Chris@16 695 virtual bool is_directed() const = 0;
Chris@16 696 virtual void do_add_vertex(const node_t& node) = 0;
Chris@16 697
Chris@16 698 virtual void
Chris@16 699 do_add_edge(const edge_t& edge, const node_t& source, const node_t& target)
Chris@16 700 = 0;
Chris@16 701
Chris@16 702 virtual void
Chris@16 703 set_node_property(const id_t& key, const node_t& node, const id_t& value) = 0;
Chris@16 704
Chris@16 705 virtual void
Chris@16 706 set_edge_property(const id_t& key, const edge_t& edge, const id_t& value) = 0;
Chris@16 707
Chris@16 708 virtual void // RG: need new second parameter to support BGL subgraphs
Chris@16 709 set_graph_property(const id_t& key, const id_t& value) = 0;
Chris@16 710
Chris@16 711 virtual void
Chris@16 712 finish_building_graph() = 0;
Chris@16 713 };
Chris@16 714
Chris@16 715 template<typename MutableGraph>
Chris@16 716 class mutate_graph_impl : public mutate_graph
Chris@16 717 {
Chris@16 718 typedef typename graph_traits<MutableGraph>::vertex_descriptor bgl_vertex_t;
Chris@16 719 typedef typename graph_traits<MutableGraph>::edge_descriptor bgl_edge_t;
Chris@16 720
Chris@16 721 public:
Chris@16 722 mutate_graph_impl(MutableGraph& graph, dynamic_properties& dp,
Chris@16 723 std::string node_id_prop)
Chris@16 724 : graph_(graph), dp_(dp), node_id_prop_(node_id_prop) { }
Chris@16 725
Chris@16 726 ~mutate_graph_impl() {}
Chris@16 727
Chris@16 728 bool is_directed() const
Chris@16 729 {
Chris@16 730 return
Chris@16 731 boost::is_convertible<
Chris@16 732 typename boost::graph_traits<MutableGraph>::directed_category,
Chris@16 733 boost::directed_tag>::value;
Chris@16 734 }
Chris@16 735
Chris@16 736 virtual void do_add_vertex(const node_t& node)
Chris@16 737 {
Chris@16 738 // Add the node to the graph.
Chris@16 739 bgl_vertex_t v = add_vertex(graph_);
Chris@16 740
Chris@16 741 // Set up a mapping from name to BGL vertex.
Chris@16 742 bgl_nodes.insert(std::make_pair(node, v));
Chris@16 743
Chris@16 744 // node_id_prop_ allows the caller to see the real id names for nodes.
Chris@16 745 put(node_id_prop_, dp_, v, node);
Chris@16 746 }
Chris@16 747
Chris@16 748 void
Chris@16 749 do_add_edge(const edge_t& edge, const node_t& source, const node_t& target)
Chris@16 750 {
Chris@16 751 std::pair<bgl_edge_t, bool> result =
Chris@16 752 add_edge(bgl_nodes[source], bgl_nodes[target], graph_);
Chris@16 753
Chris@16 754 if(!result.second) {
Chris@16 755 // In the case of no parallel edges allowed
Chris@16 756 boost::throw_exception(bad_parallel_edge(source, target));
Chris@16 757 } else {
Chris@16 758 bgl_edges.insert(std::make_pair(edge, result.first));
Chris@16 759 }
Chris@16 760 }
Chris@16 761
Chris@16 762 void
Chris@16 763 set_node_property(const id_t& key, const node_t& node, const id_t& value)
Chris@16 764 {
Chris@16 765 put(key, dp_, bgl_nodes[node], value);
Chris@16 766 }
Chris@16 767
Chris@16 768 void
Chris@16 769 set_edge_property(const id_t& key, const edge_t& edge, const id_t& value)
Chris@16 770 {
Chris@16 771 put(key, dp_, bgl_edges[edge], value);
Chris@16 772 }
Chris@16 773
Chris@16 774 void
Chris@16 775 set_graph_property(const id_t& key, const id_t& value)
Chris@16 776 {
Chris@16 777 /* RG: pointer to graph prevents copying */
Chris@16 778 put(key, dp_, &graph_, value);
Chris@16 779 }
Chris@16 780
Chris@16 781 void finish_building_graph() {}
Chris@16 782
Chris@16 783
Chris@16 784 protected:
Chris@16 785 MutableGraph& graph_;
Chris@16 786 dynamic_properties& dp_;
Chris@16 787 std::string node_id_prop_;
Chris@16 788 std::map<node_t, bgl_vertex_t> bgl_nodes;
Chris@16 789 std::map<edge_t, bgl_edge_t> bgl_edges;
Chris@16 790 };
Chris@16 791
Chris@16 792 template<typename Directed,
Chris@16 793 typename VertexProperty,
Chris@16 794 typename EdgeProperty,
Chris@16 795 typename GraphProperty,
Chris@16 796 typename Vertex,
Chris@16 797 typename EdgeIndex>
Chris@16 798 class mutate_graph_impl<compressed_sparse_row_graph<Directed, VertexProperty, EdgeProperty, GraphProperty, Vertex, EdgeIndex> >
Chris@16 799 : public mutate_graph
Chris@16 800 {
Chris@16 801 typedef compressed_sparse_row_graph<Directed, VertexProperty, EdgeProperty, GraphProperty, Vertex, EdgeIndex> CSRGraph;
Chris@16 802 typedef typename graph_traits<CSRGraph>::vertices_size_type bgl_vertex_t;
Chris@16 803 typedef typename graph_traits<CSRGraph>::edges_size_type bgl_edge_t;
Chris@16 804 typedef typename graph_traits<CSRGraph>::edge_descriptor edge_descriptor;
Chris@16 805
Chris@16 806 public:
Chris@16 807 mutate_graph_impl(CSRGraph& graph, dynamic_properties& dp,
Chris@16 808 std::string node_id_prop)
Chris@16 809 : graph_(graph), dp_(dp), vertex_count(0), node_id_prop_(node_id_prop) { }
Chris@16 810
Chris@16 811 ~mutate_graph_impl() {}
Chris@16 812
Chris@16 813 void finish_building_graph() {
Chris@16 814 typedef compressed_sparse_row_graph<directedS, no_property, bgl_edge_t, GraphProperty, Vertex, EdgeIndex> TempCSRGraph;
Chris@16 815 TempCSRGraph temp(edges_are_unsorted_multi_pass,
Chris@16 816 edges_to_add.begin(), edges_to_add.end(),
Chris@16 817 counting_iterator<bgl_edge_t>(0),
Chris@16 818 vertex_count);
Chris@16 819 set_property(temp, graph_all, get_property(graph_, graph_all));
Chris@16 820 graph_.assign(temp); // Copies structure, not properties
Chris@16 821 std::vector<edge_descriptor> edge_permutation_from_sorting(num_edges(temp));
Chris@16 822 BGL_FORALL_EDGES_T(e, temp, TempCSRGraph) {
Chris@16 823 edge_permutation_from_sorting[temp[e]] = e;
Chris@16 824 }
Chris@16 825 typedef boost::tuple<id_t, bgl_vertex_t, id_t> v_prop;
Chris@16 826 BOOST_FOREACH(const v_prop& t, vertex_props) {
Chris@16 827 put(boost::get<0>(t), dp_, boost::get<1>(t), boost::get<2>(t));
Chris@16 828 }
Chris@16 829 typedef boost::tuple<id_t, bgl_edge_t, id_t> e_prop;
Chris@16 830 BOOST_FOREACH(const e_prop& t, edge_props) {
Chris@16 831 put(boost::get<0>(t), dp_, edge_permutation_from_sorting[boost::get<1>(t)], boost::get<2>(t));
Chris@16 832 }
Chris@16 833 }
Chris@16 834
Chris@16 835 bool is_directed() const
Chris@16 836 {
Chris@16 837 return
Chris@16 838 boost::is_convertible<
Chris@16 839 typename boost::graph_traits<CSRGraph>::directed_category,
Chris@16 840 boost::directed_tag>::value;
Chris@16 841 }
Chris@16 842
Chris@16 843 virtual void do_add_vertex(const node_t& node)
Chris@16 844 {
Chris@16 845 // Add the node to the graph.
Chris@16 846 bgl_vertex_t v = vertex_count++;
Chris@16 847
Chris@16 848 // Set up a mapping from name to BGL vertex.
Chris@16 849 bgl_nodes.insert(std::make_pair(node, v));
Chris@16 850
Chris@16 851 // node_id_prop_ allows the caller to see the real id names for nodes.
Chris@16 852 vertex_props.push_back(boost::make_tuple(node_id_prop_, v, node));
Chris@16 853 }
Chris@16 854
Chris@16 855 void
Chris@16 856 do_add_edge(const edge_t& edge, const node_t& source, const node_t& target)
Chris@16 857 {
Chris@16 858 bgl_edge_t result = edges_to_add.size();
Chris@16 859 edges_to_add.push_back(std::make_pair(bgl_nodes[source], bgl_nodes[target]));
Chris@16 860 bgl_edges.insert(std::make_pair(edge, result));
Chris@16 861 }
Chris@16 862
Chris@16 863 void
Chris@16 864 set_node_property(const id_t& key, const node_t& node, const id_t& value)
Chris@16 865 {
Chris@16 866 vertex_props.push_back(boost::make_tuple(key, bgl_nodes[node], value));
Chris@16 867 }
Chris@16 868
Chris@16 869 void
Chris@16 870 set_edge_property(const id_t& key, const edge_t& edge, const id_t& value)
Chris@16 871 {
Chris@16 872 edge_props.push_back(boost::make_tuple(key, bgl_edges[edge], value));
Chris@16 873 }
Chris@16 874
Chris@16 875 void
Chris@16 876 set_graph_property(const id_t& key, const id_t& value)
Chris@16 877 {
Chris@16 878 /* RG: pointer to graph prevents copying */
Chris@16 879 put(key, dp_, &graph_, value);
Chris@16 880 }
Chris@16 881
Chris@16 882
Chris@16 883 protected:
Chris@16 884 CSRGraph& graph_;
Chris@16 885 dynamic_properties& dp_;
Chris@16 886 bgl_vertex_t vertex_count;
Chris@16 887 std::string node_id_prop_;
Chris@16 888 std::vector<boost::tuple<id_t, bgl_vertex_t, id_t> > vertex_props;
Chris@16 889 std::vector<boost::tuple<id_t, bgl_edge_t, id_t> > edge_props;
Chris@16 890 std::vector<std::pair<bgl_vertex_t, bgl_vertex_t> > edges_to_add;
Chris@16 891 std::map<node_t, bgl_vertex_t> bgl_nodes;
Chris@16 892 std::map<edge_t, bgl_edge_t> bgl_edges;
Chris@16 893 };
Chris@16 894
Chris@16 895 } } } // end namespace boost::detail::graph
Chris@16 896
Chris@16 897 #ifdef BOOST_GRAPH_USE_SPIRIT_PARSER
Chris@16 898 # ifndef BOOST_GRAPH_READ_GRAPHVIZ_ITERATORS
Chris@16 899 # define BOOST_GRAPH_READ_GRAPHVIZ_ITERATORS
Chris@16 900 # endif
Chris@16 901 # include <boost/graph/detail/read_graphviz_spirit.hpp>
Chris@16 902 #else // New default parser
Chris@16 903 # include <boost/graph/detail/read_graphviz_new.hpp>
Chris@16 904 #endif // BOOST_GRAPH_USE_SPIRIT_PARSER
Chris@16 905
Chris@16 906 namespace boost {
Chris@16 907
Chris@16 908 // Parse the passed string as a GraphViz dot file.
Chris@16 909 template <typename MutableGraph>
Chris@16 910 bool read_graphviz(const std::string& data,
Chris@16 911 MutableGraph& graph,
Chris@16 912 dynamic_properties& dp,
Chris@16 913 std::string const& node_id = "node_id") {
Chris@16 914 #ifdef BOOST_GRAPH_USE_SPIRIT_PARSER
Chris@16 915 return read_graphviz_spirit(data.begin(), data.end(), graph, dp, node_id);
Chris@16 916 #else // Non-Spirit parser
Chris@16 917 return read_graphviz_new(data,graph,dp,node_id);
Chris@16 918 #endif
Chris@16 919 }
Chris@16 920
Chris@16 921 // Parse the passed iterator range as a GraphViz dot file.
Chris@16 922 template <typename InputIterator, typename MutableGraph>
Chris@16 923 bool read_graphviz(InputIterator user_first,
Chris@16 924 InputIterator user_last,
Chris@16 925 MutableGraph& graph,
Chris@16 926 dynamic_properties& dp,
Chris@16 927 std::string const& node_id = "node_id") {
Chris@16 928 #ifdef BOOST_GRAPH_USE_SPIRIT_PARSER
Chris@16 929 typedef InputIterator is_t;
Chris@16 930 typedef boost::spirit::classic::multi_pass<is_t> iterator_t;
Chris@16 931
Chris@16 932 iterator_t first(boost::spirit::classic::make_multi_pass(user_first));
Chris@16 933 iterator_t last(boost::spirit::classic::make_multi_pass(user_last));
Chris@16 934
Chris@16 935 return read_graphviz_spirit(first, last, graph, dp, node_id);
Chris@16 936 #else // Non-Spirit parser
Chris@16 937 return read_graphviz_new(std::string(user_first, user_last), graph, dp, node_id);
Chris@16 938 #endif
Chris@16 939 }
Chris@16 940
Chris@16 941 // Parse the passed stream as a GraphViz dot file.
Chris@16 942 template <typename MutableGraph>
Chris@16 943 bool read_graphviz(std::istream& in, MutableGraph& graph,
Chris@16 944 dynamic_properties& dp,
Chris@16 945 std::string const& node_id = "node_id")
Chris@16 946 {
Chris@16 947 typedef std::istream_iterator<char> is_t;
Chris@16 948 in >> std::noskipws;
Chris@16 949 return read_graphviz(is_t(in), is_t(), graph, dp, node_id);
Chris@16 950 }
Chris@16 951
Chris@16 952 } // namespace boost
Chris@16 953
Chris@16 954 #ifdef BOOST_GRAPH_USE_MPI
Chris@16 955 # include <boost/graph/distributed/graphviz.hpp>
Chris@16 956 #endif
Chris@16 957
Chris@16 958 #endif // BOOST_GRAPHVIZ_HPP