graphviz.hpp 31 KB

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