graphviz.hpp 32 KB

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