File indexing completed on 2025-01-30 09:42:59
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010 #ifndef BOOST_GRAPHVIZ_HPP
0011 #define BOOST_GRAPHVIZ_HPP
0012
0013 #include <boost/config.hpp>
0014 #include <cstdio> // for FILE
0015 #include <fstream>
0016 #include <iostream>
0017 #include <map>
0018 #include <string>
0019 #include <boost/property_map/property_map.hpp>
0020 #include <boost/tuple/tuple.hpp>
0021 #include <boost/graph/graph_traits.hpp>
0022 #include <boost/graph/properties.hpp>
0023 #include <boost/graph/subgraph.hpp>
0024 #include <boost/graph/adjacency_list.hpp>
0025 #include <boost/property_map/dynamic_property_map.hpp>
0026 #include <boost/graph/overloading.hpp>
0027 #include <boost/graph/dll_import_export.hpp>
0028 #include <boost/graph/compressed_sparse_row_graph.hpp>
0029 #include <boost/graph/iteration_macros.hpp>
0030 #include <boost/graph/detail/mpi_include.hpp>
0031 #include <boost/spirit/include/classic_multi_pass.hpp>
0032 #include <boost/lexical_cast.hpp>
0033 #include <boost/static_assert.hpp>
0034 #include <boost/algorithm/string/replace.hpp>
0035 #include <boost/xpressive/xpressive_static.hpp>
0036 #include <boost/foreach.hpp>
0037
0038 namespace boost
0039 {
0040
0041 template < typename directed_category > struct graphviz_io_traits
0042 {
0043 static std::string name() { return "digraph"; }
0044 static std::string delimiter() { return "->"; }
0045 };
0046
0047 template <> struct graphviz_io_traits< undirected_tag >
0048 {
0049 static std::string name() { return "graph"; }
0050 static std::string delimiter() { return "--"; }
0051 };
0052
0053 struct default_writer
0054 {
0055 void operator()(std::ostream&) const {}
0056 template < class VorE > void operator()(std::ostream&, const VorE&) const {}
0057 };
0058
0059 template < typename T > inline std::string escape_dot_string(const T& obj)
0060 {
0061 using namespace boost::xpressive;
0062 static sregex valid_unquoted_id = (((alpha | '_') >> *_w)
0063 | (!as_xpr('-') >> (('.' >> *_d) | (+_d >> !('.' >> *_d)))));
0064 std::string s(boost::lexical_cast< std::string >(obj));
0065 if (regex_match(s, valid_unquoted_id))
0066 {
0067 return s;
0068 }
0069 else
0070 {
0071 boost::algorithm::replace_all(s, "\"", "\\\"");
0072 return "\"" + s + "\"";
0073 }
0074 }
0075
0076 template < class Name > class label_writer
0077 {
0078 public:
0079 label_writer(Name _name) : name(_name) {}
0080 template < class VertexOrEdge >
0081 void operator()(std::ostream& out, const VertexOrEdge& v) const
0082 {
0083 out << "[label=" << escape_dot_string(get(name, v)) << "]";
0084 }
0085
0086 private:
0087 Name name;
0088 };
0089 template < class Name > inline label_writer< Name > make_label_writer(Name n)
0090 {
0091 return label_writer< Name >(n);
0092 }
0093
0094 enum edge_attribute_t
0095 {
0096 edge_attribute = 1111
0097 };
0098 enum vertex_attribute_t
0099 {
0100 vertex_attribute = 2222
0101 };
0102 enum graph_graph_attribute_t
0103 {
0104 graph_graph_attribute = 3333
0105 };
0106 enum graph_vertex_attribute_t
0107 {
0108 graph_vertex_attribute = 4444
0109 };
0110 enum graph_edge_attribute_t
0111 {
0112 graph_edge_attribute = 5555
0113 };
0114
0115 BOOST_INSTALL_PROPERTY(edge, attribute);
0116 BOOST_INSTALL_PROPERTY(vertex, attribute);
0117 BOOST_INSTALL_PROPERTY(graph, graph_attribute);
0118 BOOST_INSTALL_PROPERTY(graph, vertex_attribute);
0119 BOOST_INSTALL_PROPERTY(graph, edge_attribute);
0120
0121 template < class Attribute >
0122 inline void write_attributes(const Attribute& attr, std::ostream& out)
0123 {
0124 typename Attribute::const_iterator i, iend;
0125 i = attr.begin();
0126 iend = attr.end();
0127
0128 while (i != iend)
0129 {
0130 out << i->first << "=" << escape_dot_string(i->second);
0131 ++i;
0132 if (i != iend)
0133 out << ", ";
0134 }
0135 }
0136
0137 template < typename Attributes >
0138 inline void write_all_attributes(
0139 Attributes attributes, const std::string& name, std::ostream& out)
0140 {
0141 typename Attributes::const_iterator i = attributes.begin(),
0142 end = attributes.end();
0143 if (i != end)
0144 {
0145 out << name << " [\n";
0146 write_attributes(attributes, out);
0147 out << "];\n";
0148 }
0149 }
0150
0151 inline void write_all_attributes(
0152 detail::error_property_not_found, const std::string&, std::ostream&)
0153 {
0154
0155 }
0156
0157 template < typename GraphGraphAttributes, typename GraphNodeAttributes,
0158 typename GraphEdgeAttributes >
0159 struct graph_attributes_writer
0160 {
0161 graph_attributes_writer(
0162 GraphGraphAttributes gg, GraphNodeAttributes gn, GraphEdgeAttributes ge)
0163 : g_attributes(gg), n_attributes(gn), e_attributes(ge)
0164 {
0165 }
0166
0167 void operator()(std::ostream& out) const
0168 {
0169 write_all_attributes(g_attributes, "graph", out);
0170 write_all_attributes(n_attributes, "node", out);
0171 write_all_attributes(e_attributes, "edge", out);
0172 }
0173 GraphGraphAttributes g_attributes;
0174 GraphNodeAttributes n_attributes;
0175 GraphEdgeAttributes e_attributes;
0176 };
0177
0178 template < typename GAttrMap, typename NAttrMap, typename EAttrMap >
0179 graph_attributes_writer< GAttrMap, NAttrMap, EAttrMap >
0180 make_graph_attributes_writer(
0181 const GAttrMap& g_attr, const NAttrMap& n_attr, const EAttrMap& e_attr)
0182 {
0183 return graph_attributes_writer< GAttrMap, NAttrMap, EAttrMap >(
0184 g_attr, n_attr, e_attr);
0185 }
0186
0187 template < typename Graph >
0188 graph_attributes_writer<
0189 typename graph_property< Graph, graph_graph_attribute_t >::type,
0190 typename graph_property< Graph, graph_vertex_attribute_t >::type,
0191 typename graph_property< Graph, graph_edge_attribute_t >::type >
0192 make_graph_attributes_writer(const Graph& g)
0193 {
0194 typedef typename graph_property< Graph, graph_graph_attribute_t >::type
0195 GAttrMap;
0196 typedef typename graph_property< Graph, graph_vertex_attribute_t >::type
0197 NAttrMap;
0198 typedef
0199 typename graph_property< Graph, graph_edge_attribute_t >::type EAttrMap;
0200 GAttrMap gam = get_property(g, graph_graph_attribute);
0201 NAttrMap nam = get_property(g, graph_vertex_attribute);
0202 EAttrMap eam = get_property(g, graph_edge_attribute);
0203 graph_attributes_writer< GAttrMap, NAttrMap, EAttrMap > writer(
0204 gam, nam, eam);
0205 return writer;
0206 }
0207
0208 template < typename AttributeMap > struct attributes_writer
0209 {
0210 attributes_writer(AttributeMap attr) : attributes(attr) {}
0211
0212 template < class VorE >
0213 void operator()(std::ostream& out, const VorE& e) const
0214 {
0215 this->write_attribute(out, attributes[e]);
0216 }
0217
0218 private:
0219 template < typename AttributeSequence >
0220 void write_attribute(std::ostream& out, const AttributeSequence& seq) const
0221 {
0222 if (!seq.empty())
0223 {
0224 out << "[";
0225 write_attributes(seq, out);
0226 out << "]";
0227 }
0228 }
0229
0230 void write_attribute(std::ostream&, detail::error_property_not_found) const
0231 {
0232 }
0233 AttributeMap attributes;
0234 };
0235
0236 template < typename Graph >
0237 attributes_writer<
0238 typename property_map< Graph, edge_attribute_t >::const_type >
0239 make_edge_attributes_writer(const Graph& g)
0240 {
0241 typedef typename property_map< Graph, edge_attribute_t >::const_type
0242 EdgeAttributeMap;
0243 return attributes_writer< EdgeAttributeMap >(get(edge_attribute, g));
0244 }
0245
0246 template < typename Graph >
0247 attributes_writer<
0248 typename property_map< Graph, vertex_attribute_t >::const_type >
0249 make_vertex_attributes_writer(const Graph& g)
0250 {
0251 typedef typename property_map< Graph, vertex_attribute_t >::const_type
0252 VertexAttributeMap;
0253 return attributes_writer< VertexAttributeMap >(get(vertex_attribute, g));
0254 }
0255
0256 template < typename Graph, typename VertexPropertiesWriter,
0257 typename EdgePropertiesWriter, typename GraphPropertiesWriter,
0258 typename VertexID >
0259 inline void write_graphviz(std::ostream& out, const Graph& g,
0260 VertexPropertiesWriter vpw, EdgePropertiesWriter epw,
0261 GraphPropertiesWriter gpw,
0262 VertexID vertex_id BOOST_GRAPH_ENABLE_IF_MODELS_PARM(
0263 Graph, vertex_list_graph_tag))
0264 {
0265 BOOST_CONCEPT_ASSERT((EdgeListGraphConcept< Graph >));
0266
0267 typedef typename graph_traits< Graph >::directed_category cat_type;
0268 typedef graphviz_io_traits< cat_type > Traits;
0269 std::string name = "G";
0270 out << Traits::name() << " " << escape_dot_string(name) << " {"
0271 << std::endl;
0272
0273 gpw(out);
0274
0275 typename graph_traits< Graph >::vertex_iterator i, end;
0276
0277 for (boost::tie(i, end) = vertices(g); i != end; ++i)
0278 {
0279 out << escape_dot_string(get(vertex_id, *i));
0280 vpw(out, *i);
0281 out << ";" << std::endl;
0282 }
0283 typename graph_traits< Graph >::edge_iterator ei, edge_end;
0284 for (boost::tie(ei, edge_end) = edges(g); ei != edge_end; ++ei)
0285 {
0286 out << escape_dot_string(get(vertex_id, source(*ei, g)))
0287 << Traits::delimiter()
0288 << escape_dot_string(get(vertex_id, target(*ei, g))) << " ";
0289 epw(out, *ei);
0290 out << ";" << std::endl;
0291 }
0292 out << "}" << std::endl;
0293 }
0294
0295 template < typename Graph, typename VertexPropertiesWriter,
0296 typename EdgePropertiesWriter, typename GraphPropertiesWriter >
0297 inline void write_graphviz(std::ostream& out, const Graph& g,
0298 VertexPropertiesWriter vpw, EdgePropertiesWriter epw,
0299 GraphPropertiesWriter gpw BOOST_GRAPH_ENABLE_IF_MODELS_PARM(
0300 Graph, vertex_list_graph_tag))
0301 {
0302 write_graphviz(out, g, vpw, epw, gpw, get(vertex_index, g));
0303 }
0304
0305 template < typename Graph >
0306 inline void write_graphviz(std::ostream& out,
0307 const Graph& g BOOST_GRAPH_ENABLE_IF_MODELS_PARM(
0308 Graph, vertex_list_graph_tag))
0309 {
0310 default_writer dw;
0311 default_writer gw;
0312 write_graphviz(out, g, dw, dw, gw);
0313 }
0314
0315 template < typename Graph, typename VertexWriter >
0316 inline void write_graphviz(std::ostream& out, const Graph& g,
0317 VertexWriter vw BOOST_GRAPH_ENABLE_IF_MODELS_PARM(
0318 Graph, vertex_list_graph_tag))
0319 {
0320 default_writer dw;
0321 default_writer gw;
0322 write_graphviz(out, g, vw, dw, gw);
0323 }
0324
0325 template < typename Graph, typename VertexWriter, typename EdgeWriter >
0326 inline void write_graphviz(std::ostream& out, const Graph& g, VertexWriter vw,
0327 EdgeWriter ew BOOST_GRAPH_ENABLE_IF_MODELS_PARM(
0328 Graph, vertex_list_graph_tag))
0329 {
0330 default_writer gw;
0331 write_graphviz(out, g, vw, ew, gw);
0332 }
0333
0334 namespace detail
0335 {
0336
0337 template < class Graph_, class RandomAccessIterator, class VertexID >
0338 void write_graphviz_subgraph(std::ostream& out, const subgraph< Graph_ >& g,
0339 RandomAccessIterator vertex_marker, RandomAccessIterator edge_marker,
0340 VertexID vertex_id)
0341 {
0342 typedef subgraph< Graph_ > Graph;
0343 typedef typename graph_traits< Graph >::vertex_descriptor Vertex;
0344 typedef typename graph_traits< Graph >::directed_category cat_type;
0345 typedef graphviz_io_traits< cat_type > Traits;
0346
0347 typedef typename graph_property< Graph, graph_name_t >::type NameType;
0348 const NameType& g_name = get_property(g, graph_name);
0349
0350 if (g.is_root())
0351 out << Traits::name();
0352 else
0353 out << "subgraph";
0354
0355 out << " " << escape_dot_string(g_name) << " {" << std::endl;
0356
0357 typename Graph::const_children_iterator i_child, j_child;
0358
0359
0360 make_graph_attributes_writer(g)(out);
0361
0362
0363 for (boost::tie(i_child, j_child) = g.children(); i_child != j_child;
0364 ++i_child)
0365 write_graphviz_subgraph(
0366 out, *i_child, vertex_marker, edge_marker, vertex_id);
0367
0368
0369
0370 typename graph_traits< Graph >::vertex_iterator i, end;
0371 typename graph_traits< Graph >::edge_iterator ei, edge_end;
0372
0373 for (boost::tie(i, end) = vertices(g); i != end; ++i)
0374 {
0375 Vertex v = g.local_to_global(*i);
0376 int pos = get(vertex_id, v);
0377 if (vertex_marker[pos])
0378 {
0379 vertex_marker[pos] = false;
0380 out << escape_dot_string(pos);
0381 make_vertex_attributes_writer(g.root())(out, v);
0382 out << ";" << std::endl;
0383 }
0384 }
0385
0386 for (boost::tie(ei, edge_end) = edges(g); ei != edge_end; ++ei)
0387 {
0388 Vertex u = g.local_to_global(source(*ei, g)),
0389 v = g.local_to_global(target(*ei, g));
0390 int pos = get(get(edge_index, g.root()), g.local_to_global(*ei));
0391 if (edge_marker[pos])
0392 {
0393 edge_marker[pos] = false;
0394 out << escape_dot_string(get(vertex_id, u)) << " "
0395 << Traits::delimiter() << " "
0396 << escape_dot_string(get(vertex_id, v));
0397 make_edge_attributes_writer(g)(
0398 out, *ei);
0399 out << ";" << std::endl;
0400 }
0401 }
0402 out << "}" << std::endl;
0403 }
0404 }
0405
0406
0407 template < typename Graph >
0408 void write_graphviz(std::ostream& out, const subgraph< Graph >& g)
0409 {
0410 std::vector< bool > edge_marker(num_edges(g), true);
0411 std::vector< bool > vertex_marker(num_vertices(g), true);
0412
0413 detail::write_graphviz_subgraph(out, g, vertex_marker.begin(),
0414 edge_marker.begin(), get(vertex_index, g));
0415 }
0416
0417 template < typename Graph >
0418 void write_graphviz(const std::string& filename, const subgraph< Graph >& g)
0419 {
0420 std::ofstream out(filename.c_str());
0421 std::vector< bool > edge_marker(num_edges(g), true);
0422 std::vector< bool > vertex_marker(num_vertices(g), true);
0423
0424 detail::write_graphviz_subgraph(out, g, vertex_marker.begin(),
0425 edge_marker.begin(), get(vertex_index, g));
0426 }
0427
0428 template < typename Graph, typename VertexID >
0429 void write_graphviz(
0430 std::ostream& out, const subgraph< Graph >& g, VertexID vertex_id)
0431 {
0432 std::vector< bool > edge_marker(num_edges(g), true);
0433 std::vector< bool > vertex_marker(num_vertices(g), true);
0434
0435 detail::write_graphviz_subgraph(
0436 out, g, vertex_marker.begin(), edge_marker.begin(), vertex_id);
0437 }
0438
0439 template < typename Graph, typename VertexID >
0440 void write_graphviz(
0441 const std::string& filename, const subgraph< Graph >& g, VertexID vertex_id)
0442 {
0443 std::ofstream out(filename.c_str());
0444 std::vector< bool > edge_marker(num_edges(g), true);
0445 std::vector< bool > vertex_marker(num_vertices(g), true);
0446
0447 detail::write_graphviz_subgraph(
0448 out, g, vertex_marker.begin(), edge_marker.begin(), vertex_id);
0449 }
0450
0451 #if 0
0452
0453 typedef std::map<std::string, std::string> GraphvizAttrList;
0454
0455 typedef property<vertex_attribute_t, GraphvizAttrList>
0456 GraphvizVertexProperty;
0457
0458 typedef property<edge_attribute_t, GraphvizAttrList,
0459 property<edge_index_t, int> >
0460 GraphvizEdgeProperty;
0461
0462 typedef property<graph_graph_attribute_t, GraphvizAttrList,
0463 property<graph_vertex_attribute_t, GraphvizAttrList,
0464 property<graph_edge_attribute_t, GraphvizAttrList,
0465 property<graph_name_t, std::string> > > >
0466 GraphvizGraphProperty;
0467
0468 typedef subgraph<adjacency_list<vecS,
0469 vecS, directedS,
0470 GraphvizVertexProperty,
0471 GraphvizEdgeProperty,
0472 GraphvizGraphProperty> >
0473 GraphvizDigraph;
0474
0475 typedef subgraph<adjacency_list<vecS,
0476 vecS, undirectedS,
0477 GraphvizVertexProperty,
0478 GraphvizEdgeProperty,
0479 GraphvizGraphProperty> >
0480 GraphvizGraph;
0481
0482
0483
0484
0485 extern void read_graphviz(const std::string& file, GraphvizDigraph& g);
0486 extern void read_graphviz(FILE* file, GraphvizDigraph& g);
0487
0488 extern void read_graphviz(const std::string& file, GraphvizGraph& g);
0489 extern void read_graphviz(FILE* file, GraphvizGraph& g);
0490 #endif
0491
0492 class dynamic_properties_writer
0493 {
0494 public:
0495 dynamic_properties_writer(const dynamic_properties& dp) : dp(&dp) {}
0496
0497 template < typename Descriptor >
0498 void operator()(std::ostream& out, Descriptor key) const
0499 {
0500 bool first = true;
0501 for (dynamic_properties::const_iterator i = dp->begin(); i != dp->end();
0502 ++i)
0503 {
0504 if (typeid(key) == i->second->key())
0505 {
0506 if (first)
0507 out << " [";
0508 else
0509 out << ", ";
0510 first = false;
0511
0512 out << i->first << "="
0513 << escape_dot_string(i->second->get_string(key));
0514 }
0515 }
0516
0517 if (!first)
0518 out << "]";
0519 }
0520
0521 private:
0522 const dynamic_properties* dp;
0523 };
0524
0525 class dynamic_vertex_properties_writer
0526 {
0527 public:
0528 dynamic_vertex_properties_writer(
0529 const dynamic_properties& dp, const std::string& node_id)
0530 : dp(&dp), node_id(&node_id)
0531 {
0532 }
0533
0534 template < typename Descriptor >
0535 void operator()(std::ostream& out, Descriptor key) const
0536 {
0537 bool first = true;
0538 for (dynamic_properties::const_iterator i = dp->begin(); i != dp->end();
0539 ++i)
0540 {
0541 if (typeid(key) == i->second->key() && i->first != *node_id)
0542 {
0543 if (first)
0544 out << " [";
0545 else
0546 out << ", ";
0547 first = false;
0548
0549 out << i->first << "="
0550 << escape_dot_string(i->second->get_string(key));
0551 }
0552 }
0553
0554 if (!first)
0555 out << "]";
0556 }
0557
0558 private:
0559 const dynamic_properties* dp;
0560 const std::string* node_id;
0561 };
0562
0563 template < typename Graph > class dynamic_graph_properties_writer
0564 {
0565 public:
0566 dynamic_graph_properties_writer(
0567 const dynamic_properties& dp, const Graph& g)
0568 : g(&g), dp(&dp)
0569 {
0570 }
0571
0572 void operator()(std::ostream& out) const
0573 {
0574 for (dynamic_properties::const_iterator i = dp->begin(); i != dp->end();
0575 ++i)
0576 {
0577 if (typeid(Graph*) == i->second->key())
0578 {
0579
0580 out << i->first << "="
0581 << escape_dot_string(
0582 i->second->get_string(const_cast< Graph* >(g)))
0583 << ";\n";
0584 }
0585 }
0586 }
0587
0588 private:
0589 const Graph* g;
0590 const dynamic_properties* dp;
0591 };
0592
0593 namespace graph
0594 {
0595 namespace detail
0596 {
0597
0598 template < typename Vertex > struct node_id_property_map
0599 {
0600 typedef std::string value_type;
0601 typedef value_type reference;
0602 typedef Vertex key_type;
0603 typedef readable_property_map_tag category;
0604
0605 node_id_property_map() {}
0606
0607 node_id_property_map(
0608 const dynamic_properties& dp, const std::string& node_id)
0609 : dp(&dp), node_id(&node_id)
0610 {
0611 }
0612
0613 const dynamic_properties* dp;
0614 const std::string* node_id;
0615 };
0616
0617 template < typename Vertex >
0618 inline std::string get(node_id_property_map< Vertex > pm,
0619 typename node_id_property_map< Vertex >::key_type v)
0620 {
0621 return get(*pm.node_id, *pm.dp, v);
0622 }
0623
0624 }
0625 }
0626
0627 template < typename Graph >
0628 inline void write_graphviz_dp(std::ostream& out, const Graph& g,
0629 const dynamic_properties& dp,
0630 const std::string& node_id
0631 = "node_id" BOOST_GRAPH_ENABLE_IF_MODELS_PARM(Graph, vertex_list_graph_tag))
0632 {
0633 typedef typename graph_traits< Graph >::vertex_descriptor Vertex;
0634 write_graphviz_dp(out, g, dp, node_id,
0635 graph::detail::node_id_property_map< Vertex >(dp, node_id));
0636 }
0637
0638 template < typename Graph, typename VertexID >
0639 void write_graphviz_dp(std::ostream& out, const Graph& g,
0640 const dynamic_properties& dp, const std::string& node_id,
0641 VertexID id BOOST_GRAPH_ENABLE_IF_MODELS_PARM(Graph, vertex_list_graph_tag))
0642 {
0643 write_graphviz(out, g,
0644 dynamic_vertex_properties_writer(dp, node_id),
0645 dynamic_properties_writer(dp),
0646 dynamic_graph_properties_writer< Graph >(dp, g), id);
0647 }
0648
0649
0650
0651
0652 struct BOOST_SYMBOL_VISIBLE graph_exception : public std::exception
0653 {
0654 ~graph_exception() throw() BOOST_OVERRIDE {}
0655 const char* what() const throw() BOOST_OVERRIDE = 0;
0656 };
0657
0658 struct BOOST_SYMBOL_VISIBLE bad_parallel_edge : public graph_exception
0659 {
0660 std::string from;
0661 std::string to;
0662 mutable std::string statement;
0663 bad_parallel_edge(const std::string& i, const std::string& j)
0664 : from(i), to(j)
0665 {
0666 }
0667
0668 ~bad_parallel_edge() throw() BOOST_OVERRIDE {}
0669 const char* what() const throw() BOOST_OVERRIDE
0670 {
0671 if (statement.empty())
0672 statement = std::string("Failed to add parallel edge: (") + from
0673 + "," + to + ")\n";
0674
0675 return statement.c_str();
0676 }
0677 };
0678
0679 struct BOOST_SYMBOL_VISIBLE directed_graph_error : public graph_exception
0680 {
0681 ~directed_graph_error() throw() BOOST_OVERRIDE {}
0682 const char* what() const throw() BOOST_OVERRIDE
0683 {
0684 return "read_graphviz: "
0685 "Tried to read a directed graph into an undirected graph.";
0686 }
0687 };
0688
0689 struct BOOST_SYMBOL_VISIBLE undirected_graph_error : public graph_exception
0690 {
0691 ~undirected_graph_error() throw() BOOST_OVERRIDE {}
0692 const char* what() const throw() BOOST_OVERRIDE
0693 {
0694 return "read_graphviz: "
0695 "Tried to read an undirected graph into a directed graph.";
0696 }
0697 };
0698
0699 struct BOOST_SYMBOL_VISIBLE bad_graphviz_syntax : public graph_exception
0700 {
0701 std::string errmsg;
0702 bad_graphviz_syntax(const std::string& errmsg) : errmsg(errmsg) {}
0703 const char* what() const throw() BOOST_OVERRIDE { return errmsg.c_str(); }
0704 ~bad_graphviz_syntax() throw() BOOST_OVERRIDE {}
0705 };
0706
0707 namespace detail
0708 {
0709 namespace graph
0710 {
0711
0712 typedef std::string id_t;
0713 typedef id_t node_t;
0714
0715
0716 class edge_t
0717 {
0718 int idx_;
0719 explicit edge_t(int i) : idx_(i) {}
0720
0721 public:
0722 static edge_t new_edge()
0723 {
0724 static int idx = 0;
0725 return edge_t(idx++);
0726 }
0727
0728 bool operator==(const edge_t& rhs) const
0729 {
0730 return idx_ == rhs.idx_;
0731 }
0732 bool operator<(const edge_t& rhs) const { return idx_ < rhs.idx_; }
0733 };
0734
0735 class mutate_graph
0736 {
0737 public:
0738 virtual ~mutate_graph() {}
0739 virtual bool is_directed() const = 0;
0740 virtual void do_add_vertex(const node_t& node) = 0;
0741
0742 virtual void do_add_edge(
0743 const edge_t& edge, const node_t& source, const node_t& target)
0744 = 0;
0745
0746 virtual void set_node_property(
0747 const id_t& key, const node_t& node, const id_t& value)
0748 = 0;
0749
0750 virtual void set_edge_property(
0751 const id_t& key, const edge_t& edge, const id_t& value)
0752 = 0;
0753
0754 virtual void
0755
0756 set_graph_property(const id_t& key, const id_t& value)
0757 = 0;
0758
0759 virtual void finish_building_graph() = 0;
0760 };
0761
0762 template < typename MutableGraph >
0763 class mutate_graph_impl : public mutate_graph
0764 {
0765 typedef typename graph_traits< MutableGraph >::vertex_descriptor
0766 bgl_vertex_t;
0767 typedef typename graph_traits< MutableGraph >::edge_descriptor
0768 bgl_edge_t;
0769
0770 public:
0771 mutate_graph_impl(MutableGraph& graph, dynamic_properties& dp,
0772 std::string node_id_prop)
0773 : graph_(graph), dp_(dp), node_id_prop_(node_id_prop)
0774 {
0775 }
0776
0777 ~mutate_graph_impl() BOOST_OVERRIDE {}
0778
0779 bool is_directed() const BOOST_OVERRIDE
0780 {
0781 return boost::is_convertible<
0782 typename boost::graph_traits<
0783 MutableGraph >::directed_category,
0784 boost::directed_tag >::value;
0785 }
0786
0787 void do_add_vertex(const node_t& node) BOOST_OVERRIDE
0788 {
0789
0790 bgl_vertex_t v = add_vertex(graph_);
0791
0792
0793 bgl_nodes.insert(std::make_pair(node, v));
0794
0795
0796
0797 put(node_id_prop_, dp_, v, node);
0798 }
0799
0800 void do_add_edge(const edge_t& edge, const node_t& source,
0801 const node_t& target) BOOST_OVERRIDE
0802 {
0803 std::pair< bgl_edge_t, bool > result
0804 = add_edge(bgl_nodes[source], bgl_nodes[target], graph_);
0805
0806 if (!result.second)
0807 {
0808
0809 boost::throw_exception(bad_parallel_edge(source, target));
0810 }
0811 else
0812 {
0813 bgl_edges.insert(std::make_pair(edge, result.first));
0814 }
0815 }
0816
0817 void set_node_property(const id_t& key, const node_t& node,
0818 const id_t& value) BOOST_OVERRIDE
0819 {
0820 put(key, dp_, bgl_nodes[node], value);
0821 }
0822
0823 void set_edge_property(const id_t& key, const edge_t& edge,
0824 const id_t& value) BOOST_OVERRIDE
0825 {
0826 put(key, dp_, bgl_edges[edge], value);
0827 }
0828
0829 void set_graph_property(const id_t& key,
0830 const id_t& value) BOOST_OVERRIDE
0831 {
0832
0833 put(key, dp_, &graph_, value);
0834 }
0835
0836 void finish_building_graph() BOOST_OVERRIDE {}
0837
0838 protected:
0839 MutableGraph& graph_;
0840 dynamic_properties& dp_;
0841 std::string node_id_prop_;
0842 std::map< node_t, bgl_vertex_t > bgl_nodes;
0843 std::map< edge_t, bgl_edge_t > bgl_edges;
0844 };
0845
0846 template < typename Directed, typename VertexProperty,
0847 typename EdgeProperty, typename GraphProperty, typename Vertex,
0848 typename EdgeIndex >
0849 class mutate_graph_impl< compressed_sparse_row_graph< Directed,
0850 VertexProperty, EdgeProperty, GraphProperty, Vertex, EdgeIndex > >
0851 : public mutate_graph
0852 {
0853 typedef compressed_sparse_row_graph< Directed, VertexProperty,
0854 EdgeProperty, GraphProperty, Vertex, EdgeIndex >
0855 CSRGraph;
0856 typedef typename graph_traits< CSRGraph >::vertices_size_type
0857 bgl_vertex_t;
0858 typedef
0859 typename graph_traits< CSRGraph >::edges_size_type bgl_edge_t;
0860 typedef typename graph_traits< CSRGraph >::edge_descriptor
0861 edge_descriptor;
0862
0863 public:
0864 mutate_graph_impl(CSRGraph& graph, dynamic_properties& dp,
0865 std::string node_id_prop)
0866 : graph_(graph)
0867 , dp_(dp)
0868 , vertex_count(0)
0869 , node_id_prop_(node_id_prop)
0870 {
0871 }
0872
0873 ~mutate_graph_impl() BOOST_OVERRIDE {}
0874
0875 void finish_building_graph() BOOST_OVERRIDE
0876 {
0877 typedef compressed_sparse_row_graph< directedS, no_property,
0878 bgl_edge_t, GraphProperty, Vertex, EdgeIndex >
0879 TempCSRGraph;
0880 TempCSRGraph temp(edges_are_unsorted_multi_pass,
0881 edges_to_add.begin(), edges_to_add.end(),
0882 counting_iterator< bgl_edge_t >(0), vertex_count);
0883 set_property(temp, graph_all, get_property(graph_, graph_all));
0884 graph_.assign(temp);
0885 std::vector< edge_descriptor > edge_permutation_from_sorting(
0886 num_edges(temp));
0887 BGL_FORALL_EDGES_T(e, temp, TempCSRGraph)
0888 {
0889 edge_permutation_from_sorting[temp[e]] = e;
0890 }
0891 typedef boost::tuple< id_t, bgl_vertex_t, id_t > v_prop;
0892 BOOST_FOREACH (const v_prop& t, vertex_props)
0893 {
0894 put(boost::get< 0 >(t), dp_, boost::get< 1 >(t),
0895 boost::get< 2 >(t));
0896 }
0897 typedef boost::tuple< id_t, bgl_edge_t, id_t > e_prop;
0898 BOOST_FOREACH (const e_prop& t, edge_props)
0899 {
0900 put(boost::get< 0 >(t), dp_,
0901 edge_permutation_from_sorting[boost::get< 1 >(t)],
0902 boost::get< 2 >(t));
0903 }
0904 }
0905
0906 bool is_directed() const BOOST_OVERRIDE
0907 {
0908 return boost::is_convertible<
0909 typename boost::graph_traits< CSRGraph >::directed_category,
0910 boost::directed_tag >::value;
0911 }
0912
0913 void do_add_vertex(const node_t& node) BOOST_OVERRIDE
0914 {
0915
0916 bgl_vertex_t v = vertex_count++;
0917
0918
0919 bgl_nodes.insert(std::make_pair(node, v));
0920
0921
0922
0923 vertex_props.push_back(
0924 boost::make_tuple(node_id_prop_, v, node));
0925 }
0926
0927 void do_add_edge(const edge_t& edge, const node_t& source,
0928 const node_t& target) BOOST_OVERRIDE
0929 {
0930 bgl_edge_t result = edges_to_add.size();
0931 edges_to_add.push_back(
0932 std::make_pair(bgl_nodes[source], bgl_nodes[target]));
0933 bgl_edges.insert(std::make_pair(edge, result));
0934 }
0935
0936 void set_node_property(const id_t& key, const node_t& node,
0937 const id_t& value) BOOST_OVERRIDE
0938 {
0939 vertex_props.push_back(
0940 boost::make_tuple(key, bgl_nodes[node], value));
0941 }
0942
0943 void set_edge_property(const id_t& key, const edge_t& edge,
0944 const id_t& value) BOOST_OVERRIDE
0945 {
0946 edge_props.push_back(
0947 boost::make_tuple(key, bgl_edges[edge], value));
0948 }
0949
0950 void set_graph_property(const id_t& key,
0951 const id_t& value) BOOST_OVERRIDE
0952 {
0953
0954 put(key, dp_, &graph_, value);
0955 }
0956
0957 protected:
0958 CSRGraph& graph_;
0959 dynamic_properties& dp_;
0960 bgl_vertex_t vertex_count;
0961 std::string node_id_prop_;
0962 std::vector< boost::tuple< id_t, bgl_vertex_t, id_t > >
0963 vertex_props;
0964 std::vector< boost::tuple< id_t, bgl_edge_t, id_t > > edge_props;
0965 std::vector< std::pair< bgl_vertex_t, bgl_vertex_t > > edges_to_add;
0966 std::map< node_t, bgl_vertex_t > bgl_nodes;
0967 std::map< edge_t, bgl_edge_t > bgl_edges;
0968 };
0969
0970 }
0971 }
0972 }
0973
0974 #ifdef BOOST_GRAPH_USE_SPIRIT_PARSER
0975 #ifndef BOOST_GRAPH_READ_GRAPHVIZ_ITERATORS
0976 #define BOOST_GRAPH_READ_GRAPHVIZ_ITERATORS
0977 #endif
0978 #include <boost/graph/detail/read_graphviz_spirit.hpp>
0979 #else
0980 #include <boost/graph/detail/read_graphviz_new.hpp>
0981 #endif
0982
0983 namespace boost
0984 {
0985
0986
0987 template < typename MutableGraph >
0988 bool read_graphviz(const std::string& data, MutableGraph& graph,
0989 dynamic_properties& dp, std::string const& node_id = "node_id")
0990 {
0991 #ifdef BOOST_GRAPH_USE_SPIRIT_PARSER
0992 return read_graphviz_spirit(data.begin(), data.end(), graph, dp, node_id);
0993 #else
0994 return read_graphviz_new(data, graph, dp, node_id);
0995 #endif
0996 }
0997
0998
0999 template < typename InputIterator, typename MutableGraph >
1000 bool read_graphviz(InputIterator user_first, InputIterator user_last,
1001 MutableGraph& graph, dynamic_properties& dp,
1002 std::string const& node_id = "node_id")
1003 {
1004 #ifdef BOOST_GRAPH_USE_SPIRIT_PARSER
1005 typedef InputIterator is_t;
1006 typedef boost::spirit::classic::multi_pass< is_t > iterator_t;
1007
1008 iterator_t first(boost::spirit::classic::make_multi_pass(user_first));
1009 iterator_t last(boost::spirit::classic::make_multi_pass(user_last));
1010
1011 return read_graphviz_spirit(first, last, graph, dp, node_id);
1012 #else
1013 return read_graphviz_new(
1014 std::string(user_first, user_last), graph, dp, node_id);
1015 #endif
1016 }
1017
1018
1019 template < typename MutableGraph >
1020 bool read_graphviz(std::istream& in, MutableGraph& graph,
1021 dynamic_properties& dp, std::string const& node_id = "node_id")
1022 {
1023 typedef std::istream_iterator< char > is_t;
1024 in >> std::noskipws;
1025 return read_graphviz(is_t(in), is_t(), graph, dp, node_id);
1026 }
1027
1028 }
1029
1030 #include BOOST_GRAPH_MPI_INCLUDE( <boost/graph/distributed/graphviz.hpp >)
1031
1032 #endif