graphviz.hpp 33 KB

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