From 154ef8658d8c4a159b3018af807105445bfb6b24 Mon Sep 17 00:00:00 2001 From: Tiago de Paula Peixoto Date: Tue, 22 Dec 2009 18:22:38 -0200 Subject: [PATCH] Relax boost version requirements This allows compilation with older versions of boost (>=1.38), which in some sistems are the only option. This commit also removes the linking of the boost_graph shared library, since none of its symbols are actually required. --- configure.ac | 6 +- .../boost/graph/betweenness_centrality.hpp | 10 +- src/boost-workaround/boost/graph/copy.hpp | 7 +- .../boost/graph/detail/read_graphviz_new.hpp | 120 +++ src/boost-workaround/boost/graph/graphviz.hpp | 827 ++++++++++++++++++ src/graph/Makefile.am | 2 + src/graph/fast_vector_property_map.hh | 7 +- src/graph/generation/graph_rewiring.hh | 4 +- src/graph/graph_properties.hh | 10 +- src/graph/read_graphviz_new.cpp | 7 +- 10 files changed, 989 insertions(+), 11 deletions(-) create mode 100644 src/boost-workaround/boost/graph/detail/read_graphviz_new.hpp create mode 100644 src/boost-workaround/boost/graph/graphviz.hpp diff --git a/configure.ac b/configure.ac index c555b8a4..b05ad6e8 100644 --- a/configure.ac +++ b/configure.ac @@ -156,7 +156,7 @@ AC_PYTHON_DEVEL([2.5]) [LDFLAGS="${LDFLAGS} ${PYTHON_LDFLAGS}"] dnl boost -AX_BOOST_BASE([1.40.0]) +AX_BOOST_BASE([1.38.0]) AX_BOOST_PYTHON if test "$BOOST_PYTHON_LIB" = ""; then AC_MSG_ERROR([No usable boost::python found]) @@ -169,10 +169,12 @@ AX_BOOST_REGEX if test "$BOOST_REGEX_LIB" = ""; then AC_MSG_ERROR([No usable boost::regex found]) fi + AX_BOOST_GRAPH if test "$BOOST_GRAPH_LIB" = ""; then AC_MSG_ERROR([No usable boost::graph found]) fi + [CPPFLAGS="${CPPFLAGS} ${BOOST_CPPFLAGS}"] dnl CGAL @@ -292,7 +294,7 @@ AC_SUBST(MOD_DIR) # default LIBADD flags for submodules [MOD_LIBADD="${PYTHON_LDFLAGS} ${BOOST_IOSTREAMS_LIB} -l${BOOST_PYTHON_LIB} \ -${BOOST_REGEX_LIB} -l${BOOST_GRAPH_LIB} ${OPENMP_LDFLAGS} -lexpat"] +${BOOST_REGEX_LIB} ${OPENMP_LDFLAGS} -lexpat"] AC_SUBST(MOD_LIBADD) # needed for typeinfo objects to work across DSO boundaries. diff --git a/src/boost-workaround/boost/graph/betweenness_centrality.hpp b/src/boost-workaround/boost/graph/betweenness_centrality.hpp index d0aa29da..73a17ddd 100644 --- a/src/boost-workaround/boost/graph/betweenness_centrality.hpp +++ b/src/boost-workaround/boost/graph/betweenness_centrality.hpp @@ -22,10 +22,16 @@ #include #include #include -#include +#include +#if (BOOST_VERSION >= 104000) +# include +# include +#else +# include +# include +#endif #include #include -#include namespace boost { diff --git a/src/boost-workaround/boost/graph/copy.hpp b/src/boost-workaround/boost/graph/copy.hpp index 6ec4d6b5..1ff6b921 100644 --- a/src/boost-workaround/boost/graph/copy.hpp +++ b/src/boost-workaround/boost/graph/copy.hpp @@ -44,7 +44,12 @@ #include #include #include -#include +#include +#if (BOOST_VERSION >= 104000) +# include +#else +# include +#endif #include #include #include diff --git a/src/boost-workaround/boost/graph/detail/read_graphviz_new.hpp b/src/boost-workaround/boost/graph/detail/read_graphviz_new.hpp new file mode 100644 index 00000000..d34c0b45 --- /dev/null +++ b/src/boost-workaround/boost/graph/detail/read_graphviz_new.hpp @@ -0,0 +1,120 @@ +// Copyright 2004-9 Trustees of Indiana University + +// Distributed under the Boost Software License, Version 1.0. +// (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +// +// read_graphviz_new.hpp - +// Initialize a model of the BGL's MutableGraph concept and an associated +// collection of property maps using a graph expressed in the GraphViz +// DOT Language. +// +// Based on the grammar found at: +// http://www.graphviz.org/cvs/doc/info/lang.html +// +// Jeremiah rewrite used grammar found at: +// http://www.graphviz.org/doc/info/lang.html +// and page 34 or http://www.graphviz.org/pdf/dotguide.pdf +// +// See documentation for this code at: +// http://www.boost.org/libs/graph/doc/read-graphviz.html +// + +// Author: Jeremiah Willcock +// Ronald Garcia +// + +#ifndef BOOST_READ_GRAPHVIZ_NEW_HPP +#define BOOST_READ_GRAPHVIZ_NEW_HPP + +#include +#if (BOOST_VERSION >= 104000) +# include +#else +# include +#endif +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +namespace boost { + +namespace read_graphviz_detail { + typedef std::string node_name; + typedef std::string subgraph_name; + + typedef std::map properties; + + struct node_and_port { + node_name name; + std::string angle; // Or empty if no angle + std::vector location; // Up to two identifiers + + friend inline bool operator==(const node_and_port& a, const node_and_port& b) { + return a.name == b.name && + a.angle == b.angle && + a.location == b.location; + } + + friend inline bool operator<(const node_and_port& a, const node_and_port& b) { + if (a.name != b.name) return a.name < b.name; + if (a.angle != b.angle) return a.angle < b.angle; + return a.location < b.location; + } + }; + + struct edge_info { + node_and_port source; + node_and_port target; + properties props; + }; + + struct parser_result { + bool graph_is_directed; + bool graph_is_strict; + std::map nodes; // Global set + std::vector edges; + std::map graph_props; // Root and subgraphs + }; + + // The actual parser, from libs/graph/src/read_graphviz_new.cpp + void parse_graphviz_from_string(const std::string& str, parser_result& result, bool want_directed); + + // Translate from those results to a graph + void translate_results_to_graph(const parser_result& r, ::boost::detail::graph::mutate_graph* mg); + +} // namespace read_graphviz_detail + +// This is also in boost/graph/graphviz.hpp +namespace detail { + namespace graph { + BOOST_GRAPH_DECL bool read_graphviz(const std::string& str, boost::detail::graph::mutate_graph* mg); + } // end namespace graph +} // end namespace detail + +template +bool read_graphviz(const std::string& str, + MutableGraph& graph, boost::dynamic_properties& dp, + std::string const& node_id = "node_id") { + boost::detail::graph::mutate_graph_impl mg(graph, dp, node_id); + return detail::graph::read_graphviz(str, &mg); +} + +template +bool read_graphviz(InputIter begin, InputIter end, + MutableGraph& graph, boost::dynamic_properties& dp, + std::string const& node_id = "node_id") { + return read_graphviz(std::string(begin, end), graph, dp, node_id); +} + +} // namespace boost + +#endif // BOOST_READ_GRAPHVIZ_NEW_HPP diff --git a/src/boost-workaround/boost/graph/graphviz.hpp b/src/boost-workaround/boost/graph/graphviz.hpp new file mode 100644 index 00000000..26edc28f --- /dev/null +++ b/src/boost-workaround/boost/graph/graphviz.hpp @@ -0,0 +1,827 @@ +//======================================================================= +// Copyright 2001 University of Notre Dame. +// Copyright 2003 Jeremy Siek +// Authors: Lie-Quan Lee, Jeremy Siek, and Douglas Gregor +// +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) +//======================================================================= +#ifndef BOOST_GRAPHVIZ_HPP +#define BOOST_GRAPHVIZ_HPP + +#include +#include +#include +#include +#include +#include // for FILE +#include +#if (BOOST_VERSION >= 104000) +# include +# include +#else +# include +# include +#endif +#include +#include +#include +#include +#include +#include + +#ifdef BOOST_HAS_DECLSPEC +# if defined(BOOST_ALL_DYN_LINK) || defined(BOOST_GRAPH_DYN_LINK) +# ifdef BOOST_GRAPH_SOURCE +# define BOOST_GRAPH_DECL __declspec(dllexport) +# else +# define BOOST_GRAPH_DECL __declspec(dllimport) +# endif // BOOST_GRAPH_SOURCE +# endif // DYN_LINK +#endif // BOOST_HAS_DECLSPEC + +#ifndef BOOST_GRAPH_DECL +# define BOOST_GRAPH_DECL +#endif + +namespace boost { + + template + struct graphviz_io_traits { + static std::string name() { + return "digraph"; + } + static std::string delimiter() { + return "->"; + } }; + + template <> + struct graphviz_io_traits { + static std::string name() { + return "graph"; + } + static std::string delimiter() { + return "--"; + } + }; + + struct default_writer { + void operator()(std::ostream&) const { + } + template + void operator()(std::ostream&, const VorE&) const { + } + }; + + template + class label_writer { + public: + label_writer(Name _name) : name(_name) {} + template + void operator()(std::ostream& out, const VertexOrEdge& v) const { + out << "[label=\"" << get(name, v) << "\"]"; + } + private: + Name name; + }; + template + inline label_writer + make_label_writer(Name n) { + return label_writer(n); + } + + enum edge_attribute_t { edge_attribute = 1111 }; + enum vertex_attribute_t { vertex_attribute = 2222 }; + enum graph_graph_attribute_t { graph_graph_attribute = 3333 }; + enum graph_vertex_attribute_t { graph_vertex_attribute = 4444 }; + enum graph_edge_attribute_t { graph_edge_attribute = 5555 }; + + BOOST_INSTALL_PROPERTY(edge, attribute); + BOOST_INSTALL_PROPERTY(vertex, attribute); + BOOST_INSTALL_PROPERTY(graph, graph_attribute); + BOOST_INSTALL_PROPERTY(graph, vertex_attribute); + BOOST_INSTALL_PROPERTY(graph, edge_attribute); + + + template + inline void write_attributes(const Attribute& attr, std::ostream& out) { + typename Attribute::const_iterator i, iend; + i = attr.begin(); + iend = attr.end(); + + while ( i != iend ) { + out << i->first << "=\"" << i->second << "\""; + ++i; + if ( i != iend ) + out << ", "; + } + } + + template + inline void write_all_attributes(Attributes attributes, + const std::string& name, + std::ostream& out) + { + typename Attributes::const_iterator i = attributes.begin(), + end = attributes.end(); + if (i != end) { + out << name << " [\n"; + write_attributes(attributes, out); + out << "];\n"; + } + } + + inline void write_all_attributes(detail::error_property_not_found, + const std::string&, + std::ostream&) + { + // Do nothing - no attributes exist + } + + + + + template + struct graph_attributes_writer + { + graph_attributes_writer(GraphGraphAttributes gg, + GraphNodeAttributes gn, + GraphEdgeAttributes ge) + : g_attributes(gg), n_attributes(gn), e_attributes(ge) { } + + void operator()(std::ostream& out) const { + write_all_attributes(g_attributes, "graph", out); + write_all_attributes(n_attributes, "node", out); + write_all_attributes(e_attributes, "edge", out); + } + GraphGraphAttributes g_attributes; + GraphNodeAttributes n_attributes; + GraphEdgeAttributes e_attributes; + }; + + template + graph_attributes_writer + make_graph_attributes_writer(const GAttrMap& g_attr, const NAttrMap& n_attr, + const EAttrMap& e_attr) { + return graph_attributes_writer + (g_attr, n_attr, e_attr); + } + + + template + graph_attributes_writer + ::type, + typename graph_property::type, + typename graph_property::type> + make_graph_attributes_writer(const Graph& g) + { + typedef typename graph_property::type + GAttrMap; + typedef typename graph_property::type + NAttrMap; + typedef typename graph_property::type + EAttrMap; + GAttrMap gam = get_property(g, graph_graph_attribute); + NAttrMap nam = get_property(g, graph_vertex_attribute); + EAttrMap eam = get_property(g, graph_edge_attribute); + graph_attributes_writer writer(gam, nam, eam); + return writer; + } + + template + struct attributes_writer { + attributes_writer(AttributeMap attr) + : attributes(attr) { } + + template + void operator()(std::ostream& out, const VorE& e) const { + this->write_attribute(out, attributes[e]); + } + + private: + template + void write_attribute(std::ostream& out, + const AttributeSequence& seq) const + { + if (!seq.empty()) { + out << "["; + write_attributes(seq, out); + out << "]"; + } + } + + void write_attribute(std::ostream&, + detail::error_property_not_found) const + { + } + AttributeMap attributes; + }; + + template + attributes_writer + ::const_type> + make_edge_attributes_writer(const Graph& g) + { + typedef typename property_map::const_type + EdgeAttributeMap; + return attributes_writer(get(edge_attribute, g)); + } + + template + attributes_writer + ::const_type> + make_vertex_attributes_writer(const Graph& g) + { + typedef typename property_map::const_type + VertexAttributeMap; + return attributes_writer(get(vertex_attribute, g)); + } + + template + inline void + write_graphviz + (std::ostream& out, const Graph& g, + VertexPropertiesWriter vpw, + EdgePropertiesWriter epw, + GraphPropertiesWriter gpw, + VertexID vertex_id + BOOST_GRAPH_ENABLE_IF_MODELS_PARM(Graph,vertex_list_graph_tag)) + { + BOOST_CONCEPT_ASSERT((EdgeListGraphConcept)); + + typedef typename graph_traits::directed_category cat_type; + typedef graphviz_io_traits Traits; + std::string name = "G"; + out << Traits::name() << " " << name << " {" << std::endl; + + gpw(out); //print graph properties + + typename graph_traits::vertex_iterator i, end; + + for(tie(i,end) = vertices(g); i != end; ++i) { + out << get(vertex_id, *i); + vpw(out, *i); //print vertex attributes + out << ";" << std::endl; + } + typename graph_traits::edge_iterator ei, edge_end; + for(tie(ei, edge_end) = edges(g); ei != edge_end; ++ei) { + out << get(vertex_id, source(*ei, g)) << Traits::delimiter() << get(vertex_id, target(*ei, g)) << " "; + epw(out, *ei); //print edge attributes + out << ";" << std::endl; + } + out << "}" << std::endl; + } + + template + inline void + write_graphviz(std::ostream& out, const Graph& g, + VertexPropertiesWriter vpw, + EdgePropertiesWriter epw, + GraphPropertiesWriter gpw + BOOST_GRAPH_ENABLE_IF_MODELS_PARM(Graph,vertex_list_graph_tag)) + { write_graphviz(out, g, vpw, epw, gpw, get(vertex_index, g)); } + +#if !defined(BOOST_MSVC) || BOOST_MSVC > 1300 + // ambiguous overload problem with VC++ + template + inline void + write_graphviz(std::ostream& out, const Graph& g + BOOST_GRAPH_ENABLE_IF_MODELS_PARM(Graph,vertex_list_graph_tag)) + { + default_writer dw; + default_writer gw; + write_graphviz(out, g, dw, dw, gw); + } +#endif + + template + inline void + write_graphviz(std::ostream& out, const Graph& g, VertexWriter vw + BOOST_GRAPH_ENABLE_IF_MODELS_PARM(Graph,vertex_list_graph_tag)) + { + default_writer dw; + default_writer gw; + write_graphviz(out, g, vw, dw, gw); + } + + template + inline void + write_graphviz(std::ostream& out, const Graph& g, + VertexWriter vw, EdgeWriter ew + BOOST_GRAPH_ENABLE_IF_MODELS_PARM(Graph,vertex_list_graph_tag)) + { + default_writer gw; + write_graphviz(out, g, vw, ew, gw); + } + + namespace detail { + + template + void write_graphviz_subgraph (std::ostream& out, + const subgraph& g, + RandomAccessIterator vertex_marker, + RandomAccessIterator edge_marker, + VertexID vertex_id) + { + typedef subgraph Graph; + typedef typename graph_traits::vertex_descriptor Vertex; + typedef typename graph_traits::directed_category cat_type; + typedef graphviz_io_traits Traits; + + typedef typename graph_property::type NameType; + const NameType& g_name = get_property(g, graph_name); + + if ( g.is_root() ) + out << Traits::name() ; + else + out << "subgraph"; + + out << " " << g_name << " {" << std::endl; + + typename Graph::const_children_iterator i_child, j_child; + + //print graph/node/edge attributes +#if defined(BOOST_MSVC) && BOOST_MSVC <= 1300 + typedef typename graph_property::type + GAttrMap; + typedef typename graph_property::type + NAttrMap; + typedef typename graph_property::type + EAttrMap; + GAttrMap gam = get_property(g, graph_graph_attribute); + NAttrMap nam = get_property(g, graph_vertex_attribute); + EAttrMap eam = get_property(g, graph_edge_attribute); + graph_attributes_writer writer(gam, nam, eam); + writer(out); +#else + make_graph_attributes_writer(g)(out); +#endif + + //print subgraph + for ( tie(i_child,j_child) = g.children(); + i_child != j_child; ++i_child ) + write_graphviz_subgraph(out, *i_child, vertex_marker, edge_marker, + vertex_id); + + // Print out vertices and edges not in the subgraphs. + + typename graph_traits::vertex_iterator i, end; + typename graph_traits::edge_iterator ei, edge_end; + + for(tie(i,end) = vertices(g); i != end; ++i) { + Vertex v = g.local_to_global(*i); + int pos = get(vertex_id, v); + if ( vertex_marker[pos] ) { + vertex_marker[pos] = false; + out << pos; +#if defined(BOOST_MSVC) && BOOST_MSVC <= 1300 + typedef typename property_map::const_type + VertexAttributeMap; + attributes_writer vawriter(get(vertex_attribute, + g.root())); + vawriter(out, v); +#else + make_vertex_attributes_writer(g.root())(out, v); +#endif + out << ";" << std::endl; + } + } + + for (tie(ei, edge_end) = edges(g); ei != edge_end; ++ei) { + Vertex u = g.local_to_global(source(*ei,g)), + v = g.local_to_global(target(*ei, g)); + int pos = get(get(edge_index, g.root()), g.local_to_global(*ei)); + if ( edge_marker[pos] ) { + edge_marker[pos] = false; + out << get(vertex_id, u) << " " << Traits::delimiter() + << " " << get(vertex_id, v); +#if defined(BOOST_MSVC) && BOOST_MSVC <= 1300 + typedef typename property_map::const_type + EdgeAttributeMap; + attributes_writer eawriter(get(edge_attribute, g)); + eawriter(out, *ei); +#else + make_edge_attributes_writer(g)(out, *ei); //print edge properties +#endif + out << ";" << std::endl; + } + } + out << "}" << std::endl; + } + } // namespace detail + + // requires graph_name graph property + template + void write_graphviz(std::ostream& out, const subgraph& g) { + std::vector edge_marker(num_edges(g), true); + std::vector vertex_marker(num_vertices(g), true); + + detail::write_graphviz_subgraph(out, g, + vertex_marker.begin(), + edge_marker.begin(), + get(vertex_index, g)); + } + + template + void write_graphviz(const std::string& filename, const subgraph& g) { + std::ofstream out(filename.c_str()); + std::vector edge_marker(num_edges(g), true); + std::vector vertex_marker(num_vertices(g), true); + + detail::write_graphviz_subgraph(out, g, + vertex_marker.begin(), + edge_marker.begin(), + get(vertex_index, g)); + } + + template + void write_graphviz(std::ostream& out, const subgraph& g, + VertexID vertex_id) + { + std::vector edge_marker(num_edges(g), true); + std::vector vertex_marker(num_vertices(g), true); + + detail::write_graphviz_subgraph(out, g, + vertex_marker.begin(), + edge_marker.begin(), + vertex_id); + } + + template + void write_graphviz(const std::string& filename, const subgraph& g, + VertexID vertex_id) + { + std::ofstream out(filename.c_str()); + std::vector edge_marker(num_edges(g), true); + std::vector vertex_marker(num_vertices(g), true); + + detail::write_graphviz_subgraph(out, g, + vertex_marker.begin(), + edge_marker.begin(), + vertex_id); + } + + typedef std::map GraphvizAttrList; + + typedef property + GraphvizVertexProperty; + + typedef property > + GraphvizEdgeProperty; + + typedef property > > > + GraphvizGraphProperty; + + typedef subgraph > + GraphvizDigraph; + + typedef subgraph > + GraphvizGraph; + + + // These four require linking the BGL-Graphviz library: libbgl-viz.a + // from the /src directory. + // Library has not existed for a while + // extern void read_graphviz(const std::string& file, GraphvizDigraph& g); + // extern void read_graphviz(FILE* file, GraphvizDigraph& g); + // + // extern void read_graphviz(const std::string& file, GraphvizGraph& g); + // extern void read_graphviz(FILE* file, GraphvizGraph& g); + + class dynamic_properties_writer + { + public: + dynamic_properties_writer(const dynamic_properties& dp) : dp(&dp) { } + + template + void operator()(std::ostream& out, Descriptor key) const + { + bool first = true; + for (dynamic_properties::const_iterator i = dp->begin(); + i != dp->end(); ++i) { + if (typeid(key) == i->second->key()) { + if (first) out << " ["; + else out << ", "; + first = false; + + out << i->first << "=\"" << i->second->get_string(key) << "\""; + } + } + + if (!first) out << "]"; + } + + private: + const dynamic_properties* dp; + }; + + class dynamic_vertex_properties_writer + { + public: + dynamic_vertex_properties_writer(const dynamic_properties& dp, + const std::string& node_id) + : dp(&dp), node_id(&node_id) { } + + template + void operator()(std::ostream& out, Descriptor key) const + { + bool first = true; + for (dynamic_properties::const_iterator i = dp->begin(); + i != dp->end(); ++i) { + if (typeid(key) == i->second->key() + && i->first != *node_id) { + if (first) out << " ["; + else out << ", "; + first = false; + + out << i->first << "=\"" << i->second->get_string(key) << "\""; + } + } + + if (!first) out << "]"; + } + + private: + const dynamic_properties* dp; + const std::string* node_id; + }; + + namespace graph { namespace detail { + + template + struct node_id_property_map + { + typedef std::string value_type; + typedef value_type reference; + typedef Vertex key_type; + typedef readable_property_map_tag category; + + node_id_property_map() {} + + node_id_property_map(const dynamic_properties& dp, + const std::string& node_id) + : dp(&dp), node_id(&node_id) { } + + const dynamic_properties* dp; + const std::string* node_id; + }; + + template + inline std::string + get(node_id_property_map pm, + typename node_id_property_map::key_type v) + { return get(*pm.node_id, *pm.dp, v); } + + } } // end namespace graph::detail + + template + inline void + write_graphviz(std::ostream& out, const Graph& g, + const dynamic_properties& dp, + const std::string& node_id = "node_id" + BOOST_GRAPH_ENABLE_IF_MODELS_PARM(Graph,vertex_list_graph_tag)) + { + typedef typename graph_traits::vertex_descriptor Vertex; + write_graphviz(out, g, dp, node_id, + graph::detail::node_id_property_map(dp, node_id)); + } + + template + void + write_graphviz(std::ostream& out, const Graph& g, + const dynamic_properties& dp, const std::string& node_id, + VertexID id + BOOST_GRAPH_ENABLE_IF_MODELS_PARM(Graph,vertex_list_graph_tag)) + { + write_graphviz + (out, g, + /*vertex_writer=*/dynamic_vertex_properties_writer(dp, node_id), + /*edge_writer=*/dynamic_properties_writer(dp), + /*graph_writer=*/default_writer(), + id); + } + +///////////////////////////////////////////////////////////////////////////// +// Graph reader exceptions +///////////////////////////////////////////////////////////////////////////// +struct graph_exception : public std::exception { + virtual ~graph_exception() throw() {} + virtual const char* what() const throw() = 0; +}; + +struct bad_parallel_edge : public graph_exception { + std::string from; + std::string to; + mutable std::string statement; + bad_parallel_edge(const std::string& i, const std::string& j) : + from(i), to(j) {} + + virtual ~bad_parallel_edge() throw() {} + const char* what() const throw() { + if(statement.empty()) + statement = + std::string("Failed to add parallel edge: (") + + from + "," + to + ")\n"; + + return statement.c_str(); + } +}; + +struct directed_graph_error : public graph_exception { + virtual ~directed_graph_error() throw() {} + virtual const char* what() const throw() { + return + "read_graphviz: " + "Tried to read a directed graph into an undirected graph."; + } +}; + +struct undirected_graph_error : public graph_exception { + virtual ~undirected_graph_error() throw() {} + virtual const char* what() const throw() { + return + "read_graphviz: " + "Tried to read an undirected graph into a directed graph."; + } +}; + +struct bad_graphviz_syntax: public graph_exception { + std::string errmsg; + bad_graphviz_syntax(const std::string& errmsg) + : errmsg(errmsg) {} + const char* what() const throw () {return errmsg.c_str();} + ~bad_graphviz_syntax() throw () {}; +}; + +namespace detail { namespace graph { + +typedef std::string id_t; +typedef id_t node_t; + +// edges are not uniquely determined by adjacent nodes +class edge_t { + int idx_; + explicit edge_t(int i) : idx_(i) {} +public: + static edge_t new_edge() { + static int idx = 0; + return edge_t(idx++); + }; + + bool operator==(const edge_t& rhs) const { + return idx_ == rhs.idx_; + } + bool operator<(const edge_t& rhs) const { + return idx_ < rhs.idx_; + } +}; + +class mutate_graph +{ + public: + virtual ~mutate_graph() {} + virtual bool is_directed() const = 0; + virtual void do_add_vertex(const node_t& node) = 0; + + virtual void + do_add_edge(const edge_t& edge, const node_t& source, const node_t& target) + = 0; + + virtual void + set_node_property(const id_t& key, const node_t& node, const id_t& value) = 0; + + virtual void + set_edge_property(const id_t& key, const edge_t& edge, const id_t& value) = 0; + + virtual void // RG: need new second parameter to support BGL subgraphs + set_graph_property(const id_t& key, const id_t& value) = 0; +}; + +template +class mutate_graph_impl : public mutate_graph +{ + typedef typename graph_traits::vertex_descriptor bgl_vertex_t; + typedef typename graph_traits::edge_descriptor bgl_edge_t; + + public: + mutate_graph_impl(MutableGraph& graph, dynamic_properties& dp, + std::string node_id_prop) + : graph_(graph), dp_(dp), node_id_prop_(node_id_prop) { } + + ~mutate_graph_impl() {} + + bool is_directed() const + { + return + boost::is_convertible< + typename boost::graph_traits::directed_category, + boost::directed_tag>::value; + } + + virtual void do_add_vertex(const node_t& node) + { + // Add the node to the graph. + bgl_vertex_t v = add_vertex(graph_); + + // Set up a mapping from name to BGL vertex. + bgl_nodes.insert(std::make_pair(node, v)); + + // node_id_prop_ allows the caller to see the real id names for nodes. + put(node_id_prop_, dp_, v, node); + } + + void + do_add_edge(const edge_t& edge, const node_t& source, const node_t& target) + { + std::pair result = + add_edge(bgl_nodes[source], bgl_nodes[target], graph_); + + if(!result.second) { + // In the case of no parallel edges allowed + boost::throw_exception(bad_parallel_edge(source, target)); + } else { + bgl_edges.insert(std::make_pair(edge, result.first)); + } + } + + void + set_node_property(const id_t& key, const node_t& node, const id_t& value) + { + put(key, dp_, bgl_nodes[node], value); + } + + void + set_edge_property(const id_t& key, const edge_t& edge, const id_t& value) + { + put(key, dp_, bgl_edges[edge], value); + } + + void + set_graph_property(const id_t& key, const id_t& value) + { + /* RG: pointer to graph prevents copying */ + put(key, dp_, &graph_, value); + } + + + protected: + MutableGraph& graph_; + dynamic_properties& dp_; + std::string node_id_prop_; + std::map bgl_nodes; + std::map bgl_edges; +}; + +BOOST_GRAPH_DECL +bool read_graphviz(std::istream& in, mutate_graph& graph); + +} } // end namespace detail::graph + +// Parse the passed stream as a GraphViz dot file. +template +bool read_graphviz(std::istream& in, MutableGraph& graph, + dynamic_properties& dp, + std::string const& node_id = "node_id") +{ + std::string data; + in >> std::noskipws; + std::copy(std::istream_iterator(in), + std::istream_iterator(), + std::back_inserter(data)); + return read_graphviz(data,graph,dp,node_id); +} + +} // namespace boost + +#ifdef BOOST_GRAPH_USE_SPIRIT_PARSER +# ifndef BOOST_GRAPH_READ_GRAPHVIZ_ITERATORS +# define BOOST_GRAPH_READ_GRAPHVIZ_ITERATORS +# endif +# include +#else // New default parser +# include +#endif // BOOST_GRAPH_USE_SPIRIT_PARSER + +#ifdef BOOST_GRAPH_USE_MPI +# include +#endif + +#endif // BOOST_GRAPHVIZ_HPP diff --git a/src/graph/Makefile.am b/src/graph/Makefile.am index 8887a8e3..637824f9 100644 --- a/src/graph/Makefile.am +++ b/src/graph/Makefile.am @@ -33,6 +33,8 @@ libgraph_tool_core_la_SOURCES = \ read_graphviz_new.cpp\ ../boost-workaround/boost/graph/filtered_graph.hpp\ ../boost-workaround/boost/graph/graphml.hpp\ + ../boost-workaround/boost/graph/graphviz.hpp\ + ../boost-workaround/boost/graph/detail/read_graphviz_new.hpp\ ../boost-workaround/boost/graph/betweenness_centrality.hpp\ ../boost-workaround/boost/graph/copy.hpp\ ../boost-workaround/boost/graph/overloading.hpp\ diff --git a/src/graph/fast_vector_property_map.hh b/src/graph/fast_vector_property_map.hh index 30a24373..d0b5290b 100644 --- a/src/graph/fast_vector_property_map.hh +++ b/src/graph/fast_vector_property_map.hh @@ -32,7 +32,12 @@ #ifndef FAST_VECTOR_PROPERTY_MAP_HH #define FAST_VECTOR_PROPERTY_MAP_HH -#include +#include +#if (BOOST_VERSION >= 104000) +# include +#else +# include +#endif #include #include diff --git a/src/graph/generation/graph_rewiring.hh b/src/graph/generation/graph_rewiring.hh index 82ad68d5..d2b2919c 100644 --- a/src/graph/generation/graph_rewiring.hh +++ b/src/graph/generation/graph_rewiring.hh @@ -369,7 +369,7 @@ private: Graph& _g; EdgeIndexMap _edge_index; vector::vertex_descriptor> _vertices; - vector_property_map _edge_is_new; + checked_vector_property_map _edge_is_new; rng_t& _rng; }; @@ -456,7 +456,7 @@ public: private: Graph& _g; EdgeIndexMap _edge_index; - vector_property_map _edge_is_new; + checked_vector_property_map _edge_is_new; rng_t& _rng; }; diff --git a/src/graph/graph_properties.hh b/src/graph/graph_properties.hh index e2499605..c333c61d 100644 --- a/src/graph/graph_properties.hh +++ b/src/graph/graph_properties.hh @@ -24,8 +24,14 @@ #include #include -#include -#include +#include +#if (BOOST_VERSION >= 104000) +# include +# include +#else +# include +# include +#endif #include "fast_vector_property_map.hh" #include #include diff --git a/src/graph/read_graphviz_new.cpp b/src/graph/read_graphviz_new.cpp index 66a0d395..8809c312 100644 --- a/src/graph/read_graphviz_new.cpp +++ b/src/graph/read_graphviz_new.cpp @@ -27,7 +27,12 @@ #include #include -#include +#include +#if (BOOST_VERSION >= 104000) +# include +#else +# include +#endif #include #include #include -- GitLab