graphviz.hpp 33 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032
  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 <cstdio> // for FILE
  14. #include <fstream>
  15. #include <iostream>
  16. #include <map>
  17. #include <string>
  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. ~graph_exception() throw() BOOST_OVERRIDE {}
  571. const char* what() const throw() BOOST_OVERRIDE = 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. ~bad_parallel_edge() throw() BOOST_OVERRIDE {}
  583. const char* what() const throw() BOOST_OVERRIDE
  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. ~directed_graph_error() throw() BOOST_OVERRIDE {}
  594. const char* what() const throw() BOOST_OVERRIDE
  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. ~undirected_graph_error() throw() BOOST_OVERRIDE {}
  603. const char* what() const throw() BOOST_OVERRIDE
  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() BOOST_OVERRIDE { return errmsg.c_str(); }
  614. ~bad_graphviz_syntax() throw() BOOST_OVERRIDE {}
  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() BOOST_OVERRIDE {}
  674. bool is_directed() const BOOST_OVERRIDE
  675. {
  676. return boost::is_convertible<
  677. typename boost::graph_traits<
  678. MutableGraph >::directed_category,
  679. boost::directed_tag >::value;
  680. }
  681. void do_add_vertex(const node_t& node) BOOST_OVERRIDE
  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(const edge_t& edge, const node_t& source,
  692. const node_t& target) BOOST_OVERRIDE
  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(const id_t& key, const node_t& node,
  707. const id_t& value) BOOST_OVERRIDE
  708. {
  709. put(key, dp_, bgl_nodes[node], value);
  710. }
  711. void set_edge_property(const id_t& key, const edge_t& edge,
  712. const id_t& value) BOOST_OVERRIDE
  713. {
  714. put(key, dp_, bgl_edges[edge], value);
  715. }
  716. void set_graph_property(const id_t& key,
  717. const id_t& value) BOOST_OVERRIDE
  718. {
  719. /* RG: pointer to graph prevents copying */
  720. put(key, dp_, &graph_, value);
  721. }
  722. void finish_building_graph() BOOST_OVERRIDE {}
  723. protected:
  724. MutableGraph& graph_;
  725. dynamic_properties& dp_;
  726. std::string node_id_prop_;
  727. std::map< node_t, bgl_vertex_t > bgl_nodes;
  728. std::map< edge_t, bgl_edge_t > bgl_edges;
  729. };
  730. template < typename Directed, typename VertexProperty,
  731. typename EdgeProperty, typename GraphProperty, typename Vertex,
  732. typename EdgeIndex >
  733. class mutate_graph_impl< compressed_sparse_row_graph< Directed,
  734. VertexProperty, EdgeProperty, GraphProperty, Vertex, EdgeIndex > >
  735. : public mutate_graph
  736. {
  737. typedef compressed_sparse_row_graph< Directed, VertexProperty,
  738. EdgeProperty, GraphProperty, Vertex, EdgeIndex >
  739. CSRGraph;
  740. typedef typename graph_traits< CSRGraph >::vertices_size_type
  741. bgl_vertex_t;
  742. typedef
  743. typename graph_traits< CSRGraph >::edges_size_type bgl_edge_t;
  744. typedef typename graph_traits< CSRGraph >::edge_descriptor
  745. edge_descriptor;
  746. public:
  747. mutate_graph_impl(CSRGraph& graph, dynamic_properties& dp,
  748. std::string node_id_prop)
  749. : graph_(graph)
  750. , dp_(dp)
  751. , vertex_count(0)
  752. , node_id_prop_(node_id_prop)
  753. {
  754. }
  755. ~mutate_graph_impl() BOOST_OVERRIDE {}
  756. void finish_building_graph() BOOST_OVERRIDE
  757. {
  758. typedef compressed_sparse_row_graph< directedS, no_property,
  759. bgl_edge_t, GraphProperty, Vertex, EdgeIndex >
  760. TempCSRGraph;
  761. TempCSRGraph temp(edges_are_unsorted_multi_pass,
  762. edges_to_add.begin(), edges_to_add.end(),
  763. counting_iterator< bgl_edge_t >(0), vertex_count);
  764. set_property(temp, graph_all, get_property(graph_, graph_all));
  765. graph_.assign(temp); // Copies structure, not properties
  766. std::vector< edge_descriptor > edge_permutation_from_sorting(
  767. num_edges(temp));
  768. BGL_FORALL_EDGES_T(e, temp, TempCSRGraph)
  769. {
  770. edge_permutation_from_sorting[temp[e]] = e;
  771. }
  772. typedef boost::tuple< id_t, bgl_vertex_t, id_t > v_prop;
  773. BOOST_FOREACH (const v_prop& t, vertex_props)
  774. {
  775. put(boost::get< 0 >(t), dp_, boost::get< 1 >(t),
  776. boost::get< 2 >(t));
  777. }
  778. typedef boost::tuple< id_t, bgl_edge_t, id_t > e_prop;
  779. BOOST_FOREACH (const e_prop& t, edge_props)
  780. {
  781. put(boost::get< 0 >(t), dp_,
  782. edge_permutation_from_sorting[boost::get< 1 >(t)],
  783. boost::get< 2 >(t));
  784. }
  785. }
  786. bool is_directed() const BOOST_OVERRIDE
  787. {
  788. return boost::is_convertible<
  789. typename boost::graph_traits< CSRGraph >::directed_category,
  790. boost::directed_tag >::value;
  791. }
  792. void do_add_vertex(const node_t& node) BOOST_OVERRIDE
  793. {
  794. // Add the node to the graph.
  795. bgl_vertex_t v = vertex_count++;
  796. // Set up a mapping from name to BGL vertex.
  797. bgl_nodes.insert(std::make_pair(node, v));
  798. // node_id_prop_ allows the caller to see the real id names for
  799. // nodes.
  800. vertex_props.push_back(
  801. boost::make_tuple(node_id_prop_, v, node));
  802. }
  803. void do_add_edge(const edge_t& edge, const node_t& source,
  804. const node_t& target) BOOST_OVERRIDE
  805. {
  806. bgl_edge_t result = edges_to_add.size();
  807. edges_to_add.push_back(
  808. std::make_pair(bgl_nodes[source], bgl_nodes[target]));
  809. bgl_edges.insert(std::make_pair(edge, result));
  810. }
  811. void set_node_property(const id_t& key, const node_t& node,
  812. const id_t& value) BOOST_OVERRIDE
  813. {
  814. vertex_props.push_back(
  815. boost::make_tuple(key, bgl_nodes[node], value));
  816. }
  817. void set_edge_property(const id_t& key, const edge_t& edge,
  818. const id_t& value) BOOST_OVERRIDE
  819. {
  820. edge_props.push_back(
  821. boost::make_tuple(key, bgl_edges[edge], value));
  822. }
  823. void set_graph_property(const id_t& key,
  824. const id_t& value) BOOST_OVERRIDE
  825. {
  826. /* RG: pointer to graph prevents copying */
  827. put(key, dp_, &graph_, value);
  828. }
  829. protected:
  830. CSRGraph& graph_;
  831. dynamic_properties& dp_;
  832. bgl_vertex_t vertex_count;
  833. std::string node_id_prop_;
  834. std::vector< boost::tuple< id_t, bgl_vertex_t, id_t > >
  835. vertex_props;
  836. std::vector< boost::tuple< id_t, bgl_edge_t, id_t > > edge_props;
  837. std::vector< std::pair< bgl_vertex_t, bgl_vertex_t > > edges_to_add;
  838. std::map< node_t, bgl_vertex_t > bgl_nodes;
  839. std::map< edge_t, bgl_edge_t > bgl_edges;
  840. };
  841. }
  842. }
  843. } // end namespace boost::detail::graph
  844. #ifdef BOOST_GRAPH_USE_SPIRIT_PARSER
  845. #ifndef BOOST_GRAPH_READ_GRAPHVIZ_ITERATORS
  846. #define BOOST_GRAPH_READ_GRAPHVIZ_ITERATORS
  847. #endif
  848. #include <boost/graph/detail/read_graphviz_spirit.hpp>
  849. #else // New default parser
  850. #include <boost/graph/detail/read_graphviz_new.hpp>
  851. #endif // BOOST_GRAPH_USE_SPIRIT_PARSER
  852. namespace boost
  853. {
  854. // Parse the passed string as a GraphViz dot file.
  855. template < typename MutableGraph >
  856. bool read_graphviz(const std::string& data, MutableGraph& graph,
  857. dynamic_properties& dp, std::string const& node_id = "node_id")
  858. {
  859. #ifdef BOOST_GRAPH_USE_SPIRIT_PARSER
  860. return read_graphviz_spirit(data.begin(), data.end(), graph, dp, node_id);
  861. #else // Non-Spirit parser
  862. return read_graphviz_new(data, graph, dp, node_id);
  863. #endif
  864. }
  865. // Parse the passed iterator range as a GraphViz dot file.
  866. template < typename InputIterator, typename MutableGraph >
  867. bool read_graphviz(InputIterator user_first, InputIterator user_last,
  868. MutableGraph& graph, dynamic_properties& dp,
  869. std::string const& node_id = "node_id")
  870. {
  871. #ifdef BOOST_GRAPH_USE_SPIRIT_PARSER
  872. typedef InputIterator is_t;
  873. typedef boost::spirit::classic::multi_pass< is_t > iterator_t;
  874. iterator_t first(boost::spirit::classic::make_multi_pass(user_first));
  875. iterator_t last(boost::spirit::classic::make_multi_pass(user_last));
  876. return read_graphviz_spirit(first, last, graph, dp, node_id);
  877. #else // Non-Spirit parser
  878. return read_graphviz_new(
  879. std::string(user_first, user_last), graph, dp, node_id);
  880. #endif
  881. }
  882. // Parse the passed stream as a GraphViz dot file.
  883. template < typename MutableGraph >
  884. bool read_graphviz(std::istream& in, MutableGraph& graph,
  885. dynamic_properties& dp, std::string const& node_id = "node_id")
  886. {
  887. typedef std::istream_iterator< char > is_t;
  888. in >> std::noskipws;
  889. return read_graphviz(is_t(in), is_t(), graph, dp, node_id);
  890. }
  891. } // namespace boost
  892. #include BOOST_GRAPH_MPI_INCLUDE(<boost/graph/distributed/graphviz.hpp>)
  893. #endif // BOOST_GRAPHVIZ_HPP