graphviz.hpp 31 KB

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